@protoyard/blueprint 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1149 -2
  3. package/dist/aggregate.d.ts +83 -0
  4. package/dist/aggregate.js +268 -0
  5. package/dist/app-model.d.ts +76 -0
  6. package/dist/app-model.js +287 -0
  7. package/dist/archetypes/index.d.ts +1 -0
  8. package/dist/archetypes/index.js +1 -0
  9. package/dist/archetypes/schema.d.ts +126 -0
  10. package/dist/archetypes/schema.js +77 -0
  11. package/dist/audit.d.ts +52 -0
  12. package/dist/audit.js +149 -0
  13. package/dist/authoring/deck-lint.d.ts +32 -0
  14. package/dist/authoring/deck-lint.js +567 -0
  15. package/dist/authoring/index.d.ts +1 -0
  16. package/dist/authoring/index.js +1 -0
  17. package/dist/authoring/select-deck-layouts.d.ts +50 -0
  18. package/dist/authoring/select-deck-layouts.js +213 -0
  19. package/dist/authoring-apis.d.ts +13 -0
  20. package/dist/authoring-apis.js +13 -0
  21. package/dist/authoring-validation.d.ts +65 -0
  22. package/dist/authoring-validation.js +267 -0
  23. package/dist/avatar.d.ts +25 -0
  24. package/dist/avatar.js +30 -0
  25. package/dist/brand.d.ts +70 -0
  26. package/dist/brand.js +294 -0
  27. package/dist/brief/archetypes.d.ts +28 -0
  28. package/dist/brief/archetypes.js +798 -0
  29. package/dist/brief/content-synthesize.d.ts +31 -0
  30. package/dist/brief/content-synthesize.js +210 -0
  31. package/dist/brief/deck-outlines.d.ts +96 -0
  32. package/dist/brief/deck-outlines.js +561 -0
  33. package/dist/brief/draft-bodies.d.ts +29 -0
  34. package/dist/brief/draft-bodies.js +224 -0
  35. package/dist/brief/fields.d.ts +19 -0
  36. package/dist/brief/fields.js +229 -0
  37. package/dist/brief/index.d.ts +8 -0
  38. package/dist/brief/index.js +8 -0
  39. package/dist/brief/kind-detection.d.ts +69 -0
  40. package/dist/brief/kind-detection.js +353 -0
  41. package/dist/brief/limits.d.ts +117 -0
  42. package/dist/brief/limits.js +217 -0
  43. package/dist/brief/page-doc-outlines.d.ts +80 -0
  44. package/dist/brief/page-doc-outlines.js +485 -0
  45. package/dist/brief/synthesize.d.ts +59 -0
  46. package/dist/brief/synthesize.js +511 -0
  47. package/dist/brief/text.d.ts +13 -0
  48. package/dist/brief/text.js +59 -0
  49. package/dist/canvas-screen.d.ts +31 -0
  50. package/dist/canvas-screen.js +33 -0
  51. package/dist/canvas-seed.d.ts +58 -0
  52. package/dist/canvas-seed.js +82 -0
  53. package/dist/computed/evaluate.d.ts +11 -0
  54. package/dist/computed/evaluate.js +101 -0
  55. package/dist/computed/index.d.ts +4 -0
  56. package/dist/computed/index.js +3 -0
  57. package/dist/computed/public.d.ts +14 -0
  58. package/dist/computed/public.js +19 -0
  59. package/dist/computed/schema.d.ts +10 -0
  60. package/dist/computed/schema.js +140 -0
  61. package/dist/computed/types.d.ts +70 -0
  62. package/dist/computed/types.js +1 -0
  63. package/dist/computed/validate.d.ts +6 -0
  64. package/dist/computed/validate.js +146 -0
  65. package/dist/csv-guard.d.ts +15 -0
  66. package/dist/csv-guard.js +29 -0
  67. package/dist/csv.d.ts +85 -0
  68. package/dist/csv.js +288 -0
  69. package/dist/files.d.ts +35 -0
  70. package/dist/files.js +246 -0
  71. package/dist/form-schema.d.ts +124 -0
  72. package/dist/form-schema.js +300 -0
  73. package/dist/generator-version.d.ts +11 -0
  74. package/dist/generator-version.js +51 -0
  75. package/dist/generator.d.ts +34 -0
  76. package/dist/generator.js +445 -0
  77. package/dist/identity.d.ts +34 -0
  78. package/dist/identity.js +91 -0
  79. package/dist/import/csv-shape.d.ts +40 -0
  80. package/dist/import/csv-shape.js +265 -0
  81. package/dist/import/json-shape.d.ts +55 -0
  82. package/dist/import/json-shape.js +491 -0
  83. package/dist/import/limits.d.ts +13 -0
  84. package/dist/import/limits.js +14 -0
  85. package/dist/import/sqlite-schema.d.ts +36 -0
  86. package/dist/import/sqlite-schema.js +729 -0
  87. package/dist/index.d.ts +60 -0
  88. package/dist/index.js +58 -0
  89. package/dist/kinds/anchors.d.ts +18 -0
  90. package/dist/kinds/anchors.js +46 -0
  91. package/dist/kinds/bodies.d.ts +6 -0
  92. package/dist/kinds/bodies.js +32 -0
  93. package/dist/kinds/brand-runtime.d.ts +19 -0
  94. package/dist/kinds/brand-runtime.js +35 -0
  95. package/dist/kinds/deck.d.ts +8 -0
  96. package/dist/kinds/deck.js +34 -0
  97. package/dist/kinds/doc.d.ts +19 -0
  98. package/dist/kinds/doc.js +41 -0
  99. package/dist/kinds/embed/index.d.ts +39 -0
  100. package/dist/kinds/embed/index.js +91 -0
  101. package/dist/kinds/envelope.d.ts +159 -0
  102. package/dist/kinds/envelope.js +78 -0
  103. package/dist/kinds/index.d.ts +11 -0
  104. package/dist/kinds/index.js +11 -0
  105. package/dist/kinds/kind.d.ts +36 -0
  106. package/dist/kinds/kind.js +55 -0
  107. package/dist/kinds/limits.d.ts +64 -0
  108. package/dist/kinds/limits.js +190 -0
  109. package/dist/kinds/page-doc-runtime.d.ts +37 -0
  110. package/dist/kinds/page-doc-runtime.js +55 -0
  111. package/dist/kinds/page.d.ts +16 -0
  112. package/dist/kinds/page.js +67 -0
  113. package/dist/kinds/parse.d.ts +18 -0
  114. package/dist/kinds/parse.js +27 -0
  115. package/dist/kinds/runtime.d.ts +128 -0
  116. package/dist/kinds/runtime.js +206 -0
  117. package/dist/kinds/services.d.ts +49 -0
  118. package/dist/kinds/services.js +249 -0
  119. package/dist/kinds/testing.d.ts +9 -0
  120. package/dist/kinds/testing.js +16 -0
  121. package/dist/migrations.d.ts +97 -0
  122. package/dist/migrations.js +351 -0
  123. package/dist/motion.d.ts +50 -0
  124. package/dist/motion.js +52 -0
  125. package/dist/notifications.d.ts +19 -0
  126. package/dist/notifications.js +177 -0
  127. package/dist/patch.d.ts +122 -0
  128. package/dist/patch.js +322 -0
  129. package/dist/policy.d.ts +23 -0
  130. package/dist/policy.js +105 -0
  131. package/dist/runtime-definition.d.ts +39 -0
  132. package/dist/runtime-definition.js +74 -0
  133. package/dist/scenarios.d.ts +9 -0
  134. package/dist/scenarios.js +49 -0
  135. package/dist/schema/blueprint.schema.json +10191 -0
  136. package/dist/schema-json.d.ts +6 -0
  137. package/dist/schema-json.js +36 -0
  138. package/dist/schema.d.ts +6348 -0
  139. package/dist/schema.js +1269 -0
  140. package/dist/search.d.ts +16 -0
  141. package/dist/search.js +96 -0
  142. package/dist/services.d.ts +89 -0
  143. package/dist/services.js +898 -0
  144. package/dist/share.d.ts +78 -0
  145. package/dist/share.js +234 -0
  146. package/dist/sheet-screen.d.ts +49 -0
  147. package/dist/sheet-screen.js +91 -0
  148. package/dist/storage.d.ts +43 -0
  149. package/dist/storage.js +179 -0
  150. package/dist/stream.d.ts +26 -0
  151. package/dist/stream.js +173 -0
  152. package/dist/untrusted.d.ts +63 -0
  153. package/dist/untrusted.js +502 -0
  154. package/dist/validation-tasks.d.ts +178 -0
  155. package/dist/validation-tasks.js +199 -0
  156. package/dist/validation.d.ts +35 -0
  157. package/dist/validation.js +312 -0
  158. package/dist/variants.d.ts +112 -0
  159. package/dist/variants.js +283 -0
  160. package/dist/workflows/index.d.ts +3 -0
  161. package/dist/workflows/index.js +3 -0
  162. package/dist/workflows/schema.d.ts +50 -0
  163. package/dist/workflows/schema.js +34 -0
  164. package/dist/workflows/transition.d.ts +15 -0
  165. package/dist/workflows/transition.js +25 -0
  166. package/dist/workflows/validate.d.ts +17 -0
  167. package/dist/workflows/validate.js +140 -0
  168. package/package.json +120 -3
