@civitai/app-sdk 0.46.0 → 0.48.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.
Files changed (44) hide show
  1. package/README.md +120 -33
  2. package/dist/blocks/appStorageLimits.d.ts +113 -0
  3. package/dist/blocks/appStorageLimits.d.ts.map +1 -0
  4. package/dist/blocks/appStorageLimits.js +113 -0
  5. package/dist/blocks/appStorageLimits.js.map +1 -0
  6. package/dist/blocks/index.d.ts +26 -7
  7. package/dist/blocks/index.d.ts.map +1 -1
  8. package/dist/blocks/index.js +25 -5
  9. package/dist/blocks/index.js.map +1 -1
  10. package/dist/blocks/manifestError.d.ts +20 -0
  11. package/dist/blocks/manifestError.d.ts.map +1 -0
  12. package/dist/blocks/manifestError.js +22 -0
  13. package/dist/blocks/manifestError.js.map +1 -0
  14. package/dist/blocks/messages.d.ts.map +1 -1
  15. package/dist/blocks/messages.js.map +1 -1
  16. package/dist/blocks/scopes.d.ts +7 -3
  17. package/dist/blocks/scopes.d.ts.map +1 -1
  18. package/dist/blocks/scopes.js +7 -3
  19. package/dist/blocks/scopes.js.map +1 -1
  20. package/dist/blocks/types.d.ts +197 -50
  21. package/dist/blocks/types.d.ts.map +1 -1
  22. package/dist/blocks/types.js +56 -0
  23. package/dist/blocks/types.js.map +1 -1
  24. package/dist/manifest/defineBlock.d.ts +145 -0
  25. package/dist/manifest/defineBlock.d.ts.map +1 -0
  26. package/dist/manifest/defineBlock.js +390 -0
  27. package/dist/manifest/defineBlock.js.map +1 -0
  28. package/dist/manifest/index.d.ts +19 -0
  29. package/dist/manifest/index.d.ts.map +1 -0
  30. package/dist/manifest/index.js +17 -0
  31. package/dist/manifest/index.js.map +1 -0
  32. package/dist/oauth/token.d.ts +34 -3
  33. package/dist/oauth/token.d.ts.map +1 -1
  34. package/dist/oauth/token.js +116 -4
  35. package/dist/oauth/token.js.map +1 -1
  36. package/dist/vite/index.d.ts +14 -0
  37. package/dist/vite/index.d.ts.map +1 -0
  38. package/dist/vite/index.js +61 -0
  39. package/dist/vite/index.js.map +1 -0
  40. package/package.json +42 -2
  41. package/dist/blocks/defineBlock.d.ts +0 -53
  42. package/dist/blocks/defineBlock.d.ts.map +0 -1
  43. package/dist/blocks/defineBlock.js +0 -338
  44. package/dist/blocks/defineBlock.js.map +0 -1
@@ -5,12 +5,33 @@ interface CommonOpts {
5
5
  /** Only required for confidential clients. Public clients omit this. */
6
6
  clientSecret?: string;
7
7
  }
