@webiny/website-builder-sdk 0.0.0-unstable.a4f3e4ea8b → 0.0.0-unstable.a85ef555b2

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 (117) hide show
  1. package/ComponentInputTraverser.js +4 -0
  2. package/ComponentInputTraverser.js.map +1 -1
  3. package/ComponentResolver.d.ts +3 -1
  4. package/ComponentResolver.js +4 -2
  5. package/ComponentResolver.js.map +1 -1
  6. package/ContentSdk.d.ts +64 -1
  7. package/ContentSdk.js +80 -8
  8. package/ContentSdk.js.map +1 -1
  9. package/DocumentStoreManager.d.ts +9 -2
  10. package/DocumentStoreManager.js +24 -5
  11. package/DocumentStoreManager.js.map +1 -1
  12. package/EditingSdk.d.ts +7 -1
  13. package/EditingSdk.js +5 -3
  14. package/EditingSdk.js.map +1 -1
  15. package/ElementFactory.js +3 -1
  16. package/ElementFactory.js.map +1 -1
  17. package/ElementFactory.test.js +102 -0
  18. package/ElementFactory.test.js.map +1 -1
  19. package/LiveSdk.d.ts +3 -1
  20. package/LiveSdk.js +3 -2
  21. package/LiveSdk.js.map +1 -1
  22. package/PreviewDocument.d.ts +2 -1
  23. package/PreviewDocument.js +2 -2
  24. package/PreviewDocument.js.map +1 -1
  25. package/PreviewSdk.d.ts +3 -1
  26. package/PreviewSdk.js +3 -2
  27. package/PreviewSdk.js.map +1 -1
  28. package/ResizeObserver.js +1 -1
  29. package/ResizeObserver.js.map +1 -1
  30. package/asset/deliveryUrl.test.js +1 -1
  31. package/asset/deliveryUrl.test.js.map +1 -1
  32. package/asset/imageSrcSet.test.js +1 -1
  33. package/asset/imageSrcSet.test.js.map +1 -1
  34. package/asset/normalize.d.ts +1 -1
  35. package/asset/normalize.js +18 -14
  36. package/asset/normalize.js.map +1 -1
  37. package/asset/normalize.test.js +15 -8
  38. package/asset/normalize.test.js.map +1 -1
  39. package/componentLoader/ComponentLoader.d.ts +16 -0
  40. package/componentLoader/ComponentLoader.js +0 -0
  41. package/componentLoader/RegistryOnlyComponentLoader.d.ts +9 -0
  42. package/componentLoader/RegistryOnlyComponentLoader.js +8 -0
  43. package/componentLoader/RegistryOnlyComponentLoader.js.map +1 -0
  44. package/componentLoader/createComponentLoader.d.ts +7 -0
  45. package/componentLoader/createComponentLoader.js +10 -0
  46. package/componentLoader/createComponentLoader.js.map +1 -0
  47. package/componentLoader/defaultComponentLoader.d.ts +7 -0
  48. package/componentLoader/defaultComponentLoader.js +8 -0
  49. package/componentLoader/defaultComponentLoader.js.map +1 -0
  50. package/componentLoader/index.d.ts +3 -0
  51. package/componentLoader/index.js +3 -0
  52. package/contentClientState.test.d.ts +1 -0
  53. package/contentClientState.test.js +384 -0
  54. package/contentClientState.test.js.map +1 -0
  55. package/contentEntry/ContentEntryBindingsResolver.d.ts +8 -5
  56. package/contentEntry/ContentEntryBindingsResolver.js +30 -23
  57. package/contentEntry/ContentEntryBindingsResolver.js.map +1 -1
  58. package/contentEntry/ContentEntryCache.d.ts +7 -4
  59. package/contentEntry/ContentEntryCache.js +10 -9
  60. package/contentEntry/ContentEntryCache.js.map +1 -1
  61. package/createContentClient.d.ts +17 -0
  62. package/createContentClient.js +16 -0
  63. package/createContentClient.js.map +1 -0
  64. package/createContentClient.test.d.ts +1 -0
  65. package/createContentClient.test.js +165 -0
  66. package/createContentClient.test.js.map +1 -0
  67. package/dataProviders/ApiClient.js.map +1 -1
  68. package/dataProviders/DefaultDataProvider.d.ts +4 -0
  69. package/dataProviders/DefaultDataProvider.js +35 -0
  70. package/dataProviders/DefaultDataProvider.js.map +1 -1
  71. package/dataProviders/GET_EXPERIMENT_PAUSED.d.ts +1 -0
  72. package/dataProviders/GET_EXPERIMENT_PAUSED.js +17 -0
  73. package/dataProviders/GET_EXPERIMENT_PAUSED.js.map +1 -0
  74. package/dataProviders/GET_PAGE_BY_ID.d.ts +1 -1
  75. package/dataProviders/GET_PAGE_BY_ID.js +2 -0
  76. package/dataProviders/GET_PAGE_BY_ID.js.map +1 -1
  77. package/dataProviders/GET_PAGE_BY_PATH.d.ts +1 -1
  78. package/dataProviders/GET_PAGE_BY_PATH.js +2 -0
  79. package/dataProviders/GET_PAGE_BY_PATH.js.map +1 -1
  80. package/dataProviders/GET_PAGE_EXPERIMENT.d.ts +1 -0
  81. package/dataProviders/GET_PAGE_EXPERIMENT.js +32 -0
  82. package/dataProviders/GET_PAGE_EXPERIMENT.js.map +1 -0
  83. package/dataProviders/GET_VARIANT_CONTENT.d.ts +1 -0
  84. package/dataProviders/GET_VARIANT_CONTENT.js +24 -0
  85. package/dataProviders/GET_VARIANT_CONTENT.js.map +1 -0
  86. package/dataProviders/NullDataProvider.d.ts +4 -0
  87. package/dataProviders/NullDataProvider.js +9 -0
  88. package/dataProviders/NullDataProvider.js.map +1 -1
  89. package/dataProviders/queries.test.d.ts +1 -0
  90. package/dataProviders/queries.test.js +45 -0
  91. package/dataProviders/queries.test.js.map +1 -0
  92. package/experiments/PostHogAnalyticsProvider.d.ts +31 -0
  93. package/experiments/PostHogAnalyticsProvider.js +28 -0
  94. package/experiments/PostHogAnalyticsProvider.js.map +1 -0
  95. package/experiments/analyticsProvider.d.ts +4 -0
  96. package/experiments/analyticsProvider.js +11 -0
  97. package/experiments/analyticsProvider.js.map +1 -0
  98. package/experiments/bucketing.d.ts +27 -0
  99. package/experiments/bucketing.js +91 -0
  100. package/experiments/bucketing.js.map +1 -0
  101. package/experiments/bucketing.test.d.ts +1 -0
  102. package/experiments/bucketing.test.js +183 -0
  103. package/experiments/bucketing.test.js.map +1 -0
  104. package/experiments/index.d.ts +5 -0
  105. package/experiments/index.js +5 -0
  106. package/experiments/render.d.ts +82 -0
  107. package/experiments/render.js +149 -0
  108. package/experiments/render.js.map +1 -0
  109. package/experiments/types.d.ts +108 -0
  110. package/experiments/types.js +4 -0
  111. package/experiments/types.js.map +1 -0
  112. package/headersProvider.d.ts +1 -2
  113. package/headersProvider.js.map +1 -1
  114. package/index.d.ts +5 -0
  115. package/index.js +5 -0
  116. package/package.json +6 -6
  117. package/types.d.ts +5 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ElementFactory.js","sources":["../src/ElementFactory.ts"],"sourcesContent":["import { generateElementId } from \"./generateElementId.js\";\nimport type {\n DocumentElement,\n ComponentManifest,\n InputValueBinding,\n StyleValueBinding,\n CssProperties\n} from \"~/types.js\";\nimport { type IDocumentOperation, DocumentOperations } from \"./documentOperations/index.js\";\nimport {\n ComponentManifestToAstConverter,\n type InputAstNode\n} from \"./ComponentManifestToAstConverter.js\";\nimport { ComponentInputTraverser } from \"./ComponentInputTraverser.js\";\n\nconst defaultStyles = {\n display: \"flex\",\n flexDirection: \"column\"\n};\n\nconst withDefaultStyles = (styles: CssProperties) => {\n return { ...defaultStyles, ...styles };\n};\n\nexport interface ElementFactoryCreateElementParams {\n componentName: string;\n parentId: string;\n slot: string;\n index?: number;\n bindings?: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n overrides?: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsParams {\n element: DocumentElement;\n inputsAst: InputAstNode[];\n operations: ElementFactoryOperations;\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n overrides: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsFromBindingsParams {\n elementId: string;\n inputsAst: InputAstNode[];\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n };\n operations: ElementFactoryOperations;\n ignoreDefaultValues: boolean;\n}\n\ntype ElementFactoryOperations = {\n addElement: (element: DocumentElement) => IDocumentOperation;\n addToParent: (element: DocumentElement, index?: number) => IDocumentOperation;\n setInputBinding: (\n elementId: string,\n bindingPath: string,\n binding: InputValueBinding\n ) => IDocumentOperation;\n setStyleBinding: (\n elementId: string,\n bindingPath: string,\n binding: StyleValueBinding\n ) => IDocumentOperation;\n};\n\nconst defaultOperations: ElementFactoryOperations = {\n addElement: (element: DocumentElement) => {\n return new DocumentOperations.AddElement(element);\n },\n addToParent: (element: DocumentElement, index?: number) => {\n return new DocumentOperations.AddToParent(element, index);\n },\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalInputBinding(elementId, bindingPath, binding);\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalStyleBinding(elementId, bindingPath, binding);\n }\n};\n\nexport class ElementFactory {\n constructor(private components: Record<string, ComponentManifest>) {}\n\n public createElementFromComponent({\n componentName,\n parentId,\n slot,\n index,\n bindings\n }: ElementFactoryCreateElementParams) {\n const { element, componentManifest, inputsAst } = this.createElement(\n componentName,\n parentId,\n slot\n );\n\n const documentOps: IDocumentOperation[] = [\n defaultOperations.addElement(element),\n defaultOperations.addToParent(element, index)\n ];\n\n documentOps.push(\n ...this.generateOperations({\n element,\n inputsAst,\n bindings: {\n inputs: bindings?.inputs ?? componentManifest.defaults?.inputs ?? {},\n styles: withDefaultStyles(\n bindings?.styles ?? componentManifest.defaults?.styles ?? {}\n ),\n overrides: bindings?.overrides ?? {}\n },\n operations: defaultOperations\n })\n );\n\n return { element, operations: documentOps };\n }\n\n public generateOperations({\n element,\n inputsAst,\n bindings,\n operations\n }: GenerateOperationsParams): IDocumentOperation[] {\n const ops = this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues: false\n });\n\n if (bindings.overrides) {\n for (const [breakpoint, overrides] of Object.entries(bindings.overrides)) {\n ops.push(\n ...this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings: {\n inputs: overrides.inputs ?? {},\n styles: overrides.styles ?? {}\n },\n operations: {\n ...operations,\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetInputBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetStyleBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n }\n },\n ignoreDefaultValues: true\n })\n );\n }\n }\n\n return ops;\n }\n\n private generateOperationsFromBindings({\n elementId,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues\n }: GenerateOperationsFromBindingsParams): IDocumentOperation[] {\n const inputData = bindings.inputs;\n const traverser = new ComponentInputTraverser(inputsAst);\n\n const ops: IDocumentOperation[] = [];\n\n traverser.traverse(inputData, (node, path, value) => {\n const isCreateElement = value?.action === \"CreateElement\";\n const isList = node.list;\n const isObject = node.type === \"object\";\n\n if (isCreateElement) {\n const factory = new ElementFactory(this.components);\n const newElement = factory.createElementFromComponent({\n componentName: value.params.component,\n // undefined index = append to end of the slot array\n index: isList ? undefined : 0,\n slot: path,\n parentId: elementId,\n bindings: value.params\n });\n\n const newElementId = newElement.element.id;\n\n ops.push(...newElement.operations);\n\n if (isList) {\n // For list slots, AddToParent already manages the static array.\n // We only set metadata here.\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: newElementId,\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n }\n } else if (isObject && isList) {\n return;\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: ignoreDefaultValues\n ? undefined\n : (value ?? node.input.defaultValue),\n type: node.type,\n list: node.list,\n translatable: node.input.translatable\n })\n );\n }\n });\n\n // Process styles\n for (const key in bindings.styles) {\n ops.push(\n operations.setStyleBinding(elementId, key, {\n static: bindings.styles[key]\n })\n );\n }\n\n return ops;\n }\n\n private getComponentManifest(componentName: string): ComponentManifest {\n const manifest = this.components[componentName];\n if (!manifest) {\n const registered = Object.keys(this.components).join(\", \");\n throw new Error(\n `Component \"${componentName}\" not registered. Registered components: ${registered}`\n );\n }\n\n return manifest;\n }\n\n private createElement(componentName: string, parentId: string, slot: string) {\n const element: DocumentElement = {\n type: \"Webiny/Element\",\n id: generateElementId(),\n parent: { id: parentId, slot },\n component: { name: componentName }\n };\n\n const componentManifest = this.getComponentManifest(componentName);\n const inputsAst = ComponentManifestToAstConverter.convert(componentManifest.inputs ?? []);\n\n return {\n element,\n inputsAst,\n componentManifest\n };\n }\n}\n"],"names":["defaultStyles","withDefaultStyles","styles","defaultOperations","element","DocumentOperations","index","elementId","bindingPath","binding","ElementFactory","components","componentName","parentId","slot","bindings","componentManifest","inputsAst","documentOps","operations","ops","breakpoint","overrides","Object","ignoreDefaultValues","inputData","traverser","ComponentInputTraverser","node","path","value","isCreateElement","isList","isObject","factory","newElement","undefined","newElementId","generateElementId","key","manifest","registered","Error","ComponentManifestToAstConverter"],"mappings":"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"}
