@stoneforge/quarry 0.1.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.
- package/LICENSE +13 -0
- package/README.md +160 -0
- package/dist/api/index.d.ts +8 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/quarry-api.d.ts +268 -0
- package/dist/api/quarry-api.d.ts.map +1 -0
- package/dist/api/quarry-api.js +3905 -0
- package/dist/api/quarry-api.js.map +1 -0
- package/dist/api/types.d.ts +1359 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +204 -0
- package/dist/api/types.js.map +1 -0
- package/dist/bin/sf.d.ts +3 -0
- package/dist/bin/sf.d.ts.map +1 -0
- package/dist/bin/sf.js +9 -0
- package/dist/bin/sf.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +11 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +465 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/commands/alias.d.ts +8 -0
- package/dist/cli/commands/alias.d.ts.map +1 -0
- package/dist/cli/commands/alias.js +70 -0
- package/dist/cli/commands/alias.js.map +1 -0
- package/dist/cli/commands/channel.d.ts +13 -0
- package/dist/cli/commands/channel.d.ts.map +1 -0
- package/dist/cli/commands/channel.js +680 -0
- package/dist/cli/commands/channel.js.map +1 -0
- package/dist/cli/commands/completion.d.ts +8 -0
- package/dist/cli/commands/completion.d.ts.map +1 -0
- package/dist/cli/commands/completion.js +87 -0
- package/dist/cli/commands/completion.js.map +1 -0
- package/dist/cli/commands/config.d.ts +12 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +242 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/crud.d.ts +64 -0
- package/dist/cli/commands/crud.d.ts.map +1 -0
- package/dist/cli/commands/crud.js +805 -0
- package/dist/cli/commands/crud.js.map +1 -0
- package/dist/cli/commands/dep.d.ts +16 -0
- package/dist/cli/commands/dep.d.ts.map +1 -0
- package/dist/cli/commands/dep.js +499 -0
- package/dist/cli/commands/dep.js.map +1 -0
- package/dist/cli/commands/document.d.ts +12 -0
- package/dist/cli/commands/document.d.ts.map +1 -0
- package/dist/cli/commands/document.js +1039 -0
- package/dist/cli/commands/document.js.map +1 -0
- package/dist/cli/commands/embeddings.d.ts +12 -0
- package/dist/cli/commands/embeddings.d.ts.map +1 -0
- package/dist/cli/commands/embeddings.js +273 -0
- package/dist/cli/commands/embeddings.js.map +1 -0
- package/dist/cli/commands/entity.d.ts +16 -0
- package/dist/cli/commands/entity.d.ts.map +1 -0
- package/dist/cli/commands/entity.js +522 -0
- package/dist/cli/commands/entity.js.map +1 -0
- package/dist/cli/commands/gc.d.ts +10 -0
- package/dist/cli/commands/gc.d.ts.map +1 -0
- package/dist/cli/commands/gc.js +257 -0
- package/dist/cli/commands/gc.js.map +1 -0
- package/dist/cli/commands/help.d.ts +11 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +169 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/history.d.ts +9 -0
- package/dist/cli/commands/history.d.ts.map +1 -0
- package/dist/cli/commands/history.js +160 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/identity.d.ts +18 -0
- package/dist/cli/commands/identity.d.ts.map +1 -0
- package/dist/cli/commands/identity.js +698 -0
- package/dist/cli/commands/identity.js.map +1 -0
- package/dist/cli/commands/inbox.d.ts +20 -0
- package/dist/cli/commands/inbox.d.ts.map +1 -0
- package/dist/cli/commands/inbox.js +493 -0
- package/dist/cli/commands/inbox.js.map +1 -0
- package/dist/cli/commands/init.d.ts +20 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +144 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +9 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +200 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/library.d.ts +12 -0
- package/dist/cli/commands/library.d.ts.map +1 -0
- package/dist/cli/commands/library.js +665 -0
- package/dist/cli/commands/library.js.map +1 -0
- package/dist/cli/commands/message.d.ts +11 -0
- package/dist/cli/commands/message.d.ts.map +1 -0
- package/dist/cli/commands/message.js +608 -0
- package/dist/cli/commands/message.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +17 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +698 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/playbook.d.ts +12 -0
- package/dist/cli/commands/playbook.d.ts.map +1 -0
- package/dist/cli/commands/playbook.js +730 -0
- package/dist/cli/commands/playbook.js.map +1 -0
- package/dist/cli/commands/reset.d.ts +12 -0
- package/dist/cli/commands/reset.d.ts.map +1 -0
- package/dist/cli/commands/reset.js +306 -0
- package/dist/cli/commands/reset.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +11 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +106 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +82 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +14 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +370 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/task.d.ts +25 -0
- package/dist/cli/commands/task.d.ts.map +1 -0
- package/dist/cli/commands/task.js +1153 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/cli/commands/team.d.ts +13 -0
- package/dist/cli/commands/team.d.ts.map +1 -0
- package/dist/cli/commands/team.js +471 -0
- package/dist/cli/commands/team.js.map +1 -0
- package/dist/cli/commands/workflow.d.ts +16 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +753 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/completion.d.ts +28 -0
- package/dist/cli/completion.d.ts.map +1 -0
- package/dist/cli/completion.js +295 -0
- package/dist/cli/completion.js.map +1 -0
- package/dist/cli/db.d.ts +38 -0
- package/dist/cli/db.d.ts.map +1 -0
- package/dist/cli/db.js +90 -0
- package/dist/cli/db.js.map +1 -0
- package/dist/cli/formatter.d.ts +87 -0
- package/dist/cli/formatter.d.ts.map +1 -0
- package/dist/cli/formatter.js +464 -0
- package/dist/cli/formatter.js.map +1 -0
- package/dist/cli/index.d.ts +33 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +38 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/parser.d.ts +45 -0
- package/dist/cli/parser.d.ts.map +1 -0
- package/dist/cli/parser.js +256 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/cli/plugin-loader.d.ts +39 -0
- package/dist/cli/plugin-loader.d.ts.map +1 -0
- package/dist/cli/plugin-loader.js +165 -0
- package/dist/cli/plugin-loader.js.map +1 -0
- package/dist/cli/plugin-registry.d.ts +50 -0
- package/dist/cli/plugin-registry.d.ts.map +1 -0
- package/dist/cli/plugin-registry.js +206 -0
- package/dist/cli/plugin-registry.js.map +1 -0
- package/dist/cli/plugin-types.d.ts +106 -0
- package/dist/cli/plugin-types.d.ts.map +1 -0
- package/dist/cli/plugin-types.js +103 -0
- package/dist/cli/plugin-types.js.map +1 -0
- package/dist/cli/runner.d.ts +35 -0
- package/dist/cli/runner.d.ts.map +1 -0
- package/dist/cli/runner.js +340 -0
- package/dist/cli/runner.js.map +1 -0
- package/dist/cli/suggest.d.ts +15 -0
- package/dist/cli/suggest.d.ts.map +1 -0
- package/dist/cli/suggest.js +49 -0
- package/dist/cli/suggest.js.map +1 -0
- package/dist/cli/types.d.ts +138 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +63 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/config/config.d.ts +86 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +348 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +66 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +114 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/duration.d.ts +75 -0
- package/dist/config/duration.d.ts.map +1 -0
- package/dist/config/duration.js +190 -0
- package/dist/config/duration.js.map +1 -0
- package/dist/config/env.d.ts +67 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +207 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/file.d.ts +97 -0
- package/dist/config/file.d.ts.map +1 -0
- package/dist/config/file.js +365 -0
- package/dist/config/file.js.map +1 -0
- package/dist/config/index.d.ts +35 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +41 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/merge.d.ts +53 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +226 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/types.d.ts +257 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +72 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validation.d.ts +55 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +251 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/http/index.d.ts +8 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +12 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/sync-handlers.d.ts +162 -0
- package/dist/http/sync-handlers.d.ts.map +1 -0
- package/dist/http/sync-handlers.js +271 -0
- package/dist/http/sync-handlers.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/server/index.d.ts +34 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3329 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/static.d.ts +18 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +71 -0
- package/dist/server/static.js.map +1 -0
- package/dist/server/ws/broadcaster.d.ts +8 -0
- package/dist/server/ws/broadcaster.d.ts.map +1 -0
- package/dist/server/ws/broadcaster.js +7 -0
- package/dist/server/ws/broadcaster.js.map +1 -0
- package/dist/server/ws/handler.d.ts +55 -0
- package/dist/server/ws/handler.d.ts.map +1 -0
- package/dist/server/ws/handler.js +160 -0
- package/dist/server/ws/handler.js.map +1 -0
- package/dist/services/blocked-cache.d.ts +297 -0
- package/dist/services/blocked-cache.d.ts.map +1 -0
- package/dist/services/blocked-cache.js +755 -0
- package/dist/services/blocked-cache.js.map +1 -0
- package/dist/services/dependency.d.ts +205 -0
- package/dist/services/dependency.d.ts.map +1 -0
- package/dist/services/dependency.js +566 -0
- package/dist/services/dependency.js.map +1 -0
- package/dist/services/embeddings/fusion.d.ts +33 -0
- package/dist/services/embeddings/fusion.d.ts.map +1 -0
- package/dist/services/embeddings/fusion.js +34 -0
- package/dist/services/embeddings/fusion.js.map +1 -0
- package/dist/services/embeddings/index.d.ts +12 -0
- package/dist/services/embeddings/index.d.ts.map +1 -0
- package/dist/services/embeddings/index.js +10 -0
- package/dist/services/embeddings/index.js.map +1 -0
- package/dist/services/embeddings/local-provider.d.ts +31 -0
- package/dist/services/embeddings/local-provider.d.ts.map +1 -0
- package/dist/services/embeddings/local-provider.js +80 -0
- package/dist/services/embeddings/local-provider.js.map +1 -0
- package/dist/services/embeddings/service.d.ts +76 -0
- package/dist/services/embeddings/service.d.ts.map +1 -0
- package/dist/services/embeddings/service.js +153 -0
- package/dist/services/embeddings/service.js.map +1 -0
- package/dist/services/embeddings/types.d.ts +70 -0
- package/dist/services/embeddings/types.d.ts.map +1 -0
- package/dist/services/embeddings/types.js +8 -0
- package/dist/services/embeddings/types.js.map +1 -0
- package/dist/services/id-length-cache.d.ts +156 -0
- package/dist/services/id-length-cache.d.ts.map +1 -0
- package/dist/services/id-length-cache.js +197 -0
- package/dist/services/id-length-cache.js.map +1 -0
- package/dist/services/inbox.d.ts +147 -0
- package/dist/services/inbox.d.ts.map +1 -0
- package/dist/services/inbox.js +428 -0
- package/dist/services/inbox.js.map +1 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +10 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/priority-service.d.ts +145 -0
- package/dist/services/priority-service.d.ts.map +1 -0
- package/dist/services/priority-service.js +272 -0
- package/dist/services/priority-service.js.map +1 -0
- package/dist/services/search-utils.d.ts +47 -0
- package/dist/services/search-utils.d.ts.map +1 -0
- package/dist/services/search-utils.js +83 -0
- package/dist/services/search-utils.js.map +1 -0
- package/dist/sync/hash.d.ts +48 -0
- package/dist/sync/hash.d.ts.map +1 -0
- package/dist/sync/hash.js +136 -0
- package/dist/sync/hash.js.map +1 -0
- package/dist/sync/index.d.ts +11 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +16 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/merge.d.ts +80 -0
- package/dist/sync/merge.d.ts.map +1 -0
- package/dist/sync/merge.js +310 -0
- package/dist/sync/merge.js.map +1 -0
- package/dist/sync/serialization.d.ts +132 -0
- package/dist/sync/serialization.d.ts.map +1 -0
- package/dist/sync/serialization.js +306 -0
- package/dist/sync/serialization.js.map +1 -0
- package/dist/sync/service.d.ts +102 -0
- package/dist/sync/service.d.ts.map +1 -0
- package/dist/sync/service.js +493 -0
- package/dist/sync/service.js.map +1 -0
- package/dist/sync/types.d.ts +275 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +76 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/systems/identity.d.ts +479 -0
- package/dist/systems/identity.d.ts.map +1 -0
- package/dist/systems/identity.js +817 -0
- package/dist/systems/identity.js.map +1 -0
- package/dist/systems/index.d.ts +8 -0
- package/dist/systems/index.d.ts.map +1 -0
- package/dist/systems/index.js +29 -0
- package/dist/systems/index.js.map +1 -0
- package/package.json +121 -0
- package/web/assets/charts-vendor-D1YcbGux.js +55 -0
- package/web/assets/dnd-vendor-DmxE-_ZH.js +5 -0
- package/web/assets/editor-vendor-BxraAWts.js +279 -0
- package/web/assets/index-B77vv208.js +341 -0
- package/web/assets/index-CF_XnVLh.css +1 -0
- package/web/assets/router-vendor-BCKpRBrB.js +41 -0
- package/web/assets/ui-vendor-DUahGnbT.js +45 -0
- package/web/assets/utils-vendor-CfYKiENT.js +813 -0
- package/web/favicon.ico +0 -0
- package/web/index.html +23 -0
- package/web/logo.png +0 -0
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library Commands - Collection command interface for libraries
|
|
3
|
+
*
|
|
4
|
+
* Provides CLI commands for library operations:
|
|
5
|
+
* - library create: Create a new library
|
|
6
|
+
* - library list: List libraries
|
|
7
|
+
* - library add: Add document to library
|
|
8
|
+
* - library remove: Remove document from library
|
|
9
|
+
*/
|
|
10
|
+
import { success, failure, ExitCode } from '../types.js';
|
|
11
|
+
import { getFormatter, getOutputMode } from '../formatter.js';
|
|
12
|
+
import { createLibrary, } from '@stoneforge/core';
|
|
13
|
+
import { suggestCommands } from '../suggest.js';
|
|
14
|
+
import { resolveActor, createAPI } from '../db.js';
|
|
15
|
+
const libraryCreateOptions = [
|
|
16
|
+
{
|
|
17
|
+
name: 'name',
|
|
18
|
+
short: 'n',
|
|
19
|
+
description: 'Library name (required)',
|
|
20
|
+
hasValue: true,
|
|
21
|
+
required: true,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'tag',
|
|
25
|
+
description: 'Add tag (can be repeated)',
|
|
26
|
+
hasValue: true,
|
|
27
|
+
array: true,
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
async function libraryCreateHandler(_args, options) {
|
|
31
|
+
if (!options.name) {
|
|
32
|
+
return failure('--name is required for creating a library', ExitCode.INVALID_ARGUMENTS);
|
|
33
|
+
}
|
|
34
|
+
const { api, error } = createAPI(options, true);
|
|
35
|
+
if (error) {
|
|
36
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const actor = resolveActor(options);
|
|
40
|
+
// Handle tags
|
|
41
|
+
let tags;
|
|
42
|
+
if (options.tag) {
|
|
43
|
+
tags = Array.isArray(options.tag) ? options.tag : [options.tag];
|
|
44
|
+
}
|
|
45
|
+
const input = {
|
|
46
|
+
name: options.name,
|
|
47
|
+
createdBy: actor,
|
|
48
|
+
...(tags && { tags }),
|
|
49
|
+
};
|
|
50
|
+
const library = await createLibrary(input);
|
|
51
|
+
const created = await api.create(library);
|
|
52
|
+
const mode = getOutputMode(options);
|
|
53
|
+
if (mode === 'quiet') {
|
|
54
|
+
return success(created.id);
|
|
55
|
+
}
|
|
56
|
+
return success(created, `Created library ${created.id}`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
60
|
+
return failure(`Failed to create library: ${message}`, ExitCode.GENERAL_ERROR);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const libraryCreateCommand = {
|
|
64
|
+
name: 'create',
|
|
65
|
+
description: 'Create a new library',
|
|
66
|
+
usage: 'sf library create --name <name> [options]',
|
|
67
|
+
help: `Create a new document library.
|
|
68
|
+
|
|
69
|
+
Options:
|
|
70
|
+
-n, --name <name> Library name (required)
|
|
71
|
+
--tag <tag> Add tag (can be repeated)
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
sf library create --name "API Documentation"
|
|
75
|
+
sf library create -n "Design Docs" --tag design --tag frontend`,
|
|
76
|
+
options: libraryCreateOptions,
|
|
77
|
+
handler: libraryCreateHandler,
|
|
78
|
+
};
|
|
79
|
+
const libraryListOptions = [
|
|
80
|
+
{
|
|
81
|
+
name: 'limit',
|
|
82
|
+
short: 'l',
|
|
83
|
+
description: 'Maximum number of results',
|
|
84
|
+
hasValue: true,
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
async function libraryListHandler(_args, options) {
|
|
88
|
+
const { api, error } = createAPI(options);
|
|
89
|
+
if (error) {
|
|
90
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
// Build filter
|
|
94
|
+
const filter = {
|
|
95
|
+
type: 'library',
|
|
96
|
+
};
|
|
97
|
+
// Limit
|
|
98
|
+
if (options.limit) {
|
|
99
|
+
const limit = parseInt(options.limit, 10);
|
|
100
|
+
if (isNaN(limit) || limit < 1) {
|
|
101
|
+
return failure('Limit must be a positive number', ExitCode.VALIDATION);
|
|
102
|
+
}
|
|
103
|
+
filter.limit = limit;
|
|
104
|
+
}
|
|
105
|
+
const result = await api.listPaginated(filter);
|
|
106
|
+
const items = result.items;
|
|
107
|
+
const mode = getOutputMode(options);
|
|
108
|
+
const formatter = getFormatter(mode);
|
|
109
|
+
if (mode === 'json') {
|
|
110
|
+
return success(items);
|
|
111
|
+
}
|
|
112
|
+
if (mode === 'quiet') {
|
|
113
|
+
return success(items.map((l) => l.id).join('\n'));
|
|
114
|
+
}
|
|
115
|
+
if (items.length === 0) {
|
|
116
|
+
return success(null, 'No libraries found');
|
|
117
|
+
}
|
|
118
|
+
// Build table
|
|
119
|
+
const headers = ['ID', 'NAME', 'TAGS', 'CREATED'];
|
|
120
|
+
const rows = items.map((l) => [
|
|
121
|
+
l.id,
|
|
122
|
+
l.name.length > 40 ? l.name.substring(0, 37) + '...' : l.name,
|
|
123
|
+
l.tags.slice(0, 3).join(', ') + (l.tags.length > 3 ? '...' : ''),
|
|
124
|
+
l.createdAt.split('T')[0],
|
|
125
|
+
]);
|
|
126
|
+
const table = formatter.table(headers, rows);
|
|
127
|
+
const summary = `\nShowing ${items.length} of ${result.total} libraries`;
|
|
128
|
+
return success(items, table + summary);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
132
|
+
return failure(`Failed to list libraries: ${message}`, ExitCode.GENERAL_ERROR);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const libraryListCommand = {
|
|
136
|
+
name: 'list',
|
|
137
|
+
description: 'List libraries',
|
|
138
|
+
usage: 'sf library list [options]',
|
|
139
|
+
help: `List document libraries.
|
|
140
|
+
|
|
141
|
+
Options:
|
|
142
|
+
-l, --limit <n> Maximum results
|
|
143
|
+
|
|
144
|
+
Examples:
|
|
145
|
+
sf library list
|
|
146
|
+
sf library list --limit 10`,
|
|
147
|
+
options: libraryListOptions,
|
|
148
|
+
handler: libraryListHandler,
|
|
149
|
+
};
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// Library Add Command
|
|
152
|
+
// ============================================================================
|
|
153
|
+
async function libraryAddHandler(args, options) {
|
|
154
|
+
const [libraryId, docId] = args;
|
|
155
|
+
if (!libraryId || !docId) {
|
|
156
|
+
return failure('Usage: sf library add <library-id> <document-id>', ExitCode.INVALID_ARGUMENTS);
|
|
157
|
+
}
|
|
158
|
+
const { api, error } = createAPI(options);
|
|
159
|
+
if (error) {
|
|
160
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const actor = resolveActor(options);
|
|
164
|
+
// Verify library exists
|
|
165
|
+
const library = await api.get(libraryId);
|
|
166
|
+
if (!library) {
|
|
167
|
+
return failure(`Library not found: ${libraryId}`, ExitCode.NOT_FOUND);
|
|
168
|
+
}
|
|
169
|
+
if (library.type !== 'library') {
|
|
170
|
+
return failure(`Element ${libraryId} is not a library (type: ${library.type})`, ExitCode.VALIDATION);
|
|
171
|
+
}
|
|
172
|
+
// Verify document exists
|
|
173
|
+
const doc = await api.get(docId);
|
|
174
|
+
if (!doc) {
|
|
175
|
+
return failure(`Document not found: ${docId}`, ExitCode.NOT_FOUND);
|
|
176
|
+
}
|
|
177
|
+
if (doc.type !== 'document') {
|
|
178
|
+
return failure(`Element ${docId} is not a document (type: ${doc.type})`, ExitCode.VALIDATION);
|
|
179
|
+
}
|
|
180
|
+
// Add parent-child dependency (document is blocked/child, library is blocker/parent)
|
|
181
|
+
await api.addDependency({
|
|
182
|
+
blockedId: docId,
|
|
183
|
+
blockerId: libraryId,
|
|
184
|
+
type: 'parent-child',
|
|
185
|
+
actor,
|
|
186
|
+
});
|
|
187
|
+
return success({ libraryId, docId }, `Added document ${docId} to library ${libraryId}`);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
191
|
+
return failure(`Failed to add document: ${message}`, ExitCode.GENERAL_ERROR);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const libraryAddCommand = {
|
|
195
|
+
name: 'add',
|
|
196
|
+
description: 'Add document to library',
|
|
197
|
+
usage: 'sf library add <library-id> <document-id>',
|
|
198
|
+
help: `Add a document to a library.
|
|
199
|
+
|
|
200
|
+
Arguments:
|
|
201
|
+
library-id Library identifier
|
|
202
|
+
document-id Document identifier to add
|
|
203
|
+
|
|
204
|
+
Examples:
|
|
205
|
+
sf library add el-lib123 el-doc456`,
|
|
206
|
+
handler: libraryAddHandler,
|
|
207
|
+
};
|
|
208
|
+
// ============================================================================
|
|
209
|
+
// Library Remove Command
|
|
210
|
+
// ============================================================================
|
|
211
|
+
async function libraryRemoveHandler(args, options) {
|
|
212
|
+
const [libraryId, docId] = args;
|
|
213
|
+
if (!libraryId || !docId) {
|
|
214
|
+
return failure('Usage: sf library remove <library-id> <document-id>', ExitCode.INVALID_ARGUMENTS);
|
|
215
|
+
}
|
|
216
|
+
const { api, error } = createAPI(options);
|
|
217
|
+
if (error) {
|
|
218
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
// Remove parent-child dependency (document is blocked/child, library is blocker/parent)
|
|
222
|
+
await api.removeDependency(docId, libraryId, 'parent-child');
|
|
223
|
+
return success({ libraryId, docId }, `Removed document ${docId} from library ${libraryId}`);
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
227
|
+
return failure(`Failed to remove document: ${message}`, ExitCode.GENERAL_ERROR);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const libraryRemoveCommand = {
|
|
231
|
+
name: 'remove',
|
|
232
|
+
description: 'Remove document from library',
|
|
233
|
+
usage: 'sf library remove <library-id> <document-id>',
|
|
234
|
+
help: `Remove a document from a library.
|
|
235
|
+
|
|
236
|
+
Arguments:
|
|
237
|
+
library-id Library identifier
|
|
238
|
+
document-id Document identifier to remove
|
|
239
|
+
|
|
240
|
+
Examples:
|
|
241
|
+
sf library remove el-lib123 el-doc456`,
|
|
242
|
+
handler: libraryRemoveHandler,
|
|
243
|
+
};
|
|
244
|
+
// ============================================================================
|
|
245
|
+
// Library Docs Command (list documents in library)
|
|
246
|
+
// ============================================================================
|
|
247
|
+
async function libraryDocsHandler(args, options) {
|
|
248
|
+
const [libraryId] = args;
|
|
249
|
+
if (!libraryId) {
|
|
250
|
+
return failure('Usage: sf library docs <library-id>', ExitCode.INVALID_ARGUMENTS);
|
|
251
|
+
}
|
|
252
|
+
const { api, error } = createAPI(options);
|
|
253
|
+
if (error) {
|
|
254
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
// Verify library exists
|
|
258
|
+
const library = await api.get(libraryId);
|
|
259
|
+
if (!library) {
|
|
260
|
+
return failure(`Library not found: ${libraryId}`, ExitCode.NOT_FOUND);
|
|
261
|
+
}
|
|
262
|
+
if (library.type !== 'library') {
|
|
263
|
+
return failure(`Element ${libraryId} is not a library (type: ${library.type})`, ExitCode.VALIDATION);
|
|
264
|
+
}
|
|
265
|
+
// Get documents that have parent-child dependency to this library
|
|
266
|
+
// (document is blocked, library is blocker)
|
|
267
|
+
const deps = await api.getDependents(libraryId, ['parent-child']);
|
|
268
|
+
const docIds = deps.map((d) => d.blockedId);
|
|
269
|
+
if (docIds.length === 0) {
|
|
270
|
+
return success([], `No documents in library ${libraryId}`);
|
|
271
|
+
}
|
|
272
|
+
// Fetch documents
|
|
273
|
+
const docs = [];
|
|
274
|
+
for (const docId of docIds) {
|
|
275
|
+
const doc = await api.get(docId);
|
|
276
|
+
if (doc && doc.type === 'document') {
|
|
277
|
+
docs.push(doc);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const mode = getOutputMode(options);
|
|
281
|
+
const formatter = getFormatter(mode);
|
|
282
|
+
if (mode === 'json') {
|
|
283
|
+
return success(docs);
|
|
284
|
+
}
|
|
285
|
+
if (mode === 'quiet') {
|
|
286
|
+
return success(docs.map((d) => d.id).join('\n'));
|
|
287
|
+
}
|
|
288
|
+
// Build table
|
|
289
|
+
const headers = ['ID', 'TITLE', 'CREATED'];
|
|
290
|
+
const rows = docs.map((d) => {
|
|
291
|
+
const title = d.title || 'Untitled';
|
|
292
|
+
return [
|
|
293
|
+
d.id,
|
|
294
|
+
title.length > 50 ? title.substring(0, 47) + '...' : title,
|
|
295
|
+
d.createdAt.split('T')[0],
|
|
296
|
+
];
|
|
297
|
+
});
|
|
298
|
+
const table = formatter.table(headers, rows);
|
|
299
|
+
const summary = `\n${docs.length} document(s) in library`;
|
|
300
|
+
return success(docs, table + summary);
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
304
|
+
return failure(`Failed to list documents: ${message}`, ExitCode.GENERAL_ERROR);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const libraryDocsCommand = {
|
|
308
|
+
name: 'docs',
|
|
309
|
+
description: 'List documents in a library',
|
|
310
|
+
usage: 'sf library docs <library-id>',
|
|
311
|
+
help: `List all documents in a library.
|
|
312
|
+
|
|
313
|
+
Arguments:
|
|
314
|
+
library-id Library identifier
|
|
315
|
+
|
|
316
|
+
Examples:
|
|
317
|
+
sf library docs el-lib123`,
|
|
318
|
+
handler: libraryDocsHandler,
|
|
319
|
+
};
|
|
320
|
+
// ============================================================================
|
|
321
|
+
// Library Nest Command (nest library under another)
|
|
322
|
+
// ============================================================================
|
|
323
|
+
async function libraryNestHandler(args, options) {
|
|
324
|
+
const [childLibraryId, parentLibraryId] = args;
|
|
325
|
+
if (!childLibraryId || !parentLibraryId) {
|
|
326
|
+
return failure('Usage: sf library nest <child-library-id> <parent-library-id>', ExitCode.INVALID_ARGUMENTS);
|
|
327
|
+
}
|
|
328
|
+
const { api, error } = createAPI(options);
|
|
329
|
+
if (error) {
|
|
330
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
const actor = resolveActor(options);
|
|
334
|
+
// Verify child library exists
|
|
335
|
+
const childLib = await api.get(childLibraryId);
|
|
336
|
+
if (!childLib) {
|
|
337
|
+
return failure(`Library not found: ${childLibraryId}`, ExitCode.NOT_FOUND);
|
|
338
|
+
}
|
|
339
|
+
if (childLib.type !== 'library') {
|
|
340
|
+
return failure(`Element ${childLibraryId} is not a library (type: ${childLib.type})`, ExitCode.VALIDATION);
|
|
341
|
+
}
|
|
342
|
+
// Verify parent library exists
|
|
343
|
+
const parentLib = await api.get(parentLibraryId);
|
|
344
|
+
if (!parentLib) {
|
|
345
|
+
return failure(`Library not found: ${parentLibraryId}`, ExitCode.NOT_FOUND);
|
|
346
|
+
}
|
|
347
|
+
if (parentLib.type !== 'library') {
|
|
348
|
+
return failure(`Element ${parentLibraryId} is not a library (type: ${parentLib.type})`, ExitCode.VALIDATION);
|
|
349
|
+
}
|
|
350
|
+
// Prevent self-nesting
|
|
351
|
+
if (childLibraryId === parentLibraryId) {
|
|
352
|
+
return failure('Library cannot be nested under itself', ExitCode.VALIDATION);
|
|
353
|
+
}
|
|
354
|
+
// Check if child already has a parent (libraries can only have one parent)
|
|
355
|
+
const existingParent = await api.getDependencies(childLibraryId, ['parent-child']);
|
|
356
|
+
// Check if any parent-child dependency points to a library
|
|
357
|
+
for (const dep of existingParent) {
|
|
358
|
+
const target = await api.get(dep.blockerId);
|
|
359
|
+
if (target?.type === 'library') {
|
|
360
|
+
return failure(`Library ${childLibraryId} already has a parent library`, ExitCode.VALIDATION);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// Add parent-child dependency (child library is blocked, parent library is blocker)
|
|
364
|
+
// Cycle detection is handled by the dependency service
|
|
365
|
+
await api.addDependency({
|
|
366
|
+
blockedId: childLibraryId,
|
|
367
|
+
blockerId: parentLibraryId,
|
|
368
|
+
type: 'parent-child',
|
|
369
|
+
actor,
|
|
370
|
+
});
|
|
371
|
+
return success({ childLibraryId, parentLibraryId }, `Nested library ${childLibraryId} under ${parentLibraryId}`);
|
|
372
|
+
}
|
|
373
|
+
catch (err) {
|
|
374
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
375
|
+
if (message.includes('cycle')) {
|
|
376
|
+
return failure(`Cannot nest: would create a cycle`, ExitCode.VALIDATION);
|
|
377
|
+
}
|
|
378
|
+
return failure(`Failed to nest library: ${message}`, ExitCode.GENERAL_ERROR);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const libraryNestCommand = {
|
|
382
|
+
name: 'nest',
|
|
383
|
+
description: 'Nest a library under another (create hierarchy)',
|
|
384
|
+
usage: 'sf library nest <child-library-id> <parent-library-id>',
|
|
385
|
+
help: `Nest a library under another library to create a hierarchy.
|
|
386
|
+
|
|
387
|
+
A library can only have one parent library.
|
|
388
|
+
Cycle detection prevents circular nesting.
|
|
389
|
+
|
|
390
|
+
Arguments:
|
|
391
|
+
child-library-id Library to nest (becomes a sub-library)
|
|
392
|
+
parent-library-id Library to nest under (becomes parent)
|
|
393
|
+
|
|
394
|
+
Examples:
|
|
395
|
+
sf library nest el-sub123 el-parent456`,
|
|
396
|
+
handler: libraryNestHandler,
|
|
397
|
+
};
|
|
398
|
+
// ============================================================================
|
|
399
|
+
// Library Stats Command
|
|
400
|
+
// ============================================================================
|
|
401
|
+
async function libraryStatsHandler(args, options) {
|
|
402
|
+
const [libraryId] = args;
|
|
403
|
+
if (!libraryId) {
|
|
404
|
+
return failure('Usage: sf library stats <library-id>', ExitCode.INVALID_ARGUMENTS);
|
|
405
|
+
}
|
|
406
|
+
const { api, error } = createAPI(options);
|
|
407
|
+
if (error) {
|
|
408
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
409
|
+
}
|
|
410
|
+
try {
|
|
411
|
+
// Verify library exists
|
|
412
|
+
const library = await api.get(libraryId);
|
|
413
|
+
if (!library) {
|
|
414
|
+
return failure(`Library not found: ${libraryId}`, ExitCode.NOT_FOUND);
|
|
415
|
+
}
|
|
416
|
+
if (library.type !== 'library') {
|
|
417
|
+
return failure(`Element ${libraryId} is not a library (type: ${library.type})`, ExitCode.VALIDATION);
|
|
418
|
+
}
|
|
419
|
+
// Get direct children (documents and sub-libraries that have this library as parent)
|
|
420
|
+
const deps = await api.getDependents(libraryId, ['parent-child']);
|
|
421
|
+
let documentCount = 0;
|
|
422
|
+
let subLibraryCount = 0;
|
|
423
|
+
for (const dep of deps) {
|
|
424
|
+
const child = await api.get(dep.blockedId);
|
|
425
|
+
if (child) {
|
|
426
|
+
if (child.type === 'document') {
|
|
427
|
+
documentCount++;
|
|
428
|
+
}
|
|
429
|
+
else if (child.type === 'library') {
|
|
430
|
+
subLibraryCount++;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
const stats = {
|
|
435
|
+
libraryId,
|
|
436
|
+
name: library.name,
|
|
437
|
+
documentCount,
|
|
438
|
+
subLibraryCount,
|
|
439
|
+
};
|
|
440
|
+
const mode = getOutputMode(options);
|
|
441
|
+
if (mode === 'json') {
|
|
442
|
+
return success(stats);
|
|
443
|
+
}
|
|
444
|
+
if (mode === 'quiet') {
|
|
445
|
+
return success(`${documentCount} docs, ${subLibraryCount} sub-libraries`);
|
|
446
|
+
}
|
|
447
|
+
const output = `Library: ${library.name} (${libraryId})
|
|
448
|
+
Documents: ${documentCount}
|
|
449
|
+
Sub-libraries: ${subLibraryCount}`;
|
|
450
|
+
return success(stats, output);
|
|
451
|
+
}
|
|
452
|
+
catch (err) {
|
|
453
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
454
|
+
return failure(`Failed to get stats: ${message}`, ExitCode.GENERAL_ERROR);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const libraryStatsCommand = {
|
|
458
|
+
name: 'stats',
|
|
459
|
+
description: 'Show library statistics',
|
|
460
|
+
usage: 'sf library stats <library-id>',
|
|
461
|
+
help: `Show statistics for a library.
|
|
462
|
+
|
|
463
|
+
Arguments:
|
|
464
|
+
library-id Library identifier
|
|
465
|
+
|
|
466
|
+
Examples:
|
|
467
|
+
sf library stats el-lib123`,
|
|
468
|
+
handler: libraryStatsHandler,
|
|
469
|
+
};
|
|
470
|
+
// ============================================================================
|
|
471
|
+
// Library Roots Command (list root libraries)
|
|
472
|
+
// ============================================================================
|
|
473
|
+
async function libraryRootsHandler(_args, options) {
|
|
474
|
+
const { api, error } = createAPI(options);
|
|
475
|
+
if (error) {
|
|
476
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
// Get all libraries
|
|
480
|
+
const result = await api.listPaginated({ type: 'library' });
|
|
481
|
+
const libraries = result.items;
|
|
482
|
+
if (libraries.length === 0) {
|
|
483
|
+
return success([], 'No libraries found');
|
|
484
|
+
}
|
|
485
|
+
// Get all parent-child dependencies where target is a library
|
|
486
|
+
const libraryIds = new Set(libraries.map((l) => l.id));
|
|
487
|
+
// A library is a root if it doesn't have a parent-child dependency
|
|
488
|
+
// pointing to another library
|
|
489
|
+
const rootLibraries = [];
|
|
490
|
+
for (const lib of libraries) {
|
|
491
|
+
const deps = await api.getDependencies(lib.id, ['parent-child']);
|
|
492
|
+
const hasLibraryParent = deps.some((d) => libraryIds.has(d.blockerId));
|
|
493
|
+
if (!hasLibraryParent) {
|
|
494
|
+
rootLibraries.push(lib);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
const mode = getOutputMode(options);
|
|
498
|
+
const formatter = getFormatter(mode);
|
|
499
|
+
if (mode === 'json') {
|
|
500
|
+
return success(rootLibraries);
|
|
501
|
+
}
|
|
502
|
+
if (mode === 'quiet') {
|
|
503
|
+
return success(rootLibraries.map((l) => l.id).join('\n'));
|
|
504
|
+
}
|
|
505
|
+
if (rootLibraries.length === 0) {
|
|
506
|
+
return success([], 'No root libraries found');
|
|
507
|
+
}
|
|
508
|
+
// Build table
|
|
509
|
+
const headers = ['ID', 'NAME', 'CREATED'];
|
|
510
|
+
const rows = rootLibraries.map((l) => [
|
|
511
|
+
l.id,
|
|
512
|
+
l.name.length > 40 ? l.name.substring(0, 37) + '...' : l.name,
|
|
513
|
+
l.createdAt.split('T')[0],
|
|
514
|
+
]);
|
|
515
|
+
const table = formatter.table(headers, rows);
|
|
516
|
+
const summary = `\n${rootLibraries.length} root library(ies)`;
|
|
517
|
+
return success(rootLibraries, table + summary);
|
|
518
|
+
}
|
|
519
|
+
catch (err) {
|
|
520
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
521
|
+
return failure(`Failed to list root libraries: ${message}`, ExitCode.GENERAL_ERROR);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const libraryRootsCommand = {
|
|
525
|
+
name: 'roots',
|
|
526
|
+
description: 'List root libraries (not nested under other libraries)',
|
|
527
|
+
usage: 'sf library roots',
|
|
528
|
+
help: `List all root libraries (libraries not nested under other libraries).
|
|
529
|
+
|
|
530
|
+
Examples:
|
|
531
|
+
sf library roots`,
|
|
532
|
+
handler: libraryRootsHandler,
|
|
533
|
+
};
|
|
534
|
+
const libraryDeleteOptions = [
|
|
535
|
+
{
|
|
536
|
+
name: 'force',
|
|
537
|
+
short: 'f',
|
|
538
|
+
description: 'Force deletion even if library has contents',
|
|
539
|
+
hasValue: false,
|
|
540
|
+
},
|
|
541
|
+
];
|
|
542
|
+
async function libraryDeleteHandler(args, options) {
|
|
543
|
+
const [libraryId] = args;
|
|
544
|
+
if (!libraryId) {
|
|
545
|
+
return failure('Usage: sf library delete <library-id>', ExitCode.INVALID_ARGUMENTS);
|
|
546
|
+
}
|
|
547
|
+
const { api, error } = createAPI(options);
|
|
548
|
+
if (error) {
|
|
549
|
+
return failure(error, ExitCode.GENERAL_ERROR);
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
// Verify library exists
|
|
553
|
+
const library = await api.get(libraryId);
|
|
554
|
+
if (!library) {
|
|
555
|
+
return failure(`Library not found: ${libraryId}`, ExitCode.NOT_FOUND);
|
|
556
|
+
}
|
|
557
|
+
if (library.type !== 'library') {
|
|
558
|
+
return failure(`Element ${libraryId} is not a library (type: ${library.type})`, ExitCode.VALIDATION);
|
|
559
|
+
}
|
|
560
|
+
// Check if library has contents
|
|
561
|
+
const deps = await api.getDependents(libraryId, ['parent-child']);
|
|
562
|
+
if (deps.length > 0 && !options.force) {
|
|
563
|
+
return failure(`Library has ${deps.length} child element(s). Use --force to delete anyway (contents will be orphaned).`, ExitCode.VALIDATION);
|
|
564
|
+
}
|
|
565
|
+
// Orphan strategy: remove all parent-child dependencies pointing to this library
|
|
566
|
+
for (const dep of deps) {
|
|
567
|
+
await api.removeDependency(dep.blockedId, libraryId, 'parent-child');
|
|
568
|
+
}
|
|
569
|
+
// Delete the library
|
|
570
|
+
await api.delete(libraryId);
|
|
571
|
+
return success({ libraryId, orphanedCount: deps.length }, `Deleted library ${libraryId}` + (deps.length > 0 ? ` (orphaned ${deps.length} element(s))` : ''));
|
|
572
|
+
}
|
|
573
|
+
catch (err) {
|
|
574
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
575
|
+
return failure(`Failed to delete library: ${message}`, ExitCode.GENERAL_ERROR);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
const libraryDeleteCommand = {
|
|
579
|
+
name: 'delete',
|
|
580
|
+
description: 'Delete a library',
|
|
581
|
+
usage: 'sf library delete <library-id> [--force]',
|
|
582
|
+
help: `Delete a library.
|
|
583
|
+
|
|
584
|
+
By default, deletion is prevented if the library has contents.
|
|
585
|
+
Use --force to delete anyway (documents and sub-libraries will be orphaned).
|
|
586
|
+
|
|
587
|
+
Options:
|
|
588
|
+
-f, --force Force deletion even with contents
|
|
589
|
+
|
|
590
|
+
Arguments:
|
|
591
|
+
library-id Library identifier
|
|
592
|
+
|
|
593
|
+
Examples:
|
|
594
|
+
sf library delete el-lib123
|
|
595
|
+
sf library delete el-lib123 --force`,
|
|
596
|
+
options: libraryDeleteOptions,
|
|
597
|
+
handler: libraryDeleteHandler,
|
|
598
|
+
};
|
|
599
|
+
// ============================================================================
|
|
600
|
+
// Library Root Command
|
|
601
|
+
// ============================================================================
|
|
602
|
+
export const libraryCommand = {
|
|
603
|
+
name: 'library',
|
|
604
|
+
description: 'Manage libraries (document collections)',
|
|
605
|
+
usage: 'sf library <subcommand> [options]',
|
|
606
|
+
help: `Manage libraries - collections of related documents.
|
|
607
|
+
|
|
608
|
+
Libraries organize documents for knowledge bases, documentation, and
|
|
609
|
+
content management. Documents can belong to multiple libraries.
|
|
610
|
+
Libraries can also be nested hierarchically.
|
|
611
|
+
|
|
612
|
+
Subcommands:
|
|
613
|
+
create Create a new library
|
|
614
|
+
list List all libraries
|
|
615
|
+
roots List root libraries (not nested)
|
|
616
|
+
docs List documents in a library
|
|
617
|
+
stats Show library statistics
|
|
618
|
+
add Add document to library
|
|
619
|
+
remove Remove document from library
|
|
620
|
+
nest Nest library under another
|
|
621
|
+
delete Delete a library
|
|
622
|
+
|
|
623
|
+
Examples:
|
|
624
|
+
sf library create --name "API Documentation"
|
|
625
|
+
sf library list
|
|
626
|
+
sf library roots
|
|
627
|
+
sf library docs el-lib123
|
|
628
|
+
sf library stats el-lib123
|
|
629
|
+
sf library add el-lib123 el-doc456
|
|
630
|
+
sf library remove el-lib123 el-doc456
|
|
631
|
+
sf library nest el-sub123 el-parent456
|
|
632
|
+
sf library delete el-lib123
|
|
633
|
+
|
|
634
|
+
Note: Use 'sf show <id>', 'sf update <id>', 'sf delete <id>' for any element.`,
|
|
635
|
+
subcommands: {
|
|
636
|
+
create: libraryCreateCommand,
|
|
637
|
+
list: libraryListCommand,
|
|
638
|
+
roots: libraryRootsCommand,
|
|
639
|
+
docs: libraryDocsCommand,
|
|
640
|
+
stats: libraryStatsCommand,
|
|
641
|
+
add: libraryAddCommand,
|
|
642
|
+
remove: libraryRemoveCommand,
|
|
643
|
+
nest: libraryNestCommand,
|
|
644
|
+
delete: libraryDeleteCommand,
|
|
645
|
+
// Aliases (hidden from --help via dedup in getCommandHelp)
|
|
646
|
+
new: libraryCreateCommand,
|
|
647
|
+
ls: libraryListCommand,
|
|
648
|
+
},
|
|
649
|
+
handler: async (args, options) => {
|
|
650
|
+
// Default to list if no subcommand
|
|
651
|
+
if (args.length === 0) {
|
|
652
|
+
return libraryListHandler(args, options);
|
|
653
|
+
}
|
|
654
|
+
// Show "did you mean?" for unknown subcommands
|
|
655
|
+
const subNames = Object.keys(libraryCommand.subcommands);
|
|
656
|
+
const suggestions = suggestCommands(args[0], subNames);
|
|
657
|
+
let msg = `Unknown subcommand: ${args[0]}`;
|
|
658
|
+
if (suggestions.length > 0) {
|
|
659
|
+
msg += `\n\nDid you mean?\n${suggestions.map(s => ` ${s}`).join('\n')}`;
|
|
660
|
+
}
|
|
661
|
+
msg += '\n\nRun "sf library --help" to see available subcommands.';
|
|
662
|
+
return failure(msg, ExitCode.INVALID_ARGUMENTS);
|
|
663
|
+
},
|
|
664
|
+
};
|
|
665
|
+
//# sourceMappingURL=library.js.map
|