@civitai/app-sdk 0.47.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.
- package/README.md +76 -32
- package/dist/blocks/index.d.ts +19 -7
- package/dist/blocks/index.d.ts.map +1 -1
- package/dist/blocks/index.js +18 -5
- package/dist/blocks/index.js.map +1 -1
- package/dist/blocks/manifestError.d.ts +20 -0
- package/dist/blocks/manifestError.d.ts.map +1 -0
- package/dist/blocks/manifestError.js +22 -0
- package/dist/blocks/manifestError.js.map +1 -0
- package/dist/blocks/scopes.d.ts +7 -3
- package/dist/blocks/scopes.d.ts.map +1 -1
- package/dist/blocks/scopes.js +7 -3
- package/dist/blocks/scopes.js.map +1 -1
- package/dist/blocks/types.d.ts +110 -22
- package/dist/blocks/types.d.ts.map +1 -1
- package/dist/manifest/defineBlock.d.ts +145 -0
- package/dist/manifest/defineBlock.d.ts.map +1 -0
- package/dist/manifest/defineBlock.js +390 -0
- package/dist/manifest/defineBlock.js.map +1 -0
- package/dist/manifest/index.d.ts +19 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +17 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/vite/index.d.ts +14 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +61 -0
- package/dist/vite/index.js.map +1 -0
- package/package.json +42 -2
- package/dist/blocks/defineBlock.d.ts +0 -53
- package/dist/blocks/defineBlock.d.ts.map +0 -1
- package/dist/blocks/defineBlock.js +0 -338
- package/dist/blocks/defineBlock.js.map +0 -1
package/README.md
CHANGED
|
@@ -19,12 +19,19 @@ pnpm add @civitai/app-sdk
|
|
|
19
19
|
| `cookies/*` — `sealCookie`, `unsealCookie`, `buildSetCookieHeader`, `readCookie` | AES-256-GCM authenticated cookie crypto. Use to seal a session blob (refresh token, expiry, scope) into an `httpOnly` cookie with zero external session store. |
|
|
20
20
|
| `orchestrator/*` — `createOrchestratorClient`, `estimateWorkflow`, `submitWorkflow`, `getWorkflow`, `pollWorkflow`, `buildTextToImageBody`, `buildImageGenBody`, `buildWorkflowBody`, `WORKFLOW_STEP_TYPES`, `IMAGE_GEN_ENGINES`, `isTerminal`, `extractImageUrls`, `OrchestratorError`, `WorkflowSnapshot`, `GenerateInput`, `ImageGenInput`, `WorkflowStepType`, `ImageGenEngine`, `DEFAULT_MODEL_AIR` | Orchestrator workflow glue — types, body builders, raw HTTP, and long-poll helper. Client + server safe (fetch-only). `estimateWorkflow` calls `?whatif=true` to preview Buzz cost without spending. `pollWorkflow` long-polls to terminal status. `WORKFLOW_STEP_TYPES` is the catalog of every step `$type` the orchestrator accepts. |
|
|
21
21
|
| `orchestrator/steps` — `WorkflowStepTemplates`, `WorkflowStepTemplateFor`, `WorkflowStepInputFor`, `AnyWorkflowStepTemplate`, `TypedWorkflowTemplate` | **Type-only** subpath (0 runtime bytes) keying the orchestrator's generated workflow-step shapes from `@civitai/client` by wire `$type`, so apps compose real step bodies against types that track the spec instead of hand-maintained copies. Requires the optional peer `@civitai/client@beta`. Type surface only — it grants no submit permission; see "Typed step shapes" below. |
|
|
22
|
-
| `blocks/*` — `
|
|
22
|
+
| `blocks/*` — `BlockManifestError`, `BLOCK_SCOPES`, `BLOCK_SCOPE_PATTERN`, `isMessage`, types (`BlockManifestV1`, `BlockContext`, `BlockToken`, `BlockSettings`, `ViewerInfo`, `ThemeInfo`, `BlockWorkflowSnapshot`, `BlockInitPayload`, `ParentToBlockMessage`, `BlockToParentMessage`, …) | Framework-agnostic contract for [Civitai Apps](https://github.com/civitai/civitai-app-starters/blob/main/docs/build-your-first-app-block.md). Ships a byte-identical copy of the server-published canonical JSON Schema (draft 2020-12, https://civitai.com/schemas/app-block/v1.json) at the `./schemas/app-block/v1.json` subpath for offline validation; a CI drift-check keeps it in sync. Runtime-agnostic and **zero runtime dependencies** — no React, no DOM types, nothing in your install graph. Hooks and the iframe transport live in a separate package. |
|
|
23
|
+
| `manifest/*` — `defineBlock`, `SCHEMA_DIVERGENCES`, `KNOWN_GAPS` (**Node only**) | Build-time manifest validation. `defineBlock(config)` compiles the vendored canonical schema with [Ajv](https://ajv.js.org) and validates a `BlockManifestV1` against it, so authoring mistakes surface in `pnpm dev` instead of at `civitai app validate`/submit. It is **derived from the schema, not a hand-written mirror of it** — that mirror is what produced [#330](https://github.com/civitai/civitai-app-starters/issues/330). Needs `node:fs` and the optional peer `ajv`, which is why it is not on the browser-facing `./blocks` surface. |
|
|
24
|
+
| `vite/*` — `blockManifestPlugin` (**Node only**) | A Vite plugin wrapping `defineBlock`, firing from `configResolved` — the one hook Vite calls on both the dev-server and the build path. Every block scaffold registers it, so `pnpm dev`, `pnpm dev:harness` and `pnpm build` all fail on a bad manifest with the offending field path. Optional peers: `ajv` (runtime) and `vite` (types only). |
|
|
23
25
|
|
|
24
26
|
## Subpath imports
|
|
25
27
|
|
|
26
28
|
```ts
|
|
27
|
-
import {
|
|
29
|
+
import { BLOCK_SCOPES, isSignedIn } from '@civitai/app-sdk/blocks';
|
|
30
|
+
// Build-time manifest validation (NODE ONLY — needs the optional peer `ajv`).
|
|
31
|
+
// Most projects want the Vite plugin below rather than calling this directly:
|
|
32
|
+
import { defineBlock } from '@civitai/app-sdk/manifest';
|
|
33
|
+
// The same gate as a Vite plugin (NODE ONLY — optional peers `ajv` + `vite`):
|
|
34
|
+
import { blockManifestPlugin } from '@civitai/app-sdk/vite';
|
|
28
35
|
// Type-only: the orchestrator's generated per-step shapes. Needs the optional
|
|
29
36
|
// peer `@civitai/client@beta` — see "Typed step shapes" below:
|
|
30
37
|
import type { TypedWorkflowTemplate } from '@civitai/app-sdk/orchestrator/steps';
|
|
@@ -37,9 +44,11 @@ import manifestSchema from '@civitai/app-sdk/schemas/app-block/v1.json' with { t
|
|
|
37
44
|
## Civitai Apps contract (`@civitai/app-sdk/blocks`)
|
|
38
45
|
|
|
39
46
|
> Building a **Civitai App** (an iframe-embedded UI on a civitai.com page)? This
|
|
40
|
-
> subpath is the framework-agnostic contract — manifest types, scope strings
|
|
41
|
-
> the `postMessage` protocol
|
|
42
|
-
>
|
|
47
|
+
> subpath is the framework-agnostic contract — manifest types, scope strings and
|
|
48
|
+
> the `postMessage` protocol. (The `defineBlock` validator moved to the node-only
|
|
49
|
+
> [`@civitai/app-sdk/manifest`](#defineblock-validator-rules) subpath; `./blocks`
|
|
50
|
+
> keeps zero runtime dependencies.) The React hooks + transport that consume it
|
|
51
|
+
> live in
|
|
43
52
|
> [`@civitai/blocks-react`](https://www.npmjs.com/package/@civitai/blocks-react).
|
|
44
53
|
> Start from the runnable [examples](https://github.com/civitai/civitai-app-starters/tree/main/starters/examples).
|
|
45
54
|
>
|
|
@@ -103,8 +112,7 @@ interface BlockInitPayload {
|
|
|
103
112
|
|
|
104
113
|
| Export | What |
|
|
105
114
|
|---|---|
|
|
106
|
-
| `
|
|
107
|
-
| `BLOCK_SCOPES` / `BLOCK_SCOPE_PATTERN` | The 15 known block scope strings (the authoritative enum `defineBlock` validates against) + the `domain:verb:target` format-helper regex. A scope is valid only if it's a member of `BLOCK_SCOPES`, matching the [canonical schema](https://civitai.com/schemas/app-block/v1.json). |
|
|
115
|
+
| `BLOCK_SCOPES` / `BLOCK_SCOPE_PATTERN` | The 15 known block scope strings (the authoritative enum the canonical schema validates `scopes` against) + the `domain:verb:target` format-helper regex. A scope is valid only if it's a member of `BLOCK_SCOPES`, matching the [canonical schema](https://civitai.com/schemas/app-block/v1.json). |
|
|
108
116
|
| `isMessage(data, type)` | Discriminator-only message narrowing (see above). |
|
|
109
117
|
| `isModelSlotContext(ctx)` / `isPageSlotContext(ctx)` | Runtime narrowing for the `slotId`-discriminated `BlockContext` union. Real checks on a value that crossed a `postMessage` boundary — they verify every field they assert, not just `slotId`. |
|
|
110
118
|
| `isSignedIn(viewer)` | **The sign-in gate.** `isSignedIn(useBlockContext().viewer)` — do not open-code it as `viewer !== null` or `viewer?.signedIn === true`. Which of those is correct has already changed once with the host contract, and this is the one place it is decided. It reads neither `viewer.id` nor `viewer.username` (both `@deprecated`), so nothing written through it changes when those are removed. Need the identity rather than the presence? `useViewer()` — scope-gated and audited per call. |
|
|
@@ -154,31 +162,67 @@ const body: WorkflowBody = {
|
|
|
154
162
|
|
|
155
163
|
### `defineBlock` validator rules
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
165
|
+
**There is no rule list here, and that is the point.** `defineBlock` does not
|
|
166
|
+
maintain one: it compiles the vendored copy of the
|
|
167
|
+
[canonical schema](https://civitai.com/schemas/app-block/v1.json) with
|
|
168
|
+
[Ajv](https://ajv.js.org) and validates against **that**. Every `required`,
|
|
169
|
+
`enum`, `pattern`, bound, `additionalProperties` and `allOf` the canonical
|
|
170
|
+
expresses is enforced, and moves when the canonical moves. The schema is the
|
|
171
|
+
rule list; read it, or read the errors.
|
|
172
|
+
|
|
173
|
+
That is [#330](https://github.com/civitai/civitai-app-starters/issues/330)'s own
|
|
174
|
+
proposed fix. The previous implementation hand-mirrored the schema, and the
|
|
175
|
+
mirror diverged exactly as the issue predicted: it required 11 fields where the
|
|
176
|
+
canonical requires **five** (`blockId`, `version`, `name`, `contentRating`,
|
|
177
|
+
`scopes`), required `appId` — not a canonical property at all — and *required*
|
|
178
|
+
the SERVER-OWNED `iframe.src` that `civitai app submit` refuses, so it rejected
|
|
179
|
+
every `block.manifest.json` this repo ships.
|
|
180
|
+
|
|
181
|
+
On top of the schema, `defineBlock` applies exactly five extra rules, each
|
|
182
|
+
mirroring a server rejection the canonical states only in **prose**:
|
|
183
|
+
|
|
184
|
+
| Rule | The canonical prose it mirrors |
|
|
185
|
+
|---|---|
|
|
186
|
+
| a dev-set **`iframe.src`** is rejected | *"SERVER-OWNED. Do NOT set `iframe.src` — the platform assigns it."* The JSON-Schema `not` is deliberately absent; the top-level `allOf` `$comment` says the platform validator and the Go CLI reject it instead. |
|
|
187
|
+
| a dev-set **`trustTier`** is rejected | *"SERVER-OWNED … the platform assigns the trust tier during review."* Same shape. |
|
|
188
|
+
| **`iframe.sandbox`** rejects `allow-same-origin` and every `allow-top-navigation*` token | *"Never combine allow-same-origin with allow-scripts."* Top-navigation is refused because a block must route navigation through the `NAVIGATE` postMessage. |
|
|
189
|
+
| every **`scopeJustifications`** key must be a scope in `scopes` | *"The requirement is enforced imperatively by the manifest validator (not expressed as JSON-Schema conditionals here)."* |
|
|
190
|
+
| **`settings`** is validated against the W3 settings meta-schema | Not in the app-block schema at all — settings are validated server-side by `manifest-settings.meta.schema.ts`. |
|
|
191
|
+
|
|
192
|
+
Each is **strictly additive**: it can only reject a manifest Ajv accepted, never
|
|
193
|
+
relax a canonical rule. `test/manifest/divergences.test.ts` asserts exactly that
|
|
194
|
+
per entry — the fixture must be schema-VALID and `defineBlock`-REJECTED — and the
|
|
195
|
+
table and the fixture set must be the same set, so a sixth hand-written rule with
|
|
196
|
+
no entry fails the suite.
|
|
197
|
+
|
|
198
|
+
> **Passing is necessary, not sufficient**, and it is **not** a replacement for
|
|
199
|
+
> `civitai app validate` (the Go CLI's local pre-check against the same
|
|
200
|
+
> canonical). Run that before `civitai app submit`. `KNOWN_GAPS` in
|
|
201
|
+
> `src/manifest/defineBlock.ts` names each thing only the server can check —
|
|
202
|
+
> including one that cuts the *other* way: the canonical's sandbox description is
|
|
203
|
+
> an **allowlist** (*"Unverified tier allows only: allow-scripts, allow-forms"*)
|
|
204
|
+
> while the rule above is a denylist, so `allow-popups`, `allow-modals` and
|
|
205
|
+
> `allow-downloads` **pass here and may be refused at review**. The tier is
|
|
206
|
+
> assigned server-side, so it cannot be enforced locally.
|
|
207
|
+
|
|
208
|
+
**Where it runs.** Every scaffold that ships a `block.manifest.json`
|
|
209
|
+
(`starters/civitai-block-starter` and all six `starters/examples/*`) registers
|
|
210
|
+
`blockManifestPlugin` from `@civitai/app-sdk/vite` in its `vite.config.ts`. It
|
|
211
|
+
fires from Vite's `configResolved`, the one hook called on both the dev-server
|
|
212
|
+
and the build path — so `pnpm dev`, `pnpm dev:harness` and `pnpm build` all fail
|
|
213
|
+
loudly on a bad manifest, with the offending field path in the message. Add
|
|
214
|
+
`ajv` to your devDependencies (it is an optional peer):
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
pnpm add -D ajv
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
// vite.config.ts — drop this into your existing `defineConfig({ plugins: [...] })`.
|
|
222
|
+
import { blockManifestPlugin } from '@civitai/app-sdk/vite';
|
|
223
|
+
|
|
224
|
+
const plugins = [blockManifestPlugin()];
|
|
225
|
+
```
|
|
182
226
|
|
|
183
227
|
### Web storage in a block (`@civitai/app-sdk/safe-storage`)
|
|
184
228
|
|
package/dist/blocks/index.d.ts
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@civitai/app-sdk/blocks` — framework-agnostic contract for Civitai Apps.
|
|
3
3
|
*
|
|
4
|
-
* This subpath exports the manifest type, scope strings
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* This subpath exports the manifest type, scope strings and postMessage
|
|
5
|
+
* protocol. Hooks and transport implementations live in a separate package (see
|
|
6
|
+
* `@civitai/blocks-react`) so this module stays usable from any runtime — Node,
|
|
7
|
+
* browsers, workers — with no React dependency and no runtime dependencies at
|
|
8
|
+
* all. Build-time manifest validation lives at `@civitai/app-sdk/manifest`
|
|
9
|
+
* (node-only); see the note on `BlockManifestError` below.
|
|
8
10
|
*/
|
|
9
11
|
import '../safe-storage/index.js';
|
|
10
12
|
export { installSafeStorage, createMemoryStorage } from '../safe-storage/index.js';
|
|
11
13
|
export type { SafeStorageInstallResult, SafeStorageName } from '../safe-storage/index.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
/**
|
|
15
|
+
* `defineBlock` MOVED to `@civitai/app-sdk/manifest` (a NODE-ONLY subpath) in
|
|
16
|
+
* the release that closed #330. It now validates by compiling the vendored
|
|
17
|
+
* canonical schema with Ajv instead of maintaining a hand-written mirror of it,
|
|
18
|
+
* which needs `node:fs` and a runtime dependency — neither of which belongs on
|
|
19
|
+
* this browser-facing, zero-dependency surface. Most callers want the Vite
|
|
20
|
+
* plugin at `@civitai/app-sdk/vite` rather than the function.
|
|
21
|
+
*
|
|
22
|
+
* `BlockManifestError` stays exported here, from its own module, so
|
|
23
|
+
* `instanceof` means the same thing on both subpaths.
|
|
24
|
+
*/
|
|
25
|
+
export { BlockManifestError } from './manifestError.js';
|
|
14
26
|
export { BLOCK_SCOPES, BLOCK_SCOPE_PATTERN, BLOCK_CATEGORIES, BLOCK_TAGLINE_MAX_LENGTH, } from './scopes.js';
|
|
15
27
|
export type { BlockScope, BlockScopeKey, BlockCategory } from './scopes.js';
|
|
16
28
|
export { BrowsingLevel, SFW_LEVELS, NSFW_LEVELS, isSfwCeiling, isLevelAllowed, effectiveBrowsingCeiling, } from './browsingLevel.js';
|
|
@@ -32,5 +44,5 @@ export { isModelSlotContext, isPageSlotContext } from './types.js';
|
|
|
32
44
|
* in `types.ts` for which of the two it uses and why.
|
|
33
45
|
*/
|
|
34
46
|
export { isSignedIn } from './types.js';
|
|
35
|
-
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockManifest, BlockManifestV1, BlockSettings, BlockToken, ContentRating,
|
|
47
|
+
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockManifest, BlockManifestV1, BlockSettings, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockTextToImageParams, BlockWorkflowSnapshot, BuzzAccountType, ShowcaseImage, WorkflowBody, WorkflowBodyTextToImage, WorkflowBodyCustomComfy, WorkflowBodyCustomComfyRecipe, WorkflowBodyCustomComfyInline, InlineComfyNode, WorkflowBodyStep, WorkflowBodyPassThroughStep, WorkflowStatus, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, AppWorkflowImage, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostRequest, BlockCreatePostResult, BlockCreatePostHostError, } from './types.js';
|
|
36
48
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blocks/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blocks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,OAAO,0BAA0B,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACnF,YAAY,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE1F;;;;;;;;;;GAUG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EACL,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EACd,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE1F,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EACL,SAAS,EACT,6BAA6B,EAC7B,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,YAAY,EACZ,2BAA2B,EAC3B,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,KAAK,EACL,UAAU,EACV,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,6BAA6B,EAC7B,eAAe,EACf,gBAAgB,EAChB,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,8BAA8B,EAC9B,WAAW,EACX,iBAAiB,EACjB,0BAA0B,EAC1B,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,8BAA8B,EAC9B,2BAA2B,EAC3B,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
package/dist/blocks/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@civitai/app-sdk/blocks` — framework-agnostic contract for Civitai Apps.
|
|
3
3
|
*
|
|
4
|
-
* This subpath exports the manifest type, scope strings
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* This subpath exports the manifest type, scope strings and postMessage
|
|
5
|
+
* protocol. Hooks and transport implementations live in a separate package (see
|
|
6
|
+
* `@civitai/blocks-react`) so this module stays usable from any runtime — Node,
|
|
7
|
+
* browsers, workers — with no React dependency and no runtime dependencies at
|
|
8
|
+
* all. Build-time manifest validation lives at `@civitai/app-sdk/manifest`
|
|
9
|
+
* (node-only); see the note on `BlockManifestError` below.
|
|
8
10
|
*/
|
|
9
11
|
// FIRST import, on purpose. Blocks are framed at an opaque origin (sandbox
|
|
10
12
|
// without `allow-same-origin`), where touching `localStorage`/`sessionStorage`
|
|
@@ -14,7 +16,18 @@
|
|
|
14
16
|
// or is absent (Node/SSR/workers); see `../safe-storage/index.ts`.
|
|
15
17
|
import '../safe-storage/index.js';
|
|
16
18
|
export { installSafeStorage, createMemoryStorage } from '../safe-storage/index.js';
|
|
17
|
-
|
|
19
|
+
/**
|
|
20
|
+
* `defineBlock` MOVED to `@civitai/app-sdk/manifest` (a NODE-ONLY subpath) in
|
|
21
|
+
* the release that closed #330. It now validates by compiling the vendored
|
|
22
|
+
* canonical schema with Ajv instead of maintaining a hand-written mirror of it,
|
|
23
|
+
* which needs `node:fs` and a runtime dependency — neither of which belongs on
|
|
24
|
+
* this browser-facing, zero-dependency surface. Most callers want the Vite
|
|
25
|
+
* plugin at `@civitai/app-sdk/vite` rather than the function.
|
|
26
|
+
*
|
|
27
|
+
* `BlockManifestError` stays exported here, from its own module, so
|
|
28
|
+
* `instanceof` means the same thing on both subpaths.
|
|
29
|
+
*/
|
|
30
|
+
export { BlockManifestError } from './manifestError.js';
|
|
18
31
|
export { BLOCK_SCOPES, BLOCK_SCOPE_PATTERN, BLOCK_CATEGORIES, BLOCK_TAGLINE_MAX_LENGTH, } from './scopes.js';
|
|
19
32
|
export { BrowsingLevel, SFW_LEVELS, NSFW_LEVELS, isSfwCeiling, isLevelAllowed, effectiveBrowsingCeiling, } from './browsingLevel.js';
|
|
20
33
|
export { APP_STORAGE_MAX_VALUE_BYTES, APP_STORAGE_MAX_BYTES, APP_STORAGE_MAX_ROWS, } from './appStorageLimits.js';
|
package/dist/blocks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blocks/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blocks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,2EAA2E;AAC3E,+EAA+E;AAC/E,6EAA6E;AAC7E,4EAA4E;AAC5E,8EAA8E;AAC9E,mEAAmE;AACnE,OAAO,0BAA0B,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGnF;;;;;;;;;;GAUG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EACd,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,SAAS,EACT,6BAA6B,EAC7B,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,eAAe,CAAC;AAiBvB;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manifest-validation error type, in its own zero-dependency module.
|
|
3
|
+
*
|
|
4
|
+
* It lives here rather than beside `defineBlock` because `defineBlock` now
|
|
5
|
+
* lives at the node-only `@civitai/app-sdk/manifest` subpath (it reads the
|
|
6
|
+
* vendored canonical schema off disk and compiles it with Ajv). The error class
|
|
7
|
+
* has to stay importable from the browser-safe `./blocks` surface so that
|
|
8
|
+
* `instanceof BlockManifestError` means the same thing on both sides — one
|
|
9
|
+
* class, one module, no duplicate identity.
|
|
10
|
+
*/
|
|
11
|
+
/** Thrown by `defineBlock` for any manifest violation. */
|
|
12
|
+
export declare class BlockManifestError extends Error {
|
|
13
|
+
/** Dot-path to the offending field, e.g. `iframe.sandbox`. */
|
|
14
|
+
readonly field?: string | undefined;
|
|
15
|
+
readonly name = "BlockManifestError";
|
|
16
|
+
constructor(message: string,
|
|
17
|
+
/** Dot-path to the offending field, e.g. `iframe.sandbox`. */
|
|
18
|
+
field?: string | undefined);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=manifestError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifestError.d.ts","sourceRoot":"","sources":["../../src/blocks/manifestError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manifest-validation error type, in its own zero-dependency module.
|
|
3
|
+
*
|
|
4
|
+
* It lives here rather than beside `defineBlock` because `defineBlock` now
|
|
5
|
+
* lives at the node-only `@civitai/app-sdk/manifest` subpath (it reads the
|
|
6
|
+
* vendored canonical schema off disk and compiles it with Ajv). The error class
|
|
7
|
+
* has to stay importable from the browser-safe `./blocks` surface so that
|
|
8
|
+
* `instanceof BlockManifestError` means the same thing on both sides — one
|
|
9
|
+
* class, one module, no duplicate identity.
|
|
10
|
+
*/
|
|
11
|
+
/** Thrown by `defineBlock` for any manifest violation. */
|
|
12
|
+
export class BlockManifestError extends Error {
|
|
13
|
+
field;
|
|
14
|
+
name = 'BlockManifestError';
|
|
15
|
+
constructor(message,
|
|
16
|
+
/** Dot-path to the offending field, e.g. `iframe.sandbox`. */
|
|
17
|
+
field) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.field = field;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=manifestError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifestError.js","sourceRoot":"","sources":["../../src/blocks/manifestError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,0DAA0D;AAC1D,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAKhC;IAJO,IAAI,GAAG,oBAAoB,CAAC;IAC9C,YACE,OAAe;IACf,8DAA8D;IACrD,KAAc;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,UAAK,GAAL,KAAK,CAAS;IAGzB,CAAC;CACF"}
|
package/dist/blocks/scopes.d.ts
CHANGED
|
@@ -67,11 +67,15 @@ export type BlockCategory = (typeof BLOCK_CATEGORIES)[number];
|
|
|
67
67
|
* `src/server/services/block-manifest-validator.service.ts` (the authoritative
|
|
68
68
|
* gate) and the `tagline.maxLength` in the canonical schema
|
|
69
69
|
* (https://civitai.com/schemas/app-block/v1.json). Keep all three in lockstep —
|
|
70
|
-
*
|
|
70
|
+
* `test/manifest/canonical-derivation.test.ts` asserts this const equals the
|
|
71
|
+
* vendored schema's bound.
|
|
71
72
|
*
|
|
72
73
|
* NOTE: the SERVER measures the TRIMMED length; JSON Schema's `maxLength` counts
|
|
73
|
-
* the
|
|
74
|
-
*
|
|
74
|
+
* the RAW string, so a tagline padded with whitespace past 140 is rejected by
|
|
75
|
+
* the schema and accepted by the server. `defineBlock` takes the SCHEMA's
|
|
76
|
+
* verdict — it applies no relaxation to any canonical rule — so that one shape
|
|
77
|
+
* is rejected locally. The canonical documents the asymmetry as deliberate
|
|
78
|
+
* ("this schema is never more permissive than the server"); trim the tagline.
|
|
75
79
|
*/
|
|
76
80
|
export declare const BLOCK_TAGLINE_MAX_LENGTH = 140;
|
|
77
81
|
//# sourceMappingURL=scopes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/blocks/scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAsCf,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAC;AACtD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,aAAa,CAAC,CAAC;AAE9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,mBAAmB,QAAuC,CAAC;AAExE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,8FAQnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D
|
|
1
|
+
{"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/blocks/scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAsCf,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAC;AACtD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,aAAa,CAAC,CAAC;AAE9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,mBAAmB,QAAuC,CAAC;AAExE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,8FAQnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC"}
|
package/dist/blocks/scopes.js
CHANGED
|
@@ -96,11 +96,15 @@ export const BLOCK_CATEGORIES = [
|
|
|
96
96
|
* `src/server/services/block-manifest-validator.service.ts` (the authoritative
|
|
97
97
|
* gate) and the `tagline.maxLength` in the canonical schema
|
|
98
98
|
* (https://civitai.com/schemas/app-block/v1.json). Keep all three in lockstep —
|
|
99
|
-
*
|
|
99
|
+
* `test/manifest/canonical-derivation.test.ts` asserts this const equals the
|
|
100
|
+
* vendored schema's bound.
|
|
100
101
|
*
|
|
101
102
|
* NOTE: the SERVER measures the TRIMMED length; JSON Schema's `maxLength` counts
|
|
102
|
-
* the
|
|
103
|
-
*
|
|
103
|
+
* the RAW string, so a tagline padded with whitespace past 140 is rejected by
|
|
104
|
+
* the schema and accepted by the server. `defineBlock` takes the SCHEMA's
|
|
105
|
+
* verdict — it applies no relaxation to any canonical rule — so that one shape
|
|
106
|
+
* is rejected locally. The canonical documents the asymmetry as deliberate
|
|
107
|
+
* ("this schema is never more permissive than the server"); trim the tagline.
|
|
104
108
|
*/
|
|
105
109
|
export const BLOCK_TAGLINE_MAX_LENGTH = 140;
|
|
106
110
|
//# sourceMappingURL=scopes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/blocks/scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;IAClC,0EAA0E;IAC1E,8EAA8E;IAC9E,gEAAgE;IAChE,iBAAiB,EAAE,mBAAmB;IACtC,kBAAkB,EAAE,oBAAoB;IACxC,+EAA+E;IAC/E,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,wBAAwB,EAAE,0BAA0B;IACpD,yBAAyB,EAAE,2BAA2B;IACtD,8EAA8E;IAC9E,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,kFAAkF;IAClF,yEAAyE;IACzE,qFAAqF;IACrF,qBAAqB,EAAE,uBAAuB;IAC9C,sBAAsB,EAAE,wBAAwB;IAChD,wBAAwB,EAAE,0BAA0B;IACpD,4EAA4E;IAC5E,qEAAqE;IACrE,8EAA8E;IAC9E,4DAA4D;IAC5D,2EAA2E;IAC3E,uEAAuE;IACvE,2EAA2E;IAC3E,8EAA8E;IAC9E,6EAA6E;IAC7E,8BAA8B;IAC9B,gBAAgB,EAAE,kBAAkB;CAC5B,CAAC;AAKX;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,oCAAoC,CAAC;AAExE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,YAAY;IACZ,OAAO;IACP,SAAS;IACT,WAAW;IACX,YAAY;IACZ,WAAW;IACX,OAAO;CACC,CAAC;AAIX
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/blocks/scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;IAClC,0EAA0E;IAC1E,8EAA8E;IAC9E,gEAAgE;IAChE,iBAAiB,EAAE,mBAAmB;IACtC,kBAAkB,EAAE,oBAAoB;IACxC,+EAA+E;IAC/E,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,wBAAwB,EAAE,0BAA0B;IACpD,yBAAyB,EAAE,2BAA2B;IACtD,8EAA8E;IAC9E,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,kFAAkF;IAClF,yEAAyE;IACzE,qFAAqF;IACrF,qBAAqB,EAAE,uBAAuB;IAC9C,sBAAsB,EAAE,wBAAwB;IAChD,wBAAwB,EAAE,0BAA0B;IACpD,4EAA4E;IAC5E,qEAAqE;IACrE,8EAA8E;IAC9E,4DAA4D;IAC5D,2EAA2E;IAC3E,uEAAuE;IACvE,2EAA2E;IAC3E,8EAA8E;IAC9E,6EAA6E;IAC7E,8BAA8B;IAC9B,gBAAgB,EAAE,kBAAkB;CAC5B,CAAC;AAKX;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,oCAAoC,CAAC;AAExE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,YAAY;IACZ,OAAO;IACP,SAAS;IACT,WAAW;IACX,YAAY;IACZ,WAAW;IACX,OAAO;CACC,CAAC;AAIX;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC"}
|
package/dist/blocks/types.d.ts
CHANGED
|
@@ -1335,20 +1335,47 @@ export type ManifestSettings = Record<string, ManifestSettingField>;
|
|
|
1335
1335
|
export type ContentRating = 'g' | 'pg' | 'pg13' | 'r' | 'x';
|
|
1336
1336
|
export interface ManifestTarget {
|
|
1337
1337
|
slotId: string;
|
|
1338
|
-
|
|
1338
|
+
/**
|
|
1339
|
+
* Slot ordering hint. NOT a property of the canonical schema (whose target
|
|
1340
|
+
* items require only `slotId`), so it is optional and shape-checked only.
|
|
1341
|
+
*/
|
|
1342
|
+
priority?: number;
|
|
1339
1343
|
requiredContext?: string[];
|
|
1340
1344
|
}
|
|
1345
|
+
/**
|
|
1346
|
+
* iframe envelope. Every field is optional — the canonical schema declares no
|
|
1347
|
+
* `required` list here, and the platform supplies its own defaults.
|
|
1348
|
+
*/
|
|
1341
1349
|
export interface ManifestIframe {
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1350
|
+
/**
|
|
1351
|
+
* SERVER-OWNED — the platform stamps the canonical bundle URL at
|
|
1352
|
+
* build/approve time. Typed `never` so setting it is a compile error;
|
|
1353
|
+
* `defineBlock` rejects it at runtime too. Until #330 the SDK REQUIRED this
|
|
1354
|
+
* field, which made every valid manifest fail local validation and every
|
|
1355
|
+
* locally-valid manifest fail `civitai app submit`.
|
|
1356
|
+
*/
|
|
1357
|
+
src?: never;
|
|
1358
|
+
/** Canonical bounds: integer, 40–4000 px. */
|
|
1359
|
+
minHeight?: number;
|
|
1360
|
+
/** Optional. Omit or set to `null` for no cap. Canonical bounds: 40–4000 px. */
|
|
1345
1361
|
maxHeight?: number | null;
|
|
1346
|
-
resizable
|
|
1347
|
-
sandbox
|
|
1362
|
+
resizable?: boolean;
|
|
1363
|
+
sandbox?: string;
|
|
1348
1364
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1365
|
+
/** Full-page surface descriptor (W10). Page apps mount at `/apps/run/<slug>`. */
|
|
1366
|
+
export interface ManifestPage {
|
|
1367
|
+
/** Sub-path the page mounts at; must start with `/`. */
|
|
1368
|
+
path: string;
|
|
1369
|
+
/** Title shown in host chrome. */
|
|
1370
|
+
title: string;
|
|
1371
|
+
icon?: string;
|
|
1372
|
+
/**
|
|
1373
|
+
* Per-generation Buzz SAFETY CEILING for `ai:write:budgeted` tokens — a
|
|
1374
|
+
* ceiling against a drained wallet, NOT a cost forecast. Size it well above
|
|
1375
|
+
* your worst-case generation; a budget set to your estimate becomes a hard
|
|
1376
|
+
* outage the moment real cost drifts up.
|
|
1377
|
+
*/
|
|
1378
|
+
buzzBudgetPerGen?: number;
|
|
1352
1379
|
}
|
|
1353
1380
|
export interface ManifestPreview {
|
|
1354
1381
|
thumbnail: string;
|
|
@@ -1358,18 +1385,42 @@ export interface ManifestPreview {
|
|
|
1358
1385
|
/**
|
|
1359
1386
|
* v1 manifest shape. Mirrors `schemas/app-block/v1.json` — keep them in sync.
|
|
1360
1387
|
*
|
|
1361
|
-
*
|
|
1362
|
-
*
|
|
1363
|
-
*
|
|
1388
|
+
* REQUIRED HERE = REQUIRED THERE. Only `blockId`, `version`, `name`,
|
|
1389
|
+
* `contentRating` and `scopes` are required, because those are exactly the five
|
|
1390
|
+
* entries in the canonical schema's `required` array. Before #330 this
|
|
1391
|
+
* interface required eleven (including `appId`, which the canonical does not
|
|
1392
|
+
* declare at all, and `iframe.src`, which the platform REFUSES), so the type
|
|
1393
|
+
* itself rejected every manifest the starters ship.
|
|
1364
1394
|
*/
|
|
1365
1395
|
export interface BlockManifestV1 {
|
|
1366
|
-
|
|
1367
|
-
|
|
1396
|
+
/**
|
|
1397
|
+
* Optional JSON-Schema reference. The canonical types it as a plain string
|
|
1398
|
+
* and its own description says it is "ignored by the platform validator", so
|
|
1399
|
+
* `defineBlock` does NOT constrain the value — point it at a vendored copy or
|
|
1400
|
+
* a preview draft if that is what your editor needs. Until #330 a mismatch
|
|
1401
|
+
* was a hard throw, which (once the gate was wired into Vite) failed the
|
|
1402
|
+
* build on a field the server provably ignores.
|
|
1403
|
+
*
|
|
1404
|
+
* The union below is an AUTOCOMPLETE NUDGE, not a rule: `string & {}` keeps
|
|
1405
|
+
* the literal visible in editor suggestions while still admitting any string.
|
|
1406
|
+
*/
|
|
1407
|
+
$schema?: 'https://civitai.com/schemas/app-block/v1.json' | (string & {});
|
|
1408
|
+
/**
|
|
1409
|
+
* NOT a canonical manifest property, and NOT validated. Your app id lives in
|
|
1410
|
+
* `civitai.app.json` (`{"appId": "..."}`), which is what the `civitai` CLI
|
|
1411
|
+
* reads. The canonical does not forbid extra top-level keys, so the server
|
|
1412
|
+
* ignores this one; the scaffolds still carry `"app_REPLACE_ME"` and it is
|
|
1413
|
+
* inert.
|
|
1414
|
+
*/
|
|
1415
|
+
appId?: string;
|
|
1368
1416
|
blockId: string;
|
|
1369
1417
|
version: string;
|
|
1418
|
+
/** Human-readable display name. Non-empty; the canonical imposes NO length cap. */
|
|
1370
1419
|
name: string;
|
|
1371
|
-
|
|
1372
|
-
|
|
1420
|
+
/** Canonical enum — `block` is the only member. */
|
|
1421
|
+
type?: 'block';
|
|
1422
|
+
/** Optional (page-only apps declare none). Canonical cap: 16 entries. */
|
|
1423
|
+
targets?: ManifestTarget[];
|
|
1373
1424
|
scopes: string[];
|
|
1374
1425
|
/**
|
|
1375
1426
|
* Optional per-scope justification: a map of scope-id → free-text rationale
|
|
@@ -1381,8 +1432,17 @@ export interface BlockManifestV1 {
|
|
|
1381
1432
|
* with the canonical schema's `scopeJustifications` (civitai #3195).
|
|
1382
1433
|
*/
|
|
1383
1434
|
scopeJustifications?: Record<string, string>;
|
|
1384
|
-
|
|
1385
|
-
|
|
1435
|
+
/** Optional; the canonical declares no required sub-field. */
|
|
1436
|
+
iframe?: ManifestIframe;
|
|
1437
|
+
/** Full-page surface descriptor (W10). */
|
|
1438
|
+
page?: ManifestPage;
|
|
1439
|
+
/**
|
|
1440
|
+
* The app's shipped `index.html` paints its own loading state inside `#root`,
|
|
1441
|
+
* so the full-page run host stands down its branded overlay. Only declare it
|
|
1442
|
+
* if the markup really exists — with the overlay gone, an empty `#root` is a
|
|
1443
|
+
* blank iframe for the whole load.
|
|
1444
|
+
*/
|
|
1445
|
+
bootSkeleton?: boolean;
|
|
1386
1446
|
/**
|
|
1387
1447
|
* Per-field settings declaration the platform validates user input
|
|
1388
1448
|
* against AND renders the publisher/viewer settings UI from. v0 shape;
|
|
@@ -1403,26 +1463,54 @@ export interface BlockManifestV1 {
|
|
|
1403
1463
|
* + detail page. Manifest-governed: it flows to the store listing on
|
|
1404
1464
|
* moderator-approve and is re-synced from the manifest on every subsequent
|
|
1405
1465
|
* approved version — for an ON-SITE app the manifest is the ONLY surface that
|
|
1406
|
-
* sets it. Omit it and the store simply shows no tagline.
|
|
1466
|
+
* sets it. Omit it and the store simply shows no tagline. Capped at
|
|
1407
1467
|
* {@link BLOCK_TAGLINE_MAX_LENGTH} (140) characters, the same bound off-site
|
|
1408
1468
|
* listings use, so both store kinds render the same slot. Kept in lockstep with
|
|
1409
|
-
* the canonical schema's `tagline` (civitai #3441).
|
|
1469
|
+
* the canonical schema's `tagline` (civitai #3441). NOTE the canonical counts
|
|
1470
|
+
* the RAW string while the server measures the trimmed one, and `defineBlock`
|
|
1471
|
+
* takes the canonical's verdict — so trim before you count.
|
|
1410
1472
|
*/
|
|
1411
1473
|
tagline?: string;
|
|
1474
|
+
/**
|
|
1475
|
+
* Optional PUBLIC source-repository link rendered as a `Source` row on the
|
|
1476
|
+
* app's store detail page. `https://` root URL on github.com, gitlab.com or
|
|
1477
|
+
* codeberg.org, at most 200 chars. `defineBlock` mirrors the canonical's
|
|
1478
|
+
* COARSE pattern; the server applies stricter per-segment rules, so passing
|
|
1479
|
+
* locally is necessary, not sufficient.
|
|
1480
|
+
*/
|
|
1481
|
+
repository?: string;
|
|
1412
1482
|
preview?: ManifestPreview;
|
|
1413
1483
|
promotionEligible?: boolean;
|
|
1414
|
-
|
|
1484
|
+
/** Optional; dot-separated integers (e.g. `"1"` or `"1.0"`). Informational. */
|
|
1485
|
+
minApiVersion?: string;
|
|
1415
1486
|
/**
|
|
1416
1487
|
* Author-declared mode preference. `hybrid` is a manifest-only hint that
|
|
1417
1488
|
* the host resolves to a concrete `iframe` | `inline` value before sending
|
|
1418
1489
|
* `BLOCK_INIT` — that's why `BlockInitPayload.renderMode` is narrower.
|
|
1419
1490
|
*/
|
|
1420
1491
|
renderMode?: 'iframe' | 'inline' | 'hybrid';
|
|
1492
|
+
/**
|
|
1493
|
+
* Config-as-code: the command the platform runs to build the static bundle.
|
|
1494
|
+
* One of an allowlisted set (`npm|pnpm|yarn run <script>`, `vite build`,
|
|
1495
|
+
* `npx vite build`). When set, `outputDir` is REQUIRED.
|
|
1496
|
+
*/
|
|
1497
|
+
buildCommand?: string;
|
|
1498
|
+
/** Directory `buildCommand` emits into. Safe relative path; required with `buildCommand`. */
|
|
1499
|
+
outputDir?: string;
|
|
1500
|
+
/** Allowlist of settings keys exposed to anonymous viewers. Max 32 keys, 64 chars each. */
|
|
1501
|
+
publicSettingsKeys?: string[];
|
|
1502
|
+
/** Optional v2 surface — a public `https://` URL to a hosted asset bundle. */
|
|
1503
|
+
assetBundleUrl?: string;
|
|
1421
1504
|
assetBundle?: {
|
|
1422
1505
|
url: string | null;
|
|
1423
1506
|
sha256: string | null;
|
|
1424
1507
|
};
|
|
1425
|
-
|
|
1508
|
+
/**
|
|
1509
|
+
* SERVER-OWNED — the platform assigns the trust tier during review. Typed
|
|
1510
|
+
* `never` so setting it is a compile error; `defineBlock` rejects it at
|
|
1511
|
+
* runtime too.
|
|
1512
|
+
*/
|
|
1513
|
+
trustTier?: never;
|
|
1426
1514
|
}
|
|
1427
1515
|
export type BlockManifest = BlockManifestV1;
|
|
1428
1516
|
/**
|