1
+ {"version":3,"file":"ElementFactory.js","sources":["../src/ElementFactory.ts"],"sourcesContent":["import { generateElementId } from \"./generateElementId.js\";\nimport type {\n DocumentElement,\n ComponentManifest,\n InputValueBinding,\n StyleValueBinding,\n CssProperties\n} from \"~/types.js\";\nimport { type IDocumentOperation, DocumentOperations } from \"./documentOperations/index.js\";\nimport {\n ComponentManifestToAstConverter,\n type InputAstNode\n} from \"./ComponentManifestToAstConverter.js\";\nimport { ComponentInputTraverser } from \"./ComponentInputTraverser.js\";\n\nconst defaultStyles = {\n display: \"flex\",\n flexDirection: \"column\"\n};\n\nconst withDefaultStyles = (styles: CssProperties) => {\n return { ...defaultStyles, ...styles };\n};\n\nexport interface ElementFactoryCreateElementParams {\n componentName: string;\n parentId: string;\n slot: string;\n index?: number;\n bindings?: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n overrides?: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsParams {\n element: DocumentElement;\n inputsAst: InputAstNode[];\n operations: ElementFactoryOperations;\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n overrides: {\n [breakpoint: string]: {\n inputs?: Record<string, any>;\n styles?: Record<string, any>;\n };\n };\n };\n}\n\ninterface GenerateOperationsFromBindingsParams {\n elementId: string;\n inputsAst: InputAstNode[];\n bindings: {\n inputs: Record<string, any>;\n styles: Record<string, any>;\n };\n operations: ElementFactoryOperations;\n ignoreDefaultValues: boolean;\n}\n\ntype ElementFactoryOperations = {\n addElement: (element: DocumentElement) => IDocumentOperation;\n addToParent: (element: DocumentElement, index?: number) => IDocumentOperation;\n setInputBinding: (\n elementId: string,\n bindingPath: string,\n binding: InputValueBinding\n ) => IDocumentOperation;\n setStyleBinding: (\n elementId: string,\n bindingPath: string,\n binding: StyleValueBinding\n ) => IDocumentOperation;\n};\n\nconst defaultOperations: ElementFactoryOperations = {\n addElement: (element: DocumentElement) => {\n return new DocumentOperations.AddElement(element);\n },\n addToParent: (element: DocumentElement, index?: number) => {\n return new DocumentOperations.AddToParent(element, index);\n },\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalInputBinding(elementId, bindingPath, binding);\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetGlobalStyleBinding(elementId, bindingPath, binding);\n }\n};\n\nexport class ElementFactory {\n constructor(private components: Record<string, ComponentManifest>) {}\n\n public createElementFromComponent({\n componentName,\n parentId,\n slot,\n index,\n bindings\n }: ElementFactoryCreateElementParams) {\n const { element, componentManifest, inputsAst } = this.createElement(\n componentName,\n parentId,\n slot\n );\n\n const documentOps: IDocumentOperation[] = [\n defaultOperations.addElement(element),\n defaultOperations.addToParent(element, index)\n ];\n\n const baseStyles = bindings?.styles ?? componentManifest.defaults?.styles ?? {};\n const resolvedStyles =\n componentManifest.applyDefaultStyles === false\n ? baseStyles\n : withDefaultStyles(baseStyles);\n\n documentOps.push(\n ...this.generateOperations({\n element,\n inputsAst,\n bindings: {\n inputs: bindings?.inputs ?? componentManifest.defaults?.inputs ?? {},\n styles: resolvedStyles,\n overrides: bindings?.overrides ?? {}\n },\n operations: defaultOperations\n })\n );\n\n return { element, operations: documentOps };\n }\n\n public generateOperations({\n element,\n inputsAst,\n bindings,\n operations\n }: GenerateOperationsParams): IDocumentOperation[] {\n const ops = this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues: false\n });\n\n if (bindings.overrides) {\n for (const [breakpoint, overrides] of Object.entries(bindings.overrides)) {\n ops.push(\n ...this.generateOperationsFromBindings({\n elementId: element.id,\n inputsAst,\n bindings: {\n inputs: overrides.inputs ?? {},\n styles: overrides.styles ?? {}\n },\n operations: {\n ...operations,\n setInputBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetInputBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n },\n setStyleBinding: (elementId, bindingPath, binding) => {\n return new DocumentOperations.SetStyleBindingOverride(\n elementId,\n bindingPath,\n binding,\n breakpoint\n );\n }\n },\n ignoreDefaultValues: true\n })\n );\n }\n }\n\n return ops;\n }\n\n private generateOperationsFromBindings({\n elementId,\n inputsAst,\n bindings,\n operations,\n ignoreDefaultValues\n }: GenerateOperationsFromBindingsParams): IDocumentOperation[] {\n const inputData = bindings.inputs;\n const traverser = new ComponentInputTraverser(inputsAst);\n\n const ops: IDocumentOperation[] = [];\n\n traverser.traverse(inputData, (node, path, value) => {\n const isCreateElement = value?.action === \"CreateElement\";\n const isList = node.list;\n const isObject = node.type === \"object\";\n\n if (isCreateElement) {\n const factory = new ElementFactory(this.components);\n const newElement = factory.createElementFromComponent({\n componentName: value.params.component,\n // undefined index = append to end of the slot array\n index: isList ? undefined : 0,\n slot: path,\n parentId: elementId,\n bindings: value.params\n });\n\n const newElementId = newElement.element.id;\n\n ops.push(...newElement.operations);\n\n if (isList) {\n // For list slots, AddToParent already manages the static array.\n // We only set metadata here.\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: newElementId,\n type: node.type,\n translatable: node.input.translatable,\n list: node.list\n })\n );\n }\n } else if (isObject && isList) {\n return;\n } else {\n ops.push(\n operations.setInputBinding(elementId, path, {\n id: generateElementId(),\n static: ignoreDefaultValues\n ? undefined\n : (value ?? node.input.defaultValue),\n type: node.type,\n list: node.list,\n translatable: node.input.translatable\n })\n );\n }\n });\n\n // Process styles\n for (const key in bindings.styles) {\n ops.push(\n operations.setStyleBinding(elementId, key, {\n static: bindings.styles[key]\n })\n );\n }\n\n return ops;\n }\n\n private getComponentManifest(componentName: string): ComponentManifest {\n const manifest = this.components[componentName];\n if (!manifest) {\n const registered = Object.keys(this.components).join(\", \");\n throw new Error(\n `Component \"${componentName}\" not registered. Registered components: ${registered}`\n );\n }\n\n return manifest;\n }\n\n private createElement(componentName: string, parentId: string, slot: string) {\n const element: DocumentElement = {\n type: \"Webiny/Element\",\n id: generateElementId(),\n parent: { id: parentId, slot },\n component: { name: componentName }\n };\n\n const componentManifest = this.getComponentManifest(componentName);\n const inputsAst = ComponentManifestToAstConverter.convert(componentManifest.inputs ?? []);\n\n return {\n element,\n inputsAst,\n componentManifest\n };\n }\n}\n"],"names":["defaultStyles","withDefaultStyles","styles","defaultOperations","element","DocumentOperations","index","elementId","bindingPath","binding","ElementFactory","components","componentName","parentId","slot","bindings","componentManifest","inputsAst","documentOps","baseStyles","resolvedStyles","operations","ops","breakpoint","overrides","Object","ignoreDefaultValues","inputData","traverser","ComponentInputTraverser","node","path","value","isCreateElement","isList","isObject","factory","newElement","undefined","newElementId","generateElementId","key","manifest","registered","Error","ComponentManifestToAstConverter"],"mappings":"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"}
@@ -246,6 +246,108 @@ describe("ElementFactory", ()=>{
246
246
  step2.id
247
247
  ]);
248
248
  });
249
+ it("should keep every item of a primitive list (tags) from the component defaults", ()=>{
250
+ const pricing = {
251
+ name: "Custom/PricingPlans",
252
+ label: "Pricing Plans",
253
+ tags: [],
254
+ inputs: [
255
+ {
256
+ type: "text",
257
+ list: true,
258
+ renderer: "Webiny/Tags",
259
+ name: "highlights",
260
+ defaultValue: [
261
+ "Default"
262
+ ]
263
+ },
264
+ {
265
+ type: "object",
266
+ list: true,
267
+ renderer: "Webiny/Object",
268
+ name: "plans",
269
+ fields: [
270
+ {
271
+ type: "text",
272
+ renderer: "Webiny/Input",
273
+ name: "name"
274
+ },
275
+ {
276
+ type: "text",
277
+ list: true,
278
+ renderer: "Webiny/Tags",
279
+ name: "features",
280
+ defaultValue: [
281
+ "Feature one",
282
+ "Feature two"
283
+ ]
284
+ }
285
+ ]
286
+ }
287
+ ],
288
+ defaults: {
289
+ inputs: {
290
+ highlights: [
291
+ "Fast",
292
+ "Cheap"
293
+ ],
294
+ plans: [
295
+ {
296
+ name: "Hobby",
297
+ features: [
298
+ "Autocomplete",
299
+ "Limited AI integration"
300
+ ]
301
+ },
302
+ {
303
+ name: "Enterprise",
304
+ features: [
305
+ "Everything in Hobby",
306
+ "24/7 Support"
307
+ ]
308
+ }
309
+ ]
310
+ }
311
+ }
312
+ };
313
+ const factory = new ElementFactory({
314
+ ...components,
315
+ [pricing.name]: pricing
316
+ });
317
+ const result = factory.createElementFromComponent({
318
+ componentName: pricing.name,
319
+ parentId: "root",
320
+ slot: "children"
321
+ });
322
+ const document = {
323
+ state: {},
324
+ elements: {
325
+ root: {
326
+ type: "Webiny/Element",
327
+ id: "root",
328
+ component: {
329
+ name: "Webiny/Root"
330
+ }
331
+ }
332
+ },
333
+ bindings: {}
334
+ };
335
+ for (const op of result.operations)op.apply(document);
336
+ const inputs = document.bindings[result.element.id].inputs;
337
+ expect(inputs["highlights"]?.static).toEqual([
338
+ "Fast",
339
+ "Cheap"
340
+ ]);
341
+ expect(inputs["plans/0/name"]?.static).toBe("Hobby");
342
+ expect(inputs["plans/0/features"]?.static).toEqual([
343
+ "Autocomplete",
344
+ "Limited AI integration"
345
+ ]);
346
+ expect(inputs["plans/1/features"]?.static).toEqual([
347
+ "Everything in Hobby",
348
+ "24/7 Support"
349
+ ]);
350
+ });
249
351
  });
250
352
 
