primitive-admin 1.0.25 → 1.0.26

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,512 @@
1
+ import { ApiClient } from "../lib/api-client.js";
2
+ import { getCurrentAppId } from "../lib/config.js";
3
+ import { success, error, info, keyValue, formatTable, formatId, formatDate, json, } from "../lib/output.js";
4
+ function resolveAppId(appId, options) {
5
+ const resolved = appId || options.app || getCurrentAppId();
6
+ if (!resolved) {
7
+ error("No app specified. Use <app-id>, --app, or 'primitive use <app-id>' to set context.");
8
+ process.exit(1);
9
+ }
10
+ return resolved;
11
+ }
12
+ export function registerCollectionsCommands(program) {
13
+ const collections = program
14
+ .command("collections")
15
+ .description("Create and manage document collections and their access")
16
+ .addHelpText("after", `
17
+ Examples:
18
+ $ primitive collections list
19
+ $ primitive collections create "Sprint 12"
20
+ $ primitive collections get <collection-id>
21
+ $ primitive collections docs list <collection-id>
22
+ $ primitive collections docs add <collection-id> <document-id>
23
+ $ primitive collections access <collection-id>
24
+ $ primitive collections share <collection-id> --group team/engineering --permission read-write
25
+ $ primitive collections members add <collection-id> <user-id> --permission reader
26
+ $ primitive collections for-document <document-id>
27
+ `);
28
+ // List collections
29
+ collections
30
+ .command("list")
31
+ .description("List collections in an app")
32
+ .argument("[app-id]", "App ID (uses current app if not specified)")
33
+ .option("--app <app-id>", "App ID")
34
+ .option("--json", "Output as JSON")
35
+ .action(async (appId, options) => {
36
+ const resolvedAppId = resolveAppId(appId, options);
37
+ const client = new ApiClient();
38
+ try {
39
+ const result = await client.listCollections(resolvedAppId);
40
+ const list = Array.isArray(result) ? result : result?.items ?? [];
41
+ if (options.json) {
42
+ json(result);
43
+ return;
44
+ }
45
+ if (list.length === 0) {
46
+ info("No collections found.");
47
+ return;
48
+ }
49
+ console.log(formatTable(list, [
50
+ { header: "ID", key: "collectionId", format: formatId },
51
+ { header: "NAME", key: "name" },
52
+ { header: "DESCRIPTION", key: "description", format: (v) => v || "—" },
53
+ { header: "DOCS", key: "documentCount" },
54
+ { header: "CREATED", key: "createdAt", format: formatDate },
55
+ ]));
56
+ if (result?.nextCursor) {
57
+ info(`More results available. Use --json to get the cursor for pagination.`);
58
+ }
59
+ }
60
+ catch (err) {
61
+ error(err.message);
62
+ process.exit(1);
63
+ }
64
+ });
65
+ // Create collection
66
+ collections
67
+ .command("create")
68
+ .description("Create a new collection")
69
+ .argument("<name>", "Collection name")
70
+ .option("--description <description>", "Collection description")
71
+ .option("--app <app-id>", "App ID")
72
+ .option("--json", "Output as JSON")
73
+ .action(async (name, options) => {
74
+ const resolvedAppId = resolveAppId(undefined, options);
75
+ const client = new ApiClient();
76
+ try {
77
+ const data = { name };
78
+ if (options.description)
79
+ data.description = options.description;
80
+ const result = await client.createCollection(resolvedAppId, data);
81
+ if (options.json) {
82
+ json(result);
83
+ return;
84
+ }
85
+ success("Collection created.");
86
+ keyValue("Collection ID", result.collectionId);
87
+ keyValue("Name", result.name);
88
+ if (result.description)
89
+ keyValue("Description", result.description);
90
+ }
91
+ catch (err) {
92
+ error(err.message);
93
+ process.exit(1);
94
+ }
95
+ });
96
+ // Get collection
97
+ collections
98
+ .command("get")
99
+ .description("Get collection details")
100
+ .argument("<collection-id>", "Collection ID")
101
+ .option("--app <app-id>", "App ID")
102
+ .option("--json", "Output as JSON")
103
+ .action(async (collectionId, options) => {
104
+ const resolvedAppId = resolveAppId(undefined, options);
105
+ const client = new ApiClient();
106
+ try {
107
+ const result = await client.getCollection(resolvedAppId, collectionId);
108
+ if (options.json) {
109
+ json(result);
110
+ return;
111
+ }
112
+ keyValue("Collection ID", result.collectionId);
113
+ keyValue("Name", result.name);
114
+ keyValue("Description", result.description || "—");
115
+ keyValue("Documents", result.documentCount);
116
+ keyValue("Created", formatDate(result.createdAt));
117
+ }
118
+ catch (err) {
119
+ error(err.message);
120
+ process.exit(1);
121
+ }
122
+ });
123
+ // Update collection
124
+ collections
125
+ .command("update")
126
+ .description("Update a collection")
127
+ .argument("<collection-id>", "Collection ID")
128
+ .option("--name <name>", "New collection name")
129
+ .option("--description <description>", "New collection description")
130
+ .option("--app <app-id>", "App ID")
131
+ .option("--json", "Output as JSON")
132
+ .action(async (collectionId, options) => {
133
+ const resolvedAppId = resolveAppId(undefined, options);
134
+ const client = new ApiClient();
135
+ const data = {};
136
+ if (options.name)
137
+ data.name = options.name;
138
+ if (options.description)
139
+ data.description = options.description;
140
+ if (Object.keys(data).length === 0) {
141
+ error("Provide at least --name or --description to update.");
142
+ process.exit(1);
143
+ }
144
+ try {
145
+ const result = await client.updateCollection(resolvedAppId, collectionId, data);
146
+ if (options.json) {
147
+ json(result);
148
+ return;
149
+ }
150
+ success(`Collection ${collectionId} updated.`);
151
+ }
152
+ catch (err) {
153
+ error(err.message);
154
+ process.exit(1);
155
+ }
156
+ });
157
+ // Delete collection
158
+ collections
159
+ .command("delete")
160
+ .description("Delete a collection (documents are preserved)")
161
+ .argument("<collection-id>", "Collection ID")
162
+ .option("--app <app-id>", "App ID")
163
+ .option("-y, --yes", "Skip confirmation prompt")
164
+ .action(async (collectionId, options) => {
165
+ const resolvedAppId = resolveAppId(undefined, options);
166
+ if (!options.yes) {
167
+ const inquirer = await import("inquirer");
168
+ const { confirm } = await inquirer.default.prompt([
169
+ {
170
+ type: "confirm",
171
+ name: "confirm",
172
+ message: `Delete collection ${collectionId}? This revokes all collection-granted permissions but does NOT delete documents.`,
173
+ default: false,
174
+ },
175
+ ]);
176
+ if (!confirm) {
177
+ info("Cancelled.");
178
+ return;
179
+ }
180
+ }
181
+ const client = new ApiClient();
182
+ try {
183
+ await client.deleteCollection(resolvedAppId, collectionId);
184
+ success(`Collection ${collectionId} deleted.`);
185
+ }
186
+ catch (err) {
187
+ error(err.message);
188
+ process.exit(1);
189
+ }
190
+ });
191
+ // ---- Access command ----
192
+ collections
193
+ .command("access")
194
+ .description("View groups and members with access to a collection")
195
+ .argument("<collection-id>", "Collection ID")
196
+ .option("--app <app-id>", "App ID")
197
+ .option("--json", "Output as JSON")
198
+ .action(async (collectionId, options) => {
199
+ const resolvedAppId = resolveAppId(undefined, options);
200
+ const client = new ApiClient();
201
+ try {
202
+ const result = await client.getCollectionAccess(resolvedAppId, collectionId);
203
+ if (options.json) {
204
+ json(result);
205
+ return;
206
+ }
207
+ const groups = result.groups || [];
208
+ const members = result.members || [];
209
+ if (groups.length === 0 && members.length === 0) {
210
+ info("No groups or members have access to this collection.");
211
+ return;
212
+ }
213
+ if (groups.length > 0) {
214
+ console.log("\nGroups:");
215
+ console.log(formatTable(groups, [
216
+ { header: "TYPE", key: "groupType" },
217
+ { header: "ID", key: "groupId" },
218
+ { header: "PERMISSION", key: "permission" },
219
+ { header: "GRANTED", key: "grantedAt", format: formatDate },
220
+ ]));
221
+ }
222
+ if (members.length > 0) {
223
+ console.log("\nMembers:");
224
+ console.log(formatTable(members, [
225
+ { header: "USER_ID", key: "userId", format: formatId },
226
+ { header: "PERMISSION", key: "permission" },
227
+ ]));
228
+ }
229
+ }
230
+ catch (err) {
231
+ error(err.message);
232
+ process.exit(1);
233
+ }
234
+ });
235
+ // ---- Share / unshare (group permissions) ----
236
+ collections
237
+ .command("share")
238
+ .description("Grant a group access to a collection")
239
+ .argument("<collection-id>", "Collection ID")
240
+ .requiredOption("--group <group>", "Group in format type/id (e.g. team/engineering)")
241
+ .requiredOption("--permission <permission>", "Permission level (reader or read-write)")
242
+ .option("--app <app-id>", "App ID")
243
+ .option("--json", "Output as JSON")
244
+ .action(async (collectionId, options) => {
245
+ const resolvedAppId = resolveAppId(undefined, options);
246
+ const client = new ApiClient();
247
+ const parts = options.group.split("/");
248
+ if (parts.length !== 2) {
249
+ error("Group must be in format type/id (e.g. team/engineering).");
250
+ process.exit(1);
251
+ }
252
+ const [groupType, groupId] = parts;
253
+ try {
254
+ const result = await client.grantCollectionGroupPermission(resolvedAppId, collectionId, {
255
+ groupType,
256
+ groupId,
257
+ permission: options.permission,
258
+ });
259
+ if (options.json) {
260
+ json(result);
261
+ return;
262
+ }
263
+ success(`Granted ${options.permission} access to ${groupType}/${groupId} on collection.`);
264
+ }
265
+ catch (err) {
266
+ error(err.message);
267
+ process.exit(1);
268
+ }
269
+ });
270
+ collections
271
+ .command("unshare")
272
+ .description("Revoke a group's access to a collection")
273
+ .argument("<collection-id>", "Collection ID")
274
+ .requiredOption("--group <group>", "Group in format type/id (e.g. team/engineering)")
275
+ .option("--app <app-id>", "App ID")
276
+ .option("-y, --yes", "Skip confirmation prompt")
277
+ .action(async (collectionId, options) => {
278
+ const resolvedAppId = resolveAppId(undefined, options);
279
+ const parts = options.group.split("/");
280
+ if (parts.length !== 2) {
281
+ error("Group must be in format type/id (e.g. team/engineering).");
282
+ process.exit(1);
283
+ }
284
+ const [groupType, groupId] = parts;
285
+ if (!options.yes) {
286
+ const inquirer = await import("inquirer");
287
+ const { confirm } = await inquirer.default.prompt([
288
+ {
289
+ type: "confirm",
290
+ name: "confirm",
291
+ message: `Revoke ${groupType}/${groupId} access to collection ${collectionId}?`,
292
+ default: false,
293
+ },
294
+ ]);
295
+ if (!confirm) {
296
+ info("Cancelled.");
297
+ return;
298
+ }
299
+ }
300
+ const client = new ApiClient();
301
+ try {
302
+ await client.revokeCollectionGroupPermission(resolvedAppId, collectionId, groupType, groupId);
303
+ success(`Revoked ${groupType}/${groupId} access from collection.`);
304
+ }
305
+ catch (err) {
306
+ error(err.message);
307
+ process.exit(1);
308
+ }
309
+ });
310
+ // ---- Documents subcommand group ----
311
+ const docs = collections
312
+ .command("docs")
313
+ .description("Manage documents in a collection");
314
+ // List documents
315
+ docs
316
+ .command("list")
317
+ .description("List documents in a collection")
318
+ .argument("<collection-id>", "Collection ID")
319
+ .option("--app <app-id>", "App ID")
320
+ .option("--json", "Output as JSON")
321
+ .action(async (collectionId, options) => {
322
+ const resolvedAppId = resolveAppId(undefined, options);
323
+ const client = new ApiClient();
324
+ try {
325
+ const result = await client.listCollectionDocuments(resolvedAppId, collectionId);
326
+ const list = Array.isArray(result) ? result : result?.items ?? [];
327
+ if (options.json) {
328
+ json(result);
329
+ return;
330
+ }
331
+ if (list.length === 0) {
332
+ info("No documents in this collection.");
333
+ return;
334
+ }
335
+ console.log(formatTable(list, [
336
+ { header: "DOCUMENT_ID", key: "documentId", format: formatId },
337
+ { header: "ADDED", key: "addedAt", format: formatDate },
338
+ ]));
339
+ if (result?.nextCursor) {
340
+ info(`More results available. Use --json to get the cursor for pagination.`);
341
+ }
342
+ }
343
+ catch (err) {
344
+ error(err.message);
345
+ process.exit(1);
346
+ }
347
+ });
348
+ // Add document
349
+ docs
350
+ .command("add")
351
+ .description("Add a document to a collection")
352
+ .argument("<collection-id>", "Collection ID")
353
+ .argument("<document-id>", "Document ID")
354
+ .option("--app <app-id>", "App ID")
355
+ .option("--json", "Output as JSON")
356
+ .action(async (collectionId, documentId, options) => {
357
+ const resolvedAppId = resolveAppId(undefined, options);
358
+ const client = new ApiClient();
359
+ try {
360
+ const result = await client.addCollectionDocument(resolvedAppId, collectionId, {
361
+ documentId,
362
+ });
363
+ if (options.json) {
364
+ json(result);
365
+ return;
366
+ }
367
+ success(`Document ${documentId} added to collection.`);
368
+ }
369
+ catch (err) {
370
+ error(err.message);
371
+ process.exit(1);
372
+ }
373
+ });
374
+ // Remove document
375
+ docs
376
+ .command("remove")
377
+ .description("Remove a document from a collection")
378
+ .argument("<collection-id>", "Collection ID")
379
+ .argument("<document-id>", "Document ID")
380
+ .option("--app <app-id>", "App ID")
381
+ .option("-y, --yes", "Skip confirmation prompt")
382
+ .action(async (collectionId, documentId, options) => {
383
+ const resolvedAppId = resolveAppId(undefined, options);
384
+ if (!options.yes) {
385
+ const inquirer = await import("inquirer");
386
+ const { confirm } = await inquirer.default.prompt([
387
+ {
388
+ type: "confirm",
389
+ name: "confirm",
390
+ message: `Remove document ${documentId} from collection? Collection-sourced permissions will be revoked.`,
391
+ default: false,
392
+ },
393
+ ]);
394
+ if (!confirm) {
395
+ info("Cancelled.");
396
+ return;
397
+ }
398
+ }
399
+ const client = new ApiClient();
400
+ try {
401
+ await client.removeCollectionDocument(resolvedAppId, collectionId, documentId);
402
+ success(`Document ${documentId} removed from collection.`);
403
+ }
404
+ catch (err) {
405
+ error(err.message);
406
+ process.exit(1);
407
+ }
408
+ });
409
+ // ---- List collections for a document (reverse lookup) ----
410
+ collections
411
+ .command("for-document")
412
+ .description("List collections that a document belongs to")
413
+ .argument("<document-id>", "Document ID")
414
+ .option("--app <app-id>", "App ID")
415
+ .option("--json", "Output as JSON")
416
+ .action(async (documentId, options) => {
417
+ const resolvedAppId = resolveAppId(undefined, options);
418
+ const client = new ApiClient();
419
+ try {
420
+ const result = await client.listCollectionsForDocument(resolvedAppId, documentId);
421
+ const list = Array.isArray(result) ? result : result?.items ?? [];
422
+ if (options.json) {
423
+ json(result);
424
+ return;
425
+ }
426
+ if (list.length === 0) {
427
+ info("Document is not in any collections.");
428
+ return;
429
+ }
430
+ console.log(formatTable(list, [
431
+ { header: "COLLECTION_ID", key: "collectionId", format: formatId },
432
+ { header: "NAME", key: "name" },
433
+ { header: "ADDED", key: "addedAt", format: formatDate },
434
+ ]));
435
+ if (result?.nextCursor) {
436
+ info(`More results available. Use --json to get the cursor for pagination.`);
437
+ }
438
+ }
439
+ catch (err) {
440
+ error(err.message);
441
+ process.exit(1);
442
+ }
443
+ });
444
+ // ---- Members subcommand group ----
445
+ const members = collections
446
+ .command("members")
447
+ .description("Manage individual user access to a collection");
448
+ // Add member
449
+ members
450
+ .command("add")
451
+ .description("Add a user to a collection")
452
+ .argument("<collection-id>", "Collection ID")
453
+ .argument("<user-id>", "User ID")
454
+ .requiredOption("--permission <permission>", "Permission level (reader or read-write)")
455
+ .option("--app <app-id>", "App ID")
456
+ .option("--json", "Output as JSON")
457
+ .action(async (collectionId, userId, options) => {
458
+ const resolvedAppId = resolveAppId(undefined, options);
459
+ const client = new ApiClient();
460
+ try {
461
+ const result = await client.addCollectionMember(resolvedAppId, collectionId, {
462
+ userId,
463
+ permission: options.permission,
464
+ });
465
+ if (options.json) {
466
+ json(result);
467
+ return;
468
+ }
469
+ success(`User ${userId} added to collection with ${options.permission} access.`);
470
+ }
471
+ catch (err) {
472
+ error(err.message);
473
+ process.exit(1);
474
+ }
475
+ });
476
+ // Remove member
477
+ members
478
+ .command("remove")
479
+ .description("Remove a user from a collection")
480
+ .argument("<collection-id>", "Collection ID")
481
+ .argument("<user-id>", "User ID")
482
+ .option("--app <app-id>", "App ID")
483
+ .option("-y, --yes", "Skip confirmation prompt")
484
+ .action(async (collectionId, userId, options) => {
485
+ const resolvedAppId = resolveAppId(undefined, options);
486
+ if (!options.yes) {
487
+ const inquirer = await import("inquirer");
488
+ const { confirm } = await inquirer.default.prompt([
489
+ {
490
+ type: "confirm",
491
+ name: "confirm",
492
+ message: `Remove user ${userId} from collection ${collectionId}?`,
493
+ default: false,
494
+ },
495
+ ]);
496
+ if (!confirm) {
497
+ info("Cancelled.");
498
+ return;
499
+ }
500
+ }
501
+ const client = new ApiClient();
502
+ try {
503
+ await client.removeCollectionMember(resolvedAppId, collectionId, userId);
504
+ success(`User ${userId} removed from collection.`);
505
+ }
506
+ catch (err) {
507
+ error(err.message);
508
+ process.exit(1);
509
+ }
510
+ });
511
+ }
512
+ //# sourceMappingURL=collections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collections.js","sourceRoot":"","sources":["../../../src/commands/collections.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { ApiClient } from "../lib/api-client.js";
2
2
  import { resolveAppId } from "../lib/config.js";
