@colixsystems/widget-sdk 0.121.0 → 0.122.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/README.md +12 -1
- package/dist/contract.cjs +23 -5
- package/dist/contract.js +23 -5
- package/dist/hooks.js +12 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,7 +70,18 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
70
70
|
|
|
71
71
|
## Status
|
|
72
72
|
|
|
73
|
-
`v0.
|
|
73
|
+
`v0.122.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
74
|
+
|
|
75
|
+
### What's new in 0.122.0 (contract 1.94.0)
|
|
76
|
+
|
|
77
|
+
**A refused filestore upload now says it is a PERMISSION problem (sc-6977).** `useFilestoreUpload` and `usePdfExport` relay whatever the destination decides, and that decision used to arrive as a bare `404 "Space not found"` no matter who asked. sc-5395 chose that masking for one good reason — an **anonymous** prober must not be able to enumerate which workspaces have opened their public space — but it applied to every caller, so a signed-in author uploading a cover image hit a dead end with nothing to act on.
|
|
78
|
+
|
|
79
|
+
The refusal now splits along what the caller can already see:
|
|
80
|
+
|
|
81
|
+
- **403** when the caller can READ the destination (the response body carries `code: "UPLOAD_NOT_PERMITTED"`, which the client puts on `err.details.code` — `err.code` is the client's own `"FORBIDDEN"`, so branch on `err.status`). The common case is a `public` space, which is world-readable but upload-**deny-by-default**: the workspace operator has to switch upload access on (Studio → File library → the space → upload access). Naming that discloses nothing the caller could not already see.
|
|
82
|
+
- **404 `"Space not found"`** wherever saying more would leak: an anonymous caller, or a position hidden from this one (a restricted folder, a foreign `owner_id`, another tenant). A masked refusal carries no `code`.
|
|
83
|
+
|
|
84
|
+
No hook signature moved, so nothing has to change to keep working — but a widget that branched on `404` alone should accept **both**, which is what the built-in Files widget now does. Folder creation and a folder move report the same split (`FOLDER_CREATE_NOT_PERMITTED` / `FOLDER_MOVE_NOT_PERMITTED`).
|
|
74
85
|
|
|
75
86
|
### What's new in 0.121.0 (contract 1.93.0)
|
|
76
87
|
|
package/dist/contract.cjs
CHANGED
|
@@ -896,8 +896,14 @@ const HOOKS = [
|
|
|
896
896
|
"snake_case fields the backend reads verbatim (`space_type`, " +
|
|
897
897
|
"`owner_id`, `folder_id`, plus the binary `file`), and POSTs through " +
|
|
898
898
|
"ctx.filestore.files.upload. `upload(file, { folderId?, compress? })` " +
|
|
899
|
-
"resolves to the created file row or throws the wire error
|
|
900
|
-
"means the destination
|
|
899
|
+
"resolves to the created file row or throws the wire error. Branch " +
|
|
900
|
+
"on `err.status`: 403 means the destination denied the add and says " +
|
|
901
|
+
"so, because the caller can see that position — for a public space " +
|
|
902
|
+
"that means an operator has not switched upload access on yet; 404 " +
|
|
903
|
+
"means the position is hidden from the caller (or it is anonymous), " +
|
|
904
|
+
"so the refusal states no reason. Treat both as \"you can't upload " +
|
|
905
|
+
"here\". The server's `UPLOAD_NOT_PERMITTED` is at " +
|
|
906
|
+
"`err.details.code`; `err.code` is the client's own \"FORBIDDEN\". " +
|
|
901
907
|
"Uploaded images are compressed to WebP by the backend; pass " +
|
|
902
908
|
"`compress: false` (on the hook or per upload) to store the file " +
|
|
903
909
|
"byte-for-byte as the user provided it — use that whenever the " +
|
|
@@ -927,8 +933,10 @@ const HOOKS = [
|
|
|
927
933
|
"(`{ spaceType, folderId? }`); the hook resolves owner_id from the host " +
|
|
928
934
|
"context and POSTs JSON through ctx.filestore.files.exportPdf. " +
|
|
929
935
|
"`exportToPdf(html, { fileName?, folderId? })` resolves to the created " +
|
|
930
|
-
"file row (mime_type `application/pdf`) or throws the wire error;
|
|
931
|
-
"means the destination
|
|
936
|
+
"file row (mime_type `application/pdf`) or throws the wire error; " +
|
|
937
|
+
"`err.status` 403/404 means the destination denied the add (403 " +
|
|
938
|
+
"when the caller can see the position, 404 when it cannot), a 413 " +
|
|
939
|
+
"that the rendered " +
|
|
932
940
|
"PDF exceeded the size cap. The HTML is rendered by the host's PDF " +
|
|
933
941
|
"service (headless Chromium) — the SAME server-side pipeline on the web " +
|
|
934
942
|
"Player and the native export, so no browser-only PDF library is used.",
|
|
@@ -3603,7 +3611,17 @@ const CONTRACT = deepFreeze({
|
|
|
3603
3611
|
// JOINED to the page refuses it. An app that colours its rail or bar
|
|
3604
3612
|
// explicitly is untouched; an app that themed NOTHING moves from
|
|
3605
3613
|
// `#ffffff` to the `#f8fafc` its page already was.
|
|
3606
|
-
|
|
3614
|
+
// 1.94.0: behavioural (sc-6977) -- a filestore destination that refuses an
|
|
3615
|
+
// ADD now answers 403 with `code: UPLOAD_NOT_PERMITTED` when the caller
|
|
3616
|
+
// can already READ that position, and keeps the bare 404 only where
|
|
3617
|
+
// saying more would disclose something: an anonymous caller (sc-5395's
|
|
3618
|
+
// guarantee that a prober cannot enumerate which workspaces opened their
|
|
3619
|
+
// public space) or a position hidden from the caller. Affects
|
|
3620
|
+
// `useFilestoreUpload` and `usePdfExport`; no signature moved, but a
|
|
3621
|
+
// widget that branched on 404 alone should accept both, and the actionable
|
|
3622
|
+
// case -- a public space whose upload access is still off -- is now
|
|
3623
|
+
// distinguishable instead of arriving as a bare "Space not found".
|
|
3624
|
+
version: "1.94.0",
|
|
3607
3625
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
3608
3626
|
hooks: HOOKS,
|
|
3609
3627
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -896,8 +896,14 @@ const HOOKS = [
|
|
|
896
896
|
"snake_case fields the backend reads verbatim (`space_type`, " +
|
|
897
897
|
"`owner_id`, `folder_id`, plus the binary `file`), and POSTs through " +
|
|
898
898
|
"ctx.filestore.files.upload. `upload(file, { folderId?, compress? })` " +
|
|
899
|
-
"resolves to the created file row or throws the wire error
|
|
900
|
-
"means the destination
|
|
899
|
+
"resolves to the created file row or throws the wire error. Branch " +
|
|
900
|
+
"on `err.status`: 403 means the destination denied the add and says " +
|
|
901
|
+
"so, because the caller can see that position — for a public space " +
|
|
902
|
+
"that means an operator has not switched upload access on yet; 404 " +
|
|
903
|
+
"means the position is hidden from the caller (or it is anonymous), " +
|
|
904
|
+
"so the refusal states no reason. Treat both as \"you can't upload " +
|
|
905
|
+
"here\". The server's `UPLOAD_NOT_PERMITTED` is at " +
|
|
906
|
+
"`err.details.code`; `err.code` is the client's own \"FORBIDDEN\". " +
|
|
901
907
|
"Uploaded images are compressed to WebP by the backend; pass " +
|
|
902
908
|
"`compress: false` (on the hook or per upload) to store the file " +
|
|
903
909
|
"byte-for-byte as the user provided it — use that whenever the " +
|
|
@@ -927,8 +933,10 @@ const HOOKS = [
|
|
|
927
933
|
"(`{ spaceType, folderId? }`); the hook resolves owner_id from the host " +
|
|
928
934
|
"context and POSTs JSON through ctx.filestore.files.exportPdf. " +
|
|
929
935
|
"`exportToPdf(html, { fileName?, folderId? })` resolves to the created " +
|
|
930
|
-
"file row (mime_type `application/pdf`) or throws the wire error;
|
|
931
|
-
"means the destination
|
|
936
|
+
"file row (mime_type `application/pdf`) or throws the wire error; " +
|
|
937
|
+
"`err.status` 403/404 means the destination denied the add (403 " +
|
|
938
|
+
"when the caller can see the position, 404 when it cannot), a 413 " +
|
|
939
|
+
"that the rendered " +
|
|
932
940
|
"PDF exceeded the size cap. The HTML is rendered by the host's PDF " +
|
|
933
941
|
"service (headless Chromium) — the SAME server-side pipeline on the web " +
|
|
934
942
|
"Player and the native export, so no browser-only PDF library is used.",
|
|
@@ -3603,7 +3611,17 @@ const CONTRACT = deepFreeze({
|
|
|
3603
3611
|
// JOINED to the page refuses it. An app that colours its rail or bar
|
|
3604
3612
|
// explicitly is untouched; an app that themed NOTHING moves from
|
|
3605
3613
|
// `#ffffff` to the `#f8fafc` its page already was.
|
|
3606
|
-
|
|
3614
|
+
// 1.94.0: behavioural (sc-6977) -- a filestore destination that refuses an
|
|
3615
|
+
// ADD now answers 403 with `code: UPLOAD_NOT_PERMITTED` when the caller
|
|
3616
|
+
// can already READ that position, and keeps the bare 404 only where
|
|
3617
|
+
// saying more would disclose something: an anonymous caller (sc-5395's
|
|
3618
|
+
// guarantee that a prober cannot enumerate which workspaces opened their
|
|
3619
|
+
// public space) or a position hidden from the caller. Affects
|
|
3620
|
+
// `useFilestoreUpload` and `usePdfExport`; no signature moved, but a
|
|
3621
|
+
// widget that branched on 404 alone should accept both, and the actionable
|
|
3622
|
+
// case -- a public space whose upload access is still off -- is now
|
|
3623
|
+
// distinguishable instead of arriving as a bare "Space not found".
|
|
3624
|
+
version: "1.94.0",
|
|
3607
3625
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
3608
3626
|
hooks: HOOKS,
|
|
3609
3627
|
primitives: PRIMITIVES,
|
package/dist/hooks.js
CHANGED
|
@@ -3203,9 +3203,14 @@ export function useFilestoreFile(fileId) {
|
|
|
3203
3203
|
* on web). FormData serialises both verbatim, so the same hook code path
|
|
3204
3204
|
* feeds the multipart on both platforms.
|
|
3205
3205
|
*
|
|
3206
|
-
*
|
|
3207
|
-
* the
|
|
3208
|
-
*
|
|
3206
|
+
* The destination can refuse the add two ways (sc-6977). BRANCH ON
|
|
3207
|
+
* `err.status`: 403 means the caller may know why — most often a public space
|
|
3208
|
+
* whose upload access an operator has not switched on — and 404 means the
|
|
3209
|
+
* position is hidden from it (or it is anonymous), so the refusal states no
|
|
3210
|
+
* reason. Treat both as "you can't upload here" rather than showing the raw
|
|
3211
|
+
* error. NOT `err.status === 403 && err.code === "UPLOAD_NOT_PERMITTED"`:
|
|
3212
|
+
* `err.code` is the CLIENT's taxonomy ("FORBIDDEN"), and the server's
|
|
3213
|
+
* `UPLOAD_NOT_PERMITTED` arrives at `err.details.code`.
|
|
3209
3214
|
*/
|
|
3210
3215
|
export function useFilestoreUpload(options) {
|
|
3211
3216
|
const ctx = useWidgetContextOrThrow("useFilestoreUpload");
|
|
@@ -3291,8 +3296,10 @@ export function useFilestoreUpload(options) {
|
|
|
3291
3296
|
* so the capability behaves identically on both platforms (no browser-only PDF
|
|
3292
3297
|
* library is involved).
|
|
3293
3298
|
*
|
|
3294
|
-
* A 404 means the destination
|
|
3295
|
-
*
|
|
3299
|
+
* A 403 or 404 means the destination denied the add — 403 when the caller can
|
|
3300
|
+
* see that position, 404 when it cannot; a 413 means the rendered PDF exceeded
|
|
3301
|
+
* the size cap. Branch on `err.status`; the server's `UPLOAD_NOT_PERMITTED` is
|
|
3302
|
+
* at `err.details.code`, not `err.code` (which is the client's "FORBIDDEN").
|
|
3296
3303
|
*/
|
|
3297
3304
|
export function usePdfExport(options) {
|
|
3298
3305
|
const ctx = useWidgetContextOrThrow("usePdfExport");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.122.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|