8
- export interface ExchangeCodeOpts extends CommonOpts {
8
+ /** Mixed into the grants that return tokens (not into revoke). */
9
+ interface ScopeFallbackOpts {
10
+ /**
11
+ * Bitmask to use when the token response's `scope` is absent or unusable.
12
+ * RFC 6749 §5.1/§6 let the server omit `scope` when the grant is identical
13
+ * to what was requested, so pass the scope you asked for
14
+ * (`REQUESTED_SCOPES` on exchange, the previously granted `tokens.scope` on
15
+ * refresh). Without it, an absent or unusable `scope` resolves to `0`, i.e.
16
+ * "no permissions".
17
+ *
18
+ * Must itself be a whole number in `[0, 2**31-1]`. `NaN` (the result of
19
+ * `Number(undefined)` — easy to pass by accident from a half-populated
20
+ * store), a negative, a fraction and anything past the ceiling are
21
+ * **discarded in favour of `0`**, with a warning: an unchecked fallback is
22
+ * the same silent-`NaN` defect this guard exists to close.
23
+ *
24
+ * On a *present but unreadable* `scope` this value can **over-state** the
25
+ * grant — see {@link parseScope}. The over-statement is logged.
26
+ */
27
+ fallbackScope?: number;
28
+ }
29
+ export interface ExchangeCodeOpts extends CommonOpts, ScopeFallbackOpts {
9
30
  code: string;
10
31
  redirectUri: string;
11
32
  codeVerifier: string;
12
33
  }
13
- export interface RefreshTokenOpts extends CommonOpts {
34
+ export interface RefreshTokenOpts extends CommonOpts, ScopeFallbackOpts {
14
35
  refreshToken: string;
15
36
  }
16
37
  export interface RevokeTokenOpts extends CommonOpts {
@@ -26,7 +47,9 @@ export declare class OAuthError extends Error {
26
47
  * Exchange an authorization code for tokens (PKCE flow). Call this in your
27
48
  * `redirect_uri` callback handler with the `code` from the query string and the
28
49
  * `codeVerifier` you stashed when starting the flow. Omit `clientSecret` for
29
- * public clients. Throws {@link OAuthError} on a non-2xx token response.
50
+ * public clients. Throws {@link OAuthError} on a non-2xx token response. Pass
51
+ * `fallbackScope` so a `scope` the server omits — or one this SDK cannot read
52
+ * as a bitmask — resolves to what you requested rather than to `0`.
30
53
  *
31
54
  * @example
32
55
  * const tokens = await exchangeCode({
@@ -35,6 +58,7 @@ export declare class OAuthError extends Error {
35
58
  * redirectUri: 'https://your-app.com/api/auth/callback/civitai',
36
59
  * code: codeFromQuery,
37
60
  * codeVerifier: verifierFromSealedCookie,
61
+ * fallbackScope: REQUESTED_SCOPES,
38
62
  * });
39
63
  */
40
64
  export declare function exchangeCode(opts: ExchangeCodeOpts): Promise<OAuthTokens>;
@@ -43,11 +67,18 @@ export declare function exchangeCode(opts: ExchangeCodeOpts): Promise<OAuthToken
43
67
  * {@link OAuthTokens} (with a recomputed `expires_at`). Throws
44
68
  * {@link OAuthError} on failure — treat that as "re-authenticate."
45
69
  *
70
+ * Pass `fallbackScope: stored.scope`: RFC 6749 §6 lets the server omit `scope`
71
+ * when the refreshed grant is unchanged, and callers that replace the whole
72
+ * token blob (`{ ...session, tokens: fresh }`) would otherwise persist a `0`
73
+ * scope and lock the user out of their own features. The same value is used if
74
+ * the server sends a `scope` this SDK cannot read as a bitmask.
75
+ *
46
76
  * @example
47
77
  * const tokens = await refreshToken({
48
78
  * clientId: process.env.CIVITAI_CLIENT_ID!,
49
79
  * clientSecret: process.env.CIVITAI_CLIENT_SECRET, // omit for public clients
50
80
  * refreshToken: stored.refresh_token,
81
+ * fallbackScope: stored.scope,
51
82
  * });
52
83
  */
53
84
  export declare function refreshToken(opts: RefreshTokenOpts): Promise<OAuthTokens>;
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/oauth/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,WAAW,EAAE,MAAM,aAAa,CAAC;AAOnE,UAAU,UAAU;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAClD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,UAAW,SAAQ,KAAK;IAIjC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO;IAJxB,SAAkB,IAAI,gBAAgB;gBAEpC,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO;CAIzB;AA0CD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAW/E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAS/E;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtE;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAS/F;AAED,oDAAoD;AACpD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,+CAA+C;IAC/C,WAAW,EAAE,eAAe,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAqBzF"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/oauth/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,WAAW,EAAE,MAAM,aAAa,CAAC;AAOnE,UAAU,UAAU;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,kEAAkE;AAClE,UAAU,iBAAiB;IACzB;;;;;;;;;;;;;;;;OAgBG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU,EAAE,iBAAiB;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAiB,SAAQ,UAAU,EAAE,iBAAiB;IACrE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,UAAW,SAAQ,KAAK;IAIjC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO;IAJxB,SAAkB,IAAI,gBAAgB;gBAEpC,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO;CAIzB;AAsJD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAW/E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAS/E;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtE;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAS/F;AAED,oDAAoD;AACpD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,+CAA+C;IAC/C,WAAW,EAAE,eAAe,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAqBzF"}
@@ -36,12 +36,114 @@ async function postForm(url, body) {
36
36
  }
37
37
  return parsed;
38
38
  }
39
+ /**
40
+ * Largest value accepted as a scope bitmask. Scopes are combined and tested
41
+ * with `&`/`|`, which are 32-bit *signed* operations in JS — anything at or
42
+ * above 2**31 wraps negative and silently corrupts every later `hasScope`
43
+ * check. `TokenScope.Full` is 2**25-1, so this leaves six bits of headroom.
44
+ */
45
+ const MAX_SCOPE_BITMASK = 2 ** 31 - 1;
46
+ /**
47
+ * The one predicate for "is this a bitmask we can safely `&`/`|`". Both the
48
+ * wire value and the caller-supplied `fallback` go through it — a fallback
49
+ * checked by a *different* rule (or by none) is how #326 comes back through
50
+ * the very option that was added to prevent it.
51
+ */
52
+ function isUsableBitmask(value) {
53
+ return Number.isSafeInteger(value) && value >= 0 && value <= MAX_SCOPE_BITMASK;
54
+ }
55
+ /**
56
+ * Resolve the caller's `fallback` into a bitmask that is safe to return.
57
+ *
58
+ * `fallback` is typed `number`, which admits `NaN`, `Infinity`, negatives and
59
+ * values past the ceiling — and `?? ` does **not** catch any of them. A caller
60
+ * writing `fallbackScope: Number(stored.scope)` against an absent
61
+ * `stored.scope` passes `NaN`, so an unvalidated fallback puts `NaN` straight
62
+ * into `tokens.scope` and every `hasScope()` answers `false`: #326 verbatim.
63
+ *
64
+ * An unusable fallback is therefore **discarded in favour of `0`**, with its
65
+ * own warning. `0` is the same "no permissions" answer a caller who passed no
66
+ * fallback at all gets; it is wrong in the safe direction (features stay
67
+ * disabled) where `NaN` is wrong in a direction nothing downstream can detect,
68
+ * and an over-ceiling value is wrong in the *unsafe* direction once `|` wraps
69
+ * it negative. The warning fires on the absent-scope path too, which is
70
+ * otherwise silent — the caller's own argument is a caller bug, not a server
71
+ * quirk, so it is worth saying out loud.
72
+ */
73
+ function usableFallback(fallback) {
74
+ if (fallback === undefined)
75
+ return 0;
76
+ if (!isUsableBitmask(fallback)) {
77
+ console.warn(`[@civitai/app-sdk] \`fallbackScope\` is not a usable bitmask: ${String(fallback)}. ` +
78
+ `Expected a whole number in [0, ${MAX_SCOPE_BITMASK}] (e.g. 114689). ` +
79
+ `Discarding it and using 0 ("no permissions") instead.`);
80
+ return 0;
81
+ }
82
+ return fallback;
83
+ }
84
+ /**
85
+ * Coerce a token response's `scope` into a usable bitmask.
86
+ *
87
+ * Civitai sends a decimal bitmask as a JSON string (`"scope": "114689"` — see
88
+ * https://developer.civitai.com/site/oauth/endpoints), so `Number()` is the
89
+ * right coercion; what was missing is a guard on its RESULT. RFC 6749 §5.1
90
+ * defines `scope` as a space-delimited *list*, and
91
+ * `Number('ai:write:budgeted user:read:self')` is `NaN`. `NaN & anything` is
92
+ * `0`, so every `hasScope()` answered `false` and a user who had just consented
93
+ * was told they granted nothing, with no error anywhere (#326). Anything that
94
+ * is not a whole number in `[0, 2**31-1]` is therefore rejected — including the
95
+ * `fallback`, see {@link usableFallback}.
96
+ *
97
+ * The `typeof` check before `Number()` is load-bearing on its own: `Number()`
98
+ * coerces a one-element array and a boolean into *valid-looking* bitmasks
99
+ * (`Number(['65537'])` is `65537`, `Number(true)` is `1`, i.e.
100
+ * `TokenScope.UserRead`), so without it a wrong-typed `scope` becomes a real,
101
+ * wrong grant rather than a rejected one.
102
+ *
103
+ * **Rejected means fall back and warn, not throw.** #326 left that open
104
+ * ("ignored *or* an error — say which"). A throw here turns a
105
+ * degraded-but-working session into a hard login failure, and the callers that
106
+ * could act on the distinction are exactly the ones already passing `fallback`
107
+ * — a better answer than either `0` or an abort. The warning names the value
108
+ * received so an unexpected wire format stays diagnosable.
109
+ *
110
+ * The two rejected-into-`fallback` paths are **not** equally sound, and the
111
+ * difference is invisible at this seam:
112
+ *
113
+ * - An **absent** `scope` (`undefined`, `null`, or whitespace-only) is not a
114
+ * fault at all — RFC 6749 §5.1/§6 make it optional precisely when the grant
115
+ * *matches the request*, so the requested scope IS the granted scope and
116
+ * `fallback` is exactly right. This path is silent.
117
+ * - A **present but unreadable** `scope` carries no such guarantee. The server
118
+ * is saying something about the grant that this SDK cannot read, and it may
119
+ * be a *reduced* grant. Falling back to the requested scope can therefore
120
+ * **over-state** what the user granted — every starter renders
121
+ * `scopesFromBitmask(tokens.scope)` to the user as "Granted scopes". #326
122
+ * weighed that against `0` and against throwing and chose fallback ("more
123
+ * honest than 0"), which is why this path warns: the over-statement is a
124
+ * known, logged trade, not an invariant.
125
+ */
126
+ function parseScope(raw, fallback) {
127
+ if (raw === undefined || raw === null)
128
+ return usableFallback(fallback);
129
+ if (typeof raw === 'string' && raw.trim() === '')
130
+ return usableFallback(fallback);
131
+ const value = typeof raw === 'number' || typeof raw === 'string' ? Number(raw) : NaN;
132
+ if (!isUsableBitmask(value)) {
133
+ const resolved = usableFallback(fallback);
134
+ console.warn(`[@civitai/app-sdk] OAuth token response has an unusable \`scope\`: ${JSON.stringify(raw)}. ` +
135
+ `Expected a decimal bitmask in [0, ${MAX_SCOPE_BITMASK}] (e.g. "114689"). ` +
136
+ `Falling back to ${resolved}.`);
137
+ return resolved;
138
+ }
139
+ return value;
140
+ }
39
141
  function shapeTokens(json, fallbackScope) {
40
142
  return {
41
143
  access_token: json.access_token,
42
144
  refresh_token: json.refresh_token,
43
145
  expires_at: Date.now() + (json.expires_in ?? 3600) * 1000,
44
- scope: typeof json.scope === 'number' ? json.scope : Number(json.scope ?? fallbackScope ?? 0),
146
+ scope: parseScope(json.scope, fallbackScope),
45
147
  token_type: json.token_type ?? 'Bearer',
46
148
  };
47
149
  }
@@ -49,7 +151,9 @@ function shapeTokens(json, fallbackScope) {
49
151
  * Exchange an authorization code for tokens (PKCE flow). Call this in your
50
152
  * `redirect_uri` callback handler with the `code` from the query string and the
51
153
  * `codeVerifier` you stashed when starting the flow. Omit `clientSecret` for
52
- * public clients. Throws {@link OAuthError} on a non-2xx token response.
154
+ * public clients. Throws {@link OAuthError} on a non-2xx token response. Pass
155
+ * `fallbackScope` so a `scope` the server omits — or one this SDK cannot read
156
+ * as a bitmask — resolves to what you requested rather than to `0`.
53
157
  *
54
158
  * @example
55
159
  * const tokens = await exchangeCode({
@@ -58,6 +162,7 @@ function shapeTokens(json, fallbackScope) {
58
162
  * redirectUri: 'https://your-app.com/api/auth/callback/civitai',
59
163
  * code: codeFromQuery,
60
164
  * codeVerifier: verifierFromSealedCookie,
165
+ * fallbackScope: REQUESTED_SCOPES,
61
166
  * });
62
167
  */
63
168
  export async function exchangeCode(opts) {
@@ -70,18 +175,25 @@ export async function exchangeCode(opts) {
70
175
  client_secret: opts.clientSecret,
71
176
  code_verifier: opts.codeVerifier,
72
177
  }));
73
- return shapeTokens(json);
178
+ return shapeTokens(json, opts.fallbackScope);
74
179
  }
75
180
  /**
76
181
  * Refresh an access token using a refresh_token grant. Returns a fresh
77
182
  * {@link OAuthTokens} (with a recomputed `expires_at`). Throws
78
183
  * {@link OAuthError} on failure — treat that as "re-authenticate."
79
184
  *
185
+ * Pass `fallbackScope: stored.scope`: RFC 6749 §6 lets the server omit `scope`
186
+ * when the refreshed grant is unchanged, and callers that replace the whole
187
+ * token blob (`{ ...session, tokens: fresh }`) would otherwise persist a `0`
188
+ * scope and lock the user out of their own features. The same value is used if
189
+ * the server sends a `scope` this SDK cannot read as a bitmask.
190
+ *
80
191
  * @example
81
192
  * const tokens = await refreshToken({
82
193
  * clientId: process.env.CIVITAI_CLIENT_ID!,
83
194
  * clientSecret: process.env.CIVITAI_CLIENT_SECRET, // omit for public clients
84
195
  * refreshToken: stored.refresh_token,
196
+ * fallbackScope: stored.scope,
85
197
  * });
86
198
  */
87
199
  export async function refreshToken(opts) {
@@ -92,7 +204,7 @@ export async function refreshToken(opts) {
92
204
  client_id: opts.clientId,
93
205
  client_secret: opts.clientSecret,
94
206
  }));
95
- return shapeTokens(json);
207
+ return shapeTokens(json, opts.fallbackScope);
96
208
  }
97
209
  /**
98
210
  * Revoke an access or refresh token (e.g. on logout). Omit `clientSecret` for
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/oauth/token.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/oauth/token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Plugin } from 'vite';
2
+ export interface BlockManifestPluginOptions {
3
+ /**
4
+ * Path to the manifest. Relative paths resolve against `root`, which defaults
5
+ * to the Vite project root reported by `configResolved`. Defaults to
6
+ * `./block.manifest.json`.
7
+ */
8
+ manifestPath?: string;
9
+ /** Overrides the Vite project root used to resolve a relative `manifestPath`. */
10
+ root?: string;
11
+ }
12
+ export declare function blockManifestPlugin(options?: BlockManifestPluginOptions): Plugin;
13
+ export { BlockManifestError } from '../blocks/manifestError.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAKnC,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,MAAM,CA+BpF;AAGD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `@civitai/app-sdk/vite` — NODE-ONLY Vite plugin that validates
3
+ * `block.manifest.json` on every dev-server boot and every build.
4
+ *
5
+ * WHY THIS EXISTS. `defineBlock` shipped for months with zero callers outside
6
+ * markdown (#330), so the manifests this repo ships were never validated by
7
+ * anything and the validator was free to drift into rejecting all of them. A
8
+ * gate that only runs where someone remembers to run it is the defect, not the
9
+ * fix. This is the cheapest place that runs unavoidably: `pnpm dev`,
10
+ * `pnpm dev:harness` and `pnpm build` all pass through `configResolved`.
11
+ *
12
+ * `configResolved` rather than `buildStart` on purpose — it is the one hook
13
+ * Vite calls in BOTH the dev-server and build paths, so there is no mode in
14
+ * which the check silently does not run. It is kept SYNCHRONOUS so the throw
15
+ * cannot depend on whether Vite awaits the hook.
16
+ *
17
+ * This is NOT a substitute for `civitai app validate` (the Go CLI's own local
18
+ * pre-check against the same canonical). It exists so a manifest mistake
19
+ * surfaces in the dev loop rather than at submit time.
20
+ *
21
+ * PEERS: `ajv` (used at runtime by `@civitai/app-sdk/manifest`) and `vite`
22
+ * (types only). Both are optional peers of `@civitai/app-sdk`; a scaffold using
23
+ * this plugin needs both in its devDependencies.
24
+ */
25
+ import { readFileSync } from 'node:fs';
26
+ import { resolve } from 'node:path';
27
+ import { BlockManifestError, defineBlock } from '../manifest/index.js';
28
+ export function blockManifestPlugin(options = {}) {
29
+ return {
30
+ name: 'civitai-block-manifest',
31
+ // `enforce: 'pre'` so the manifest error is the FIRST thing reported rather
32
+ // than being buried under whatever else a slow plugin logs.
33
+ enforce: 'pre',
34
+ configResolved(config) {
35
+ // Resolve against the Vite root (or an explicit override) rather than
36
+ // this module's own location — this file now lives inside the installed
37
+ // package, not next to the consumer's manifest.
38
+ const root = options.root ?? config?.root ?? process.cwd();
39
+ const manifestPath = resolve(root, options.manifestPath ?? './block.manifest.json');
40
+ let manifest;
41
+ try {
42
+ manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
43
+ }
44
+ catch (err) {
45
+ throw new Error(`block.manifest.json could not be read or parsed (${manifestPath}): ${err.message}`);
46
+ }
47
+ try {
48
+ defineBlock({ manifest });
49
+ }
50
+ catch (err) {
51
+ // Re-thrown with the field path up front: Vite prints the message, not
52
+ // the error's own properties, so `.field` would otherwise be invisible.
53
+ const field = err instanceof BlockManifestError && err.field ? ` [${err.field}]` : '';
54
+ throw new Error(`block.manifest.json is invalid${field}: ${err.message}`);
55
+ }
56
+ },
57
+ };
58
+ }
59
+ // Re-exported so a consumer can catch the typed error without a second import.
60
+ export { BlockManifestError } from '../blocks/manifestError.js';
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAcvE,MAAM,UAAU,mBAAmB,CAAC,UAAsC,EAAE;IAC1E,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,4EAA4E;QAC5E,4DAA4D;QAC5D,OAAO,EAAE,KAAK;QACd,cAAc,CAAC,MAAM;YACnB,sEAAsE;YACtE,wEAAwE;YACxE,gDAAgD;YAChD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,IAAI,uBAAuB,CAAC,CAAC;YAEpF,IAAI,QAAuB,CAAC;YAC5B,IAAI,CAAC;gBACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAkB,CAAC;YAC7E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,oDAAoD,YAAY,MAAO,GAAa,CAAC,OAAO,EAAE,CAC/F,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,uEAAuE;gBACvE,wEAAwE;gBACxE,MAAM,KAAK,GAAG,GAAG,YAAY,kBAAkB,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@civitai/app-sdk",
3
- "version": "0.46.0",
3
+ "version": "0.48.0",
4
4
  "description": "OAuth + PKCE, encrypted-cookie sessions, scopes, and orchestrator helpers for building third-party Civitai apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,6 +43,14 @@
43
43
  "types": "./dist/safe-storage/index.d.ts",
44
44
  "import": "./dist/safe-storage/index.js"
45
45
  },