251
353
  //# sourceMappingURL=ElementFactory.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElementFactory.test.js","sources":["../src/ElementFactory.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { ElementFactory } from \"./ElementFactory.js\";\nimport { DocumentOperations } from \"./documentOperations/index.js\";\nimport type { ComponentManifest, Document } from \"~/types.js\";\n\nconst components: Record<string, ComponentManifest> = {\n \"Webiny/Root\": {\n name: \"Webiny/Root\",\n label: \"Main Content\",\n tags: [],\n inputs: [\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n },\n \"FunnelBuilder/Funnel\": {\n name: \"FunnelBuilder/Funnel\",\n label: \"Funnel\",\n tags: [],\n inputs: [\n {\n type: \"object\",\n renderer: \"Webiny/Object\",\n name: \"fields\",\n list: true,\n fields: [],\n defaultValue: []\n },\n {\n type: \"number\",\n renderer: \"Webiny/Number\",\n name: \"activeStep\",\n label: \"Active Step\",\n defaultValue: 0\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"steps\"\n },\n {\n type: \"object\",\n renderer: \"FunnelBuilder/ConditionRulesRenderer\",\n name: \"conditionRules\",\n list: true,\n fields: []\n }\n ]\n },\n \"FunnelBuilder/Step\": {\n name: \"FunnelBuilder/Step\",\n label: \"Funnel Step\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n renderer: \"Webiny/Input\",\n name: \"label\",\n label: \"Label\"\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n }\n};\n\n/**\n * Extract private fields from operation instances for assertion.\n */\nfunction serializeOp(op: any) {\n if (op instanceof DocumentOperations.AddElement) {\n return { type: \"AddElement\", element: op[\"element\"] };\n }\n if (op instanceof DocumentOperations.AddToParent) {\n return { type: \"AddToParent\", element: op[\"element\"], index: op[\"index\"] };\n }\n if (op instanceof DocumentOperations.SetGlobalInputBinding) {\n return {\n type: \"SetGlobalInputBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n if (op instanceof DocumentOperations.SetGlobalStyleBinding) {\n return {\n type: \"SetGlobalStyleBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n return op;\n}\n\ndescribe(\"ElementFactory\", () => {\n it(\"should produce correct operation sequence for a Funnel with two Steps\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const ops = result.operations.map(serializeOp);\n const funnelId = result.element.id;\n\n // 0: AddElement — Funnel\n expect(ops[0].type).toBe(\"AddElement\");\n expect(ops[0].element.component.name).toBe(\"FunnelBuilder/Funnel\");\n\n // 1: AddToParent — Funnel → root/children at index 0\n expect(ops[1].type).toBe(\"AddToParent\");\n expect(ops[1].element.id).toBe(funnelId);\n expect(ops[1].index).toBe(0);\n\n // 2: SetGlobalInputBinding — activeStep = 0\n expect(ops[2].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[2].elementId).toBe(funnelId);\n expect(ops[2].bindingPath).toBe(\"activeStep\");\n expect(ops[2].binding.static).toBe(0);\n\n // 3: AddElement — Step 1\n const step1Id = ops[3].element.id;\n expect(ops[3].type).toBe(\"AddElement\");\n expect(ops[3].element.component.name).toBe(\"FunnelBuilder/Step\");\n expect(ops[3].element.parent).toEqual({ id: funnelId, slot: \"steps\" });\n\n // 4: AddToParent — Step 1 (undefined = append)\n expect(ops[4].type).toBe(\"AddToParent\");\n expect(ops[4].element.id).toBe(step1Id);\n expect(ops[4].index).toBeUndefined();\n\n // 5: Step 1 label binding\n expect(ops[5].bindingPath).toBe(\"label\");\n expect(ops[5].binding.static).toBe(\"Step 1\");\n\n // 6: Step 1 children binding\n expect(ops[6].bindingPath).toBe(\"children\");\n expect(ops[6].binding.static).toEqual([]);\n\n // 7-8: Step 1 style bindings\n expect(ops[7].bindingPath).toBe(\"display\");\n expect(ops[8].bindingPath).toBe(\"flexDirection\");\n\n // 9: SetGlobalInputBinding — steps slot metadata (no static, AddToParent handles it)\n expect(ops[9].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[9].elementId).toBe(funnelId);\n expect(ops[9].bindingPath).toBe(\"steps\");\n expect(ops[9].binding.static).toBeUndefined();\n expect(ops[9].binding.type).toBe(\"slot\");\n expect(ops[9].binding.list).toBe(true);\n\n // 10: AddElement — Step 2\n expect(ops[10].element.component.name).toBe(\"FunnelBuilder/Step\");\n\n // 11: AddToParent — Step 2 (undefined = append)\n expect(ops[11].index).toBeUndefined();\n\n // 12-15: Step 2 bindings + styles\n expect(ops[12].binding.static).toBe(\"Final Step\");\n expect(ops[13].binding.static).toEqual([]);\n\n // 16: SetGlobalInputBinding — steps slot metadata (no static)\n expect(ops[16].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[16].elementId).toBe(funnelId);\n expect(ops[16].bindingPath).toBe(\"steps\");\n expect(ops[16].binding.static).toBeUndefined();\n\n // 17-18: Funnel style bindings\n expect(ops[17].bindingPath).toBe(\"display\");\n expect(ops[18].bindingPath).toBe(\"flexDirection\");\n\n expect(ops).toHaveLength(19);\n });\n\n it(\"should produce correct document after applying all operations\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const document = {\n state: {},\n elements: {\n root: {\n type: \"Webiny/Element\",\n id: \"root\",\n component: { name: \"Webiny/Root\" }\n }\n },\n bindings: {}\n } as unknown as Document;\n\n for (const op of result.operations) {\n op.apply(document);\n }\n\n const funnelId = result.element.id;\n\n // Both step elements exist in the document.\n const stepElements = Object.values(document.elements).filter(\n el => el.component.name === \"FunnelBuilder/Step\"\n );\n expect(stepElements).toHaveLength(2);\n\n // Both steps have their correct labels.\n const labels = stepElements.map(el => document.bindings[el.id]?.inputs?.label?.static);\n expect(labels).toContain(\"Step 1\");\n expect(labels).toContain(\"Final Step\");\n\n // The steps binding contains both step IDs in order.\n const stepsBinding = document.bindings[funnelId]?.inputs?.steps;\n expect(stepsBinding?.list).toBe(true);\n expect(stepsBinding?.type).toBe(\"slot\");\n expect(stepsBinding?.static).toHaveLength(2);\n\n const step1 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Step 1\"\n )!;\n const step2 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Final Step\"\n )!;\n expect(stepsBinding?.static).toEqual([step1.id, step2.id]);\n });\n});\n"],"names":["components","serializeOp","op","DocumentOperations","describe","it","factory","ElementFactory","result","ops","funnelId","expect","step1Id","document","stepElements","Object","el","labels","stepsBinding","step1","step2"],"mappings":"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"}
