@baseworks/account 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,506 @@
1
+ import * as drizzle_orm_sqlite_core from 'drizzle-orm/sqlite-core';
2
+
3
+ declare const users: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
4
+ name: "users";
5
+ schema: undefined;
6
+ columns: {
7
+ id: drizzle_orm_sqlite_core.SQLiteColumn<{
8
+ name: "id";
9
+ tableName: "users";
10
+ dataType: "string";
11
+ columnType: "SQLiteText";
12
+ data: string;
13
+ driverParam: string;
14
+ notNull: true;
15
+ hasDefault: false;
16
+ isPrimaryKey: true;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: false;
19
+ enumValues: [string, ...string[]];
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {
24
+ length: number | undefined;
25
+ }>;
26
+ subject: drizzle_orm_sqlite_core.SQLiteColumn<{
27
+ name: "subject";
28
+ tableName: "users";
29
+ dataType: "string";
30
+ columnType: "SQLiteText";
31
+ data: string;
32
+ driverParam: string;
33
+ notNull: true;
34
+ hasDefault: false;
35
+ isPrimaryKey: false;
36
+ isAutoincrement: false;
37
+ hasRuntimeDefault: false;
38
+ enumValues: [string, ...string[]];
39
+ baseColumn: never;
40
+ identity: undefined;
41
+ generated: undefined;
42
+ }, {}, {
43
+ length: number | undefined;
44
+ }>;
45
+ issuer: drizzle_orm_sqlite_core.SQLiteColumn<{
46
+ name: "issuer";
47
+ tableName: "users";
48
+ dataType: "string";
49
+ columnType: "SQLiteText";
50
+ data: string;
51
+ driverParam: string;
52
+ notNull: true;
53
+ hasDefault: false;
54
+ isPrimaryKey: false;
55
+ isAutoincrement: false;
56
+ hasRuntimeDefault: false;
57
+ enumValues: [string, ...string[]];
58
+ baseColumn: never;
59
+ identity: undefined;
60
+ generated: undefined;
61
+ }, {}, {
62
+ length: number | undefined;
63
+ }>;
64
+ email: drizzle_orm_sqlite_core.SQLiteColumn<{
65
+ name: "email";
66
+ tableName: "users";
67
+ dataType: "string";
68
+ columnType: "SQLiteText";
69
+ data: string;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: [string, ...string[]];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {
81
+ length: number | undefined;
82
+ }>;
83
+ name: drizzle_orm_sqlite_core.SQLiteColumn<{
84
+ name: "name";
85
+ tableName: "users";
86
+ dataType: "string";
87
+ columnType: "SQLiteText";
88
+ data: string;
89
+ driverParam: string;
90
+ notNull: false;
91
+ hasDefault: false;
92
+ isPrimaryKey: false;
93
+ isAutoincrement: false;
94
+ hasRuntimeDefault: false;
95
+ enumValues: [string, ...string[]];
96
+ baseColumn: never;
97
+ identity: undefined;
98
+ generated: undefined;
99
+ }, {}, {
100
+ length: number | undefined;
101
+ }>;
102
+ picture: drizzle_orm_sqlite_core.SQLiteColumn<{
103
+ name: "picture";
104
+ tableName: "users";
105
+ dataType: "string";
106
+ columnType: "SQLiteText";
107
+ data: string;
108
+ driverParam: string;
109
+ notNull: false;
110
+ hasDefault: false;
111
+ isPrimaryKey: false;
112
+ isAutoincrement: false;
113
+ hasRuntimeDefault: false;
114
+ enumValues: [string, ...string[]];
115
+ baseColumn: never;
116
+ identity: undefined;
117
+ generated: undefined;
118
+ }, {}, {
119
+ length: number | undefined;
120
+ }>;
121
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
122
+ name: "created_at";
123
+ tableName: "users";
124
+ dataType: "number";
125
+ columnType: "SQLiteInteger";
126
+ data: number;
127
+ driverParam: number;
128
+ notNull: true;
129
+ hasDefault: false;
130
+ isPrimaryKey: false;
131
+ isAutoincrement: false;
132
+ hasRuntimeDefault: false;
133
+ enumValues: undefined;
134
+ baseColumn: never;
135
+ identity: undefined;
136
+ generated: undefined;
137
+ }, {}, {}>;
138
+ updatedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
139
+ name: "updated_at";
140
+ tableName: "users";
141
+ dataType: "number";
142
+ columnType: "SQLiteInteger";
143
+ data: number;
144
+ driverParam: number;
145
+ notNull: true;
146
+ hasDefault: false;
147
+ isPrimaryKey: false;
148
+ isAutoincrement: false;
149
+ hasRuntimeDefault: false;
150
+ enumValues: undefined;
151
+ baseColumn: never;
152
+ identity: undefined;
153
+ generated: undefined;
154
+ }, {}, {}>;
155
+ };
156
+ dialect: "sqlite";
157
+ }>;
158
+
159
+ declare const OrgRoles: readonly ["owner", "admin", "member", "viewer"];
160
+ type OrgRole = typeof OrgRoles[number];
161
+ declare const orgMemberships: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
162
+ name: "org_memberships";
163
+ schema: undefined;
164
+ columns: {
165
+ id: drizzle_orm_sqlite_core.SQLiteColumn<{
166
+ name: "id";
167
+ tableName: "org_memberships";
168
+ dataType: "string";
169
+ columnType: "SQLiteText";
170
+ data: string;
171
+ driverParam: string;
172
+ notNull: true;
173
+ hasDefault: false;
174
+ isPrimaryKey: true;
175
+ isAutoincrement: false;
176
+ hasRuntimeDefault: false;
177
+ enumValues: [string, ...string[]];
178
+ baseColumn: never;
179
+ identity: undefined;
180
+ generated: undefined;
181
+ }, {}, {
182
+ length: number | undefined;
183
+ }>;
184
+ userId: drizzle_orm_sqlite_core.SQLiteColumn<{
185
+ name: "user_id";
186
+ tableName: "org_memberships";
187
+ dataType: "string";
188
+ columnType: "SQLiteText";
189
+ data: string;
190
+ driverParam: string;
191
+ notNull: true;
192
+ hasDefault: false;
193
+ isPrimaryKey: false;
194
+ isAutoincrement: false;
195
+ hasRuntimeDefault: false;
196
+ enumValues: [string, ...string[]];
197
+ baseColumn: never;
198
+ identity: undefined;
199
+ generated: undefined;
200
+ }, {}, {
201
+ length: number | undefined;
202
+ }>;
203
+ organizationId: drizzle_orm_sqlite_core.SQLiteColumn<{
204
+ name: "organization_id";
205
+ tableName: "org_memberships";
206
+ dataType: "string";
207
+ columnType: "SQLiteText";
208
+ data: string;
209
+ driverParam: string;
210
+ notNull: true;
211
+ hasDefault: false;
212
+ isPrimaryKey: false;
213
+ isAutoincrement: false;
214
+ hasRuntimeDefault: false;
215
+ enumValues: [string, ...string[]];
216
+ baseColumn: never;
217
+ identity: undefined;
218
+ generated: undefined;
219
+ }, {}, {
220
+ length: number | undefined;
221
+ }>;
222
+ role: drizzle_orm_sqlite_core.SQLiteColumn<{
223
+ name: "role";
224
+ tableName: "org_memberships";
225
+ dataType: "string";
226
+ columnType: "SQLiteText";
227
+ data: "owner" | "admin" | "member" | "viewer";
228
+ driverParam: string;
229
+ notNull: true;
230
+ hasDefault: false;
231
+ isPrimaryKey: false;
232
+ isAutoincrement: false;
233
+ hasRuntimeDefault: false;
234
+ enumValues: [string, ...string[]];
235
+ baseColumn: never;
236
+ identity: undefined;
237
+ generated: undefined;
238
+ }, {}, {
239
+ length: number | undefined;
240
+ $type: "owner" | "admin" | "member" | "viewer";
241
+ }>;
242
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
243
+ name: "created_at";
244
+ tableName: "org_memberships";
245
+ dataType: "number";
246
+ columnType: "SQLiteInteger";
247
+ data: number;
248
+ driverParam: number;
249
+ notNull: true;
250
+ hasDefault: false;
251
+ isPrimaryKey: false;
252
+ isAutoincrement: false;
253
+ hasRuntimeDefault: false;
254
+ enumValues: undefined;
255
+ baseColumn: never;
256
+ identity: undefined;
257
+ generated: undefined;
258
+ }, {}, {}>;
259
+ updatedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
260
+ name: "updated_at";
261
+ tableName: "org_memberships";
262
+ dataType: "number";
263
+ columnType: "SQLiteInteger";
264
+ data: number;
265
+ driverParam: number;
266
+ notNull: true;
267
+ hasDefault: false;
268
+ isPrimaryKey: false;
269
+ isAutoincrement: false;
270
+ hasRuntimeDefault: false;
271
+ enumValues: undefined;
272
+ baseColumn: never;
273
+ identity: undefined;
274
+ generated: undefined;
275
+ }, {}, {}>;
276
+ };
277
+ dialect: "sqlite";
278
+ }>;
279
+
280
+ declare const apiTokens: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
281
+ name: "api_tokens";
282
+ schema: undefined;
283
+ columns: {
284
+ id: drizzle_orm_sqlite_core.SQLiteColumn<{
285
+ name: "id";
286
+ tableName: "api_tokens";
287
+ dataType: "string";
288
+ columnType: "SQLiteText";
289
+ data: string;
290
+ driverParam: string;
291
+ notNull: true;
292
+ hasDefault: false;
293
+ isPrimaryKey: true;
294
+ isAutoincrement: false;
295
+ hasRuntimeDefault: false;
296
+ enumValues: [string, ...string[]];
297
+ baseColumn: never;
298
+ identity: undefined;
299
+ generated: undefined;
300
+ }, {}, {
301
+ length: number | undefined;
302
+ }>;
303
+ organizationId: drizzle_orm_sqlite_core.SQLiteColumn<{
304
+ name: "organization_id";
305
+ tableName: "api_tokens";
306
+ dataType: "string";
307
+ columnType: "SQLiteText";
308
+ data: string;
309
+ driverParam: string;
310
+ notNull: true;
311
+ hasDefault: false;
312
+ isPrimaryKey: false;
313
+ isAutoincrement: false;
314
+ hasRuntimeDefault: false;
315
+ enumValues: [string, ...string[]];
316
+ baseColumn: never;
317
+ identity: undefined;
318
+ generated: undefined;
319
+ }, {}, {
320
+ length: number | undefined;
321
+ }>;
322
+ userId: drizzle_orm_sqlite_core.SQLiteColumn<{
323
+ name: "user_id";
324
+ tableName: "api_tokens";
325
+ dataType: "string";
326
+ columnType: "SQLiteText";
327
+ data: string;
328
+ driverParam: string;
329
+ notNull: false;
330
+ hasDefault: false;
331
+ isPrimaryKey: false;
332
+ isAutoincrement: false;
333
+ hasRuntimeDefault: false;
334
+ enumValues: [string, ...string[]];
335
+ baseColumn: never;
336
+ identity: undefined;
337
+ generated: undefined;
338
+ }, {}, {
339
+ length: number | undefined;
340
+ }>;
341
+ name: drizzle_orm_sqlite_core.SQLiteColumn<{
342
+ name: "name";
343
+ tableName: "api_tokens";
344
+ dataType: "string";
345
+ columnType: "SQLiteText";
346
+ data: string;
347
+ driverParam: string;
348
+ notNull: true;
349
+ hasDefault: false;
350
+ isPrimaryKey: false;
351
+ isAutoincrement: false;
352
+ hasRuntimeDefault: false;
353
+ enumValues: [string, ...string[]];
354
+ baseColumn: never;
355
+ identity: undefined;
356
+ generated: undefined;
357
+ }, {}, {
358
+ length: number | undefined;
359
+ }>;
360
+ tokenHash: drizzle_orm_sqlite_core.SQLiteColumn<{
361
+ name: "token_hash";
362
+ tableName: "api_tokens";
363
+ dataType: "string";
364
+ columnType: "SQLiteText";
365
+ data: string;
366
+ driverParam: string;
367
+ notNull: true;
368
+ hasDefault: false;
369
+ isPrimaryKey: false;
370
+ isAutoincrement: false;
371
+ hasRuntimeDefault: false;
372
+ enumValues: [string, ...string[]];
373
+ baseColumn: never;
374
+ identity: undefined;
375
+ generated: undefined;
376
+ }, {}, {
377
+ length: number | undefined;
378
+ }>;
379
+ keyPrefix: drizzle_orm_sqlite_core.SQLiteColumn<{
380
+ name: "key_prefix";
381
+ tableName: "api_tokens";
382
+ dataType: "string";
383
+ columnType: "SQLiteText";
384
+ data: string;
385
+ driverParam: string;
386
+ notNull: true;
387
+ hasDefault: false;
388
+ isPrimaryKey: false;
389
+ isAutoincrement: false;
390
+ hasRuntimeDefault: false;
391
+ enumValues: [string, ...string[]];
392
+ baseColumn: never;
393
+ identity: undefined;
394
+ generated: undefined;
395
+ }, {}, {
396
+ length: number | undefined;
397
+ }>;
398
+ scopes: drizzle_orm_sqlite_core.SQLiteColumn<{
399
+ name: "scopes";
400
+ tableName: "api_tokens";
401
+ dataType: "string";
402
+ columnType: "SQLiteText";
403
+ data: string;
404
+ driverParam: string;
405
+ notNull: true;
406
+ hasDefault: true;
407
+ isPrimaryKey: false;
408
+ isAutoincrement: false;
409
+ hasRuntimeDefault: false;
410
+ enumValues: [string, ...string[]];
411
+ baseColumn: never;
412
+ identity: undefined;
413
+ generated: undefined;
414
+ }, {}, {
415
+ length: number | undefined;
416
+ }>;
417
+ lastUsedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
418
+ name: "last_used_at";
419
+ tableName: "api_tokens";
420
+ dataType: "number";
421
+ columnType: "SQLiteInteger";
422
+ data: number;
423
+ driverParam: number;
424
+ notNull: false;
425
+ hasDefault: false;
426
+ isPrimaryKey: false;
427
+ isAutoincrement: false;
428
+ hasRuntimeDefault: false;
429
+ enumValues: undefined;
430
+ baseColumn: never;
431
+ identity: undefined;
432
+ generated: undefined;
433
+ }, {}, {}>;
434
+ expiresAt: drizzle_orm_sqlite_core.SQLiteColumn<{
435
+ name: "expires_at";
436
+ tableName: "api_tokens";
437
+ dataType: "number";
438
+ columnType: "SQLiteInteger";
439
+ data: number;
440
+ driverParam: number;
441
+ notNull: false;
442
+ hasDefault: false;
443
+ isPrimaryKey: false;
444
+ isAutoincrement: false;
445
+ hasRuntimeDefault: false;
446
+ enumValues: undefined;
447
+ baseColumn: never;
448
+ identity: undefined;
449
+ generated: undefined;
450
+ }, {}, {}>;
451
+ revokedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
452
+ name: "revoked_at";
453
+ tableName: "api_tokens";
454
+ dataType: "number";
455
+ columnType: "SQLiteInteger";
456
+ data: number;
457
+ driverParam: number;
458
+ notNull: false;
459
+ hasDefault: false;
460
+ isPrimaryKey: false;
461
+ isAutoincrement: false;
462
+ hasRuntimeDefault: false;
463
+ enumValues: undefined;
464
+ baseColumn: never;
465
+ identity: undefined;
466
+ generated: undefined;
467
+ }, {}, {}>;
468
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
469
+ name: "created_at";
470
+ tableName: "api_tokens";
471
+ dataType: "number";
472
+ columnType: "SQLiteInteger";
473
+ data: number;
474
+ driverParam: number;
475
+ notNull: true;
476
+ hasDefault: false;
477
+ isPrimaryKey: false;
478
+ isAutoincrement: false;
479
+ hasRuntimeDefault: false;
480
+ enumValues: undefined;
481
+ baseColumn: never;
482
+ identity: undefined;
483
+ generated: undefined;
484
+ }, {}, {}>;
485
+ updatedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
486
+ name: "updated_at";
487
+ tableName: "api_tokens";
488
+ dataType: "number";
489
+ columnType: "SQLiteInteger";
490
+ data: number;
491
+ driverParam: number;
492
+ notNull: true;
493
+ hasDefault: false;
494
+ isPrimaryKey: false;
495
+ isAutoincrement: false;
496
+ hasRuntimeDefault: false;
497
+ enumValues: undefined;
498
+ baseColumn: never;
499
+ identity: undefined;
500
+ generated: undefined;
501
+ }, {}, {}>;
502
+ };
503
+ dialect: "sqlite";
504
+ }>;
505
+
506
+ export { type OrgRole, OrgRoles, apiTokens, orgMemberships, users };
@@ -0,0 +1,60 @@
1
+ // src/schema/sqlite/users.ts
2
+ import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
3
+ var users = sqliteTable("users", {
4
+ id: text("id").primaryKey(),
5
+ // UUIDv7 — our internal key
6
+ subject: text("subject").notNull(),
7
+ // OIDC `sub` claim
8
+ issuer: text("issuer").notNull(),
9
+ // OIDC `iss` — e.g. https://auth.example.com
10
+ email: text("email").notNull(),
11
+ name: text("name"),
12
+ picture: text("picture"),
13
+ // avatar URL from OIDC `picture` claim
14
+ createdAt: integer("created_at").notNull(),
15
+ // Unix ms
16
+ updatedAt: integer("updated_at").notNull()
17
+ });
18
+
19
+ // src/schema/sqlite/memberships.ts
20
+ import { integer as integer2, sqliteTable as sqliteTable2, text as text2 } from "drizzle-orm/sqlite-core";
21
+ import { organizations } from "@baseworks/organization";
22
+ var OrgRoles = ["owner", "admin", "member", "viewer"];
23
+ var orgMemberships = sqliteTable2("org_memberships", {
24
+ id: text2("id").primaryKey(),
25
+ userId: text2("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
26
+ organizationId: text2("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
27
+ role: text2("role").notNull().$type(),
28
+ createdAt: integer2("created_at").notNull(),
29
+ updatedAt: integer2("updated_at").notNull()
30
+ });
31
+
32
+ // src/schema/sqlite/api-tokens.ts
33
+ import { integer as integer3, sqliteTable as sqliteTable3, text as text3 } from "drizzle-orm/sqlite-core";
34
+ import { organizations as organizations2 } from "@baseworks/organization";
35
+ var apiTokens = sqliteTable3("api_tokens", {
36
+ id: text3("id").primaryKey(),
37
+ organizationId: text3("organization_id").notNull().references(() => organizations2.id, { onDelete: "cascade" }),
38
+ userId: text3("user_id").references(() => users.id, { onDelete: "cascade" }),
39
+ // null = org-level key
40
+ name: text3("name").notNull(),
41
+ tokenHash: text3("token_hash").notNull().unique(),
42
+ keyPrefix: text3("key_prefix").notNull(),
43
+ // e.g. "orb_", "tally_" — service identifier
44
+ scopes: text3("scopes").notNull().default("[]"),
45
+ // JSON string[]
46
+ lastUsedAt: integer3("last_used_at"),
47
+ // Unix ms
48
+ expiresAt: integer3("expires_at"),
49
+ // Unix ms, null = never
50
+ revokedAt: integer3("revoked_at"),
51
+ // Unix ms
52
+ createdAt: integer3("created_at").notNull(),
53
+ updatedAt: integer3("updated_at").notNull()
54
+ });
55
+ export {
56
+ OrgRoles,
57
+ apiTokens,
58
+ orgMemberships,
59
+ users
60
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@baseworks/account",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./dist/index.js",
7
+ "./cli": "./dist/cli.js",
8
+ "./schema/sqlite": "./dist/schema/sqlite/index.js",
9
+ "./schema/pg": "./dist/schema/pg/index.js"
10
+ },
11
+ "files": ["dist", "src"],
12
+ "scripts": {
13
+ "build": "tsup",
14
+ "typecheck": "tsc --noEmit",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest"
17
+ },
18
+ "dependencies": {
19
+ "@baseworks/cli": "^0.2.0",
20
+ "@baseworks/core": "^0.2.0",
21
+ "@baseworks/organization": "^0.2.0",
22
+ "commander": "^15.0.0",
23
+ "drizzle-orm": "^0.44.0",
24
+ "zod": "^3.24.0"
25
+ },
26
+ "devDependencies": {
27
+ "@baseworks/tsconfig": "workspace:*",
28
+ "@types/node": "^25.9.3",
29
+ "drizzle-kit": "^0.31.10",
30
+ "msw": "^2.14.6",
31
+ "tsup": "^8.5.1",
32
+ "typescript": "^5.6.0",
33
+ "vitest": "^4.1.9"
34
+ }
35
+ }
@@ -0,0 +1,32 @@
1
+ /// <reference types="vitest/globals" />
2
+ import { beforeAll, afterEach, afterAll, describe, it, expect } from 'vitest'
3
+ import { run, mocks, server } from './helpers.js'
4
+
5
+ beforeAll(() => server.listen({ onUnhandledRequest: 'warn' }))
6
+ afterEach(() => server.resetHandlers())
7
+ afterAll(() => server.close())
8
+
9
+ const ME = {
10
+ user: { id: '019f10aa-1111-7000-9999-fffffffaaaaa', email: 'ali@dotlabs.io', name: 'Ali' },
11
+ role: 'admin',
12
+ org: { id: '019f05bd-ebf7-7db6-956d-f323dfadba50', slug: 'dotlabs', name: 'Dotlabs' },
13
+ }
14
+
15
+ describe('flect me', () => {
16
+ it('shows email, role, org slug', async () => {
17
+ mocks.mockGet('/v1/account/me', ME)
18
+ const r = await run(['me'])
19
+ expect(r.exitCode).toBe(0)
20
+ expect(r.stdout).toContain('ali@dotlabs.io')
21
+ expect(r.stdout).toContain('admin')
22
+ expect(r.stdout).toContain('dotlabs')
23
+ })
24
+
25
+ it('-o json returns raw object', async () => {
26
+ mocks.mockGet('/v1/account/me', ME)
27
+ const r = await run(['me', '-o', 'json'])
28
+ expect(r.exitCode).toBe(0)
29
+ const parsed = JSON.parse(r.stdout)
30
+ expect(parsed.user.email).toBe('ali@dotlabs.io')
31
+ })
32
+ })