46
+ "./manifest": {
47
+ "types": "./dist/manifest/index.d.ts",
48
+ "import": "./dist/manifest/index.js"
49
+ },
50
+ "./vite": {
51
+ "types": "./dist/vite/index.d.ts",
52
+ "import": "./dist/vite/index.js"
53
+ },
46
54
  "./schemas/app-block/v1.json": "./schemas/app-block/v1.json"
47
55
  },
48
56
  "files": [
@@ -74,18 +82,49 @@
74
82
  "`semver.satisfies('0.1.1-beta.0', '^0.2.0-beta.98')` === false.",
75
83
  "Install with the tag: `pnpm add -D @civitai/client@beta`."
76
84
  ],
85
+ "comment-peerDependencies-ajv-vite": [
86
+ "ajv and vite are OPTIONAL peers of the NODE-ONLY subpaths added when #330",
87
+ "was closed: `./manifest` (defineBlock) and `./vite` (blockManifestPlugin).",
88
+ "",
89
+ "`dependencies` stays EMPTY for the same reason it always has: this package",
90
+ "ships into sandboxed browser iframes and every app inherits its install",
91
+ "graph. A build-time JSON-Schema engine has no business in that graph, so",
92
+ "ajv is a peer a scaffold opts into: `pnpm add -D ajv`.",
93
+ "",
94
+ "ajv: a VALUE import (`ajv/dist/2020.js`, the draft 2020-12 entry — the",
95
+ "canonical schema declares $schema draft/2020-12, so the default `ajv`",
96
+ "entry point would refuse to compile it). FLOOR ^8.17.1: `ajv/dist/2020`",
97
+ "has existed since 8.6.0, but 8.17.x is what this repo builds and tests",
98
+ "against, and 8.x is a single major so the caret admits every later 8.",
99
+ "",
100
+ "vite: TYPES ONLY (`import type { Plugin }`). Nothing is value-imported, so",
101
+ "there is no module-evaluation failure mode -- only a typecheck one. The",
102
+ "range spans 5-8 because `Plugin.configResolved(config)` (the one member",
103
+ "`./vite` reads) has been stable across all of them; this repo builds and",
104
+ "tests against vite 8, which is what every scaffold pins."
105
+ ],
77
106
  "peerDependencies": {
78
- "@civitai/client": "^0.2.0-beta.98"
107
+ "@civitai/client": "^0.2.0-beta.98",
108
+ "ajv": "^8.17.1",
109
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
79
110
  },