3
- import { success, error, info, json } from "../lib/output.js";
3
+ import { success, error, info, formatTable, formatDate, json, } from "../lib/output.js";
4
4
  export function registerDocumentsCommands(program) {
5
5
  const documents = program
6
6
  .command("documents")
@@ -8,7 +8,7 @@ export function registerDocumentsCommands(program) {
8
8
  .addHelpText("after", `
9
9
  Examples:
10
10
  $ primitive documents transfer-owner <document-id> <new-owner-id>
11
- $ primitive documents transfer-owner <document-id> <new-owner-id> --app <app-id>
11
+ $ primitive documents group-permissions list <document-id>
12
12
  `);
13
13
  // Transfer document ownership
14
14
  documents
@@ -71,5 +71,108 @@ Examples:
71
71
  process.exit(1);
72
72
  }
73
73
  });
74
+ // ---- Group Permissions subcommand group ----
75
+ const groupPermissions = documents
76
+ .command("group-permissions")
77
+ .description("Manage group permissions on a document");
78
+ // List group permissions
79
+ groupPermissions
80
+ .command("list")
81
+ .description("List group permissions for a document")
82
+ .argument("<document-id>", "Document ID")
83
+ .option("--app <app-id>", "App ID")
84
+ .option("--json", "Output as JSON")
85
+ .action(async (documentId, options) => {
86
+ const resolvedAppId = resolveAppId(undefined, options);
87
+ const client = new ApiClient();
88
+ try {
89
+ const result = await client.listDocumentGroupPermissions(resolvedAppId, documentId);
90
+ const list = Array.isArray(result) ? result : result?.permissions ?? [];
91
+ if (options.json) {
92
+ json(list);
93
+ return;
94
+ }
95
+ if (list.length === 0) {
96
+ info("No group permissions found.");
97
+ return;
98
+ }
99
+ console.log(formatTable(list, [
100
+ { header: "GROUP_TYPE", key: "groupType" },
101
+ { header: "GROUP_ID", key: "groupId" },
102
+ { header: "PERMISSION", key: "permission" },
103
+ { header: "GRANTED", key: "grantedAt", format: formatDate },
104
+ ]));
105
+ }
106
+ catch (err) {
107
+ error(err.message);
108
+ process.exit(1);
109
+ }
110
+ });
111
+ // Grant group permission
112
+ groupPermissions
113
+ .command("grant")
114
+ .description("Grant a group permission on a document")
115
+ .argument("<document-id>", "Document ID")
116
+ .requiredOption("--group-type <type>", "Group type")
117
+ .requiredOption("--group-id <id>", "Group ID")
118
+ .requiredOption("--permission <permission>", "Permission level: read-write or reader")
119
+ .option("--app <app-id>", "App ID")
120
+ .option("--json", "Output as JSON")
121
+ .action(async (documentId, options) => {
122
+ const resolvedAppId = resolveAppId(undefined, options);
123
+ const client = new ApiClient();
124
+ try {
125
+ const result = await client.grantDocumentGroupPermission(resolvedAppId, documentId, {
126
+ groupType: options.groupType,
127
+ groupId: options.groupId,
128
+ permission: options.permission,
129
+ });
130
+ if (options.json) {
131
+ json(result);
132
+ return;
133
+ }
134
+ success(`Permission '${options.permission}' granted to group ${options.groupType}/${options.groupId}.`);
135
+ }
136
+ catch (err) {
137
+ error(err.message);
138
+ process.exit(1);
139
+ }
140
+ });
141
+ // Revoke group permission
142
+ groupPermissions
143
+ .command("revoke")
144
+ .description("Revoke a group's permission on a document")
145
+ .argument("<document-id>", "Document ID")
146
+ .argument("<group-type>", "Group type")
147
+ .argument("<group-id>", "Group ID")
148
+ .option("--app <app-id>", "App ID")
149
+ .option("-y, --yes", "Skip confirmation prompt")
150
+ .action(async (documentId, groupType, groupId, options) => {
151
+ const resolvedAppId = resolveAppId(undefined, options);
152
+ if (!options.yes) {
153
+ const inquirer = await import("inquirer");
154
+ const { confirm } = await inquirer.default.prompt([
155
+ {
156
+ type: "confirm",
157
+ name: "confirm",
158
+ message: `Revoke permission for group ${groupType}/${groupId} on document ${documentId}?`,
159
+ default: false,
160
+ },
161
+ ]);
162
+ if (!confirm) {
163
+ info("Cancelled.");
164
+ return;
165
+ }
166
+ }
167
+ const client = new ApiClient();
168
+ try {
169
+ await client.revokeDocumentGroupPermission(resolvedAppId, documentId, groupType, groupId);
170
+ success(`Permission revoked for group ${groupType}/${groupId}.`);
171
+ }
172
+ catch (err) {
173
+ error(err.message);
174
+ process.exit(1);
175
+ }
176
+ });
74
177
  }
75
178
  //# sourceMappingURL=documents.js.map