@@ -0,0 +1,60 @@
1
+ /**
2
+ * `@protoyard/blueprint` — data-only blueprints (ADR-017). A `blueprint.json`
3
+ * describes a product (entities, fields, relations, roles, screens) without
4
+ * any executable code; this package validates it and derives what a
5
+ * prototype needs from it.
6
+ *
7
+ * Framework-agnostic: it depends only on `@protoyard/core` and zod and never
8
+ * imports Svelte (ADR-002).
9
+ */
10
+ /** Version of the blueprint document format. Bumped only on breaking changes. */
11
+ export declare const BLUEPRINT_FORMAT_VERSION = 1;
12
+ /**
13
+ * Authoring APIs (brief synthesis and kind detection, outlines, deck lint and
14
+ * layout selection, authoring validation) are named exports of this entry and
15
+ * tree-shake: a prototype that only parses or generates never bundles them.
16
+ * Browser consumers that want them on demand can load them as one lazy chunk,
17
+ * together with the deck layout catalog, through `loadAuthoringApis()`.
18
+ */
19
+ export declare function loadAuthoringApis(): Promise<typeof import('./authoring-apis.ts')>;
20
+ /** What `loadAuthoringApis()` resolves to. */
21
+ export type AuthoringApis = Awaited<ReturnType<typeof loadAuthoringApis>>;
22
+ /** Layout catalog types for authoring tools (type-only; the catalog itself loads lazily). */
23
+ export type { DeckLayoutEntry, DeckLayoutId, LayoutPacing } from '@protoyard/decks/layouts';
24
+ export { type AggregateCell, type AggregateQuerySpec, type AggregateResult, type AggregateSpec, aggregate, type BucketUnit, bucketStartUtc, createAggregateQuery, MAX_BUCKETS, NO_GROUP, } from './aggregate.ts';
25
+ export { type AppLayout, type AppModel, type AppNavGroup, type AppNavItem, type AppRoute, type AppRouteTarget, deriveAppModel, entityLabel, screenHasOwnView, screenNavIcon, } from './app-model.ts';
26
+ export { ARCHETYPE_IDS as KIT_ARCHETYPE_IDS, ARCHETYPE_KIT_ENTRY_POINTS, type ArchetypeKitEntryPoint, ArchetypeSchema, type BlueprintArchetype, type BlueprintArchetypeInput, } from './archetypes/index.ts';
27
+ export { AUDIT_REDACTED, type AuditAction, type AuditChange, type AuditEntry, type AuditEvent, auditDiff, type BlueprintAuditService, blueprintUsesAudit, createAuditService, createAuditWriter, } from './audit.ts';
28
+ export { type DeckLintDiagnostic, type DeckLintResult, type DeckLintSeverity, lintDeckAssets, lintDeckContent, lintDeckStructure, } from './authoring/deck-lint.ts';
29
+ export { type DeckLayoutSelection, type DeckLayoutSlideInput, propsForSelectedLayout, type SelectDeckLayoutsOptions, selectDeckLayouts, } from './authoring/index.ts';
30
+ export { type BlueprintAuthoringDiagnostic, type BlueprintAuthoringValidation, type BlueprintDiagnosticPath, blockOrAssetHint, diagnosticCode, diagnosticsFromBlockIssues, issueToDiagnostic, toJsonPath as authoringToJsonPath, validateBlueprintForAuthoring, } from './authoring-validation.ts';
31
+ export { AVATAR_IDS, type AvatarField, type AvatarId, avatarFields, isAvatarId, nextAvatar, primaryAvatarField, } from './avatar.ts';
32
+ export { type BrandContrastFailure, BrandThemeError, brandLibraryThemeId, brandThemeExportName, brandThemeId, closestIds, emitBrandThemeModule, getStyleProfile, type ResolveBrandOptions, resolveBlueprintBrand, STYLE_PROFILES, type StyleProfile, } from './brand.ts';
33
+ export { APP_CUES, type AppBriefResult, type ApplyOutlineBoundsResult, ARCHETYPE_IDS, ARCHETYPES, type Archetype, applyOutlineBounds, type BoundBriefInput, type BriefKindDetection, type BriefLimitCode, type BriefLimitIssue, type BriefOptions, type BriefResult, blueprintFromBrief, boundBriefInput, buildDocOutline, buildPageOutline, type ContentBriefOptions, type ContentBriefResult, type CueStrength, checkOutlineBounds, chooseDeckOutline, DECK_OUTLINE_IDS, DECK_OUTLINE_LIMITS, DECK_OUTLINES, type DeckOutlineId, type DeckOutlineOptions, type DeckOutlineResult, type DeckOutlineSlide, type DeckPacing, type DeckSlidePlan, type DetectKindOptions, DOC_OUTLINE_IDS, type DocOutlineId, type DocOutlineResult, deckOutlineRange, deckTitleFromBrief, detectBriefKind, detectPageDocOmissions, fieldFromPhrase, GENERIC_ARCHETYPE, isAppBriefResult, isContentBriefResult, KIND_CUES, type KindConfidence, type KindCue, MAX_BRIEF_LENGTH, MAX_CONTENT_BRIEF_LENGTH, OUTLINE_LIMITS, type OutlineBlock, type OutlineBoundsInput, type OutlineBuildOptions, type OutlineLimits, type OutlineSection, type OutlineUnitInput, PAGE_OUTLINE_IDS, type PageOutlineId, type PageOutlineResult, PEOPLE_ENTITIES, prepareBriefForSynthesis, requestedSlideCount, type SuggestedLayout, sectionIds, selectDocOutline, selectPageOutline, synthesizeAppFromBrief, synthesizeContentFromBrief, synthesizeDeckFromBrief, synthesizeDeckOutline, synthesizeDocFromBrief, synthesizePageFromBrief, } from './brief/index.ts';
34
+ export { canvasScreenIssues } from './canvas-screen.ts';
35
+ export { guardCsvFormula, needsCsvFormulaGuard, unguardCsvFormula } from './csv-guard.ts';
36
+ export { type BlueprintFile, type BlueprintFileMetadata, createFileServices, DEFAULT_FILE_QUOTA_BYTES, type FileService, type FileServices, FileUploadError, type FileUploadProgress, } from './files.ts';
37
+ export { ENTITY_FORM_CUSTOM_KINDS, type EntityFormField, type EntityFormFieldType, type EntityFormModel, type EntityFormOption, type EntityFormSchema, type EntityFormSchemaOptions, entityFormModel, HOSTED_FORM_KINDS, UNASSIGNED_OPTION, } from './form-schema.ts';
38
+ export { BLUEPRINT_GENERATOR_SDK, blueprintGeneratorVersion } from './generator-version.ts';
39
+ export { BLUEPRINT_NAMESPACE_PREFIX, type BlueprintIdentity, blueprintIdentity, canonicalJson, } from './identity.ts';
40
+ export { type AnyBlueprint, type BlueprintBase, blueprintKind, type ContentBlueprint, type DeckBlueprint, type DocBlueprint, isAppBlueprint, isContentBlueprint, isDeckBlueprint, isDocBlueprint, isPageBlueprint, type KindBodies, type PageBlueprint, parseAnyBlueprint, safeParseAnyBlueprint, } from './kinds/envelope.ts';
41
+ export { BLUEPRINT_KINDS, type BlueprintKind, CONTENT_KINDS, type ContentKind, DEFAULT_BLUEPRINT_KIND, detectBlueprintKind, isBlueprintKind, isContentKind, type KindDetection, unknownKindMessage, } from './kinds/kind.ts';
42
+ export { DEFAULT_UNTRUSTED_DOCUMENT_LIMITS, type UntrustedDocumentLimits, } from './kinds/limits.ts';
43
+ export { appendMigration, applyUpgradeOps, type BlueprintMigration, type DiffBlueprintsOptions, defaultForField, deriveDatabaseVersions, diffBlueprints, fieldProperty, latestSchemaVersion, MigrationError, toDatabaseVersion, type UpgradeOp, } from './migrations.ts';
44
+ export { BLUEPRINT_MOTION_LEVELS, type BlueprintMotion, type BlueprintMotionLevel, BlueprintMotionSchema, blueprintMotionLevel, DEFAULT_BLUEPRINT_MOTION_LEVEL, deckWithMotionCeiling, isBlueprintMotionLevel, lowerMotionLevel, } from './motion.ts';
45
+ export { type BlueprintNotificationService, createNotificationService, createNotificationWriter, type NotificationEvent, } from './notifications.ts';
46
+ export { type ApplyBlueprintPatchOptions, applyBlueprintPatch, applyContentPatch, applyJsonPatch, BlueprintPatchError, type BlueprintPatchErrorCode, type BlueprintPatchResult, type ContentPatchResult, JSON_PATCH_MAX_NODES, JSON_PATCH_MAX_OPS, JSON_POINTER_MAX_LENGTH, type JsonPatchOperation, JsonPatchOperationSchema, JsonPatchSchema, jsonEqual, parseJsonPointer, } from './patch.ts';
47
+ export { CAPABILITIES, derivePolicy, type EntityCapabilityMap } from './policy.ts';
48
+ export { BLUEPRINT_DEFAULT_SCENARIO, blueprintBrandTheme, brandDefaultThemeId, definePrototypeFromBlueprint, type RuntimeDefinition, type RuntimeDefinitionOptions, } from './runtime-definition.ts';
49
+ export { blueprintScenarios } from './scenarios.ts';
50
+ export { AGGREGATES, type Aggregate, BLUEPRINT_SCHEMA_URL, type Blueprint, type BlueprintBrand, type BlueprintBrandInput, BlueprintBrandSchema, type BlueprintDashboardWidget, type BlueprintEntity, type BlueprintField, type BlueprintHistoryEntry, BlueprintHistoryEntrySchema, type BlueprintInput, type BlueprintNotificationRule, type BlueprintRole, BlueprintSchema, type BlueprintScreen, type BlueprintScreenFilter, type BlueprintScreenInput, type BlueprintScreenNav, BUCKET_UNITS, blueprintIssues, CHART_KINDS, DashboardWidgetSchema, type DateWindow, DateWindowSchema, DETAIL_TABS, dashboardWidgets, dateWindowDays, ENTITY_ACTIONS, type EntityAction, EntityFeaturesSchema, EntitySchema, entityTable, FIELD_KINDS, FIELD_TRENDS, type FieldKind, FieldSchema, PermissionActionSchema, parseBlueprint, RESERVED_FIELD_NAMES, RESERVED_SCREEN_PATHS, RoleSchema, SCREEN_NAV_ICONS, SCREEN_TYPES, ScreenBucketSchema, ScreenFilterSchema, type ScreenNavIcon, ScreenNavSchema, ScreenSchema, type ScreenType, SETTINGS_SECTIONS, safeParseBlueprint, screenPath, } from './schema.ts';
51
+ export { blueprintJsonSchema } from './schema-json.ts';
52
+ export { BULK_CHUNK, createEntityServices, EntityInUseError, EntityNotFoundError, type EntityService, type EntityServices, type ExportCsvFilter, ImportCsvError, type ImportCsvOptions, type ImportCsvResult, UNDO_WINDOW_MS, } from './services.ts';
53
+ export { blueprintShareFragment, type DocumentShareDecodeResult, decodeBlueprintShare, decodeDocumentShare, encodeBlueprintShare, MAX_SHARE_DECODED_BYTES, MAX_SHARE_DOCUMENT_DECODED_BYTES, MAX_SHARE_ENCODED_LENGTH, readBlueprintShareFragment, SHARE_FRAGMENT_PARAM, SHARE_LINK_BROWSERS, SHARE_LINK_VERSION, type ShareDecodeResult, type ShareLinkIssue, ShareLinkTooLargeError, supportsShareLinks, } from './share.ts';
54
+ export { SHEET_COLUMN_KINDS, SHEET_EDITABLE_KINDS, SHEET_MAX_COLUMNS, SHEET_READONLY_KINDS, SHEET_TOTAL_KINDS, sheetColumns, sheetScreenIssues, } from './sheet-screen.ts';
55
+ export { deriveIntegrity, deriveStores, entityStoreString, FEATURE_STORE_STRINGS, FEATURE_TABLES, relationProperty, storeIndexForField, } from './storage.ts';
56
+ export { MAX_STREAM_CANDIDATES, paintStreamedBlueprint, type StreamedBlueprint, truncatedJsonCandidates, } from './stream.ts';
57
+ export { DEFAULT_UNTRUSTED_BLUEPRINT_LIMITS, loadUntrustedBlueprint, loadUntrustedDocument, type UntrustedBlueprintIssue, type UntrustedBlueprintLimits, type UntrustedBlueprintResult, type UntrustedDocumentResult, } from './untrusted.ts';
58
+ export { deriveInputSchemas, type EntityInput, type EntityInputSchemas, fieldLabel, inputProperty, parseMoneyText, } from './validation.ts';
59
+ export { type BlueprintValidation, CONTAINS_FIELD_KINDS, dataHolds, evaluateValidationSuccess, routeMatches, VALIDATION_DATA_OPS, VALIDATION_MAX_TASKS, type ValidationData, type ValidationDataOp, ValidationDataSchema, type ValidationObservation, type ValidationOutcome, type ValidationRoute, ValidationRouteSchema, ValidationSchema, type ValidationSuccess, ValidationSuccessSchema, type ValidationTask, ValidationTaskSchema, validationBaseline, } from './validation-tasks.ts';
60
+ export { type BlueprintVariant, type DeriveKindVariantsOptions, type DeriveVariantsOptions, deriveKindVariants, deriveVariants, type KindBlueprintVariant, type KindVariantAxes, type KindVariantChanges, VARIANT_DECK_TRANSITIONS, VARIANT_DENSITIES, VARIANT_DENSITY_SCALE, VARIANT_MAX_COUNT, VARIANT_THEME_PRESETS, type VariantAxes, type VariantChanges, type VariantDeckTransition, type VariantDensity, } from './variants.ts';
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `@protoyard/blueprint` — data-only blueprints (ADR-017). A `blueprint.json`
3
+ * describes a product (entities, fields, relations, roles, screens) without
4
+ * any executable code; this package validates it and derives what a
5
+ * prototype needs from it.
6
+ *
7
+ * Framework-agnostic: it depends only on `@protoyard/core` and zod and never
8
+ * imports Svelte (ADR-002).
9
+ */
10
+ /** Version of the blueprint document format. Bumped only on breaking changes. */
11
+ export const BLUEPRINT_FORMAT_VERSION = 1;
12
+ /**
13
+ * Authoring APIs (brief synthesis and kind detection, outlines, deck lint and
14
+ * layout selection, authoring validation) are named exports of this entry and
15
+ * tree-shake: a prototype that only parses or generates never bundles them.
16
+ * Browser consumers that want them on demand can load them as one lazy chunk,
17
+ * together with the deck layout catalog, through `loadAuthoringApis()`.
18
+ */
19
+ export function loadAuthoringApis() {
20
+ return import("./authoring-apis.js");
21
+ }
22
+ export { aggregate, bucketStartUtc, createAggregateQuery, MAX_BUCKETS, NO_GROUP, } from "./aggregate.js";
23
+ export { deriveAppModel, entityLabel, screenHasOwnView, screenNavIcon, } from "./app-model.js";
24
+ export { ARCHETYPE_IDS as KIT_ARCHETYPE_IDS, ARCHETYPE_KIT_ENTRY_POINTS, ArchetypeSchema, } from "./archetypes/index.js";
25
+ export { AUDIT_REDACTED, auditDiff, blueprintUsesAudit, createAuditService, createAuditWriter, } from "./audit.js";
26
+ export { lintDeckAssets, lintDeckContent, lintDeckStructure, } from "./authoring/deck-lint.js";
27
+ export { propsForSelectedLayout, selectDeckLayouts, } from "./authoring/index.js";
28
+ export { blockOrAssetHint, diagnosticCode, diagnosticsFromBlockIssues, issueToDiagnostic, toJsonPath as authoringToJsonPath, validateBlueprintForAuthoring, } from "./authoring-validation.js";
29
+ export { AVATAR_IDS, avatarFields, isAvatarId, nextAvatar, primaryAvatarField, } from "./avatar.js";
30
+ export { BrandThemeError, brandLibraryThemeId, brandThemeExportName, brandThemeId, closestIds, emitBrandThemeModule, getStyleProfile, resolveBlueprintBrand, STYLE_PROFILES, } from "./brand.js";
31
+ export { APP_CUES, ARCHETYPE_IDS, ARCHETYPES, applyOutlineBounds, blueprintFromBrief, boundBriefInput, buildDocOutline, buildPageOutline, checkOutlineBounds, chooseDeckOutline, DECK_OUTLINE_IDS, DECK_OUTLINE_LIMITS, DECK_OUTLINES, DOC_OUTLINE_IDS, deckOutlineRange, deckTitleFromBrief, detectBriefKind, detectPageDocOmissions, fieldFromPhrase, GENERIC_ARCHETYPE, isAppBriefResult, isContentBriefResult, KIND_CUES, MAX_BRIEF_LENGTH, MAX_CONTENT_BRIEF_LENGTH, OUTLINE_LIMITS, PAGE_OUTLINE_IDS, PEOPLE_ENTITIES, prepareBriefForSynthesis, requestedSlideCount, sectionIds, selectDocOutline, selectPageOutline, synthesizeAppFromBrief, synthesizeContentFromBrief, synthesizeDeckFromBrief, synthesizeDeckOutline, synthesizeDocFromBrief, synthesizePageFromBrief, } from "./brief/index.js";
32
+ export { canvasScreenIssues } from "./canvas-screen.js";
33
+ export { guardCsvFormula, needsCsvFormulaGuard, unguardCsvFormula } from "./csv-guard.js";
34
+ export { createFileServices, DEFAULT_FILE_QUOTA_BYTES, FileUploadError, } from "./files.js";
35
+ export { ENTITY_FORM_CUSTOM_KINDS, entityFormModel, HOSTED_FORM_KINDS, UNASSIGNED_OPTION, } from "./form-schema.js";
36
+ export { BLUEPRINT_GENERATOR_SDK, blueprintGeneratorVersion } from "./generator-version.js";
37
+ export { BLUEPRINT_NAMESPACE_PREFIX, blueprintIdentity, canonicalJson, } from "./identity.js";
38
+ export { blueprintKind, isAppBlueprint, isContentBlueprint, isDeckBlueprint, isDocBlueprint, isPageBlueprint, parseAnyBlueprint, safeParseAnyBlueprint, } from "./kinds/envelope.js";
39
+ export { BLUEPRINT_KINDS, CONTENT_KINDS, DEFAULT_BLUEPRINT_KIND, detectBlueprintKind, isBlueprintKind, isContentKind, unknownKindMessage, } from "./kinds/kind.js";
40
+ export { DEFAULT_UNTRUSTED_DOCUMENT_LIMITS, } from "./kinds/limits.js";
41
+ export { appendMigration, applyUpgradeOps, defaultForField, deriveDatabaseVersions, diffBlueprints, fieldProperty, latestSchemaVersion, MigrationError, toDatabaseVersion, } from "./migrations.js";
42
+ export { BLUEPRINT_MOTION_LEVELS, BlueprintMotionSchema, blueprintMotionLevel, DEFAULT_BLUEPRINT_MOTION_LEVEL, deckWithMotionCeiling, isBlueprintMotionLevel, lowerMotionLevel, } from "./motion.js";
43
+ export { createNotificationService, createNotificationWriter, } from "./notifications.js";
44
+ export { applyBlueprintPatch, applyContentPatch, applyJsonPatch, BlueprintPatchError, JSON_PATCH_MAX_NODES, JSON_PATCH_MAX_OPS, JSON_POINTER_MAX_LENGTH, JsonPatchOperationSchema, JsonPatchSchema, jsonEqual, parseJsonPointer, } from "./patch.js";
45
+ export { CAPABILITIES, derivePolicy } from "./policy.js";
46
+ export { BLUEPRINT_DEFAULT_SCENARIO, blueprintBrandTheme, brandDefaultThemeId, definePrototypeFromBlueprint, } from "./runtime-definition.js";
47
+ export { blueprintScenarios } from "./scenarios.js";
48
+ export { AGGREGATES, BLUEPRINT_SCHEMA_URL, BlueprintBrandSchema, BlueprintHistoryEntrySchema, BlueprintSchema, BUCKET_UNITS, blueprintIssues, CHART_KINDS, DashboardWidgetSchema, DateWindowSchema, DETAIL_TABS, dashboardWidgets, dateWindowDays, ENTITY_ACTIONS, EntityFeaturesSchema, EntitySchema, entityTable, FIELD_KINDS, FIELD_TRENDS, FieldSchema, PermissionActionSchema, parseBlueprint, RESERVED_FIELD_NAMES, RESERVED_SCREEN_PATHS, RoleSchema, SCREEN_NAV_ICONS, SCREEN_TYPES, ScreenBucketSchema, ScreenFilterSchema, ScreenNavSchema, ScreenSchema, SETTINGS_SECTIONS, safeParseBlueprint, screenPath, } from "./schema.js";
49
+ export { blueprintJsonSchema } from "./schema-json.js";
50
+ export { BULK_CHUNK, createEntityServices, EntityInUseError, EntityNotFoundError, ImportCsvError, UNDO_WINDOW_MS, } from "./services.js";
51
+ export { blueprintShareFragment, decodeBlueprintShare, decodeDocumentShare, encodeBlueprintShare, MAX_SHARE_DECODED_BYTES, MAX_SHARE_DOCUMENT_DECODED_BYTES, MAX_SHARE_ENCODED_LENGTH, readBlueprintShareFragment, SHARE_FRAGMENT_PARAM, SHARE_LINK_BROWSERS, SHARE_LINK_VERSION, ShareLinkTooLargeError, supportsShareLinks, } from "./share.js";
52
+ export { SHEET_COLUMN_KINDS, SHEET_EDITABLE_KINDS, SHEET_MAX_COLUMNS, SHEET_READONLY_KINDS, SHEET_TOTAL_KINDS, sheetColumns, sheetScreenIssues, } from "./sheet-screen.js";
53
+ export { deriveIntegrity, deriveStores, entityStoreString, FEATURE_STORE_STRINGS, FEATURE_TABLES, relationProperty, storeIndexForField, } from "./storage.js";
54
+ export { MAX_STREAM_CANDIDATES, paintStreamedBlueprint, truncatedJsonCandidates, } from "./stream.js";
55
+ export { DEFAULT_UNTRUSTED_BLUEPRINT_LIMITS, loadUntrustedBlueprint, loadUntrustedDocument, } from "./untrusted.js";
56
+ export { deriveInputSchemas, fieldLabel, inputProperty, parseMoneyText, } from "./validation.js";
57
+ export { CONTAINS_FIELD_KINDS, dataHolds, evaluateValidationSuccess, routeMatches, VALIDATION_DATA_OPS, VALIDATION_MAX_TASKS, ValidationDataSchema, ValidationRouteSchema, ValidationSchema, ValidationSuccessSchema, ValidationTaskSchema, validationBaseline, } from "./validation-tasks.js";
58
+ export { deriveKindVariants, deriveVariants, VARIANT_DECK_TRANSITIONS, VARIANT_DENSITIES, VARIANT_DENSITY_SCALE, VARIANT_MAX_COUNT, VARIANT_THEME_PRESETS, } from "./variants.js";
@@ -0,0 +1,18 @@
1
+ import { type Block } from '@protoyard/blocks';
2
+ import type { z } from 'zod';
3
+ export type Path = (string | number)[];
4
+ /** Every block id in a list (containers included), with its path. */
5
+ export declare function blockIds(blocks: readonly Block[], base: Path): {
6
+ id: string;
7
+ path: Path;
8
+ }[];
9
+ /** Every `#fragment` link under `value`, by path. Nothing else is read. */
10
+ export declare function fragmentLinks(value: unknown, base: Path): {
11
+ target: string;
12
+ path: Path;
13
+ }[];
14
+ /** Reports every `#fragment` link whose target is not in `targets`. */
15
+ export declare function checkFragmentLinks(links: readonly {
16
+ target: string;
17
+ path: Path;
18
+ }[], targets: ReadonlySet<string>, ctx: z.RefinementCtx, what: string): void;
@@ -0,0 +1,46 @@
1
+ import { forEachBlock } from '@protoyard/blocks';
2
+ /** Every block id in a list (containers included), with its path. */
3
+ export function blockIds(blocks, base) {
4
+ const out = [];
5
+ forEachBlock(blocks, (block, path) => {
6
+ const id = 'id' in block ? block.id : undefined;
7
+ if (typeof id === 'string')
8
+ out.push({ id, path: [...base, ...path, 'id'] });
9
+ });
10
+ return out;
11
+ }
12
+ /** Every `#fragment` link under `value`, by path. Nothing else is read. */
13
+ export function fragmentLinks(value, base) {
14
+ const out = [];
15
+ const stack = [{ value, path: base }];
16
+ while (stack.length > 0) {
17
+ const { value: node, path } = stack.pop();
18
+ if (Array.isArray(node)) {
19
+ for (const [i, item] of node.entries())
20
+ stack.push({ value: item, path: [...path, i] });
21
+ }
22
+ else if (node !== null && typeof node === 'object') {
23
+ for (const [key, child] of Object.entries(node)) {
24
+ if (key === 'href' && typeof child === 'string' && child.startsWith('#')) {
25
+ out.push({ target: child.slice(1), path: [...path, key] });
26
+ }
27
+ else {
28
+ stack.push({ value: child, path: [...path, key] });
29
+ }
30
+ }
31
+ }
32
+ }
33
+ return out.sort((a, b) => JSON.stringify(a.path).localeCompare(JSON.stringify(b.path)));
34
+ }
35
+ /** Reports every `#fragment` link whose target is not in `targets`. */
36
+ export function checkFragmentLinks(links, targets, ctx, what) {
37
+ for (const link of links) {
38
+ if (!targets.has(link.target)) {
39
+ ctx.addIssue({
40
+ code: 'custom',
41
+ path: link.path,
42
+ message: `Link "#${link.target}" does not match ${what}`,
43
+ });
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,6 @@
1
+ import type { z } from 'zod';
2
+ import type { ContentKind } from './kind.ts';
3
+ /** Load only the requested kind body, keeping all content schemas off the app path. */
4
+ export declare function kindBodySchema(kind: ContentKind): Promise<z.ZodType | undefined>;
5
+ /** @internal Used only by `kinds/testing.ts`. */
6
+ export declare function setKindBodyOverride(kind: ContentKind, schema: z.ZodType | undefined): void;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Body schemas of the content kinds, one per kind, supplied by their engine
3
+ * packages (ADR-036): the deck from `@protoyard/decks/schema`, page and doc
4
+ * from `@protoyard/pages`. A kind without a schema here fails to parse with a
5
+ * "not available in this build yet" issue: there is no loose fallback.
6
+ *
7
+ * Wiring a kind is a static entry in `SHIPPED`, never runtime registration,
8
+ * so untrusted input can never be validated against a schema someone injected.
9
+ */
10
+ /** Test-only overrides (see `kinds/testing.ts`); empty outside Vitest. */
11
+ const overrides = new Map();
12
+ /** Load only the requested kind body, keeping all content schemas off the app path. */
13
+ export async function kindBodySchema(kind) {
14
+ const override = overrides.get(kind);
15
+ if (override)
16
+ return override;
17
+ switch (kind) {
18
+ case 'deck':
19
+ return (await import("./deck.js")).DeckBodySchema;
20
+ case 'page':
21
+ return (await import("./page.js")).PageBodySchema;
22
+ case 'doc':
23
+ return (await import("./doc.js")).DocBodySchema;
24
+ }
25
+ }
26
+ /** @internal Used only by `kinds/testing.ts`. */
27
+ export function setKindBodyOverride(kind, schema) {
28
+ if (schema)
29
+ overrides.set(kind, schema);
30
+ else
31
+ overrides.delete(kind);
32
+ }
@@ -0,0 +1,19 @@
1
+ import type { PrototypeDefinition, Theme } from '@protoyard/core';
2
+ import { type AnyContentBlueprint, type KindRuntimeOptions } from './runtime.ts';
3
+ /**
4
+ * Brand resolution for content kinds, kept apart from `runtime.ts`: a seed
5
+ * brand needs the palette generator (`createThemeFromSeed`), so only callers
6
+ * that resolve a brand at run time (the player, `definePrototypeFromPage`)
7
+ * load it. Generated kind prototypes get the resolved theme from
8
+ * `protoyard generate` and call `defineKindPrototype` directly.
9
+ */
10
+ /** The theme id a content blueprint opens in: its library theme, its built brand theme, or null. */
11
+ export declare function kindDefaultThemeId(doc: AnyContentBlueprint): string | null;
12
+ /** The built brand theme a content blueprint registers, or null (no brand, or a library brand). */
13
+ export declare function kindBrandTheme(doc: AnyContentBlueprint): Theme | null;
14
+ /**
15
+ * Builds a `definePrototype`-valid definition for a deck, page or doc. Throws
16
+ * `BrandThemeError` for an unknown library theme or a brand that fails AA,
17
+ * like the app path.
18
+ */
19
+ export declare function defineKindRuntime(doc: AnyContentBlueprint, options: KindRuntimeOptions): PrototypeDefinition;
@@ -0,0 +1,35 @@
1
+ import { brandLibraryThemeId, resolveBlueprintBrand } from "../brand.js";
2
+ import { defineKindPrototype, } from "./runtime.js";
3
+ /**
4
+ * Brand resolution for content kinds, kept apart from `runtime.ts`: a seed
5
+ * brand needs the palette generator (`createThemeFromSeed`), so only callers
6
+ * that resolve a brand at run time (the player, `definePrototypeFromPage`)
7
+ * load it. Generated kind prototypes get the resolved theme from
8
+ * `protoyard generate` and call `defineKindPrototype` directly.
9
+ */
10
+ /** The theme id a content blueprint opens in: its library theme, its built brand theme, or null. */
11
+ export function kindDefaultThemeId(doc) {
12
+ if (!doc.brand)
13
+ return null;
14
+ return (brandLibraryThemeId(doc.brand) ??
15
+ resolveBlueprintBrand(doc.brand, { blueprintName: doc.name }).id);
16
+ }
17
+ /** The built brand theme a content blueprint registers, or null (no brand, or a library brand). */
18
+ export function kindBrandTheme(doc) {
19
+ if (!doc.brand || brandLibraryThemeId(doc.brand))
20
+ return null;
21
+ return resolveBlueprintBrand(doc.brand, { blueprintName: doc.name });
22
+ }
23
+ /**
24
+ * Builds a `definePrototype`-valid definition for a deck, page or doc. Throws
25
+ * `BrandThemeError` for an unknown library theme or a brand that fails AA,
26
+ * like the app path.
27
+ */
28
+ export function defineKindRuntime(doc, options) {
29
+ const brandTheme = kindBrandTheme(doc);
30
+ return defineKindPrototype(doc, {
31
+ ...options,
32
+ brandTheme,
33
+ defaultThemeId: brandTheme?.id ?? kindDefaultThemeId(doc),
34
+ });
35
+ }
@@ -0,0 +1,8 @@
1
+ import { type Deck } from '@protoyard/decks/schema';
2
+ import type { z } from 'zod';
3
+ /**
4
+ * Deck-wide slide and outline references are enforced by the engine schema. The explicit type keeps
5
+ * the published declarations portable (no inferred reference into another package's zod copy).
6
+ */
7
+ export declare const DeckBodySchema: z.ZodType<Deck>;
8
+ export type DeckBody = Deck;
@@ -0,0 +1,34 @@
1
+ import { DeckSchema } from '@protoyard/decks/schema';
2
+ import { safeParseBlueprint } from "../schema.js";
3
+ import { checkContentLimits, containsEmbeddedApp, DEFAULT_UNTRUSTED_DOCUMENT_LIMITS, } from "./limits.js";
4
+ /**
5
+ * Deck-wide slide and outline references are enforced by the engine schema. The explicit type keeps
6
+ * the published declarations portable (no inferred reference into another package's zod copy).
7
+ */
8
+ export const DeckBodySchema = DeckSchema.superRefine((deck, ctx) => {
9
+ const checked = checkContentLimits({ deck }, 'deck', DEFAULT_UNTRUSTED_DOCUMENT_LIMITS);
10
+ if (checked.issue)
11
+ return;
12
+ for (const embedded of checked.embeddedApps) {
13
+ // `DeckBodySchema` is already mounted under the root `deck` property.
14
+ const bodyPath = embedded.path.slice(1);
15
+ if (containsEmbeddedApp(embedded.app)) {
16
+ ctx.addIssue({
17
+ code: 'custom',
18
+ path: bodyPath,
19
+ message: 'An embedded app cannot embed another app (one level only).',
20
+ });
21
+ continue;
22
+ }
23
+ const parsed = safeParseBlueprint(embedded.app);
24
+ if (!parsed.success) {
25
+ for (const issue of parsed.error.issues) {
26
+ ctx.addIssue({
27
+ code: 'custom',
28
+ path: [...bodyPath, ...issue.path],
29
+ message: `Embedded app is invalid: ${issue.message}`,
30
+ });
31
+ }
32
+ }
33
+ }
34
+ });
@@ -0,0 +1,19 @@
1
+ import { type DocDocument } from '@protoyard/pages';
2
+ import type { z } from 'zod';
3
+ /** The table of contents covers heading levels 2 to this one when `toc.depth` is unset. */
4
+ export declare const DOC_DEFAULT_TOC_DEPTH = 3;
5
+ /** The level a heading without `level` counts as in a doc's table of contents. */
6
+ export declare const DOC_DEFAULT_HEADING_LEVEL = 2;
7
+ /**
8
+ * The `kind: "doc"` body (ADR-036, ADR-039): `@protoyard/pages`'
9
+ * `DocDocumentSchema` (a block flow with unique block ids, plus TOC and print
10
+ * options) plus the checks that span the whole document:
11
+ *
12
+ * - a requested table of contents has at least one heading it would list
13
+ * (level 2 up to `toc.depth`, 3 by default), so it is never an empty box;
14
+ * - every `#fragment` link in a block (`cta`, `cards`) points at a block id,
15
+ * usually a heading's, in this document.
16
+ *
17
+ * Heading ids are block ids, so their uniqueness comes from the block list.
18
+ */
19
+ export declare const DocBodySchema: z.ZodType<DocDocument>;
@@ -0,0 +1,41 @@
1
+ import { forEachBlock } from '@protoyard/blocks';
2
+ import { DocDocumentSchema } from '@protoyard/pages';
3
+ import { blockIds, checkFragmentLinks, fragmentLinks } from "./anchors.js";
4
+ /** The table of contents covers heading levels 2 to this one when `toc.depth` is unset. */
5
+ export const DOC_DEFAULT_TOC_DEPTH = 3;
6
+ /** The level a heading without `level` counts as in a doc's table of contents. */
7
+ export const DOC_DEFAULT_HEADING_LEVEL = 2;
8
+ /**
9
+ * The `kind: "doc"` body (ADR-036, ADR-039): `@protoyard/pages`'
10
+ * `DocDocumentSchema` (a block flow with unique block ids, plus TOC and print
11
+ * options) plus the checks that span the whole document:
12
+ *
13
+ * - a requested table of contents has at least one heading it would list
14
+ * (level 2 up to `toc.depth`, 3 by default), so it is never an empty box;
15
+ * - every `#fragment` link in a block (`cta`, `cards`) points at a block id,
16
+ * usually a heading's, in this document.
17
+ *
18
+ * Heading ids are block ids, so their uniqueness comes from the block list.
19
+ */
20
+ export const DocBodySchema = DocDocumentSchema.superRefine((doc, ctx) => {
21
+ if (doc.toc) {
22
+ const depth = doc.toc.depth ?? DOC_DEFAULT_TOC_DEPTH;
23
+ let listed = 0;
24
+ forEachBlock(doc.blocks, (block) => {
25
+ if (block.type !== 'heading')
26
+ return;
27
+ const level = block.level ?? DOC_DEFAULT_HEADING_LEVEL;
28
+ if (level >= 2 && level <= depth)
29
+ listed += 1;
30
+ });
31
+ if (listed === 0) {
32
+ ctx.addIssue({
33
+ code: 'custom',
34
+ path: ['toc'],
35
+ message: `The table of contents lists headings of level 2 to ${depth}, and this document has none`,
36
+ });
37
+ }
38
+ }
39
+ const targets = new Set(blockIds(doc.blocks, ['blocks']).map((entry) => entry.id));
40
+ checkFragmentLinks(fragmentLinks(doc.blocks, ['blocks']), targets, ctx, 'a block id in this document');
41
+ });
@@ -0,0 +1,39 @@
1
+ import { type UntrustedBlueprintResult } from '../../untrusted.ts';
2
+ /** Same-origin protocol used by generated level-two hosts and their app frame. */
3
+ export declare const EMBEDDED_APP_PROTOCOL = "protoyard-embedded-app/1";
4
+ export interface EmbeddedAppReady {
5
+ protocol: typeof EMBEDDED_APP_PROTOCOL;
6
+ type: 'ready';
7
+ }
8
+ export interface EmbeddedAppStart {
9
+ protocol: typeof EMBEDDED_APP_PROTOCOL;
10
+ type: 'start';
11
+ requestId: string;
12
+ hostNamespace: string;
13
+ blockId: string;
14
+ app: unknown;
15
+ }
16
+ export interface EmbeddedAppLoaded {
17
+ protocol: typeof EMBEDDED_APP_PROTOCOL;
18
+ type: 'loaded';
19
+ requestId: string;
20
+ namespace: string;
21
+ name: string;
22
+ }
23
+ export interface EmbeddedAppFailure {
24
+ protocol: typeof EMBEDDED_APP_PROTOCOL;
25
+ type: 'error';
26
+ requestId: string;
27
+ message: string;
28
+ }
29
+ export type EmbeddedAppMessage = EmbeddedAppReady | EmbeddedAppStart | EmbeddedAppLoaded | EmbeddedAppFailure;
30
+ /** The app-only untrusted loader; nested content kinds and malformed apps fail closed. */
31
+ export declare function loadEmbeddedApp(input: unknown): UntrustedBlueprintResult;
32
+ /** Checks the exact data shapes exchanged between the same-origin host and app frame. */
33
+ export declare function isEmbeddedAppMessage(value: unknown): value is EmbeddedAppMessage;
34
+ /**
35
+ * Stable isolated storage namespace for one embedded block in one host.
36
+ * SHA-256 avoids collisions between block ids while keeping the manifest's
37
+ * lowercase kebab-case namespace contract (48 characters total).
38
+ */
39
+ export declare function embeddedAppNamespace(hostNamespace: string, blockId: string): Promise<string>;
@@ -0,0 +1,91 @@
1
+ import { NamespaceSchema } from '@protoyard/core';
2
+ import { loadUntrustedBlueprint } from "../../untrusted.js";
3
+ import { containsEmbeddedApp } from "../limits.js";
4
+ /** Same-origin protocol used by generated level-two hosts and their app frame. */
5
+ export const EMBEDDED_APP_PROTOCOL = 'protoyard-embedded-app/1';
6
+ /** The app-only untrusted loader; nested content kinds and malformed apps fail closed. */
7
+ export function loadEmbeddedApp(input) {
8
+ const loaded = loadUntrustedBlueprint(input);
9
+ if (!loaded.success)
10
+ return loaded;
11
+ if (containsEmbeddedApp(loaded.blueprint)) {
12
+ return {
13
+ success: false,
14
+ blueprint: null,
15
+ issues: [
16
+ {
17
+ code: 'too-deep',
18
+ path: [],
19
+ message: 'An embedded app cannot embed another app (one level only).',
20
+ fix: 'Remove the nested embed-app block.',
21
+ },
22
+ ],
23
+ };
24
+ }
25
+ return loaded;
26
+ }
27
+ function isPlainRecord(value) {
28
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
29
+ return false;
30
+ const prototype = Object.getPrototypeOf(value);
31
+ return prototype === Object.prototype || prototype === null;
32
+ }
33
+ function hasOnlyKeys(value, allowed) {
34
+ return Object.keys(value).every((key) => allowed.includes(key));
35
+ }
36
+ const REQUEST_ID = /^embed-[1-9][0-9]{0,7}$/;
37
+ /** Checks the exact data shapes exchanged between the same-origin host and app frame. */
38
+ export function isEmbeddedAppMessage(value) {
39
+ if (!isPlainRecord(value) || value.protocol !== EMBEDDED_APP_PROTOCOL)
40
+ return false;
41
+ if (value.type === 'ready') {
42
+ return hasOnlyKeys(value, ['protocol', 'type']);
43
+ }
44
+ if (value.type === 'start') {
45
+ return (hasOnlyKeys(value, ['protocol', 'type', 'requestId', 'hostNamespace', 'blockId', 'app']) &&
46
+ typeof value.requestId === 'string' &&
47
+ REQUEST_ID.test(value.requestId) &&
48
+ typeof value.hostNamespace === 'string' &&
49
+ NamespaceSchema.safeParse(value.hostNamespace).success &&
50
+ typeof value.blockId === 'string' &&
51
+ value.blockId.length > 0 &&
52
+ value.blockId.length <= 120 &&
53
+ isPlainRecord(value.app));
54
+ }
55
+ if (value.type === 'loaded') {
56
+ return (hasOnlyKeys(value, ['protocol', 'type', 'requestId', 'namespace', 'name']) &&
57
+ typeof value.requestId === 'string' &&
58
+ REQUEST_ID.test(value.requestId) &&
59
+ typeof value.namespace === 'string' &&
60
+ NamespaceSchema.safeParse(value.namespace).success &&
61
+ typeof value.name === 'string');
62
+ }
63
+ if (value.type === 'error') {
64
+ return (hasOnlyKeys(value, ['protocol', 'type', 'requestId', 'message']) &&
65
+ typeof value.requestId === 'string' &&
66
+ REQUEST_ID.test(value.requestId) &&
67
+ typeof value.message === 'string' &&
68
+ value.message.length <= 500);
69
+ }
70
+ return false;
71
+ }
72
+ /**
73
+ * Stable isolated storage namespace for one embedded block in one host.
74
+ * SHA-256 avoids collisions between block ids while keeping the manifest's
75
+ * lowercase kebab-case namespace contract (48 characters total).
76
+ */
77
+ export async function embeddedAppNamespace(hostNamespace, blockId) {
78
+ const host = NamespaceSchema.parse(hostNamespace);
79
+ if (blockId.length === 0 || blockId.length > 120) {
80
+ throw new Error('An embedded app needs a stable block id of at most 120 characters.');
81
+ }
82
+ const subtle = globalThis.crypto?.subtle;
83
+ if (!subtle)
84
+ throw new Error('This browser cannot create an isolated embedded-app namespace.');
85
+ const input = new TextEncoder().encode(`protoyard.embed.v1\0${host}\0${blockId}`);
86
+ const digest = new Uint8Array(await subtle.digest('SHA-256', input));
87
+ const suffix = [...digest.slice(0, 21)]
88
+ .map((byte) => byte.toString(16).padStart(2, '0'))
89
+ .join('');
90
+ return `embed-${suffix}`;
91
+ }