1
+ {"version":3,"file":"ElementFactory.test.js","sources":["../src/ElementFactory.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { ElementFactory } from \"./ElementFactory.js\";\nimport { DocumentOperations } from \"./documentOperations/index.js\";\nimport type { ComponentManifest, Document } from \"~/types.js\";\n\nconst components: Record<string, ComponentManifest> = {\n \"Webiny/Root\": {\n name: \"Webiny/Root\",\n label: \"Main Content\",\n tags: [],\n inputs: [\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n },\n \"FunnelBuilder/Funnel\": {\n name: \"FunnelBuilder/Funnel\",\n label: \"Funnel\",\n tags: [],\n inputs: [\n {\n type: \"object\",\n renderer: \"Webiny/Object\",\n name: \"fields\",\n list: true,\n fields: [],\n defaultValue: []\n },\n {\n type: \"number\",\n renderer: \"Webiny/Number\",\n name: \"activeStep\",\n label: \"Active Step\",\n defaultValue: 0\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"steps\"\n },\n {\n type: \"object\",\n renderer: \"FunnelBuilder/ConditionRulesRenderer\",\n name: \"conditionRules\",\n list: true,\n fields: []\n }\n ]\n },\n \"FunnelBuilder/Step\": {\n name: \"FunnelBuilder/Step\",\n label: \"Funnel Step\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n renderer: \"Webiny/Input\",\n name: \"label\",\n label: \"Label\"\n },\n {\n type: \"slot\",\n list: true,\n renderer: \"Webiny/Slot\",\n defaultValue: [],\n name: \"children\"\n }\n ]\n }\n};\n\n/**\n * Extract private fields from operation instances for assertion.\n */\nfunction serializeOp(op: any) {\n if (op instanceof DocumentOperations.AddElement) {\n return { type: \"AddElement\", element: op[\"element\"] };\n }\n if (op instanceof DocumentOperations.AddToParent) {\n return { type: \"AddToParent\", element: op[\"element\"], index: op[\"index\"] };\n }\n if (op instanceof DocumentOperations.SetGlobalInputBinding) {\n return {\n type: \"SetGlobalInputBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n if (op instanceof DocumentOperations.SetGlobalStyleBinding) {\n return {\n type: \"SetGlobalStyleBinding\",\n elementId: op[\"elementId\"],\n bindingPath: op[\"bindingPath\"],\n binding: op[\"binding\"]\n };\n }\n return op;\n}\n\ndescribe(\"ElementFactory\", () => {\n it(\"should produce correct operation sequence for a Funnel with two Steps\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const ops = result.operations.map(serializeOp);\n const funnelId = result.element.id;\n\n // 0: AddElement — Funnel\n expect(ops[0].type).toBe(\"AddElement\");\n expect(ops[0].element.component.name).toBe(\"FunnelBuilder/Funnel\");\n\n // 1: AddToParent — Funnel → root/children at index 0\n expect(ops[1].type).toBe(\"AddToParent\");\n expect(ops[1].element.id).toBe(funnelId);\n expect(ops[1].index).toBe(0);\n\n // 2: SetGlobalInputBinding — activeStep = 0\n expect(ops[2].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[2].elementId).toBe(funnelId);\n expect(ops[2].bindingPath).toBe(\"activeStep\");\n expect(ops[2].binding.static).toBe(0);\n\n // 3: AddElement — Step 1\n const step1Id = ops[3].element.id;\n expect(ops[3].type).toBe(\"AddElement\");\n expect(ops[3].element.component.name).toBe(\"FunnelBuilder/Step\");\n expect(ops[3].element.parent).toEqual({ id: funnelId, slot: \"steps\" });\n\n // 4: AddToParent — Step 1 (undefined = append)\n expect(ops[4].type).toBe(\"AddToParent\");\n expect(ops[4].element.id).toBe(step1Id);\n expect(ops[4].index).toBeUndefined();\n\n // 5: Step 1 label binding\n expect(ops[5].bindingPath).toBe(\"label\");\n expect(ops[5].binding.static).toBe(\"Step 1\");\n\n // 6: Step 1 children binding\n expect(ops[6].bindingPath).toBe(\"children\");\n expect(ops[6].binding.static).toEqual([]);\n\n // 7-8: Step 1 style bindings\n expect(ops[7].bindingPath).toBe(\"display\");\n expect(ops[8].bindingPath).toBe(\"flexDirection\");\n\n // 9: SetGlobalInputBinding — steps slot metadata (no static, AddToParent handles it)\n expect(ops[9].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[9].elementId).toBe(funnelId);\n expect(ops[9].bindingPath).toBe(\"steps\");\n expect(ops[9].binding.static).toBeUndefined();\n expect(ops[9].binding.type).toBe(\"slot\");\n expect(ops[9].binding.list).toBe(true);\n\n // 10: AddElement — Step 2\n expect(ops[10].element.component.name).toBe(\"FunnelBuilder/Step\");\n\n // 11: AddToParent — Step 2 (undefined = append)\n expect(ops[11].index).toBeUndefined();\n\n // 12-15: Step 2 bindings + styles\n expect(ops[12].binding.static).toBe(\"Final Step\");\n expect(ops[13].binding.static).toEqual([]);\n\n // 16: SetGlobalInputBinding — steps slot metadata (no static)\n expect(ops[16].type).toBe(\"SetGlobalInputBinding\");\n expect(ops[16].elementId).toBe(funnelId);\n expect(ops[16].bindingPath).toBe(\"steps\");\n expect(ops[16].binding.static).toBeUndefined();\n\n // 17-18: Funnel style bindings\n expect(ops[17].bindingPath).toBe(\"display\");\n expect(ops[18].bindingPath).toBe(\"flexDirection\");\n\n expect(ops).toHaveLength(19);\n });\n\n it(\"should produce correct document after applying all operations\", () => {\n const factory = new ElementFactory(components);\n const result = factory.createElementFromComponent({\n componentName: \"FunnelBuilder/Funnel\",\n parentId: \"root\",\n slot: \"children\",\n index: 0,\n bindings: {\n inputs: {\n fields: [],\n activeStep: 0,\n steps: [\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Step 1\", children: [] }\n }\n },\n {\n action: \"CreateElement\",\n params: {\n component: \"FunnelBuilder/Step\",\n inputs: { label: \"Final Step\", children: [] }\n }\n }\n ]\n }\n }\n });\n\n const document = {\n state: {},\n elements: {\n root: {\n type: \"Webiny/Element\",\n id: \"root\",\n component: { name: \"Webiny/Root\" }\n }\n },\n bindings: {}\n } as unknown as Document;\n\n for (const op of result.operations) {\n op.apply(document);\n }\n\n const funnelId = result.element.id;\n\n // Both step elements exist in the document.\n const stepElements = Object.values(document.elements).filter(\n el => el.component.name === \"FunnelBuilder/Step\"\n );\n expect(stepElements).toHaveLength(2);\n\n // Both steps have their correct labels.\n const labels = stepElements.map(el => document.bindings[el.id]?.inputs?.label?.static);\n expect(labels).toContain(\"Step 1\");\n expect(labels).toContain(\"Final Step\");\n\n // The steps binding contains both step IDs in order.\n const stepsBinding = document.bindings[funnelId]?.inputs?.steps;\n expect(stepsBinding?.list).toBe(true);\n expect(stepsBinding?.type).toBe(\"slot\");\n expect(stepsBinding?.static).toHaveLength(2);\n\n const step1 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Step 1\"\n )!;\n const step2 = stepElements.find(\n el => document.bindings[el.id]?.inputs?.label?.static === \"Final Step\"\n )!;\n expect(stepsBinding?.static).toEqual([step1.id, step2.id]);\n });\n it(\"should keep every item of a primitive list (tags) from the component defaults\", () => {\n const pricing: ComponentManifest = {\n name: \"Custom/PricingPlans\",\n label: \"Pricing Plans\",\n tags: [],\n inputs: [\n {\n type: \"text\",\n list: true,\n renderer: \"Webiny/Tags\",\n name: \"highlights\",\n defaultValue: [\"Default\"]\n },\n {\n type: \"object\",\n list: true,\n renderer: \"Webiny/Object\",\n name: \"plans\",\n fields: [\n { type: \"text\", renderer: \"Webiny/Input\", name: \"name\" },\n {\n type: \"text\",\n list: true,\n renderer: \"Webiny/Tags\",\n name: \"features\",\n defaultValue: [\"Feature one\", \"Feature two\"]\n }\n ]\n }\n ],\n defaults: {\n inputs: {\n highlights: [\"Fast\", \"Cheap\"],\n plans: [\n { name: \"Hobby\", features: [\"Autocomplete\", \"Limited AI integration\"] },\n { name: \"Enterprise\", features: [\"Everything in Hobby\", \"24/7 Support\"] }\n ]\n }\n }\n };\n\n const factory = new ElementFactory({ ...components, [pricing.name]: pricing });\n const result = factory.createElementFromComponent({\n componentName: pricing.name,\n parentId: \"root\",\n slot: \"children\"\n });\n\n const document = {\n state: {},\n elements: {\n root: {\n type: \"Webiny/Element\",\n id: \"root\",\n component: { name: \"Webiny/Root\" }\n }\n },\n bindings: {}\n } as unknown as Document;\n\n for (const op of result.operations) {\n op.apply(document);\n }\n\n const inputs = document.bindings[result.element.id]!.inputs!;\n expect(inputs[\"highlights\"]?.static).toEqual([\"Fast\", \"Cheap\"]);\n expect(inputs[\"plans/0/name\"]?.static).toBe(\"Hobby\");\n expect(inputs[\"plans/0/features\"]?.static).toEqual([\n \"Autocomplete\",\n \"Limited AI integration\"\n ]);\n expect(inputs[\"plans/1/features\"]?.static).toEqual([\"Everything in Hobby\", \"24/7 Support\"]);\n });\n});\n"],"names":["components","serializeOp","op","DocumentOperations","describe","it","factory","ElementFactory","result","ops","funnelId","expect","step1Id","document","stepElements","Object","el","labels","stepsBinding","step1","step2","pricing","inputs"],"mappings":";;;AAKA,MAAMA,aAAgD;IAClD,eAAe;QACX,MAAM;QACN,OAAO;QACP,MAAM,EAAE;QACR,QAAQ;YACJ;gBACI,MAAM;gBACN,MAAM;gBACN,UAAU;gBACV,cAAc,EAAE;gBAChB,MAAM;YACV;SACH;IACL;IACA,wBAAwB;QACpB,MAAM;QACN,OAAO;QACP,MAAM,EAAE;QACR,QAAQ;YACJ;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,MAAM;gBACN,QAAQ,EAAE;gBACV,cAAc,EAAE;YACpB;YACA;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,OAAO;gBACP,cAAc;YAClB;YACA;gBACI,MAAM;gBACN,MAAM;gBACN,UAAU;gBACV,cAAc,EAAE;gBAChB,MAAM;YACV;YACA;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,MAAM;gBACN,QAAQ,EAAE;YACd;SACH;IACL;IACA,sBAAsB;QAClB,MAAM;QACN,OAAO;QACP,MAAM,EAAE;QACR,QAAQ;YACJ;gBACI,MAAM;gBACN,UAAU;gBACV,MAAM;gBACN,OAAO;YACX;YACA;gBACI,MAAM;gBACN,MAAM;gBACN,UAAU;gBACV,cAAc,EAAE;gBAChB,MAAM;YACV;SACH;IACL;AACJ;AAKA,SAASC,YAAYC,EAAO;IACxB,IAAIA,cAAcC,mBAAmB,UAAU,EAC3C,OAAO;QAAE,MAAM;QAAc,SAASD,EAAE,CAAC,UAAU;IAAC;IAExD,IAAIA,cAAcC,mBAAmB,WAAW,EAC5C,OAAO;QAAE,MAAM;QAAe,SAASD,EAAE,CAAC,UAAU;QAAE,OAAOA,EAAE,CAAC,QAAQ;IAAC;IAE7E,IAAIA,cAAcC,mBAAmB,qBAAqB,EACtD,OAAO;QACH,MAAM;QACN,WAAWD,EAAE,CAAC,YAAY;QAC1B,aAAaA,EAAE,CAAC,cAAc;QAC9B,SAASA,EAAE,CAAC,UAAU;IAC1B;IAEJ,IAAIA,cAAcC,mBAAmB,qBAAqB,EACtD,OAAO;QACH,MAAM;QACN,WAAWD,EAAE,CAAC,YAAY;QAC1B,aAAaA,EAAE,CAAC,cAAc;QAC9B,SAASA,EAAE,CAAC,UAAU;IAC1B;IAEJ,OAAOA;AACX;AAEAE,SAAS,kBAAkB;IACvBC,GAAG,yEAAyE;QACxE,MAAMC,UAAU,IAAIC,eAAeP;QACnC,MAAMQ,SAASF,QAAQ,0BAA0B,CAAC;YAC9C,eAAe;YACf,UAAU;YACV,MAAM;YACN,OAAO;YACP,UAAU;gBACN,QAAQ;oBACJ,QAAQ,EAAE;oBACV,YAAY;oBACZ,OAAO;wBACH;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAU,UAAU,EAAE;gCAAC;4BAC5C;wBACJ;wBACA;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAc,UAAU,EAAE;gCAAC;4BAChD;wBACJ;qBACH;gBACL;YACJ;QACJ;QAEA,MAAMG,MAAMD,OAAO,UAAU,CAAC,GAAG,CAACP;QAClC,MAAMS,WAAWF,OAAO,OAAO,CAAC,EAAE;QAGlCG,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAG3CE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAACC;QAC/BC,OAAOF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;QAG1BE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAACC;QAC9BC,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QAGnC,MAAMG,UAAUH,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE;QACjCE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAC3CE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;YAAE,IAAIC;YAAU,MAAM;QAAQ;QAGpEC,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAACG;QAC/BD,OAAOF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa;QAGlCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QAGnCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;QAGxCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAGhCE,OAAOF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACzBE,OAAOF,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAACC;QAC9BC,OAAOF,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;QAChCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa;QAC3CE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;QACjCE,OAAOF,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;QAGjCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAG5CE,OAAOF,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa;QAGnCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;QACpCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;QAGzCE,OAAOF,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;QAC1BE,OAAOF,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAACC;QAC/BC,OAAOF,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC;QACjCE,OAAOF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa;QAG5CE,OAAOF,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC;QACjCE,OAAOF,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC;QAEjCE,OAAOF,KAAK,YAAY,CAAC;IAC7B;IAEAJ,GAAG,iEAAiE;QAChE,MAAMC,UAAU,IAAIC,eAAeP;QACnC,MAAMQ,SAASF,QAAQ,0BAA0B,CAAC;YAC9C,eAAe;YACf,UAAU;YACV,MAAM;YACN,OAAO;YACP,UAAU;gBACN,QAAQ;oBACJ,QAAQ,EAAE;oBACV,YAAY;oBACZ,OAAO;wBACH;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAU,UAAU,EAAE;gCAAC;4BAC5C;wBACJ;wBACA;4BACI,QAAQ;4BACR,QAAQ;gCACJ,WAAW;gCACX,QAAQ;oCAAE,OAAO;oCAAc,UAAU,EAAE;gCAAC;4BAChD;wBACJ;qBACH;gBACL;YACJ;QACJ;QAEA,MAAMO,WAAW;YACb,OAAO,CAAC;YACR,UAAU;gBACN,MAAM;oBACF,MAAM;oBACN,IAAI;oBACJ,WAAW;wBAAE,MAAM;oBAAc;gBACrC;YACJ;YACA,UAAU,CAAC;QACf;QAEA,KAAK,MAAMX,MAAMM,OAAO,UAAU,CAC9BN,GAAG,KAAK,CAACW;QAGb,MAAMH,WAAWF,OAAO,OAAO,CAAC,EAAE;QAGlC,MAAMM,eAAeC,OAAO,MAAM,CAACF,SAAS,QAAQ,EAAE,MAAM,CACxDG,CAAAA,KAAMA,AAAsB,yBAAtBA,GAAG,SAAS,CAAC,IAAI;QAE3BL,OAAOG,cAAc,YAAY,CAAC;QAGlC,MAAMG,SAASH,aAAa,GAAG,CAACE,CAAAA,KAAMH,SAAS,QAAQ,CAACG,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO;QAC/EL,OAAOM,QAAQ,SAAS,CAAC;QACzBN,OAAOM,QAAQ,SAAS,CAAC;QAGzB,MAAMC,eAAeL,SAAS,QAAQ,CAACH,SAAS,EAAE,QAAQ;QAC1DC,OAAOO,cAAc,MAAM,IAAI,CAAC;QAChCP,OAAOO,cAAc,MAAM,IAAI,CAAC;QAChCP,OAAOO,cAAc,QAAQ,YAAY,CAAC;QAE1C,MAAMC,QAAQL,aAAa,IAAI,CAC3BE,CAAAA,KAAMH,SAAS,QAAQ,CAACG,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO,WAAW;QAE9D,MAAMI,QAAQN,aAAa,IAAI,CAC3BE,CAAAA,KAAMH,SAAS,QAAQ,CAACG,GAAG,EAAE,CAAC,EAAE,QAAQ,OAAO,WAAW;QAE9DL,OAAOO,cAAc,QAAQ,OAAO,CAAC;YAACC,MAAM,EAAE;YAAEC,MAAM,EAAE;SAAC;IAC7D;IACAf,GAAG,iFAAiF;QAChF,MAAMgB,UAA6B;YAC/B,MAAM;YACN,OAAO;YACP,MAAM,EAAE;YACR,QAAQ;gBACJ;oBACI,MAAM;oBACN,MAAM;oBACN,UAAU;oBACV,MAAM;oBACN,cAAc;wBAAC;qBAAU;gBAC7B;gBACA;oBACI,MAAM;oBACN,MAAM;oBACN,UAAU;oBACV,MAAM;oBACN,QAAQ;wBACJ;4BAAE,MAAM;4BAAQ,UAAU;4BAAgB,MAAM;wBAAO;wBACvD;4BACI,MAAM;4BACN,MAAM;4BACN,UAAU;4BACV,MAAM;4BACN,cAAc;gCAAC;gCAAe;6BAAc;wBAChD;qBACH;gBACL;aACH;YACD,UAAU;gBACN,QAAQ;oBACJ,YAAY;wBAAC;wBAAQ;qBAAQ;oBAC7B,OAAO;wBACH;4BAAE,MAAM;4BAAS,UAAU;gCAAC;gCAAgB;6BAAyB;wBAAC;wBACtE;4BAAE,MAAM;4BAAc,UAAU;gCAAC;gCAAuB;6BAAe;wBAAC;qBAC3E;gBACL;YACJ;QACJ;QAEA,MAAMf,UAAU,IAAIC,eAAe;YAAE,GAAGP,UAAU;YAAE,CAACqB,QAAQ,IAAI,CAAC,EAAEA;QAAQ;QAC5E,MAAMb,SAASF,QAAQ,0BAA0B,CAAC;YAC9C,eAAee,QAAQ,IAAI;YAC3B,UAAU;YACV,MAAM;QACV;QAEA,MAAMR,WAAW;YACb,OAAO,CAAC;YACR,UAAU;gBACN,MAAM;oBACF,MAAM;oBACN,IAAI;oBACJ,WAAW;wBAAE,MAAM;oBAAc;gBACrC;YACJ;YACA,UAAU,CAAC;QACf;QAEA,KAAK,MAAMX,MAAMM,OAAO,UAAU,CAC9BN,GAAG,KAAK,CAACW;QAGb,MAAMS,SAAST,SAAS,QAAQ,CAACL,OAAO,OAAO,CAAC,EAAE,CAAC,CAAE,MAAM;QAC3DG,OAAOW,MAAM,CAAC,aAAa,EAAE,QAAQ,OAAO,CAAC;YAAC;YAAQ;SAAQ;QAC9DX,OAAOW,MAAM,CAAC,eAAe,EAAE,QAAQ,IAAI,CAAC;QAC5CX,OAAOW,MAAM,CAAC,mBAAmB,EAAE,QAAQ,OAAO,CAAC;YAC/C;YACA;SACH;QACDX,OAAOW,MAAM,CAAC,mBAAmB,EAAE,QAAQ,OAAO,CAAC;YAAC;YAAuB;SAAe;IAC9F;AACJ"}
package/LiveSdk.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { GetPageOptions, IContentSdk, IDataProvider, ListPagesOptions, ListPagesResult, PublicPage } from "./types.js";
2
+ import type { DocumentStoreManager } from "./DocumentStoreManager.js";
2
3
  export declare class LiveSdk implements IContentSdk {
3
4
  private dataProvider;
4
- constructor(dataProvider: IDataProvider);
5
+ private documentStoreManager;
6
+ constructor(dataProvider: IDataProvider, stores?: DocumentStoreManager);
5
7
  getPage(path: string, options?: GetPageOptions): Promise<PublicPage | null>;
6
8
  listPages(options?: ListPagesOptions): Promise<ListPagesResult>;
7
9
  }
