@seliseblocks/cli-os 0.2.10 → 0.2.11

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.
@@ -1,253 +1,253 @@
1
- ---
2
- name: blocks-data-storage
3
- description: "Build file and document-management features on SELISE Blocks Data: upload/download, directory trees, cursor-paginated browsing and search, file versions, rename/move/copy, soft delete/trash/restore, sharing, access policies, and inheritance. Use for attachments, file browsers, folders, shared files, permissions, or version history. Use 'blocks data files *' for terminal/admin work and @seliseblocks/client data.files/data.directories/data.objects for app code."
4
- ---
5
-
6
- # Blocks Data — Storage
7
-
8
- Treat storage as one permission-aware object tree containing **directories** and **files**. Uploading a new file now creates the file object in that tree; there is no second DMS registration step.
9
-
10
- Use:
11
-
12
- - **`blocks data files *`** for supported terminal/admin operations.
13
- - **`@seliseblocks/client`** for app code. Use the shared `blocksClient` created by blocks-onboarding.
14
- - **blocks-storage-configuration** only to manage the named provider configuration used by `configurationName`.
15
-
16
- Select a project first with `blocks use <tenantId>`. If login/project state or the shared client setup is unknown, use blocks-onboarding before this skill.
17
-
18
- Store the returned `fileId` in a Data record when attaching a file to domain data. Use blocks-data-gateway-crud for the record mutation.
19
-
20
- ## Choose the surface
21
-
22
- The current CLI and SDK follow the backend's file, directory, and object resource groups.
23
-
24
- ```bash
25
- blocks --version
26
- blocks data files --help
27
- ```
28
-
29
- - Use `blocks data files *` for terminal/admin work and inspect `blocks --help` for exact flags.
30
- - Use `blocksClient.data.files` for bytes, metadata, versions, and file operations.
31
- - Use `blocksClient.data.directories` for directory create/get/update/delete/move.
32
- - Use `blocksClient.data.objects` for browse/search/trash/shared/restore/share/access/inheritance.
33
-
34
- Legacy `data.dms.*`, `dms-upload`, `dms-list`, `create-folder`, and `delete-folder` wrappers are retired. Uploads need no registration call.
35
-
36
- ## Upload a new file
37
-
38
- Choose one path from the project's storage configuration.
39
-
40
- | Provider category | Sequence |
41
- |---|---|
42
- | Cloud object storage | request a pre-signed URL, then PUT the bytes to it |
43
- | Local/SFTP storage | send one authenticated multipart upload |
44
-
45
- Both paths create the file object and initial version directly. Do not call `dms-upload` afterward.
46
-
47
- ### Cloud upload from the CLI
48
-
49
- Prefer the composed command. It previews and confirms both metadata creation and the provider PUT:
50
-
51
- ```bash
52
- blocks data files upload --file ./invoice.pdf --parent-id <directoryId> \
53
- --configuration-name Default --access-modifier Private --dry-run --json
54
- blocks data files upload --file ./invoice.pdf --parent-id <directoryId> \
55
- --configuration-name Default --access-modifier Private --yes --json
56
- ```
57
-
58
- Use the two explicit commands only when the intermediate upload URL is required:
59
-
60
- ```bash
61
- blocks data files presigned-upload-url \
62
- --name invoice.pdf \
63
- --parent-directory-id <directoryId> \
64
- --configuration-name Default \
65
- --access-modifier Private \
66
- --dry-run --json
67
- blocks data files presigned-upload-url \
68
- --name invoice.pdf \
69
- --parent-directory-id <directoryId> \
70
- --configuration-name Default \
71
- --access-modifier Private \
72
- --yes --json
73
-
74
- blocks data files upload-to-url \
75
- --url "<uploadUrl>" \
76
- --file ./invoice.pdf \
77
- --content-type application/pdf \
78
- --dry-run --json
79
- blocks data files upload-to-url \
80
- --url "<uploadUrl>" \
81
- --file ./invoice.pdf \
82
- --content-type application/pdf \
83
- --yes --json
84
- ```
85
-
86
- The presign response contains `uploadUrl`, `fileId`, and `isSuccess`. The first call creates the file metadata/version; the PUT fills its object-storage key. Handle PUT failure explicitly because it can leave metadata for missing bytes.
87
-
88
- When `parentDirectoryId` is empty, the cloud upload resolves `moduleName` to that module's default directory. The backend default is module value `8` (`Default_Construct`), but pass the intended module or a concrete directory id instead of relying on that default.
89
-
90
- ### Cloud upload from app code
91
-
92
- ```ts
93
- const presign = await blocksClient.data.files.presignedUploadUrl({
94
- name: "invoice.pdf",
95
- parentDirectoryId: directoryId,
96
- configurationName: "Default",
97
- accessModifier: "Private",
98
- tags: "invoice,2026",
99
- });
100
-
101
- if (!presign || typeof presign !== "object") {
102
- throw new Error("Unexpected upload response");
103
- }
104
-
105
- const result = presign as {
106
- uploadUrl: string;
107
- fileId: string;
108
- isSuccess: boolean;
109
- errors?: Record<string, string>;
110
- };
111
-
112
- if (!result.isSuccess) throw new Error(JSON.stringify(result.errors));
113
-
114
- await blocksClient.data.files.uploadToUrl({
115
- url: result.uploadUrl,
116
- body: file,
117
- contentType: file.type || "application/octet-stream",
118
- });
119
- ```
120
-
121
- `uploadToUrl` is provider-direct and sends no bearer token or `x-blocks-key`. The SDK adds Azure's `x-ms-blob-type: Blockblob` header unless overridden; ensure that header matches the signed provider policy.
122
-
123
- ### Local-storage upload
124
-
125
- ```bash
126
- blocks data files upload-to-local-storage \
127
- --file ./invoice.pdf \
128
- --parent-directory-id <directoryId> \
129
- --configuration-name Default \
130
- --access-modifier Private \
131
- --dry-run --json
132
- blocks data files upload-to-local-storage \
133
- --file ./invoice.pdf \
134
- --parent-directory-id <directoryId> \
135
- --configuration-name Default \
136
- --access-modifier Private \
137
- --yes --json
138
- ```
139
-
140
- ```ts
141
- const uploaded = await blocksClient.data.files.uploadToLocalStorage({
142
- name: file.name,
143
- file,
144
- parentDirectoryId: directoryId,
145
- configurationName: "Default",
146
- accessModifier: "Private",
147
- tags: ["invoice", "2026"],
148
- });
149
- ```
150
-
151
- This call creates the file object and uploads version 1 in one request. Unlike cloud presign, an empty local `parentDirectoryId` stays at the top level; it is not resolved through `moduleName`.
152
-
153
- ## Add a file version
154
-
155
- Supplying an existing `itemId` to either upload flow creates another version after the caller passes the file's Edit check. For cloud storage, the dedicated command/method returns another pre-signed URL:
156
-
157
- ```bash
158
- blocks data files versions <fileId> --limit 25 --json
159
- blocks data files create-version <fileId> --configuration-name Default --dry-run --json
160
- blocks data files create-version <fileId> --configuration-name Default --yes --json
161
- ```
162
-
163
- ```ts
164
- const history = await blocksClient.data.files.versions({ fileId, limit: 25 });
165
- const next = await blocksClient.data.files.createVersion({ fileId, configurationName: "Default" });
166
- ```
167
-
168
- Version history is newest-first and cursor-paginated. Use the returned opaque `nextCursor`; the current backend uses the last version number internally, but callers must not construct cursors. Limits are 1–100, default 25.
169
-
170
- ## Read and download
171
-
172
- ```bash
173
- blocks data files get <fileId> --configuration-name Default --json
174
- blocks data files get <fileId> --version <versionNo> --configuration-name Default --json
175
- blocks data files get-many <fileId...> --configuration-name Default --json
176
- ```
177
-
178
- ```ts
179
- const file = await blocksClient.data.files.get(fileId, {
180
- configurationName: "Default",
181
- version: 2,
182
- });
183
- ```
184
-
185
- The response includes a download URL plus metadata. Download requires the caller's Download permission. Access-denied reads may deliberately look like missing resources so clients cannot probe hidden object ids.
186
-
187
- ## Directory and object workflows
188
-
189
- For browsing, directories, search, move/copy/rename, trash, sharing, and ACL behavior, read [flows/object-management.md](flows/object-management.md).
190
-
191
- ## Update custom metadata
192
-
193
- ```bash
194
- blocks data files update-additional-info <fileId> \
195
- --additional-properties '{"status":"reviewed"}' \
196
- --dry-run --json
197
- blocks data files update-additional-info <fileId> \
198
- --additional-properties '{"status":"reviewed"}' \
199
- --yes --json
200
- ```
201
-
202
- This updates `additionalProperties`; it does not rename, move, tag, or version the file.
203
-
204
- ## Delete safely
205
-
206
- Deletion now distinguishes trash from permanent removal:
207
-
208
- - `permanent: false` archives the file or directory so it can be restored.
209
- - `permanent: true` removes it for good.
210
- - The backend default is **`true`** when `permanent` is omitted.
211
-
212
- The CLI defaults to safe soft deletion. Add `--permanent` only after explicit approval.
213
-
214
- ```bash
215
- blocks data files delete <fileId> --dry-run --json
216
- blocks data files delete <fileId> --yes --json
217
- blocks data files delete <fileId> --permanent --dry-run --json
218
- ```
219
-
220
- In app code, send the choice explicitly: `blocksClient.data.files.delete({ fileId, permanent: false })`.
221
-
222
- ## Permission model
223
-
224
- Every storage request passes two checks:
225
-
226
- 1. The endpoint permission permits that class of action.
227
- 2. The object ACL permits the action on that specific file/directory.
228
-
229
- Capabilities are ordered: `View`, `Download`, `Edit`, `Delete`, `Manage`, `Owner`. Higher capabilities imply lower ones. Directory children inherit ancestor access while `inheritsParentAccess` is true. New files inherit from their directory.
230
-
231
- Do not infer permission from a visible button or endpoint grant. Render actions from each object's returned `permissions` flags and still handle 403/404 races.
232
-
233
- ## Gotchas
234
-
235
- - Upload now creates the visible file object; legacy DMS registration is wrong and may fail after the bytes were successfully PUT.
236
- - Cloud presign creates metadata before the provider PUT. Treat the two steps as a recoverable workflow and surface partial failure.
237
- - A name must contain an allowed extension. Directories may restrict extensions.
238
- - Names are unique within a directory. File move/copy can fail on a name conflict or extension policy.
239
- - `Private` is the safe default. Use `Public` only when unauthenticated download is intended.
240
- - `configurationName` selects an existing provider record; it does not configure storage.
241
- - Most legacy file SDK methods return `Promise<unknown>`; validate responses at the boundary.
242
- - Never send Blocks auth headers to a pre-signed provider URL.
243
- - Never use a raw API call to work around a missing CLI/SDK wrapper; update the client surface first.
244
-
245
- ## Example triggers
246
-
247
- - "Upload this PDF into the Contracts folder."
248
- - "Build a file browser with folders and search."
249
- - "Show files shared with the current user."
250
- - "Move this file to trash and let users restore it."
251
- - "Add version history and upload a replacement version."
252
- - "Share this directory with a role and let its children inherit access."
253
- - "Move, copy, or rename a file."
1
+ ---
2
+ name: blocks-data-storage
3
+ description: "Build file and document-management features on SELISE Blocks Data: upload/download, directory trees, cursor-paginated browsing and search, file versions, rename/move/copy, soft delete/trash/restore, sharing, access policies, and inheritance. Use for attachments, file browsers, folders, shared files, permissions, or version history. Use 'blocks data files *' for terminal/admin work and @seliseblocks/client data.files/data.directories/data.objects for app code."
4
+ ---
5
+
6
+ # Blocks Data — Storage
7
+
8
+ Treat storage as one permission-aware object tree containing **directories** and **files**. Uploading a new file now creates the file object in that tree; there is no second DMS registration step.
9
+
10
+ Use:
11
+
12
+ - **`blocks data files *`** for supported terminal/admin operations.
13
+ - **`@seliseblocks/client`** for app code. Use the shared `blocksClient` created by blocks-onboarding.
14
+ - **blocks-storage-configuration** only to manage the named provider configuration used by `configurationName`.
15
+
16
+ Select a project first with `blocks use <tenantId>`. If login/project state or the shared client setup is unknown, use blocks-onboarding before this skill.
17
+
18
+ Store the returned `fileId` in a Data record when attaching a file to domain data. Use blocks-data-gateway-crud for the record mutation.
19
+
20
+ ## Choose the surface
21
+
22
+ The current CLI and SDK follow the backend's file, directory, and object resource groups.
23
+
24
+ ```bash
25
+ blocks --version
26
+ blocks data files --help
27
+ ```
28
+
29
+ - Use `blocks data files *` for terminal/admin work and inspect `blocks --help` for exact flags.
30
+ - Use `blocksClient.data.files` for bytes, metadata, versions, and file operations.
31
+ - Use `blocksClient.data.directories` for directory create/get/update/delete/move.
32
+ - Use `blocksClient.data.objects` for browse/search/trash/shared/restore/share/access/inheritance.
33
+
34
+ Legacy `data.dms.*`, `dms-upload`, `dms-list`, `create-folder`, and `delete-folder` wrappers are retired. Uploads need no registration call.
35
+
36
+ ## Upload a new file
37
+
38
+ Choose one path from the project's storage configuration.
39
+
40
+ | Provider category | Sequence |
41
+ |---|---|
42
+ | Cloud object storage | request a pre-signed URL, then PUT the bytes to it |
43
+ | Local/SFTP storage | send one authenticated multipart upload |
44
+
45
+ Both paths create the file object and initial version directly. Do not call `dms-upload` afterward.
46
+
47
+ ### Cloud upload from the CLI
48
+
49
+ Prefer the composed command. It previews and confirms both metadata creation and the provider PUT:
50
+
51
+ ```bash
52
+ blocks data files upload --file ./invoice.pdf --parent-id <directoryId> \
53
+ --configuration-name Default --access-modifier Private --dry-run --json
54
+ blocks data files upload --file ./invoice.pdf --parent-id <directoryId> \
55
+ --configuration-name Default --access-modifier Private --yes --json
56
+ ```
57
+
58
+ Use the two explicit commands only when the intermediate upload URL is required:
59
+
60
+ ```bash
61
+ blocks data files presigned-upload-url \
62
+ --name invoice.pdf \
63
+ --parent-directory-id <directoryId> \
64
+ --configuration-name Default \
65
+ --access-modifier Private \
66
+ --dry-run --json
67
+ blocks data files presigned-upload-url \
68
+ --name invoice.pdf \
69
+ --parent-directory-id <directoryId> \
70
+ --configuration-name Default \
71
+ --access-modifier Private \
72
+ --yes --json
73
+
74
+ blocks data files upload-to-url \
75
+ --url "<uploadUrl>" \
76
+ --file ./invoice.pdf \
77
+ --content-type application/pdf \
78
+ --dry-run --json
79
+ blocks data files upload-to-url \
80
+ --url "<uploadUrl>" \
81
+ --file ./invoice.pdf \
82
+ --content-type application/pdf \
83
+ --yes --json
84
+ ```
85
+
86
+ The presign response contains `uploadUrl`, `fileId`, and `isSuccess`. The first call creates the file metadata/version; the PUT fills its object-storage key. Handle PUT failure explicitly because it can leave metadata for missing bytes.
87
+
88
+ When `parentDirectoryId` is empty, the cloud upload resolves `moduleName` to that module's default directory. The backend default is module value `8` (`Default_Construct`), but pass the intended module or a concrete directory id instead of relying on that default.
89
+
90
+ ### Cloud upload from app code
91
+
92
+ ```ts
93
+ const presign = await blocksClient.data.files.presignedUploadUrl({
94
+ name: "invoice.pdf",
95
+ parentDirectoryId: directoryId,
96
+ configurationName: "Default",
97
+ accessModifier: "Private",
98
+ tags: "invoice,2026",
99
+ });
100
+
101
+ if (!presign || typeof presign !== "object") {
102
+ throw new Error("Unexpected upload response");
103
+ }
104
+
105
+ const result = presign as {
106
+ uploadUrl: string;
107
+ fileId: string;
108
+ isSuccess: boolean;
109
+ errors?: Record<string, string>;
110
+ };
111
+
112
+ if (!result.isSuccess) throw new Error(JSON.stringify(result.errors));
113
+
114
+ await blocksClient.data.files.uploadToUrl({
115
+ url: result.uploadUrl,
116
+ body: file,
117
+ contentType: file.type || "application/octet-stream",
118
+ });
119
+ ```
120
+
121
+ `uploadToUrl` is provider-direct and sends no bearer token or `x-blocks-key`. The SDK adds Azure's `x-ms-blob-type: Blockblob` header unless overridden; ensure that header matches the signed provider policy.
122
+
123
+ ### Local-storage upload
124
+
125
+ ```bash
126
+ blocks data files upload-to-local-storage \
127
+ --file ./invoice.pdf \
128
+ --parent-directory-id <directoryId> \
129
+ --configuration-name Default \
130
+ --access-modifier Private \
131
+ --dry-run --json
132
+ blocks data files upload-to-local-storage \
133
+ --file ./invoice.pdf \
134
+ --parent-directory-id <directoryId> \
135
+ --configuration-name Default \
136
+ --access-modifier Private \
137
+ --yes --json
138
+ ```
139
+
140
+ ```ts
141
+ const uploaded = await blocksClient.data.files.uploadToLocalStorage({
142
+ name: file.name,
143
+ file,
144
+ parentDirectoryId: directoryId,
145
+ configurationName: "Default",
146
+ accessModifier: "Private",
147
+ tags: ["invoice", "2026"],
148
+ });
149
+ ```
150
+
151
+ This call creates the file object and uploads version 1 in one request. Unlike cloud presign, an empty local `parentDirectoryId` stays at the top level; it is not resolved through `moduleName`.
152
+
153
+ ## Add a file version
154
+
155
+ Supplying an existing `itemId` to either upload flow creates another version after the caller passes the file's Edit check. For cloud storage, the dedicated command/method returns another pre-signed URL:
156
+
157
+ ```bash
158
+ blocks data files versions <fileId> --limit 25 --json
159
+ blocks data files create-version <fileId> --configuration-name Default --dry-run --json
160
+ blocks data files create-version <fileId> --configuration-name Default --yes --json
161
+ ```
162
+
163
+ ```ts
164
+ const history = await blocksClient.data.files.versions({ fileId, limit: 25 });
165
+ const next = await blocksClient.data.files.createVersion({ fileId, configurationName: "Default" });
166
+ ```
167
+
168
+ Version history is newest-first and cursor-paginated. Use the returned opaque `nextCursor`; the current backend uses the last version number internally, but callers must not construct cursors. Limits are 1–100, default 25.
169
+
170
+ ## Read and download
171
+
172
+ ```bash
173
+ blocks data files get <fileId> --configuration-name Default --json
174
+ blocks data files get <fileId> --version <versionNo> --configuration-name Default --json
175
+ blocks data files get-many <fileId...> --configuration-name Default --json
176
+ ```
177
+
178
+ ```ts
179
+ const file = await blocksClient.data.files.get(fileId, {
180
+ configurationName: "Default",
181
+ version: 2,
182
+ });
183
+ ```
184
+
185
+ The response includes a download URL plus metadata. Download requires the caller's Download permission. Access-denied reads may deliberately look like missing resources so clients cannot probe hidden object ids.
186
+
187
+ ## Directory and object workflows
188
+
189
+ For browsing, directories, search, move/copy/rename, trash, sharing, and ACL behavior, read [flows/object-management.md](flows/object-management.md).
190
+
191
+ ## Update custom metadata
192
+
193
+ ```bash
194
+ blocks data files update-additional-info <fileId> \
195
+ --additional-properties '{"status":"reviewed"}' \
196
+ --dry-run --json
197
+ blocks data files update-additional-info <fileId> \
198
+ --additional-properties '{"status":"reviewed"}' \
199
+ --yes --json
200
+ ```
201
+
202
+ This updates `additionalProperties`; it does not rename, move, tag, or version the file.
203
+
204
+ ## Delete safely
205
+
206
+ Deletion now distinguishes trash from permanent removal:
207
+
208
+ - `permanent: false` archives the file or directory so it can be restored.
209
+ - `permanent: true` removes it for good.
210
+ - The backend default is **`true`** when `permanent` is omitted.
211
+
212
+ The CLI defaults to safe soft deletion. Add `--permanent` only after explicit approval.
213
+
214
+ ```bash
215
+ blocks data files delete <fileId> --dry-run --json
216
+ blocks data files delete <fileId> --yes --json
217
+ blocks data files delete <fileId> --permanent --dry-run --json
218
+ ```
219
+
220
+ In app code, send the choice explicitly: `blocksClient.data.files.delete({ fileId, permanent: false })`.
221
+
222
+ ## Permission model
223
+
224
+ Every storage request passes two checks:
225
+
226
+ 1. The endpoint permission permits that class of action.
227
+ 2. The object ACL permits the action on that specific file/directory.
228
+
229
+ Capabilities are ordered: `View`, `Download`, `Edit`, `Delete`, `Manage`, `Owner`. Higher capabilities imply lower ones. Directory children inherit ancestor access while `inheritsParentAccess` is true. New files inherit from their directory.
230
+
231
+ Do not infer permission from a visible button or endpoint grant. Render actions from each object's returned `permissions` flags and still handle 403/404 races.
232
+
233
+ ## Gotchas
234
+
235
+ - Upload now creates the visible file object; legacy DMS registration is wrong and may fail after the bytes were successfully PUT.
236
+ - Cloud presign creates metadata before the provider PUT. Treat the two steps as a recoverable workflow and surface partial failure.
237
+ - A name must contain an allowed extension. Directories may restrict extensions.
238
+ - Names are unique within a directory. File move/copy can fail on a name conflict or extension policy.
239
+ - `Private` is the safe default. Use `Public` only when unauthenticated download is intended.
240
+ - `configurationName` selects an existing provider record; it does not configure storage.
241
+ - Most legacy file SDK methods return `Promise<unknown>`; validate responses at the boundary.
242
+ - Never send Blocks auth headers to a pre-signed provider URL.
243
+ - Never use a raw API call to work around a missing CLI/SDK wrapper; update the client surface first.
244
+
245
+ ## Example triggers
246
+
247
+ - "Upload this PDF into the Contracts folder."
248
+ - "Build a file browser with folders and search."
249
+ - "Show files shared with the current user."
250
+ - "Move this file to trash and let users restore it."
251
+ - "Add version history and upload a replacement version."
252
+ - "Share this directory with a role and let its children inherit access."
253
+ - "Move, copy, or rename a file."