80
111
  "peerDependenciesMeta": {
81
112
  "@civitai/client": {
82
113
  "optional": true
114
+ },
115
+ "ajv": {
116
+ "optional": true
117
+ },
118
+ "vite": {
119
+ "optional": true
83
120
  }
84
121
  },
85
122
  "devDependencies": {
86
123
  "@civitai/client": "0.2.0-beta.98",
87
124
  "@types/node": "^25.9.1",
125
+ "ajv": "^8.17.1",
88
126
  "typescript": "^5.9.2",
127
+ "vite": "^8.0.14",
89
128
  "vitest": "^4.1.11"
90
129
  },
91
130
  "publishConfig": {
@@ -113,6 +152,7 @@
113
152
  "build": "tsc -p tsconfig.json",
114
153
  "typecheck": "tsc -p tsconfig.json --noEmit",
115
154
  "test:types": "tsc -p tsconfig.typecheck.json",
155
+ "test:exports": "node scripts/check-exports.mjs",
116
156
  "test": "vitest run && tsc -p tsconfig.typecheck.json",
117
157
  "test:watch": "vitest"
118
158
  }
@@ -1,53 +0,0 @@
1
- /**
2
- * Build-time / startup validation for a `BlockManifestV1`.
3
- *
4
- * This is a subset of what the civitai/civitai server enforces — the client
5
- * runs it so authoring mistakes surface in `pnpm dev` rather than at
6
- * `civitai deploy` time. Rules here MUST stay a strict subset of the
7
- * server's; if the server tightens, mirror the change here.
8
- *
9
- * Every check guards `typeof` before pattern-testing — the highest-value
10
- * caller is `JSON.parse(fs.readFileSync('block.manifest.json'))`, where
11
- * the TypeScript type is a lie.
12
- */
13
- import type { BlockManifest } from './types.js';
14
- /** Thrown by `defineBlock` for any manifest violation. */
15
- export declare class BlockManifestError extends Error {
16
- /** Dot-path to the offending field, e.g. `iframe.sandbox`. */
17
- readonly field?: string | undefined;
18
- readonly name = "BlockManifestError";
19
- constructor(message: string,
20
- /** Dot-path to the offending field, e.g. `iframe.sandbox`. */
21
- field?: string | undefined);
22
- }
23
- export interface DefineBlockConfig {
24
- manifest: BlockManifest;
25
- }
26
- /**
27
- * Validates the manifest and returns it unchanged. Acts as a typed identity
28
- * function — call it at module scope in the block app so violations throw
29
- * before the app mounts. Mirrors a strict subset of the civitai/civitai server
30
- * gate, so authoring mistakes surface in `pnpm dev` instead of at submit time.
31
- * Throws {@link BlockManifestError} (with a `.field` dot-path) on a bad manifest.
32
- *
33
- * @example
34
- * import { defineBlock } from '@civitai/app-sdk/blocks';
35
- *
36
- * export const manifest = defineBlock({
37
- * manifest: {
38
- * $schema: 'https://civitai.com/schemas/app-block/v1.json',
39
- * appId: 'my-app',
40
- * blockId: 'my-block',
41
- * version: '1.0.0',
42
- * name: 'My Block',
43
- * type: 'block',
44
- * targets: [{ slotId: 'model.sidebar_top', priority: 100 }],
45
- * scopes: ['ai:write:budgeted'],
46
- * iframe: { src: 'https://my-block.civit.ai/', minHeight: 200 },
47
- * contentRating: 'pg',
48
- * minApiVersion: '1.0',
49
- * },
50
- * });
51
- */
52
- export declare function defineBlock(config: DefineBlockConfig): BlockManifest;
53
- //# sourceMappingURL=defineBlock.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"defineBlock.d.ts","sourceRoot":"","sources":["../../src/blocks/defineBlock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,YAAY,CAAC;AA8D/D,0DAA0D;AAC1D,qBAAa,kBAAmB,SAAQ,KAAK;IAIzC,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM;IAJzB,SAAkB,IAAI,wBAAwB;gBAE5C,OAAO,EAAE,MAAM;IACf,8DAA8D;IACrD,KAAK,CAAC,EAAE,MAAM,YAAA;CAI1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,aAAa,CAAC;CAIzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,CA6HpE"}