package/LiveSdk.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { documentStoreManager } from "./DocumentStoreManager.js";
2
2
  class LiveSdk {
3
- constructor(dataProvider){
3
+ constructor(dataProvider, stores = documentStoreManager){
4
4
  this.dataProvider = dataProvider;
5
+ this.documentStoreManager = stores;
5
6
  }
6
7
  async getPage(path, options) {
7
8
  const page = await this.dataProvider.getPageByPath(path, options);
8
- if (page) documentStoreManager.getStore(page.properties.id).setDocument(page);
9
+ if (page) this.documentStoreManager.getStore(page.properties.id).setDocument(page);
9
10
  return page;
10
11
  }
11
12
  listPages(options) {
package/LiveSdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"LiveSdk.js","sources":["../src/LiveSdk.ts"],"sourcesContent":["import type {\n GetPageOptions,\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport { documentStoreManager } from \"~/DocumentStoreManager.js\";\n\nexport class LiveSdk implements IContentSdk {\n private dataProvider: IDataProvider;\n\n constructor(dataProvider: IDataProvider) {\n this.dataProvider = dataProvider;\n }\n\n async getPage(path: string, options?: GetPageOptions): Promise<PublicPage | null> {\n const page = await this.dataProvider.getPageByPath(path, options);\n if (page) {\n documentStoreManager.getStore<PublicPage>(page.properties.id).setDocument(page);\n }\n return page;\n }\n\n listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.dataProvider.listPages(options);\n }\n}\n"],"names":["LiveSdk","dataProvider","path","options","page","documentStoreManager"],"mappings":";AAUO,MAAMA;IAGT,YAAYC,YAA2B,CAAE;QACrC,IAAI,CAAC,YAAY,GAAGA;IACxB;IAEA,MAAM,QAAQC,IAAY,EAAEC,OAAwB,EAA8B;QAC9E,MAAMC,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAACF,MAAMC;QACzD,IAAIC,MACAC,qBAAqB,QAAQ,CAAaD,KAAK,UAAU,CAAC,EAAE,EAAE,WAAW,CAACA;QAE9E,OAAOA;IACX;IAEA,UAAUD,OAA0B,EAA4B;QAC5D,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAACA;IACvC;AACJ"}
1
+ {"version":3,"file":"LiveSdk.js","sources":["../src/LiveSdk.ts"],"sourcesContent":["import type {\n GetPageOptions,\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport type { DocumentStoreManager } from \"~/DocumentStoreManager.js\";\nimport { documentStoreManager } from \"~/DocumentStoreManager.js\";\n\nexport class LiveSdk implements IContentSdk {\n private dataProvider: IDataProvider;\n private documentStoreManager: DocumentStoreManager;\n\n constructor(dataProvider: IDataProvider, stores: DocumentStoreManager = documentStoreManager) {\n this.dataProvider = dataProvider;\n this.documentStoreManager = stores;\n }\n\n async getPage(path: string, options?: GetPageOptions): Promise<PublicPage | null> {\n const page = await this.dataProvider.getPageByPath(path, options);\n if (page) {\n this.documentStoreManager.getStore<PublicPage>(page.properties.id).setDocument(page);\n }\n return page;\n }\n\n listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.dataProvider.listPages(options);\n }\n}\n"],"names":["LiveSdk","dataProvider","stores","documentStoreManager","path","options","page"],"mappings":";AAWO,MAAMA;IAIT,YAAYC,YAA2B,EAAEC,SAA+BC,oBAAoB,CAAE;QAC1F,IAAI,CAAC,YAAY,GAAGF;QACpB,IAAI,CAAC,oBAAoB,GAAGC;IAChC;IAEA,MAAM,QAAQE,IAAY,EAAEC,OAAwB,EAA8B;QAC9E,MAAMC,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,aAAa,CAACF,MAAMC;QACzD,IAAIC,MACA,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAaA,KAAK,UAAU,CAAC,EAAE,EAAE,WAAW,CAACA;QAEnF,OAAOA;IACX;IAEA,UAAUD,OAA0B,EAA4B;QAC5D,OAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAACA;IACvC;AACJ"}
@@ -1,9 +1,10 @@
1
+ import type { HeadersProvider } from "./headersProvider.js";
1
2
  export declare class PreviewDocument {
2
3
  readonly props: Record<string, string>;
3
4
  private constructor();
4
5
  static createFromParams(params: string): PreviewDocument;
5
6
  static createFromWindow(): PreviewDocument;
6
- static createFromHeaders(): Promise<PreviewDocument>;
7
+ static createFromHeaders(provider?: HeadersProvider): Promise<PreviewDocument>;
7
8
  matches(params: Record<string, string>): boolean;
8
9
  getId(): string;
9
10
  }
@@ -16,8 +16,8 @@ class PreviewDocument {
16
16
  const query = new URLSearchParams(window.location.search);
17
17
  return new PreviewDocument("wb", query);
18
18
  }
19
- static async createFromHeaders() {
20
- const headersProvider = getHeadersProvider();
19
+ static async createFromHeaders(provider) {
20
+ const headersProvider = provider ?? getHeadersProvider();
21
21
  const headers = await headersProvider();
22
22
  const previewFromHeaders = headers.get("X-Preview-Params");
23
23
  return new PreviewDocument("wb", new URLSearchParams(previewFromHeaders ?? ""));
@@ -1 +1 @@
1
- {"version":3,"file":"PreviewDocument.js","sources":["../src/PreviewDocument.ts"],"sourcesContent":["import { getHeadersProvider } from \"./headersProvider.js\";\n\nexport class PreviewDocument {\n public readonly props: Record<string, string>;\n\n private constructor(prefix: string, query: URLSearchParams) {\n this.props = {};\n query.forEach((value, key) => {\n if (key.startsWith(prefix + \".\")) {\n const strippedKey = key.slice(prefix.length + 1); // +1 for the dot\n this.props[strippedKey] = value as string;\n }\n });\n }\n\n static createFromParams(params: string): PreviewDocument {\n return new PreviewDocument(\"wb\", new URLSearchParams(params));\n }\n\n static createFromWindow(): PreviewDocument {\n const query = new URLSearchParams(window.location.search);\n return new PreviewDocument(\"wb\", query);\n }\n\n static async createFromHeaders(): Promise<PreviewDocument> {\n const headersProvider = getHeadersProvider();\n const headers = await headersProvider();\n const previewFromHeaders = headers.get(\"X-Preview-Params\");\n\n return new PreviewDocument(\"wb\", new URLSearchParams(previewFromHeaders ?? \"\"));\n }\n\n matches(params: Record<string, string>) {\n for (const [key, value] of Object.entries(params)) {\n if (this.props[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n getId() {\n return this.props.id;\n }\n}\n"],"names":["PreviewDocument","prefix","query","value","key","strippedKey","params","URLSearchParams","window","headersProvider","getHeadersProvider","headers","previewFromHeaders","Object"],"mappings":";AAEO,MAAMA;IAGT,YAAoBC,MAAc,EAAEC,KAAsB,CAAE;QACxD,IAAI,CAAC,KAAK,GAAG,CAAC;QACdA,MAAM,OAAO,CAAC,CAACC,OAAOC;YAClB,IAAIA,IAAI,UAAU,CAACH,SAAS,MAAM;gBAC9B,MAAMI,cAAcD,IAAI,KAAK,CAACH,OAAO,MAAM,GAAG;gBAC9C,IAAI,CAAC,KAAK,CAACI,YAAY,GAAGF;YAC9B;QACJ;IACJ;IAEA,OAAO,iBAAiBG,MAAc,EAAmB;QACrD,OAAO,IAAIN,gBAAgB,MAAM,IAAIO,gBAAgBD;IACzD;IAEA,OAAO,mBAAoC;QACvC,MAAMJ,QAAQ,IAAIK,gBAAgBC,OAAO,QAAQ,CAAC,MAAM;QACxD,OAAO,IAAIR,gBAAgB,MAAME;IACrC;IAEA,aAAa,oBAA8C;QACvD,MAAMO,kBAAkBC;QACxB,MAAMC,UAAU,MAAMF;QACtB,MAAMG,qBAAqBD,QAAQ,GAAG,CAAC;QAEvC,OAAO,IAAIX,gBAAgB,MAAM,IAAIO,gBAAgBK,sBAAsB;IAC/E;IAEA,QAAQN,MAA8B,EAAE;QACpC,KAAK,MAAM,CAACF,KAAKD,MAAM,IAAIU,OAAO,OAAO,CAACP,QACtC,IAAI,IAAI,CAAC,KAAK,CAACF,IAAI,KAAKD,OACpB,OAAO;QAGf,OAAO;IACX;IAEA,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE;IACxB;AACJ"}
1
+ {"version":3,"file":"PreviewDocument.js","sources":["../src/PreviewDocument.ts"],"sourcesContent":["import type { HeadersProvider } from \"./headersProvider.js\";\nimport { getHeadersProvider } from \"./headersProvider.js\";\n\nexport class PreviewDocument {\n public readonly props: Record<string, string>;\n\n private constructor(prefix: string, query: URLSearchParams) {\n this.props = {};\n query.forEach((value, key) => {\n if (key.startsWith(prefix + \".\")) {\n const strippedKey = key.slice(prefix.length + 1); // +1 for the dot\n this.props[strippedKey] = value as string;\n }\n });\n }\n\n static createFromParams(params: string): PreviewDocument {\n return new PreviewDocument(\"wb\", new URLSearchParams(params));\n }\n\n static createFromWindow(): PreviewDocument {\n const query = new URLSearchParams(window.location.search);\n return new PreviewDocument(\"wb\", query);\n }\n\n static async createFromHeaders(provider?: HeadersProvider): Promise<PreviewDocument> {\n const headersProvider = provider ?? getHeadersProvider();\n const headers = await headersProvider();\n const previewFromHeaders = headers.get(\"X-Preview-Params\");\n\n return new PreviewDocument(\"wb\", new URLSearchParams(previewFromHeaders ?? \"\"));\n }\n\n matches(params: Record<string, string>) {\n for (const [key, value] of Object.entries(params)) {\n if (this.props[key] !== value) {\n return false;\n }\n }\n return true;\n }\n\n getId() {\n return this.props.id;\n }\n}\n"],"names":["PreviewDocument","prefix","query","value","key","strippedKey","params","URLSearchParams","window","provider","headersProvider","getHeadersProvider","headers","previewFromHeaders","Object"],"mappings":";AAGO,MAAMA;IAGT,YAAoBC,MAAc,EAAEC,KAAsB,CAAE;QACxD,IAAI,CAAC,KAAK,GAAG,CAAC;QACdA,MAAM,OAAO,CAAC,CAACC,OAAOC;YAClB,IAAIA,IAAI,UAAU,CAACH,SAAS,MAAM;gBAC9B,MAAMI,cAAcD,IAAI,KAAK,CAACH,OAAO,MAAM,GAAG;gBAC9C,IAAI,CAAC,KAAK,CAACI,YAAY,GAAGF;YAC9B;QACJ;IACJ;IAEA,OAAO,iBAAiBG,MAAc,EAAmB;QACrD,OAAO,IAAIN,gBAAgB,MAAM,IAAIO,gBAAgBD;IACzD;IAEA,OAAO,mBAAoC;QACvC,MAAMJ,QAAQ,IAAIK,gBAAgBC,OAAO,QAAQ,CAAC,MAAM;QACxD,OAAO,IAAIR,gBAAgB,MAAME;IACrC;IAEA,aAAa,kBAAkBO,QAA0B,EAA4B;QACjF,MAAMC,kBAAkBD,YAAYE;QACpC,MAAMC,UAAU,MAAMF;QACtB,MAAMG,qBAAqBD,QAAQ,GAAG,CAAC;QAEvC,OAAO,IAAIZ,gBAAgB,MAAM,IAAIO,gBAAgBM,sBAAsB;IAC/E;IAEA,QAAQP,MAA8B,EAAE;QACpC,KAAK,MAAM,CAACF,KAAKD,MAAM,IAAIW,OAAO,OAAO,CAACR,QACtC,IAAI,IAAI,CAAC,KAAK,CAACF,IAAI,KAAKD,OACpB,OAAO;QAGf,OAAO;IACX;IAEA,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE;IACxB;AACJ"}
package/PreviewSdk.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type { IContentSdk, IDataProvider, ListPagesOptions, ListPagesResult, PublicPage } from "./types.js";
2
+ import type { HeadersProvider } from "./headersProvider.js";
2
3
  export declare class PreviewSdk implements IContentSdk {
3
4
  private liveSdk;
4
5
  private dataProvider;
5
6
  private previewParams;
6
- constructor(dataProvider: IDataProvider, liveSdk: IContentSdk, previewParams?: string);
7
+ private headersProvider;
8
+ constructor(dataProvider: IDataProvider, liveSdk: IContentSdk, previewParams?: string, headersProvider?: HeadersProvider);
7
9
  getPage(path: string): Promise<PublicPage | null>;
8
10
  listPages(options?: ListPagesOptions): Promise<ListPagesResult>;
9
11
  }
package/PreviewSdk.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import { PreviewDocument } from "./PreviewDocument.js";
2
2
  import { environment } from "./Environment.js";
3
3
  class PreviewSdk {
4
- constructor(dataProvider, liveSdk, previewParams){
4
+ constructor(dataProvider, liveSdk, previewParams, headersProvider){
5
5
  this.liveSdk = liveSdk;
6
6
  this.dataProvider = dataProvider;
7
7
  this.previewParams = previewParams;
8
+ this.headersProvider = headersProvider;
8
9
  }
9
10
  async getPage(path) {
10
11
  let previewDocument;
11
- previewDocument = this.previewParams ? PreviewDocument.createFromParams(this.previewParams) : environment.isClient() ? PreviewDocument.createFromWindow() : await PreviewDocument.createFromHeaders();
12
+ previewDocument = this.previewParams ? PreviewDocument.createFromParams(this.previewParams) : environment.isClient() ? PreviewDocument.createFromWindow() : await PreviewDocument.createFromHeaders(this.headersProvider);
12
13
  if (!previewDocument.matches({
13
14
  type: "page",
14
15
  path
package/PreviewSdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"PreviewSdk.js","sources":["../src/PreviewSdk.ts"],"sourcesContent":["import type {\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport { PreviewDocument } from \"~/PreviewDocument.js\";\nimport { environment } from \"./Environment.js\";\n\nexport class PreviewSdk implements IContentSdk {\n private liveSdk: IContentSdk;\n private dataProvider: IDataProvider;\n private previewParams: string | undefined;\n\n constructor(dataProvider: IDataProvider, liveSdk: IContentSdk, previewParams?: string) {\n this.liveSdk = liveSdk;\n this.dataProvider = dataProvider;\n this.previewParams = previewParams;\n }\n\n async getPage(path: string): Promise<PublicPage | null> {\n let previewDocument: PreviewDocument;\n\n if (this.previewParams) {\n // Params were passed directly via init config (server-side SSR path).\n previewDocument = PreviewDocument.createFromParams(this.previewParams);\n } else if (environment.isClient()) {\n previewDocument = PreviewDocument.createFromWindow();\n } else {\n previewDocument = await PreviewDocument.createFromHeaders();\n }\n\n if (!previewDocument.matches({ type: \"page\", path })) {\n return this.liveSdk.getPage(path);\n }\n return this.dataProvider.getPageById(previewDocument.getId());\n }\n\n async listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.liveSdk.listPages(options);\n }\n}\n"],"names":["PreviewSdk","dataProvider","liveSdk","previewParams","path","previewDocument","PreviewDocument","environment","options"],"mappings":";;AAUO,MAAMA;IAKT,YAAYC,YAA2B,EAAEC,OAAoB,EAAEC,aAAsB,CAAE;QACnF,IAAI,CAAC,OAAO,GAAGD;QACf,IAAI,CAAC,YAAY,GAAGD;QACpB,IAAI,CAAC,aAAa,GAAGE;IACzB;IAEA,MAAM,QAAQC,IAAY,EAA8B;QACpD,IAAIC;QAIAA,kBAFA,IAAI,CAAC,aAAa,GAEAC,gBAAgB,gBAAgB,CAAC,IAAI,CAAC,aAAa,IAC9DC,YAAY,QAAQ,KACTD,gBAAgB,gBAAgB,KAEhC,MAAMA,gBAAgB,iBAAiB;QAG7D,IAAI,CAACD,gBAAgB,OAAO,CAAC;YAAE,MAAM;YAAQD;QAAK,IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAACA;QAEhC,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAACC,gBAAgB,KAAK;IAC9D;IAEA,MAAM,UAAUG,OAA0B,EAA4B;QAClE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAACA;IAClC;AACJ"}
1
+ {"version":3,"file":"PreviewSdk.js","sources":["../src/PreviewSdk.ts"],"sourcesContent":["import type {\n IContentSdk,\n IDataProvider,\n ListPagesOptions,\n ListPagesResult,\n PublicPage\n} from \"~/types.js\";\nimport { PreviewDocument } from \"~/PreviewDocument.js\";\nimport { environment } from \"./Environment.js\";\nimport type { HeadersProvider } from \"./headersProvider.js\";\n\nexport class PreviewSdk implements IContentSdk {\n private liveSdk: IContentSdk;\n private dataProvider: IDataProvider;\n private previewParams: string | undefined;\n private headersProvider: HeadersProvider | undefined;\n\n constructor(\n dataProvider: IDataProvider,\n liveSdk: IContentSdk,\n previewParams?: string,\n headersProvider?: HeadersProvider\n ) {\n this.liveSdk = liveSdk;\n this.dataProvider = dataProvider;\n this.previewParams = previewParams;\n this.headersProvider = headersProvider;\n }\n\n async getPage(path: string): Promise<PublicPage | null> {\n let previewDocument: PreviewDocument;\n\n if (this.previewParams) {\n // Params were passed directly via init config (server-side SSR path).\n previewDocument = PreviewDocument.createFromParams(this.previewParams);\n } else if (environment.isClient()) {\n previewDocument = PreviewDocument.createFromWindow();\n } else {\n previewDocument = await PreviewDocument.createFromHeaders(this.headersProvider);\n }\n\n if (!previewDocument.matches({ type: \"page\", path })) {\n return this.liveSdk.getPage(path);\n }\n return this.dataProvider.getPageById(previewDocument.getId());\n }\n\n async listPages(options?: ListPagesOptions): Promise<ListPagesResult> {\n return this.liveSdk.listPages(options);\n }\n}\n"],"names":["PreviewSdk","dataProvider","liveSdk","previewParams","headersProvider","path","previewDocument","PreviewDocument","environment","options"],"mappings":";;AAWO,MAAMA;IAMT,YACIC,YAA2B,EAC3BC,OAAoB,EACpBC,aAAsB,EACtBC,eAAiC,CACnC;QACE,IAAI,CAAC,OAAO,GAAGF;QACf,IAAI,CAAC,YAAY,GAAGD;QACpB,IAAI,CAAC,aAAa,GAAGE;QACrB,IAAI,CAAC,eAAe,GAAGC;IAC3B;IAEA,MAAM,QAAQC,IAAY,EAA8B;QACpD,IAAIC;QAIAA,kBAFA,IAAI,CAAC,aAAa,GAEAC,gBAAgB,gBAAgB,CAAC,IAAI,CAAC,aAAa,IAC9DC,YAAY,QAAQ,KACTD,gBAAgB,gBAAgB,KAEhC,MAAMA,gBAAgB,iBAAiB,CAAC,IAAI,CAAC,eAAe;QAGlF,IAAI,CAACD,gBAAgB,OAAO,CAAC;YAAE,MAAM;YAAQD;QAAK,IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAACA;QAEhC,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAACC,gBAAgB,KAAK;IAC9D;IAEA,MAAM,UAAUG,OAA0B,EAA4B;QAClE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAACA;IAClC;AACJ"}
package/ResizeObserver.js CHANGED
@@ -7,7 +7,7 @@ const flushResizeQueue = ()=>{
7
7
  resizeQueue = {};
8
8
  };
9
9
  let observer;
10
- observer = "u" < typeof window ? {
10
+ observer = "u" < typeof ResizeObserver ? {
11
11
  observe: ()=>{},
12
12
  unobserve: ()=>{}
13
13
  } : new ResizeObserver((entries)=>{
@@ -1 +1 @@
1
- {"version":3,"file":"ResizeObserver.js","sources":["../src/ResizeObserver.ts"],"sourcesContent":["let resizeQueue: Record<string, DOMRect> = {};\nconst onChangeListeners: Array<() => void> = [];\n\nconst flushResizeQueue = () => {\n if (Object.entries(resizeQueue).length > 0) {\n onChangeListeners.forEach(entry => {\n entry();\n });\n }\n resizeQueue = {};\n};\n\nlet observer: any;\n\nif (typeof window === \"undefined\") {\n observer = {\n observe: () => {},\n unobserve: () => {}\n };\n} else {\n observer = new ResizeObserver(entries => {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const id = el.getAttribute(\"data-element-id\");\n if (id) {\n resizeQueue[id] = el.getBoundingClientRect();\n }\n }\n requestAnimationFrame(flushResizeQueue);\n });\n}\n\nexport const resizeObserver = {\n observe: (element: HTMLElement) => {\n observer.observe(element);\n },\n unobserve: (element: HTMLElement) => {\n observer.unobserve(element);\n },\n onChange: (cb: () => void) => {\n onChangeListeners.push(cb);\n }\n};\n"],"names":["resizeQueue","onChangeListeners","flushResizeQueue","Object","entry","observer","window","ResizeObserver","entries","el","id","requestAnimationFrame","resizeObserver","element","cb"],"mappings":"AAAA,IAAIA,cAAuC,CAAC;AAC5C,MAAMC,oBAAuC,EAAE;AAE/C,MAAMC,mBAAmB;IACrB,IAAIC,OAAO,OAAO,CAACH,aAAa,MAAM,GAAG,GACrCC,kBAAkB,OAAO,CAACG,CAAAA;QACtBA;IACJ;IAEJJ,cAAc,CAAC;AACnB;AAEA,IAAIK;AAGAA,WADA,AAAkB,MAAlB,OAAOC,SACI;IACP,SAAS,KAAO;IAChB,WAAW,KAAO;AACtB,IAEW,IAAIC,eAAeC,CAAAA;IAC1B,KAAK,MAAMJ,SAASI,QAAS;QACzB,MAAMC,KAAKL,MAAM,MAAM;QACvB,MAAMM,KAAKD,GAAG,YAAY,CAAC;QAC3B,IAAIC,IACAV,WAAW,CAACU,GAAG,GAAGD,GAAG,qBAAqB;IAElD;IACAE,sBAAsBT;AAC1B;AAGG,MAAMU,iBAAiB;IAC1B,SAAS,CAACC;QACNR,SAAS,OAAO,CAACQ;IACrB;IACA,WAAW,CAACA;QACRR,SAAS,SAAS,CAACQ;IACvB;IACA,UAAU,CAACC;QACPb,kBAAkB,IAAI,CAACa;IAC3B;AACJ"}
1
+ {"version":3,"file":"ResizeObserver.js","sources":["../src/ResizeObserver.ts"],"sourcesContent":["let resizeQueue: Record<string, DOMRect> = {};\nconst onChangeListeners: Array<() => void> = [];\n\nconst flushResizeQueue = () => {\n if (Object.entries(resizeQueue).length > 0) {\n onChangeListeners.forEach(entry => {\n entry();\n });\n }\n resizeQueue = {};\n};\n\nlet observer: any;\n\nif (typeof ResizeObserver === \"undefined\") {\n observer = {\n observe: () => {},\n unobserve: () => {}\n };\n} else {\n observer = new ResizeObserver(entries => {\n for (const entry of entries) {\n const el = entry.target as HTMLElement;\n const id = el.getAttribute(\"data-element-id\");\n if (id) {\n resizeQueue[id] = el.getBoundingClientRect();\n }\n }\n requestAnimationFrame(flushResizeQueue);\n });\n}\n\nexport const resizeObserver = {\n observe: (element: HTMLElement) => {\n observer.observe(element);\n },\n unobserve: (element: HTMLElement) => {\n observer.unobserve(element);\n },\n onChange: (cb: () => void) => {\n onChangeListeners.push(cb);\n }\n};\n"],"names":["resizeQueue","onChangeListeners","flushResizeQueue","Object","entry","observer","ResizeObserver","entries","el","id","requestAnimationFrame","resizeObserver","element","cb"],"mappings":"AAAA,IAAIA,cAAuC,CAAC;AAC5C,MAAMC,oBAAuC,EAAE;AAE/C,MAAMC,mBAAmB;IACrB,IAAIC,OAAO,OAAO,CAACH,aAAa,MAAM,GAAG,GACrCC,kBAAkB,OAAO,CAACG,CAAAA;QACtBA;IACJ;IAEJJ,cAAc,CAAC;AACnB;AAEA,IAAIK;AAGAA,WADA,AAA0B,MAA1B,OAAOC,iBACI;IACP,SAAS,KAAO;IAChB,WAAW,KAAO;AACtB,IAEW,IAAIA,eAAeC,CAAAA;IAC1B,KAAK,MAAMH,SAASG,QAAS;QACzB,MAAMC,KAAKJ,MAAM,MAAM;QACvB,MAAMK,KAAKD,GAAG,YAAY,CAAC;QAC3B,IAAIC,IACAT,WAAW,CAACS,GAAG,GAAGD,GAAG,qBAAqB;IAElD;IACAE,sBAAsBR;AAC1B;AAGG,MAAMS,iBAAiB;IAC1B,SAAS,CAACC;QACNP,SAAS,OAAO,CAACO;IACrB;IACA,WAAW,CAACA;QACRP,SAAS,SAAS,CAACO;IACvB;IACA,UAAU,CAACC;QACPZ,kBAAkB,IAAI,CAACY;IAC3B;AACJ"}
@@ -4,7 +4,7 @@ const asset = (crop)=>({
4
4
  id: "f",
5
5
  src: "https://cdn/x/pic.jpg",
6
6
  name: "pic.jpg",
7
- type: "image/jpeg",
7
+ mimeType: "image/jpeg",
8
8
  size: 1,
9
9
  image: {
10
10
  width: 800,
@@ -1 +1 @@
1
- {"version":3,"file":"asset/deliveryUrl.test.js","sources":["../../src/asset/deliveryUrl.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { getAssetCropParam, getAssetUrl } from \"./deliveryUrl.js\";\n\nconst asset = (crop?: any) => ({\n id: \"f\",\n src: \"https://cdn/x/pic.jpg\",\n name: \"pic.jpg\",\n type: \"image/jpeg\",\n size: 1,\n image: { width: 800, height: 600, ...(crop ? { crop } : {}) }\n});\n\ndescribe(\"getAssetCropParam\", () => {\n it(\"serializes a crop as top,left,bottom,right\", () => {\n expect(getAssetCropParam(asset({ top: 0.1, left: 0.2, bottom: 0.1, right: 0.05 }))).toBe(\n \"0.1,0.2,0.1,0.05\"\n );\n });\n\n it(\"is undefined for no crop or a full crop\", () => {\n expect(getAssetCropParam(asset())).toBeUndefined();\n expect(getAssetCropParam(asset({ top: 0, left: 0, bottom: 0, right: 0 }))).toBeUndefined();\n expect(getAssetCropParam(null)).toBeUndefined();\n });\n});\n\ndescribe(\"getAssetUrl\", () => {\n it(\"bakes the crop + width + format into the URL\", () => {\n const url = getAssetUrl(asset({ top: 0.1, left: 0.2, bottom: 0.1, right: 0.05 }), {\n width: 1200,\n format: \"auto\"\n });\n expect(url).toBe(\"https://cdn/x/pic.jpg?crop=0.1,0.2,0.1,0.05&width=1200&format=auto\");\n });\n\n it(\"omits the crop when there is none\", () => {\n expect(getAssetUrl(asset(), { width: 640 })).toBe(\"https://cdn/x/pic.jpg?width=640\");\n });\n\n it(\"can opt out of the crop\", () => {\n expect(\n getAssetUrl(asset({ top: 0.1, left: 0, bottom: 0, right: 0 }), { crop: false })\n ).toBe(\"https://cdn/x/pic.jpg\");\n });\n\n it(\"returns the bare src when no options apply\", () => {\n expect(getAssetUrl(asset())).toBe(\"https://cdn/x/pic.jpg\");\n });\n\n it(\"uses & when the src already has a query string\", () => {\n const url = getAssetUrl(\n { src: \"https://cdn/x/pic.jpg?v=2\", image: {} },\n {\n width: 640\n }\n );\n expect(url).toBe(\"https://cdn/x/pic.jpg?v=2&width=640\");\n });\n\n it(\"returns empty string for a missing asset\", () => {\n expect(getAssetUrl(null)).toBe(\"\");\n expect(getAssetUrl(undefined)).toBe(\"\");\n });\n\n it(\"emits aspectRatio + focal (from the asset) when framing to a ratio\", () => {\n const a = {\n ...asset(),\n image: { width: 800, height: 600, focalPoint: { x: 0.7, y: 0.4 } }\n };\n expect(getAssetUrl(a, { aspectRatio: \"16:9\", width: 1200 })).toBe(\n \"https://cdn/x/pic.jpg?aspectRatio=16:9&focal=0.7,0.4&width=1200\"\n );\n });\n\n it(\"omits focal when it is centered or opted out\", () => {\n const centered = { ...asset(), image: { focalPoint: { x: 0.5, y: 0.5 } } };\n expect(getAssetUrl(centered, { aspectRatio: 1 })).toBe(\n \"https://cdn/x/pic.jpg?aspectRatio=1\"\n );\n const offCenter = { ...asset(), image: { focalPoint: { x: 0.7, y: 0.4 } } };\n expect(getAssetUrl(offCenter, { aspectRatio: 1, focal: false })).toBe(\n \"https://cdn/x/pic.jpg?aspectRatio=1\"\n );\n });\n});\n"],"names":["asset","crop","describe","it","expect","getAssetCropParam","url","getAssetUrl","undefined","a","centered","offCenter"],"mappings":";;AAGA,MAAMA,QAAQ,CAACC,OAAgB;QAC3B,IAAI;QACJ,KAAK;QACL,MAAM;QACN,MAAM;QACN,MAAM;QACN,OAAO;YAAE,OAAO;YAAK,QAAQ;YAAK,GAAIA,OAAO;gBAAEA;YAAK,IAAI,CAAC,CAAC;QAAE;IAChE;AAEAC,SAAS,qBAAqB;IAC1BC,GAAG,8CAA8C;QAC7CC,OAAOC,kBAAkBL,MAAM;YAAE,KAAK;YAAK,MAAM;YAAK,QAAQ;YAAK,OAAO;QAAK,KAAK,IAAI,CACpF;IAER;IAEAG,GAAG,2CAA2C;QAC1CC,OAAOC,kBAAkBL,UAAU,aAAa;QAChDI,OAAOC,kBAAkBL,MAAM;YAAE,KAAK;YAAG,MAAM;YAAG,QAAQ;YAAG,OAAO;QAAE,KAAK,aAAa;QACxFI,OAAOC,kBAAkB,OAAO,aAAa;IACjD;AACJ;AAEAH,SAAS,eAAe;IACpBC,GAAG,gDAAgD;QAC/C,MAAMG,MAAMC,YAAYP,MAAM;YAAE,KAAK;YAAK,MAAM;YAAK,QAAQ;YAAK,OAAO;QAAK,IAAI;YAC9E,OAAO;YACP,QAAQ;QACZ;QACAI,OAAOE,KAAK,IAAI,CAAC;IACrB;IAEAH,GAAG,qCAAqC;QACpCC,OAAOG,YAAYP,SAAS;YAAE,OAAO;QAAI,IAAI,IAAI,CAAC;IACtD;IAEAG,GAAG,2BAA2B;QAC1BC,OACIG,YAAYP,MAAM;YAAE,KAAK;YAAK,MAAM;YAAG,QAAQ;YAAG,OAAO;QAAE,IAAI;YAAE,MAAM;QAAM,IAC/E,IAAI,CAAC;IACX;IAEAG,GAAG,8CAA8C;QAC7CC,OAAOG,YAAYP,UAAU,IAAI,CAAC;IACtC;IAEAG,GAAG,kDAAkD;QACjD,MAAMG,MAAMC,YACR;YAAE,KAAK;YAA6B,OAAO,CAAC;QAAE,GAC9C;YACI,OAAO;QACX;QAEJH,OAAOE,KAAK,IAAI,CAAC;IACrB;IAEAH,GAAG,4CAA4C;QAC3CC,OAAOG,YAAY,OAAO,IAAI,CAAC;QAC/BH,OAAOG,YAAYC,SAAY,IAAI,CAAC;IACxC;IAEAL,GAAG,sEAAsE;QACrE,MAAMM,IAAI;YACN,GAAGT,OAAO;YACV,OAAO;gBAAE,OAAO;gBAAK,QAAQ;gBAAK,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YAAE;QACrE;QACAI,OAAOG,YAAYE,GAAG;YAAE,aAAa;YAAQ,OAAO;QAAK,IAAI,IAAI,CAC7D;IAER;IAEAN,GAAG,gDAAgD;QAC/C,MAAMO,WAAW;YAAE,GAAGV,OAAO;YAAE,OAAO;gBAAE,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YAAE;QAAE;QACzEI,OAAOG,YAAYG,UAAU;YAAE,aAAa;QAAE,IAAI,IAAI,CAClD;QAEJ,MAAMC,YAAY;YAAE,GAAGX,OAAO;YAAE,OAAO;gBAAE,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YAAE;QAAE;QAC1EI,OAAOG,YAAYI,WAAW;YAAE,aAAa;YAAG,OAAO;QAAM,IAAI,IAAI,CACjE;IAER;AACJ"}
1
+ {"version":3,"file":"asset/deliveryUrl.test.js","sources":["../../src/asset/deliveryUrl.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { getAssetCropParam, getAssetUrl } from \"./deliveryUrl.js\";\n\nconst asset = (crop?: any) => ({\n id: \"f\",\n src: \"https://cdn/x/pic.jpg\",\n name: \"pic.jpg\",\n mimeType: \"image/jpeg\",\n size: 1,\n image: { width: 800, height: 600, ...(crop ? { crop } : {}) }\n});\n\ndescribe(\"getAssetCropParam\", () => {\n it(\"serializes a crop as top,left,bottom,right\", () => {\n expect(getAssetCropParam(asset({ top: 0.1, left: 0.2, bottom: 0.1, right: 0.05 }))).toBe(\n \"0.1,0.2,0.1,0.05\"\n );\n });\n\n it(\"is undefined for no crop or a full crop\", () => {\n expect(getAssetCropParam(asset())).toBeUndefined();\n expect(getAssetCropParam(asset({ top: 0, left: 0, bottom: 0, right: 0 }))).toBeUndefined();\n expect(getAssetCropParam(null)).toBeUndefined();\n });\n});\n\ndescribe(\"getAssetUrl\", () => {\n it(\"bakes the crop + width + format into the URL\", () => {\n const url = getAssetUrl(asset({ top: 0.1, left: 0.2, bottom: 0.1, right: 0.05 }), {\n width: 1200,\n format: \"auto\"\n });\n expect(url).toBe(\"https://cdn/x/pic.jpg?crop=0.1,0.2,0.1,0.05&width=1200&format=auto\");\n });\n\n it(\"omits the crop when there is none\", () => {\n expect(getAssetUrl(asset(), { width: 640 })).toBe(\"https://cdn/x/pic.jpg?width=640\");\n });\n\n it(\"can opt out of the crop\", () => {\n expect(\n getAssetUrl(asset({ top: 0.1, left: 0, bottom: 0, right: 0 }), { crop: false })\n ).toBe(\"https://cdn/x/pic.jpg\");\n });\n\n it(\"returns the bare src when no options apply\", () => {\n expect(getAssetUrl(asset())).toBe(\"https://cdn/x/pic.jpg\");\n });\n\n it(\"uses & when the src already has a query string\", () => {\n const url = getAssetUrl(\n { src: \"https://cdn/x/pic.jpg?v=2\", image: {} },\n {\n width: 640\n }\n );\n expect(url).toBe(\"https://cdn/x/pic.jpg?v=2&width=640\");\n });\n\n it(\"returns empty string for a missing asset\", () => {\n expect(getAssetUrl(null)).toBe(\"\");\n expect(getAssetUrl(undefined)).toBe(\"\");\n });\n\n it(\"emits aspectRatio + focal (from the asset) when framing to a ratio\", () => {\n const a = {\n ...asset(),\n image: { width: 800, height: 600, focalPoint: { x: 0.7, y: 0.4 } }\n };\n expect(getAssetUrl(a, { aspectRatio: \"16:9\", width: 1200 })).toBe(\n \"https://cdn/x/pic.jpg?aspectRatio=16:9&focal=0.7,0.4&width=1200\"\n );\n });\n\n it(\"omits focal when it is centered or opted out\", () => {\n const centered = { ...asset(), image: { focalPoint: { x: 0.5, y: 0.5 } } };\n expect(getAssetUrl(centered, { aspectRatio: 1 })).toBe(\n \"https://cdn/x/pic.jpg?aspectRatio=1\"\n );\n const offCenter = { ...asset(), image: { focalPoint: { x: 0.7, y: 0.4 } } };\n expect(getAssetUrl(offCenter, { aspectRatio: 1, focal: false })).toBe(\n \"https://cdn/x/pic.jpg?aspectRatio=1\"\n );\n });\n});\n"],"names":["asset","crop","describe","it","expect","getAssetCropParam","url","getAssetUrl","undefined","a","centered","offCenter"],"mappings":";;AAGA,MAAMA,QAAQ,CAACC,OAAgB;QAC3B,IAAI;QACJ,KAAK;QACL,MAAM;QACN,UAAU;QACV,MAAM;QACN,OAAO;YAAE,OAAO;YAAK,QAAQ;YAAK,GAAIA,OAAO;gBAAEA;YAAK,IAAI,CAAC,CAAC;QAAE;IAChE;AAEAC,SAAS,qBAAqB;IAC1BC,GAAG,8CAA8C;QAC7CC,OAAOC,kBAAkBL,MAAM;YAAE,KAAK;YAAK,MAAM;YAAK,QAAQ;YAAK,OAAO;QAAK,KAAK,IAAI,CACpF;IAER;IAEAG,GAAG,2CAA2C;QAC1CC,OAAOC,kBAAkBL,UAAU,aAAa;QAChDI,OAAOC,kBAAkBL,MAAM;YAAE,KAAK;YAAG,MAAM;YAAG,QAAQ;YAAG,OAAO;QAAE,KAAK,aAAa;QACxFI,OAAOC,kBAAkB,OAAO,aAAa;IACjD;AACJ;AAEAH,SAAS,eAAe;IACpBC,GAAG,gDAAgD;QAC/C,MAAMG,MAAMC,YAAYP,MAAM;YAAE,KAAK;YAAK,MAAM;YAAK,QAAQ;YAAK,OAAO;QAAK,IAAI;YAC9E,OAAO;YACP,QAAQ;QACZ;QACAI,OAAOE,KAAK,IAAI,CAAC;IACrB;IAEAH,GAAG,qCAAqC;QACpCC,OAAOG,YAAYP,SAAS;YAAE,OAAO;QAAI,IAAI,IAAI,CAAC;IACtD;IAEAG,GAAG,2BAA2B;QAC1BC,OACIG,YAAYP,MAAM;YAAE,KAAK;YAAK,MAAM;YAAG,QAAQ;YAAG,OAAO;QAAE,IAAI;YAAE,MAAM;QAAM,IAC/E,IAAI,CAAC;IACX;IAEAG,GAAG,8CAA8C;QAC7CC,OAAOG,YAAYP,UAAU,IAAI,CAAC;IACtC;IAEAG,GAAG,kDAAkD;QACjD,MAAMG,MAAMC,YACR;YAAE,KAAK;YAA6B,OAAO,CAAC;QAAE,GAC9C;YACI,OAAO;QACX;QAEJH,OAAOE,KAAK,IAAI,CAAC;IACrB;IAEAH,GAAG,4CAA4C;QAC3CC,OAAOG,YAAY,OAAO,IAAI,CAAC;QAC/BH,OAAOG,YAAYC,SAAY,IAAI,CAAC;IACxC;IAEAL,GAAG,sEAAsE;QACrE,MAAMM,IAAI;YACN,GAAGT,OAAO;YACV,OAAO;gBAAE,OAAO;gBAAK,QAAQ;gBAAK,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YAAE;QACrE;QACAI,OAAOG,YAAYE,GAAG;YAAE,aAAa;YAAQ,OAAO;QAAK,IAAI,IAAI,CAC7D;IAER;IAEAN,GAAG,gDAAgD;QAC/C,MAAMO,WAAW;YAAE,GAAGV,OAAO;YAAE,OAAO;gBAAE,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YAAE;QAAE;QACzEI,OAAOG,YAAYG,UAAU;YAAE,aAAa;QAAE,IAAI,IAAI,CAClD;QAEJ,MAAMC,YAAY;YAAE,GAAGX,OAAO;YAAE,OAAO;gBAAE,YAAY;oBAAE,GAAG;oBAAK,GAAG;gBAAI;YAAE;QAAE;QAC1EI,OAAOG,YAAYI,WAAW;YAAE,aAAa;YAAG,OAAO;QAAM,IAAI,IAAI,CACjE;IAER;AACJ"}
@@ -4,7 +4,7 @@ const asset = (image)=>({
4
4
  id: "f",
5
5
  src: "https://cdn/x/pic.jpg",
6
6
  name: "pic.jpg",
7
- type: "image/jpeg",
7
+ mimeType: "image/jpeg",
8
8
  size: 1,
9
9
  image: {
10
10
  width: 800,
@@ -1 +1 @@
1
- {"version":3,"file":"asset/imageSrcSet.test.js","sources":["../../src/asset/imageSrcSet.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { IMAGE_RESIZE_WIDTHS, getImageDimensions, getImageSrcSet } from \"./imageSrcSet.js\";\n\nconst asset = (image?: any) => ({\n id: \"f\",\n src: \"https://cdn/x/pic.jpg\",\n name: \"pic.jpg\",\n type: \"image/jpeg\",\n size: 1,\n image: { width: 800, height: 600, ...image }\n});\n\ndescribe(\"getImageDimensions\", () => {\n it(\"returns intrinsic dimensions when there is no crop\", () => {\n expect(getImageDimensions(asset())).toEqual({ width: 800, height: 600 });\n });\n\n it(\"shrinks by the crop insets\", () => {\n expect(\n getImageDimensions(asset({ crop: { top: 0.1, left: 0.25, bottom: 0.1, right: 0.25 } }))\n ).toEqual({ width: 400, height: 480 });\n });\n\n it(\"derives height from a target aspect ratio\", () => {\n // Cropped width 400 @ 16:9 -> height 225.\n expect(\n getImageDimensions(asset({ crop: { top: 0, left: 0.25, bottom: 0, right: 0.25 } }), {\n aspectRatio: \"16:9\"\n })\n ).toEqual({ width: 400, height: 225 });\n });\n\n it(\"returns 0/0 when the intrinsic size is unknown\", () => {\n expect(getImageDimensions({ image: {} })).toEqual({ width: 0, height: 0 });\n expect(getImageDimensions(null)).toEqual({ width: 0, height: 0 });\n });\n});\n\ndescribe(\"getImageSrcSet\", () => {\n it(\"emits the full ladder with crop + format baked into every width\", () => {\n const { srcSet, width, height } = getImageSrcSet(\n asset({ crop: { top: 0.1, left: 0, bottom: 0, right: 0 } }),\n { format: \"auto\" }\n );\n const entries = srcSet.split(\", \");\n expect(entries).toHaveLength(IMAGE_RESIZE_WIDTHS.length);\n expect(entries[0]).toBe(\"https://cdn/x/pic.jpg?crop=0.1,0,0,0&width=128&format=auto 128w\");\n expect(width).toBe(800);\n expect(height).toBe(540);\n });\n\n it(\"trims the ladder to a fixed CSS width (incl. 2x DPR)\", () => {\n const { srcSet, src } = getImageSrcSet(asset(), { cssWidth: \"300px\" });\n const widths = srcSet.split(\", \").map(e => Number(e.match(/width=(\\d+)/)![1]));\n // Smallest set covering 300px up to 2x (600) -> 128, 384, 640.\n expect(widths).toEqual([128, 384, 640]);\n // `src` fallback is the largest emitted width.\n expect(src).toBe(\"https://cdn/x/pic.jpg?width=640\");\n });\n\n it(\"returns empty strings for a missing asset\", () => {\n expect(getImageSrcSet(null)).toEqual({ src: \"\", srcSet: \"\", width: 0, height: 0 });\n });\n});\n"],"names":["asset","image","describe","it","expect","getImageDimensions","srcSet","width","height","getImageSrcSet","entries","IMAGE_RESIZE_WIDTHS","src","widths","e","Number"],"mappings":";;AAGA,MAAMA,QAAQ,CAACC,QAAiB;QAC5B,IAAI;QACJ,KAAK;QACL,MAAM;QACN,MAAM;QACN,MAAM;QACN,OAAO;YAAE,OAAO;YAAK,QAAQ;YAAK,GAAGA,KAAK;QAAC;IAC/C;AAEAC,SAAS,sBAAsB;IAC3BC,GAAG,sDAAsD;QACrDC,OAAOC,mBAAmBL,UAAU,OAAO,CAAC;YAAE,OAAO;YAAK,QAAQ;QAAI;IAC1E;IAEAG,GAAG,8BAA8B;QAC7BC,OACIC,mBAAmBL,MAAM;YAAE,MAAM;gBAAE,KAAK;gBAAK,MAAM;gBAAM,QAAQ;gBAAK,OAAO;YAAK;QAAE,KACtF,OAAO,CAAC;YAAE,OAAO;YAAK,QAAQ;QAAI;IACxC;IAEAG,GAAG,6CAA6C;QAE5CC,OACIC,mBAAmBL,MAAM;YAAE,MAAM;gBAAE,KAAK;gBAAG,MAAM;gBAAM,QAAQ;gBAAG,OAAO;YAAK;QAAE,IAAI;YAChF,aAAa;QACjB,IACF,OAAO,CAAC;YAAE,OAAO;YAAK,QAAQ;QAAI;IACxC;IAEAG,GAAG,kDAAkD;QACjDC,OAAOC,mBAAmB;YAAE,OAAO,CAAC;QAAE,IAAI,OAAO,CAAC;YAAE,OAAO;YAAG,QAAQ;QAAE;QACxED,OAAOC,mBAAmB,OAAO,OAAO,CAAC;YAAE,OAAO;YAAG,QAAQ;QAAE;IACnE;AACJ;AAEAH,SAAS,kBAAkB;IACvBC,GAAG,mEAAmE;QAClE,MAAM,EAAEG,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGC,eAC9BT,MAAM;YAAE,MAAM;gBAAE,KAAK;gBAAK,MAAM;gBAAG,QAAQ;gBAAG,OAAO;YAAE;QAAE,IACzD;YAAE,QAAQ;QAAO;QAErB,MAAMU,UAAUJ,OAAO,KAAK,CAAC;QAC7BF,OAAOM,SAAS,YAAY,CAACC,oBAAoB,MAAM;QACvDP,OAAOM,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC;QACxBN,OAAOG,OAAO,IAAI,CAAC;QACnBH,OAAOI,QAAQ,IAAI,CAAC;IACxB;IAEAL,GAAG,wDAAwD;QACvD,MAAM,EAAEG,MAAM,EAAEM,GAAG,EAAE,GAAGH,eAAeT,SAAS;YAAE,UAAU;QAAQ;QACpE,MAAMa,SAASP,OAAO,KAAK,CAAC,MAAM,GAAG,CAACQ,CAAAA,IAAKC,OAAOD,EAAE,KAAK,CAAC,cAAe,CAAC,EAAE;QAE5EV,OAAOS,QAAQ,OAAO,CAAC;YAAC;YAAK;YAAK;SAAI;QAEtCT,OAAOQ,KAAK,IAAI,CAAC;IACrB;IAEAT,GAAG,6CAA6C;QAC5CC,OAAOK,eAAe,OAAO,OAAO,CAAC;YAAE,KAAK;YAAI,QAAQ;YAAI,OAAO;YAAG,QAAQ;QAAE;IACpF;AACJ"}
1
+ {"version":3,"file":"asset/imageSrcSet.test.js","sources":["../../src/asset/imageSrcSet.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport { IMAGE_RESIZE_WIDTHS, getImageDimensions, getImageSrcSet } from \"./imageSrcSet.js\";\n\nconst asset = (image?: any) => ({\n id: \"f\",\n src: \"https://cdn/x/pic.jpg\",\n name: \"pic.jpg\",\n mimeType: \"image/jpeg\",\n size: 1,\n image: { width: 800, height: 600, ...image }\n});\n\ndescribe(\"getImageDimensions\", () => {\n it(\"returns intrinsic dimensions when there is no crop\", () => {\n expect(getImageDimensions(asset())).toEqual({ width: 800, height: 600 });\n });\n\n it(\"shrinks by the crop insets\", () => {\n expect(\n getImageDimensions(asset({ crop: { top: 0.1, left: 0.25, bottom: 0.1, right: 0.25 } }))\n ).toEqual({ width: 400, height: 480 });\n });\n\n it(\"derives height from a target aspect ratio\", () => {\n // Cropped width 400 @ 16:9 -> height 225.\n expect(\n getImageDimensions(asset({ crop: { top: 0, left: 0.25, bottom: 0, right: 0.25 } }), {\n aspectRatio: \"16:9\"\n })\n ).toEqual({ width: 400, height: 225 });\n });\n\n it(\"returns 0/0 when the intrinsic size is unknown\", () => {\n expect(getImageDimensions({ image: {} })).toEqual({ width: 0, height: 0 });\n expect(getImageDimensions(null)).toEqual({ width: 0, height: 0 });\n });\n});\n\ndescribe(\"getImageSrcSet\", () => {\n it(\"emits the full ladder with crop + format baked into every width\", () => {\n const { srcSet, width, height } = getImageSrcSet(\n asset({ crop: { top: 0.1, left: 0, bottom: 0, right: 0 } }),\n { format: \"auto\" }\n );\n const entries = srcSet.split(\", \");\n expect(entries).toHaveLength(IMAGE_RESIZE_WIDTHS.length);\n expect(entries[0]).toBe(\"https://cdn/x/pic.jpg?crop=0.1,0,0,0&width=128&format=auto 128w\");\n expect(width).toBe(800);\n expect(height).toBe(540);\n });\n\n it(\"trims the ladder to a fixed CSS width (incl. 2x DPR)\", () => {\n const { srcSet, src } = getImageSrcSet(asset(), { cssWidth: \"300px\" });\n const widths = srcSet.split(\", \").map(e => Number(e.match(/width=(\\d+)/)![1]));\n // Smallest set covering 300px up to 2x (600) -> 128, 384, 640.\n expect(widths).toEqual([128, 384, 640]);\n // `src` fallback is the largest emitted width.\n expect(src).toBe(\"https://cdn/x/pic.jpg?width=640\");\n });\n\n it(\"returns empty strings for a missing asset\", () => {\n expect(getImageSrcSet(null)).toEqual({ src: \"\", srcSet: \"\", width: 0, height: 0 });\n });\n});\n"],"names":["asset","image","describe","it","expect","getImageDimensions","srcSet","width","height","getImageSrcSet","entries","IMAGE_RESIZE_WIDTHS","src","widths","e","Number"],"mappings":";;AAGA,MAAMA,QAAQ,CAACC,QAAiB;QAC5B,IAAI;QACJ,KAAK;QACL,MAAM;QACN,UAAU;QACV,MAAM;QACN,OAAO;YAAE,OAAO;YAAK,QAAQ;YAAK,GAAGA,KAAK;QAAC;IAC/C;AAEAC,SAAS,sBAAsB;IAC3BC,GAAG,sDAAsD;QACrDC,OAAOC,mBAAmBL,UAAU,OAAO,CAAC;YAAE,OAAO;YAAK,QAAQ;QAAI;IAC1E;IAEAG,GAAG,8BAA8B;QAC7BC,OACIC,mBAAmBL,MAAM;YAAE,MAAM;gBAAE,KAAK;gBAAK,MAAM;gBAAM,QAAQ;gBAAK,OAAO;YAAK;QAAE,KACtF,OAAO,CAAC;YAAE,OAAO;YAAK,QAAQ;QAAI;IACxC;IAEAG,GAAG,6CAA6C;QAE5CC,OACIC,mBAAmBL,MAAM;YAAE,MAAM;gBAAE,KAAK;gBAAG,MAAM;gBAAM,QAAQ;gBAAG,OAAO;YAAK;QAAE,IAAI;YAChF,aAAa;QACjB,IACF,OAAO,CAAC;YAAE,OAAO;YAAK,QAAQ;QAAI;IACxC;IAEAG,GAAG,kDAAkD;QACjDC,OAAOC,mBAAmB;YAAE,OAAO,CAAC;QAAE,IAAI,OAAO,CAAC;YAAE,OAAO;YAAG,QAAQ;QAAE;QACxED,OAAOC,mBAAmB,OAAO,OAAO,CAAC;YAAE,OAAO;YAAG,QAAQ;QAAE;IACnE;AACJ;AAEAH,SAAS,kBAAkB;IACvBC,GAAG,mEAAmE;QAClE,MAAM,EAAEG,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGC,eAC9BT,MAAM;YAAE,MAAM;gBAAE,KAAK;gBAAK,MAAM;gBAAG,QAAQ;gBAAG,OAAO;YAAE;QAAE,IACzD;YAAE,QAAQ;QAAO;QAErB,MAAMU,UAAUJ,OAAO,KAAK,CAAC;QAC7BF,OAAOM,SAAS,YAAY,CAACC,oBAAoB,MAAM;QACvDP,OAAOM,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC;QACxBN,OAAOG,OAAO,IAAI,CAAC;QACnBH,OAAOI,QAAQ,IAAI,CAAC;IACxB;IAEAL,GAAG,wDAAwD;QACvD,MAAM,EAAEG,MAAM,EAAEM,GAAG,EAAE,GAAGH,eAAeT,SAAS;YAAE,UAAU;QAAQ;QACpE,MAAMa,SAASP,OAAO,KAAK,CAAC,MAAM,GAAG,CAACQ,CAAAA,IAAKC,OAAOD,EAAE,KAAK,CAAC,cAAe,CAAC,EAAE;QAE5EV,OAAOS,QAAQ,OAAO,CAAC;YAAC;YAAK;YAAK;SAAI;QAEtCT,OAAOQ,KAAK,IAAI,CAAC;IACrB;IAEAT,GAAG,6CAA6C;QAC5CC,OAAOK,eAAe,OAAO,OAAO,CAAC;YAAE,KAAK;YAAI,QAAQ;YAAI,OAAO;YAAG,QAAQ;QAAE;IACpF;AACJ"}
@@ -1,5 +1,5 @@
1
1
  import type { Asset, AssetCategory, AssetImage } from "./types.js";
2
- export declare function getAssetCategory(type?: string | null): AssetCategory;
2
+ export declare function getAssetCategory(mimeType?: string | null): AssetCategory;
3
3
  interface LegacyImageEdit {
4
4
  crop?: {
5
5
  top: number;
@@ -1,7 +1,7 @@
1
- function getAssetCategory(type) {
2
- if ("string" == typeof type) {
3
- if (type.startsWith("image/")) return "image";
4
- if (type.startsWith("video/")) return "video";
1
+ function getAssetCategory(mimeType) {
2
+ if ("string" == typeof mimeType) {
3
+ if (mimeType.startsWith("image/")) return "image";
4
+ if (mimeType.startsWith("video/")) return "video";
5
5
  }
6
6
  return "document";
7
7
  }
@@ -55,35 +55,39 @@ const normalizeAssetImage = (raw)=>{
55
55
  if (caption) image.caption = caption;
56
56
  return Object.keys(image).length > 0 ? image : void 0;
57
57
  };
58
- const buildBase = (raw, type)=>{
58
+ const buildBase = (raw, mimeType)=>{
59
59
  const src = asString(raw.src) ?? "";
60
60
  return {
61
61
  id: asString(raw.id) ?? "",
62
62
  src,
63
63
  url: asString(raw.url) ?? src,
64
64
  name: asString(raw.name) ?? "",
65
- type,
65
+ mimeType,
66
66
  size: asNumber(raw.size) ?? 0
67
67
  };
68
68
  };
69
+ const syncImageDimensions = (asset)=>{
70
+ if (!asset.image) return asset;
71
+ if (void 0 !== asset.image.width) asset.width = asset.image.width;
72
+ if (void 0 !== asset.image.height) asset.height = asset.image.height;
73
+ return asset;
74
+ };
69
75
  function normalizeToAsset(input) {
70
76
  if (!isObject(input)) return null;
71
77
  const hasTypedSubObject = isObject(input.image) || isObject(input.document) || isObject(input.video);
78
+ const mimeType = asString(input.mimeType) ?? "";
79
+ const asset = buildBase(input, mimeType);
80
+ const category = getAssetCategory(mimeType);
72
81
  if (!hasTypedSubObject) {
73
- const type = asString(input.mimeType) ?? asString(input.type) ?? "";
74
- const asset = buildBase(input, type);
75
- if ("image" === getAssetCategory(type)) {
82
+ if ("image" === category) {
76
83
  const image = assetImageFromLegacyEdit(input.edit, {
77
84
  width: asNumber(input.width),
78
85
  height: asNumber(input.height)
79
86
  });
80
87
  if (image) asset.image = image;
81
88
  }
82
- return asset;
89
+ return syncImageDimensions(asset);
83
90
  }
84
- const type = asString(input.type) ?? asString(input.mimeType) ?? "";
85
- const asset = buildBase(input, type);
86
- const category = getAssetCategory(type);
87
91
  if ("image" === category) {
88
92
  const image = normalizeAssetImage(input.image);
89
93
  if (image) asset.image = image;
@@ -95,7 +99,7 @@ function normalizeToAsset(input) {
95
99
  } else if (isObject(input.document)) asset.document = {
96
100
  pages: asNumber(input.document.pages)
97
101
  };
98
- return asset;
102
+ return syncImageDimensions(asset);
99
103
  }
100
104
  export { assetImageFromLegacyEdit, getAssetCategory, normalizeToAsset };
101
105