@scalar/workspace-store 0.17.1 → 0.18.1

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 (202) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/client.d.ts +31 -19
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +267 -88
  5. package/dist/client.js.map +3 -3
  6. package/dist/events/bus.d.ts +96 -0
  7. package/dist/events/bus.d.ts.map +1 -0
  8. package/dist/events/bus.js +60 -0
  9. package/dist/events/bus.js.map +7 -0
  10. package/dist/events/definitions/analytics.d.ts +27 -0
  11. package/dist/events/definitions/analytics.d.ts.map +1 -0
  12. package/dist/events/definitions/analytics.js +1 -0
  13. package/dist/events/definitions/analytics.js.map +7 -0
  14. package/dist/events/definitions/auth.d.ts +30 -0
  15. package/dist/events/definitions/auth.d.ts.map +1 -0
  16. package/dist/events/definitions/auth.js +1 -0
  17. package/dist/events/definitions/auth.js.map +7 -0
  18. package/dist/events/definitions/common.d.ts +5 -0
  19. package/dist/events/definitions/common.d.ts.map +1 -0
  20. package/dist/events/definitions/common.js +1 -0
  21. package/dist/events/definitions/common.js.map +7 -0
  22. package/dist/events/definitions/document.d.ts +14 -0
  23. package/dist/events/definitions/document.d.ts.map +1 -0
  24. package/dist/events/definitions/document.js +1 -0
  25. package/dist/events/definitions/document.js.map +7 -0
  26. package/dist/events/definitions/environment.d.ts +37 -0
  27. package/dist/events/definitions/environment.d.ts.map +1 -0
  28. package/dist/events/definitions/environment.js +1 -0
  29. package/dist/events/definitions/environment.js.map +7 -0
  30. package/dist/events/definitions/index.d.ts +12 -0
  31. package/dist/events/definitions/index.d.ts.map +1 -0
  32. package/dist/events/definitions/index.js +1 -0
  33. package/dist/events/definitions/index.js.map +7 -0
  34. package/dist/events/definitions/meta.d.ts +17 -0
  35. package/dist/events/definitions/meta.d.ts.map +1 -0
  36. package/dist/events/definitions/meta.js +1 -0
  37. package/dist/events/definitions/meta.js.map +7 -0
  38. package/dist/events/definitions/operation.d.ts +11 -0
  39. package/dist/events/definitions/operation.d.ts.map +1 -0
  40. package/dist/events/definitions/operation.js +1 -0
  41. package/dist/events/definitions/operation.js.map +7 -0
  42. package/dist/events/definitions/server.d.ts +50 -0
  43. package/dist/events/definitions/server.d.ts.map +1 -0
  44. package/dist/events/definitions/server.js +1 -0
  45. package/dist/events/definitions/server.js.map +7 -0
  46. package/dist/events/definitions/ui.d.ts +52 -0
  47. package/dist/events/definitions/ui.d.ts.map +1 -0
  48. package/dist/events/definitions/ui.js +1 -0
  49. package/dist/events/definitions/ui.js.map +7 -0
  50. package/dist/events/index.d.ts +3 -1
  51. package/dist/events/index.d.ts.map +1 -1
  52. package/dist/events/index.js +3 -1
  53. package/dist/events/index.js.map +2 -2
  54. package/dist/events/listeners.d.ts +2 -1
  55. package/dist/events/listeners.d.ts.map +1 -1
  56. package/dist/events/listeners.js.map +2 -2
  57. package/dist/events/{definitions.d.ts → old-definitions.d.ts} +35 -11
  58. package/dist/events/old-definitions.d.ts.map +1 -0
  59. package/dist/events/{definitions.js → old-definitions.js} +1 -1
  60. package/dist/events/old-definitions.js.map +7 -0
  61. package/dist/helpers/debounce.d.ts +28 -0
  62. package/dist/helpers/debounce.d.ts.map +1 -0
  63. package/dist/helpers/debounce.js +31 -0
  64. package/dist/helpers/debounce.js.map +7 -0
  65. package/dist/helpers/detect-changes-proxy.d.ts +47 -0
  66. package/dist/helpers/detect-changes-proxy.d.ts.map +1 -0
  67. package/dist/helpers/detect-changes-proxy.js +59 -0
  68. package/dist/helpers/detect-changes-proxy.js.map +7 -0
  69. package/dist/helpers/overrides-proxy.d.ts +17 -6
  70. package/dist/helpers/overrides-proxy.d.ts.map +1 -1
  71. package/dist/helpers/overrides-proxy.js +33 -18
  72. package/dist/helpers/overrides-proxy.js.map +3 -3
  73. package/dist/helpers/unpack-proxy.d.ts +6 -0
  74. package/dist/helpers/unpack-proxy.d.ts.map +1 -0
  75. package/dist/helpers/unpack-proxy.js +9 -0
  76. package/dist/helpers/unpack-proxy.js.map +7 -0
  77. package/dist/mutators/environment.d.ts +21 -13
  78. package/dist/mutators/environment.d.ts.map +1 -1
  79. package/dist/mutators/environment.js +46 -25
  80. package/dist/mutators/environment.js.map +2 -2
  81. package/dist/mutators/index.d.ts +4 -12
  82. package/dist/mutators/index.d.ts.map +1 -1
  83. package/dist/mutators/index.js +7 -4
  84. package/dist/mutators/index.js.map +2 -2
  85. package/dist/navigation/get-navigation-options.d.ts +1 -1
  86. package/dist/navigation/get-navigation-options.d.ts.map +1 -1
  87. package/dist/navigation/get-navigation-options.js +66 -54
  88. package/dist/navigation/get-navigation-options.js.map +2 -2
  89. package/dist/navigation/helpers/get-tag.d.ts +7 -2
  90. package/dist/navigation/helpers/get-tag.d.ts.map +1 -1
  91. package/dist/navigation/helpers/get-tag.js +16 -2
  92. package/dist/navigation/helpers/get-tag.js.map +2 -2
  93. package/dist/navigation/helpers/traverse-description.d.ts +7 -2
  94. package/dist/navigation/helpers/traverse-description.d.ts.map +1 -1
  95. package/dist/navigation/helpers/traverse-description.js +24 -6
  96. package/dist/navigation/helpers/traverse-description.js.map +2 -2
  97. package/dist/navigation/helpers/traverse-document.d.ts +5 -2
  98. package/dist/navigation/helpers/traverse-document.d.ts.map +1 -1
  99. package/dist/navigation/helpers/traverse-document.js +53 -15
  100. package/dist/navigation/helpers/traverse-document.js.map +2 -2
  101. package/dist/navigation/helpers/traverse-paths.d.ts +9 -3
  102. package/dist/navigation/helpers/traverse-paths.d.ts.map +1 -1
  103. package/dist/navigation/helpers/traverse-paths.js +63 -9
  104. package/dist/navigation/helpers/traverse-paths.js.map +2 -2
  105. package/dist/navigation/helpers/traverse-schemas.d.ts +7 -8
  106. package/dist/navigation/helpers/traverse-schemas.d.ts.map +1 -1
  107. package/dist/navigation/helpers/traverse-schemas.js +35 -7
  108. package/dist/navigation/helpers/traverse-schemas.js.map +2 -2
  109. package/dist/navigation/helpers/traverse-tags.d.ts +8 -4
  110. package/dist/navigation/helpers/traverse-tags.d.ts.map +1 -1
  111. package/dist/navigation/helpers/traverse-tags.js +65 -17
  112. package/dist/navigation/helpers/traverse-tags.js.map +2 -2
  113. package/dist/navigation/helpers/traverse-webhooks.d.ts +9 -3
  114. package/dist/navigation/helpers/traverse-webhooks.d.ts.map +1 -1
  115. package/dist/navigation/helpers/traverse-webhooks.js +43 -17
  116. package/dist/navigation/helpers/traverse-webhooks.js.map +2 -2
  117. package/dist/navigation/types.d.ts +5 -24
  118. package/dist/navigation/types.d.ts.map +1 -1
  119. package/dist/persistence/index.d.ts +86 -0
  120. package/dist/persistence/index.d.ts.map +1 -0
  121. package/dist/persistence/index.js +196 -0
  122. package/dist/persistence/index.js.map +7 -0
  123. package/dist/persistence/indexdb.d.ts +87 -0
  124. package/dist/persistence/indexdb.d.ts.map +1 -0
  125. package/dist/persistence/indexdb.js +125 -0
  126. package/dist/persistence/indexdb.js.map +7 -0
  127. package/dist/{plugins.d.ts → plugins/bundler/index.d.ts} +1 -1
  128. package/dist/plugins/bundler/index.d.ts.map +1 -0
  129. package/dist/{plugins.js → plugins/bundler/index.js} +2 -2
  130. package/dist/{plugins.js.map → plugins/bundler/index.js.map} +1 -1
  131. package/dist/plugins/client/index.d.ts +3 -0
  132. package/dist/plugins/client/index.d.ts.map +1 -0
  133. package/dist/plugins/client/index.js +5 -0
  134. package/dist/plugins/client/index.js.map +7 -0
  135. package/dist/plugins/client/persistence.d.ts +13 -0
  136. package/dist/plugins/client/persistence.d.ts.map +1 -0
  137. package/dist/plugins/client/persistence.js +57 -0
  138. package/dist/plugins/client/persistence.js.map +7 -0
  139. package/dist/schemas/extensions/document/x-scalar-environments.d.ts +52 -0
  140. package/dist/schemas/extensions/document/x-scalar-environments.d.ts.map +1 -0
  141. package/dist/schemas/extensions/document/x-scalar-environments.js +25 -0
  142. package/dist/schemas/extensions/document/x-scalar-environments.js.map +7 -0
  143. package/dist/schemas/extensions/workspace/x-scalar-active-environment.d.ts +8 -0
  144. package/dist/schemas/extensions/workspace/x-scalar-active-environment.d.ts.map +1 -0
  145. package/dist/schemas/extensions/workspace/x-scalar-active-environment.js +8 -0
  146. package/dist/schemas/extensions/workspace/x-scalar-active-environment.js.map +7 -0
  147. package/dist/schemas/extensions.d.ts +1 -0
  148. package/dist/schemas/extensions.d.ts.map +1 -1
  149. package/dist/schemas/extensions.js +1 -0
  150. package/dist/schemas/extensions.js.map +2 -2
  151. package/dist/schemas/inmemory-workspace.d.ts +95 -28
  152. package/dist/schemas/inmemory-workspace.d.ts.map +1 -1
  153. package/dist/schemas/inmemory-workspace.js +1 -9
  154. package/dist/schemas/inmemory-workspace.js.map +2 -2
  155. package/dist/schemas/navigation.d.ts +128 -1
  156. package/dist/schemas/navigation.d.ts.map +1 -1
  157. package/dist/schemas/navigation.js +20 -1
  158. package/dist/schemas/navigation.js.map +2 -2
  159. package/dist/schemas/reference-config/index.d.ts +243 -206
  160. package/dist/schemas/reference-config/index.d.ts.map +1 -1
  161. package/dist/schemas/reference-config/index.js.map +2 -2
  162. package/dist/schemas/reference-config/settings.d.ts +45 -9
  163. package/dist/schemas/reference-config/settings.d.ts.map +1 -1
  164. package/dist/schemas/reference-config/settings.js +1 -1
  165. package/dist/schemas/reference-config/settings.js.map +1 -1
  166. package/dist/schemas/v3.1/strict/openapi-document.d.ts +1540 -311
  167. package/dist/schemas/v3.1/strict/openapi-document.d.ts.map +1 -1
  168. package/dist/schemas/v3.1/strict/openapi-document.js +20 -13
  169. package/dist/schemas/v3.1/strict/openapi-document.js.map +2 -2
  170. package/dist/schemas/v3.1/strict/parameter.d.ts +23 -1
  171. package/dist/schemas/v3.1/strict/parameter.d.ts.map +1 -1
  172. package/dist/schemas/v3.1/strict/parameter.js +5 -1
  173. package/dist/schemas/v3.1/strict/parameter.js.map +2 -2
  174. package/dist/schemas/v3.1/strict/ref-definitions.d.ts +2 -0
  175. package/dist/schemas/v3.1/strict/ref-definitions.d.ts.map +1 -1
  176. package/dist/schemas/v3.1/strict/ref-definitions.js +4 -1
  177. package/dist/schemas/v3.1/strict/ref-definitions.js.map +2 -2
  178. package/dist/schemas/workspace-specification/config.d.ts +46 -15
  179. package/dist/schemas/workspace-specification/config.d.ts.map +1 -1
  180. package/dist/schemas/workspace-specification/config.js.map +1 -1
  181. package/dist/schemas/workspace-specification/index.d.ts +48 -11
  182. package/dist/schemas/workspace-specification/index.d.ts.map +1 -1
  183. package/dist/schemas/workspace.d.ts +353 -85
  184. package/dist/schemas/workspace.d.ts.map +1 -1
  185. package/dist/schemas/workspace.js +19 -11
  186. package/dist/schemas/workspace.js.map +2 -2
  187. package/dist/server.d.ts +4 -3
  188. package/dist/server.d.ts.map +1 -1
  189. package/dist/server.js +7 -6
  190. package/dist/server.js.map +2 -2
  191. package/dist/workspace-plugin.d.ts +49 -0
  192. package/dist/workspace-plugin.d.ts.map +1 -0
  193. package/dist/workspace-plugin.js +1 -0
  194. package/dist/workspace-plugin.js.map +7 -0
  195. package/package.json +26 -9
  196. package/dist/events/definitions.d.ts.map +0 -1
  197. package/dist/events/definitions.js.map +0 -7
  198. package/dist/plugins.d.ts.map +0 -1
  199. package/dist/schemas/v3.1/strict/client-config-extensions/x-scalar-client-config-environments.d.ts +0 -33
  200. package/dist/schemas/v3.1/strict/client-config-extensions/x-scalar-client-config-environments.d.ts.map +0 -1
  201. package/dist/schemas/v3.1/strict/client-config-extensions/x-scalar-client-config-environments.js +0 -23
  202. package/dist/schemas/v3.1/strict/client-config-extensions/x-scalar-client-config-environments.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/navigation/helpers/traverse-webhooks.ts"],
4
- "sourcesContent": ["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { objectKeys } from '@scalar/helpers/object/object-keys'\n\nimport { getResolvedRef } from '@/helpers/get-resolved-ref'\nimport { isDeprecatedOperation } from '@/navigation/helpers/traverse-paths'\nimport type { TagsMap, TraverseSpecOptions } from '@/navigation/types'\nimport type { TraversedWebhook } from '@/schemas/navigation'\nimport type { OpenApiDocument, TagObject } from '@/schemas/v3.1/strict/openapi-document'\n\nimport { getTag } from './get-tag'\n\n/** Creates a traversed webhook entry from an OpenAPI webhook object.\n *\n * @param ref - JSON pointer reference to the webhook in the OpenAPI document\n * @param method - HTTP method of the webhook\n * @param name - Name of the webhook, defaults to 'Unknown'\n * @param title - Title of the webhook, defaults to 'Unknown'\n * @param entitiesMap - Map to store webhook IDs and titles for mobile header navigation\n * @param getWebhookId - Function to generate unique IDs for webhooks\n * @param tag - Optional tag object associated with the webhook\n * @returns A traversed webhook entry with ID, title, name, method and reference\n */\nconst createWebhookEntry = (\n ref: string,\n method: HttpMethod,\n name = 'Unknown',\n title = 'Unknown',\n getWebhookId: TraverseSpecOptions['getWebhookId'],\n tag?: TagObject,\n isDeprecated?: boolean,\n): TraversedWebhook => {\n const id = getWebhookId({ name, method }, tag)\n\n const entry = {\n id,\n title,\n name,\n ref,\n method: method,\n type: 'webhook',\n isDeprecated,\n } satisfies TraversedWebhook\n\n return entry\n}\n\n/** Traverses the webhooks in an OpenAPI document to build an array of webhook entries.\n *\n * This function processes each webhook in the document to:\n * - Filter out internal webhooks (marked with x-internal) and webhooks to ignore (marked with x-scalar-ignore)\n * - Group webhooks by their tags\n * - Create webhook entries with unique references and IDs\n * - Store webhook IDs and titles for mobile header navigation\n *\n * @param content - The OpenAPI document to traverse\n * @param tagsMap - Map of tag names to arrays of traversed entries from operations\n * @param tagsDict - Dictionary mapping tag names to their OpenAPI tag objects\n * @param entitiesMap - Map to store webhook IDs and titles for mobile header navigation\n * @param getWebhookId - Function to generate unique IDs for webhooks\n * @returns Array of untagged webhook entries\n */\nexport const traverseWebhooks = (\n content: OpenApiDocument,\n /** The tag map from from traversing paths */\n tagsMap: TagsMap,\n getWebhookId: TraverseSpecOptions['getWebhookId'],\n): TraversedWebhook[] => {\n const untagged: TraversedWebhook[] = []\n\n // Traverse webhooks\n Object.entries(content.webhooks ?? {}).forEach(([name, pathItemObject]) => {\n const pathKeys = objectKeys(pathItemObject ?? {}).filter((key) => isHttpMethod(key))\n\n pathKeys.forEach((method) => {\n const _operation = pathItemObject?.[method]\n const operation = getResolvedRef(_operation)\n if (!operation) {\n return\n }\n\n // Skip if the operation is internal or scalar-ignore\n if (operation['x-internal'] || operation['x-scalar-ignore']) {\n return\n }\n\n const ref = `#/webhooks/${name}/${method}`\n\n if (operation.tags?.length) {\n operation.tags.forEach((tagName: string) => {\n const { tag } = getTag(tagsMap, tagName)\n tagsMap\n .get(tagName)\n ?.entries.push(\n createWebhookEntry(\n ref,\n method,\n name,\n operation.summary ?? name,\n getWebhookId,\n tag,\n isDeprecatedOperation(operation),\n ),\n )\n })\n }\n // Add to untagged\n else {\n untagged.push(\n createWebhookEntry(\n ref,\n method,\n name,\n operation.summary ?? name,\n getWebhookId,\n undefined,\n isDeprecatedOperation(operation),\n ),\n )\n }\n })\n })\n\n return untagged\n}\n"],
5
- "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAE3B,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AAKtC,SAAS,cAAc;AAavB,MAAM,qBAAqB,CACzB,KACA,QACA,OAAO,WACP,QAAQ,WACR,cACA,KACA,iBACqB;AACrB,QAAM,KAAK,aAAa,EAAE,MAAM,OAAO,GAAG,GAAG;AAE7C,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EACF;AAEA,SAAO;AACT;AAiBO,MAAM,mBAAmB,CAC9B,SAEA,SACA,iBACuB;AACvB,QAAM,WAA+B,CAAC;AAGtC,SAAO,QAAQ,QAAQ,YAAY,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,cAAc,MAAM;AACzE,UAAM,WAAW,WAAW,kBAAkB,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,aAAa,GAAG,CAAC;AAEnF,aAAS,QAAQ,CAAC,WAAW;AAC3B,YAAM,aAAa,iBAAiB,MAAM;AAC1C,YAAM,YAAY,eAAe,UAAU;AAC3C,UAAI,CAAC,WAAW;AACd;AAAA,MACF;AAGA,UAAI,UAAU,YAAY,KAAK,UAAU,iBAAiB,GAAG;AAC3D;AAAA,MACF;AAEA,YAAM,MAAM,cAAc,IAAI,IAAI,MAAM;AAExC,UAAI,UAAU,MAAM,QAAQ;AAC1B,kBAAU,KAAK,QAAQ,CAAC,YAAoB;AAC1C,gBAAM,EAAE,IAAI,IAAI,OAAO,SAAS,OAAO;AACvC,kBACG,IAAI,OAAO,GACV,QAAQ;AAAA,YACR;AAAA,cACE;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,WAAW;AAAA,cACrB;AAAA,cACA;AAAA,cACA,sBAAsB,SAAS;AAAA,YACjC;AAAA,UACF;AAAA,QACJ,CAAC;AAAA,MACH,OAEK;AACH,iBAAS;AAAA,UACP;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU,WAAW;AAAA,YACrB;AAAA,YACA;AAAA,YACA,sBAAsB,SAAS;AAAA,UACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;",
4
+ "sourcesContent": ["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { objectKeys } from '@scalar/helpers/object/object-keys'\n\nimport { getResolvedRef } from '@/helpers/get-resolved-ref'\nimport { isDeprecatedOperation } from '@/navigation/helpers/traverse-paths'\nimport type { TagsMap, TraverseSpecOptions } from '@/navigation/types'\nimport type { ParentTag, TraversedWebhook } from '@/schemas/navigation'\nimport type { OpenApiDocument, OperationObject, TagObject } from '@/schemas/v3.1/strict/openapi-document'\n\nimport { getTag } from './get-tag'\n\n/** Creates a traversed webhook entry from an OpenAPI webhook object.\n *\n * @param ref - JSON pointer reference to the webhook in the OpenAPI document\n * @param method - HTTP method of the webhook\n * @param name - Name of the webhook, defaults to 'Unknown'\n * @param title - Title of the webhook, defaults to 'Unknown'\n * @param entitiesMap - Map to store webhook IDs and titles for mobile header navigation\n * @param getWebhookId - Function to generate unique IDs for webhooks\n * @param tag - Optional tag object associated with the webhook\n * @returns A traversed webhook entry with ID, title, name, method and reference\n */\nconst createWebhookEntry = ({\n ref,\n method,\n name,\n title,\n generateId,\n parentTag,\n webhook,\n isDeprecated,\n parentId,\n}: {\n ref: string\n method: HttpMethod\n webhook: OperationObject\n name: string\n title: string\n generateId: TraverseSpecOptions['generateId']\n tag?: TagObject\n parentId: string\n parentTag?: ParentTag\n isDeprecated?: boolean\n}): TraversedWebhook => {\n const id = generateId({\n type: 'webhook',\n name,\n method,\n webhook: webhook,\n parentTag,\n parentId: parentId,\n })\n\n const entry = {\n id,\n title,\n name,\n ref,\n method: method,\n type: 'webhook',\n isDeprecated,\n } satisfies TraversedWebhook\n\n return entry\n}\n\n/** Traverses the webhooks in an OpenAPI document to build an array of webhook entries.\n *\n * This function processes each webhook in the document to:\n * - Filter out internal webhooks (marked with x-internal) and webhooks to ignore (marked with x-scalar-ignore)\n * - Group webhooks by their tags\n * - Create webhook entries with unique references and IDs\n * - Store webhook IDs and titles for mobile header navigation\n *\n * @param content - The OpenAPI document to traverse\n * @param tagsMap - Map of tag names to arrays of traversed entries from operations\n * @param tagsDict - Dictionary mapping tag names to their OpenAPI tag objects\n * @param entitiesMap - Map to store webhook IDs and titles for mobile header navigation\n * @param getWebhookId - Function to generate unique IDs for webhooks\n * @returns Array of untagged webhook entries\n */\nexport const traverseWebhooks = ({\n document,\n tagsMap,\n generateId,\n untaggedWebhooksParentId,\n documentId,\n}: {\n /** Openapi document */\n document: OpenApiDocument\n /** The tag map from from traversing paths */\n tagsMap: TagsMap\n generateId: TraverseSpecOptions['generateId']\n untaggedWebhooksParentId: string\n documentId: string\n}): TraversedWebhook[] => {\n const untagged: TraversedWebhook[] = []\n\n // Traverse webhooks\n Object.entries(document.webhooks ?? {}).forEach(([name, pathItemObject]) => {\n const pathKeys = objectKeys(pathItemObject ?? {}).filter((key) => isHttpMethod(key))\n\n pathKeys.forEach((method) => {\n const _operation = pathItemObject?.[method]\n const operation = getResolvedRef(_operation)\n if (!operation) {\n return\n }\n\n // Skip if the operation is internal or scalar-ignore\n if (operation['x-internal'] || operation['x-scalar-ignore']) {\n return\n }\n\n const ref = `#/webhooks/${name}/${method}`\n\n if (operation.tags?.length) {\n operation.tags.forEach((tagName: string) => {\n const { tag, id: tagId } = getTag({ tagsMap, name: tagName, documentId, generateId })\n tagsMap.get(tagName)?.entries.push(\n createWebhookEntry({\n ref,\n method,\n name,\n title: operation.summary ?? name,\n webhook: operation,\n generateId: generateId,\n parentTag: { tag, id: tagId },\n parentId: tagId,\n isDeprecated: isDeprecatedOperation(operation),\n }),\n )\n })\n }\n // Add to untagged\n else {\n untagged.push(\n createWebhookEntry({\n ref,\n method,\n name,\n title: operation.summary ?? name,\n generateId,\n isDeprecated: isDeprecatedOperation(operation),\n webhook: operation,\n parentId: untaggedWebhooksParentId,\n }),\n )\n }\n })\n })\n\n return untagged\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAE3B,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AAKtC,SAAS,cAAc;AAavB,MAAM,qBAAqB,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAWwB;AACtB,QAAM,KAAK,WAAW;AAAA,IACpB,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EACF;AAEA,SAAO;AACT;AAiBO,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAQ0B;AACxB,QAAM,WAA+B,CAAC;AAGtC,SAAO,QAAQ,SAAS,YAAY,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,MAAM,cAAc,MAAM;AAC1E,UAAM,WAAW,WAAW,kBAAkB,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,aAAa,GAAG,CAAC;AAEnF,aAAS,QAAQ,CAAC,WAAW;AAC3B,YAAM,aAAa,iBAAiB,MAAM;AAC1C,YAAM,YAAY,eAAe,UAAU;AAC3C,UAAI,CAAC,WAAW;AACd;AAAA,MACF;AAGA,UAAI,UAAU,YAAY,KAAK,UAAU,iBAAiB,GAAG;AAC3D;AAAA,MACF;AAEA,YAAM,MAAM,cAAc,IAAI,IAAI,MAAM;AAExC,UAAI,UAAU,MAAM,QAAQ;AAC1B,kBAAU,KAAK,QAAQ,CAAC,YAAoB;AAC1C,gBAAM,EAAE,KAAK,IAAI,MAAM,IAAI,OAAO,EAAE,SAAS,MAAM,SAAS,YAAY,WAAW,CAAC;AACpF,kBAAQ,IAAI,OAAO,GAAG,QAAQ;AAAA,YAC5B,mBAAmB;AAAA,cACjB;AAAA,cACA;AAAA,cACA;AAAA,cACA,OAAO,UAAU,WAAW;AAAA,cAC5B,SAAS;AAAA,cACT;AAAA,cACA,WAAW,EAAE,KAAK,IAAI,MAAM;AAAA,cAC5B,UAAU;AAAA,cACV,cAAc,sBAAsB,SAAS;AAAA,YAC/C,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH,OAEK;AACH,iBAAS;AAAA,UACP,mBAAmB;AAAA,YACjB;AAAA,YACA;AAAA,YACA;AAAA,YACA,OAAO,UAAU,WAAW;AAAA,YAC5B;AAAA,YACA,cAAc,sBAAsB,SAAS;AAAA,YAC7C,SAAS;AAAA,YACT,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,9 @@
1
- import type { TraversedEntry } from '../schemas/navigation.js';
2
- import type { OperationObject, TagObject } from '../schemas/v3.1/strict/openapi-document.js';
1
+ import type { IdGenerator, TraversedEntry } from '../schemas/navigation.js';
2
+ import type { TagObject } from '../schemas/v3.1/strict/openapi-document.js';
3
3
  /** Map of tagNames and their entries */
4
4
  export type TagsMap = Map<string, {
5
+ id: string;
6
+ parentId: string;
5
7
  tag: TagObject;
6
8
  entries: TraversedEntry[];
7
9
  }>;
@@ -26,28 +28,7 @@ export type TraverseSpecOptions = {
26
28
  operationsSorter?: 'alpha' | 'method' | ((a: OperationSortValue, b: OperationSortValue) => number);
27
29
  /** Whether to hide model schemas from the navigation */
28
30
  hideModels: boolean;
29
- /** Function to generate unique IDs for markdown headings */
30
- getHeadingId: (heading: {
31
- depth: number;
32
- value: string;
33
- slug?: string;
34
- }) => string;
35
- /** Function to generate unique IDs for operations */
36
- getOperationId: (operation: {
37
- path: string;
38
- method: string;
39
- } & OperationObject, parentTag: TagObject) => string;
40
- /** Function to generate unique IDs for webhooks */
41
- getWebhookId: (webhook: {
42
- name: string;
43
- method?: string;
44
- }, parentTag?: TagObject) => string;
45
- /** Function to generate unique IDs for models/schemas */
46
- getModelId: (model: {
47
- name?: string;
48
- }, parentTag?: TagObject) => string;
49
- /** Function to generate unique IDs for tags */
50
- getTagId: (tag: TagObject) => string;
31
+ generateId: IdGenerator;
51
32
  };
52
33
  export type Heading = {
53
34
  depth: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/navigation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AACxF,wCAAwC;AACxC,MAAM,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAAA;AAEhF,KAAK,kBAAkB,GAAG;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,2FAA2F;IAC3F,UAAU,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,KAAK,MAAM,CAAC,CAAA;IAE/D,sGAAsG;IACtG,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,kBAAkB,KAAK,MAAM,CAAC,CAAA;IAElG,wDAAwD;IACxD,UAAU,EAAE,OAAO,CAAA;IAEnB,4DAA4D;IAC5D,YAAY,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IAElF,qDAAqD;IACrD,cAAc,EAAE,CACd,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;KACf,GAAG,eAAe,EACnB,SAAS,EAAE,SAAS,KACjB,MAAM,CAAA;IAEX,mDAAmD;IACnD,YAAY,EAAE,CACZ,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,EACD,SAAS,CAAC,EAAE,SAAS,KAClB,MAAM,CAAA;IAEX,yDAAyD;IACzD,UAAU,EAAE,CACV,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,EACD,SAAS,CAAC,EAAE,SAAS,KAClB,MAAM,CAAA;IAEX,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/navigation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAEvE,wCAAwC;AACxC,MAAM,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAAA;AAE9G,KAAK,kBAAkB,GAAG;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,2FAA2F;IAC3F,UAAU,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,KAAK,MAAM,CAAC,CAAA;IAE/D,sGAAsG;IACtG,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,kBAAkB,KAAK,MAAM,CAAC,CAAA;IAElG,wDAAwD;IACxD,UAAU,EAAE,OAAO,CAAA;IAEnB,UAAU,EAAE,WAAW,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA"}
@@ -0,0 +1,86 @@
1
+ import type { InMemoryWorkspace } from '../schemas/inmemory-workspace.js';
2
+ import type { WorkspaceMeta } from '../schemas/workspace.js';
3
+ type WorkspaceStoreShape = {
4
+ name: string;
5
+ workspace: InMemoryWorkspace;
6
+ };
7
+ /**
8
+ * Creates the persistence layer for the workspace store using IndexedDB.
9
+ * This sets up all the required tables for storing workspace chunk information,
10
+ * such as workspace meta, documents, original documents, intermediate documents, overrides, etc.
11
+ * Each logical group (meta, documents, etc) gets its own table keyed appropriately for efficient sub-document access.
12
+ * Returns an object containing `meta`, `documents`, `originalDocuments`, `intermediateDocuments`, `overrides`,
13
+ * `documentMeta`, `documentConfigs`, and `workspace` sections, each exposing a `setItem` method
14
+ * for upsetting records, and in the case of `workspace`, also `getItem` and `deleteItem`.
15
+ */
16
+ export declare const createWorkspaceStorePersistence: () => Promise<{
17
+ close: () => void;
18
+ meta: {
19
+ /**
20
+ * Set meta data for a workspace.
21
+ */
22
+ setItem: (workspaceId: string, data: WorkspaceMeta) => Promise<void>;
23
+ };
24
+ documents: {
25
+ /**
26
+ * Set (persist) a workspace document using workspaceId and documentName as composite key.
27
+ */
28
+ setItem: (workspaceId: string, documentName: string, data: InMemoryWorkspace["documents"][string]) => Promise<void>;
29
+ };
30
+ originalDocuments: {
31
+ /**
32
+ * Set an original (raw) document for a workspace/document pair.
33
+ */
34
+ setItem: (workspaceId: string, documentName: string, data: InMemoryWorkspace["originalDocuments"][string]) => Promise<void>;
35
+ };
36
+ intermediateDocuments: {
37
+ /**
38
+ * Set an intermediate (transformed) document for a workspace/document pair.
39
+ */
40
+ setItem: (workspaceId: string, documentName: string, data: InMemoryWorkspace["intermediateDocuments"][string]) => Promise<void>;
41
+ };
42
+ overrides: {
43
+ /**
44
+ * Set document overrides for a workspace/document pair.
45
+ */
46
+ setItem: (workspaceId: string, documentName: string, data: InMemoryWorkspace["overrides"][string]) => Promise<void>;
47
+ };
48
+ documentConfigs: {
49
+ /**
50
+ * Set configuration for a document in a workspace.
51
+ */
52
+ setItem: (workspaceId: string, documentName: string, data: InMemoryWorkspace["documentConfigs"][string]) => Promise<void>;
53
+ };
54
+ workspace: {
55
+ /**
56
+ * Retrieves a workspace by its ID.
57
+ * Returns undefined if the workspace does not exist.
58
+ * Gathers all workspace 'chunk' tables and assembles a full workspace shape.
59
+ */
60
+ getItem: (id: string) => Promise<(WorkspaceStoreShape & {
61
+ id: string;
62
+ }) | undefined>;
63
+ /**
64
+ * Retrieves all workspaces from the database.
65
+ * Returns only the workspace ID and name for each workspace.
66
+ * To get the full workspace data including documents and metadata, use getItem() with a specific ID.
67
+ * Returns an empty array if no workspaces exist.
68
+ */
69
+ getAll: () => Promise<{
70
+ name: string;
71
+ id: string;
72
+ }[]>;
73
+ /**
74
+ * Saves a workspace to the database.
75
+ * All chunks (meta, documents, configs, etc.) are upsert in their respective tables.
76
+ * If a workspace with the same ID already exists, it will be replaced.
77
+ */
78
+ setItem: (id: string, value: WorkspaceStoreShape) => Promise<void>;
79
+ /**
80
+ * Deletes an entire workspace and all associated chunk records from all tables by ID.
81
+ */
82
+ deleteItem: (id: string) => Promise<void>;
83
+ };
84
+ }>;
85
+ export {};
86
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/persistence/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,iBAAiB,CAAA;CAC7B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B;;;QAoDtC;;WAEG;+BAC0B,MAAM,QAAQ,aAAa;;;QAKxD;;WAEG;+BAC0B,MAAM,gBAAgB,MAAM,QAAQ,iBAAiB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;;;QAKvG;;WAEG;+BAEY,MAAM,gBACL,MAAM,QACd,iBAAiB,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC;;;QAMtD;;WAEG;+BAEY,MAAM,gBACL,MAAM,QACd,iBAAiB,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC;;;QAM1D;;WAEG;+BAC0B,MAAM,gBAAgB,MAAM,QAAQ,iBAAiB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;;;QAKvG;;WAEG;+BAEY,MAAM,gBACL,MAAM,QACd,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC;;;QAMpD;;;;WAIG;sBACiB,MAAM,KAAG,OAAO,CAAC,CAAC,mBAAmB,GAAG;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,GAAG,SAAS,CAAC;QAkCxF;;;;;WAKG;;;;;QAKH;;;;WAIG;sBACiB,MAAM,SAAS,mBAAmB,KAAG,OAAO,CAAC,IAAI,CAAC;QA0CtE;;WAEG;yBACoB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;;EAkBlD,CAAA"}
@@ -0,0 +1,196 @@
1
+ import { Type } from "@scalar/typebox";
2
+ import { createIndexDbConnection } from "../persistence/indexdb.js";
3
+ const createWorkspaceStorePersistence = async () => {
4
+ const connection = await createIndexDbConnection({
5
+ name: "scalar-workspace-store",
6
+ version: 1,
7
+ tables: {
8
+ workspace: {
9
+ schema: Type.Object({ id: Type.String(), name: Type.String() }),
10
+ index: ["id"]
11
+ },
12
+ meta: {
13
+ schema: Type.Object({ workspaceId: Type.String(), data: Type.Any() }),
14
+ index: ["workspaceId"]
15
+ },
16
+ documents: {
17
+ schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),
18
+ index: ["workspaceId", "documentName"]
19
+ },
20
+ originalDocuments: {
21
+ schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),
22
+ index: ["workspaceId", "documentName"]
23
+ },
24
+ intermediateDocuments: {
25
+ schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),
26
+ index: ["workspaceId", "documentName"]
27
+ },
28
+ overrides: {
29
+ schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),
30
+ index: ["workspaceId", "documentName"]
31
+ },
32
+ documentConfigs: {
33
+ schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),
34
+ index: ["workspaceId", "documentName"]
35
+ }
36
+ }
37
+ });
38
+ const workspaceTable = connection.get("workspace");
39
+ const metaTable = connection.get("meta");
40
+ const documentsTable = connection.get("documents");
41
+ const originalDocumentTable = connection.get("originalDocuments");
42
+ const intermediateDocumentTable = connection.get("intermediateDocuments");
43
+ const overridesTable = connection.get("overrides");
44
+ const documentConfigsTable = connection.get("documentConfigs");
45
+ return {
46
+ close: () => {
47
+ connection.closeDatabase();
48
+ },
49
+ meta: {
50
+ /**
51
+ * Set meta data for a workspace.
52
+ */
53
+ setItem: async (workspaceId, data) => {
54
+ await metaTable.addItem({ workspaceId }, { data });
55
+ }
56
+ },
57
+ documents: {
58
+ /**
59
+ * Set (persist) a workspace document using workspaceId and documentName as composite key.
60
+ */
61
+ setItem: async (workspaceId, documentName, data) => {
62
+ await documentsTable.addItem({ workspaceId, documentName }, { data });
63
+ }
64
+ },
65
+ originalDocuments: {
66
+ /**
67
+ * Set an original (raw) document for a workspace/document pair.
68
+ */
69
+ setItem: async (workspaceId, documentName, data) => {
70
+ await originalDocumentTable.addItem({ workspaceId, documentName }, { data });
71
+ }
72
+ },
73
+ intermediateDocuments: {
74
+ /**
75
+ * Set an intermediate (transformed) document for a workspace/document pair.
76
+ */
77
+ setItem: async (workspaceId, documentName, data) => {
78
+ await intermediateDocumentTable.addItem({ workspaceId, documentName }, { data });
79
+ }
80
+ },
81
+ overrides: {
82
+ /**
83
+ * Set document overrides for a workspace/document pair.
84
+ */
85
+ setItem: async (workspaceId, documentName, data) => {
86
+ await overridesTable.addItem({ workspaceId, documentName }, { data });
87
+ }
88
+ },
89
+ documentConfigs: {
90
+ /**
91
+ * Set configuration for a document in a workspace.
92
+ */
93
+ setItem: async (workspaceId, documentName, data) => {
94
+ await documentConfigsTable.addItem({ workspaceId, documentName }, { data });
95
+ }
96
+ },
97
+ workspace: {
98
+ /**
99
+ * Retrieves a workspace by its ID.
100
+ * Returns undefined if the workspace does not exist.
101
+ * Gathers all workspace 'chunk' tables and assembles a full workspace shape.
102
+ */
103
+ getItem: async (id) => {
104
+ const workspace = await workspaceTable.getItem({ id });
105
+ if (!workspace) {
106
+ return void 0;
107
+ }
108
+ const workspaceDocuments = await documentsTable.getRange([id]);
109
+ const workspaceOriginalDocuments = await originalDocumentTable.getRange([id]);
110
+ const workspaceIntermediateDocuments = await intermediateDocumentTable.getRange([id]);
111
+ const workspaceOverrides = await overridesTable.getRange([id]);
112
+ const workspaceMeta = await metaTable.getItem({ workspaceId: id });
113
+ const workspaceDocumentConfigs = await documentConfigsTable.getRange([id]);
114
+ return {
115
+ id,
116
+ name: workspace.name,
117
+ workspace: {
118
+ documents: Object.fromEntries(workspaceDocuments.map((item) => [item.documentName, item.data])),
119
+ originalDocuments: Object.fromEntries(
120
+ workspaceOriginalDocuments.map((item) => [item.documentName, item.data])
121
+ ),
122
+ intermediateDocuments: Object.fromEntries(
123
+ workspaceIntermediateDocuments.map((item) => [item.documentName, item.data])
124
+ ),
125
+ overrides: Object.fromEntries(workspaceOverrides.map((item) => [item.documentName, item.data])),
126
+ meta: workspaceMeta?.data,
127
+ documentConfigs: Object.fromEntries(workspaceDocumentConfigs.map((item) => [item.documentName, item.data]))
128
+ }
129
+ };
130
+ },
131
+ /**
132
+ * Retrieves all workspaces from the database.
133
+ * Returns only the workspace ID and name for each workspace.
134
+ * To get the full workspace data including documents and metadata, use getItem() with a specific ID.
135
+ * Returns an empty array if no workspaces exist.
136
+ */
137
+ getAll: async () => {
138
+ return await workspaceTable.getAll();
139
+ },
140
+ /**
141
+ * Saves a workspace to the database.
142
+ * All chunks (meta, documents, configs, etc.) are upsert in their respective tables.
143
+ * If a workspace with the same ID already exists, it will be replaced.
144
+ */
145
+ setItem: async (id, value) => {
146
+ await workspaceTable.addItem({ id }, { name: value.name });
147
+ await metaTable.addItem({ workspaceId: id }, { data: value.workspace.meta });
148
+ await Promise.all(
149
+ Object.entries(value.workspace.documents ?? {}).map(([name, data]) => {
150
+ return documentsTable.addItem({ workspaceId: id, documentName: name }, { data });
151
+ })
152
+ );
153
+ await Promise.all(
154
+ Object.entries(value.workspace.originalDocuments ?? {}).map(([name, data]) => {
155
+ return originalDocumentTable.addItem({ workspaceId: id, documentName: name }, { data });
156
+ })
157
+ );
158
+ await Promise.all(
159
+ Object.entries(value.workspace.intermediateDocuments ?? {}).map(([name, data]) => {
160
+ return intermediateDocumentTable.addItem({ workspaceId: id, documentName: name }, { data });
161
+ })
162
+ );
163
+ await Promise.all(
164
+ Object.entries(value.workspace.overrides ?? {}).map(([name, data]) => {
165
+ return overridesTable.addItem({ workspaceId: id, documentName: name }, { data });
166
+ })
167
+ );
168
+ await Promise.all(
169
+ Object.entries(value.workspace.documentConfigs ?? {}).map(([name, data]) => {
170
+ return documentConfigsTable.addItem({ workspaceId: id, documentName: name }, { data });
171
+ })
172
+ );
173
+ },
174
+ /**
175
+ * Deletes an entire workspace and all associated chunk records from all tables by ID.
176
+ */
177
+ deleteItem: async (id) => {
178
+ await workspaceTable.deleteItem({ id });
179
+ await Promise.all([
180
+ // By id
181
+ metaTable.deleteItem({ workspaceId: id }),
182
+ // By range (composite-key tables)
183
+ documentsTable.deleteRange([id]),
184
+ originalDocumentTable.deleteRange([id]),
185
+ intermediateDocumentTable.deleteRange([id]),
186
+ overridesTable.deleteRange([id]),
187
+ documentConfigsTable.deleteRange([id])
188
+ ]);
189
+ }
190
+ }
191
+ };
192
+ };
193
+ export {
194
+ createWorkspaceStorePersistence
195
+ };
196
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/persistence/index.ts"],
4
+ "sourcesContent": ["import { Type } from '@scalar/typebox'\n\nimport { createIndexDbConnection } from '@/persistence/indexdb'\nimport type { InMemoryWorkspace } from '@/schemas/inmemory-workspace'\nimport type { WorkspaceMeta } from '@/schemas/workspace'\n\ntype WorkspaceStoreShape = {\n name: string\n workspace: InMemoryWorkspace\n}\n\n/**\n * Creates the persistence layer for the workspace store using IndexedDB.\n * This sets up all the required tables for storing workspace chunk information,\n * such as workspace meta, documents, original documents, intermediate documents, overrides, etc.\n * Each logical group (meta, documents, etc) gets its own table keyed appropriately for efficient sub-document access.\n * Returns an object containing `meta`, `documents`, `originalDocuments`, `intermediateDocuments`, `overrides`,\n * `documentMeta`, `documentConfigs`, and `workspace` sections, each exposing a `setItem` method\n * for upsetting records, and in the case of `workspace`, also `getItem` and `deleteItem`.\n */\nexport const createWorkspaceStorePersistence = async () => {\n // Create the database connection and setup all required tables for workspace storage.\n const connection = await createIndexDbConnection({\n name: 'scalar-workspace-store',\n version: 1,\n tables: {\n workspace: {\n schema: Type.Object({ id: Type.String(), name: Type.String() }),\n index: ['id'],\n },\n meta: {\n schema: Type.Object({ workspaceId: Type.String(), data: Type.Any() }),\n index: ['workspaceId'],\n },\n documents: {\n schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),\n index: ['workspaceId', 'documentName'],\n },\n originalDocuments: {\n schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),\n index: ['workspaceId', 'documentName'],\n },\n intermediateDocuments: {\n schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),\n index: ['workspaceId', 'documentName'],\n },\n overrides: {\n schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),\n index: ['workspaceId', 'documentName'],\n },\n documentConfigs: {\n schema: Type.Object({ workspaceId: Type.String(), documentName: Type.String(), data: Type.Any() }),\n index: ['workspaceId', 'documentName'],\n },\n },\n })\n\n // Tables wrappers for each logical section.\n const workspaceTable = connection.get('workspace')\n const metaTable = connection.get('meta')\n const documentsTable = connection.get('documents')\n const originalDocumentTable = connection.get('originalDocuments')\n const intermediateDocumentTable = connection.get('intermediateDocuments')\n const overridesTable = connection.get('overrides')\n const documentConfigsTable = connection.get('documentConfigs')\n\n // The returned persistence API with logical sections for each table and mapping.\n return {\n close: () => {\n connection.closeDatabase()\n },\n meta: {\n /**\n * Set meta data for a workspace.\n */\n setItem: async (workspaceId: string, data: WorkspaceMeta) => {\n await metaTable.addItem({ workspaceId }, { data })\n },\n },\n documents: {\n /**\n * Set (persist) a workspace document using workspaceId and documentName as composite key.\n */\n setItem: async (workspaceId: string, documentName: string, data: InMemoryWorkspace['documents'][string]) => {\n await documentsTable.addItem({ workspaceId, documentName }, { data })\n },\n },\n originalDocuments: {\n /**\n * Set an original (raw) document for a workspace/document pair.\n */\n setItem: async (\n workspaceId: string,\n documentName: string,\n data: InMemoryWorkspace['originalDocuments'][string],\n ) => {\n await originalDocumentTable.addItem({ workspaceId, documentName }, { data })\n },\n },\n intermediateDocuments: {\n /**\n * Set an intermediate (transformed) document for a workspace/document pair.\n */\n setItem: async (\n workspaceId: string,\n documentName: string,\n data: InMemoryWorkspace['intermediateDocuments'][string],\n ) => {\n await intermediateDocumentTable.addItem({ workspaceId, documentName }, { data })\n },\n },\n overrides: {\n /**\n * Set document overrides for a workspace/document pair.\n */\n setItem: async (workspaceId: string, documentName: string, data: InMemoryWorkspace['overrides'][string]) => {\n await overridesTable.addItem({ workspaceId, documentName }, { data })\n },\n },\n documentConfigs: {\n /**\n * Set configuration for a document in a workspace.\n */\n setItem: async (\n workspaceId: string,\n documentName: string,\n data: InMemoryWorkspace['documentConfigs'][string],\n ) => {\n await documentConfigsTable.addItem({ workspaceId, documentName }, { data })\n },\n },\n workspace: {\n /**\n * Retrieves a workspace by its ID.\n * Returns undefined if the workspace does not exist.\n * Gathers all workspace 'chunk' tables and assembles a full workspace shape.\n */\n getItem: async (id: string): Promise<(WorkspaceStoreShape & { id: string }) | undefined> => {\n const workspace = await workspaceTable.getItem({ id })\n\n if (!workspace) {\n return undefined\n }\n\n // Retrieve all chunk records for this workspace.\n const workspaceDocuments = await documentsTable.getRange([id])\n const workspaceOriginalDocuments = await originalDocumentTable.getRange([id])\n const workspaceIntermediateDocuments = await intermediateDocumentTable.getRange([id])\n const workspaceOverrides = await overridesTable.getRange([id])\n const workspaceMeta = await metaTable.getItem({ workspaceId: id })\n const workspaceDocumentConfigs = await documentConfigsTable.getRange([id])\n\n // Compose the workspace structure from table records.\n return {\n id,\n name: workspace.name,\n workspace: {\n documents: Object.fromEntries(workspaceDocuments.map((item) => [item.documentName, item.data])),\n originalDocuments: Object.fromEntries(\n workspaceOriginalDocuments.map((item) => [item.documentName, item.data]),\n ),\n intermediateDocuments: Object.fromEntries(\n workspaceIntermediateDocuments.map((item) => [item.documentName, item.data]),\n ),\n overrides: Object.fromEntries(workspaceOverrides.map((item) => [item.documentName, item.data])),\n meta: workspaceMeta?.data,\n documentConfigs: Object.fromEntries(workspaceDocumentConfigs.map((item) => [item.documentName, item.data])),\n },\n }\n },\n\n /**\n * Retrieves all workspaces from the database.\n * Returns only the workspace ID and name for each workspace.\n * To get the full workspace data including documents and metadata, use getItem() with a specific ID.\n * Returns an empty array if no workspaces exist.\n */\n getAll: async () => {\n return await workspaceTable.getAll()\n },\n\n /**\n * Saves a workspace to the database.\n * All chunks (meta, documents, configs, etc.) are upsert in their respective tables.\n * If a workspace with the same ID already exists, it will be replaced.\n */\n setItem: async (id: string, value: WorkspaceStoreShape): Promise<void> => {\n await workspaceTable.addItem({ id }, { name: value.name })\n\n // Save all meta info for workspace.\n await metaTable.addItem({ workspaceId: id }, { data: value.workspace.meta })\n\n // Persist all workspace documents (chunks).\n await Promise.all(\n Object.entries(value.workspace.documents ?? {}).map(([name, data]) => {\n return documentsTable.addItem({ workspaceId: id, documentName: name }, { data })\n }),\n )\n\n // Persist all original documents.\n await Promise.all(\n Object.entries(value.workspace.originalDocuments ?? {}).map(([name, data]) => {\n return originalDocumentTable.addItem({ workspaceId: id, documentName: name }, { data })\n }),\n )\n\n // Persist all intermediate documents.\n await Promise.all(\n Object.entries(value.workspace.intermediateDocuments ?? {}).map(([name, data]) => {\n return intermediateDocumentTable.addItem({ workspaceId: id, documentName: name }, { data })\n }),\n )\n\n // Persist all document overrides.\n await Promise.all(\n Object.entries(value.workspace.overrides ?? {}).map(([name, data]) => {\n return overridesTable.addItem({ workspaceId: id, documentName: name }, { data })\n }),\n )\n\n // Persist all document configs.\n await Promise.all(\n Object.entries(value.workspace.documentConfigs ?? {}).map(([name, data]) => {\n return documentConfigsTable.addItem({ workspaceId: id, documentName: name }, { data })\n }),\n )\n },\n\n /**\n * Deletes an entire workspace and all associated chunk records from all tables by ID.\n */\n deleteItem: async (id: string): Promise<void> => {\n await workspaceTable.deleteItem({ id })\n\n // Remove all workspace-related records from all chunk tables.\n await Promise.all([\n // By id\n metaTable.deleteItem({ workspaceId: id }),\n\n // By range (composite-key tables)\n documentsTable.deleteRange([id]),\n originalDocumentTable.deleteRange([id]),\n intermediateDocumentTable.deleteRange([id]),\n overridesTable.deleteRange([id]),\n documentConfigsTable.deleteRange([id]),\n ])\n },\n },\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAY;AAErB,SAAS,+BAA+B;AAkBjC,MAAM,kCAAkC,YAAY;AAEzD,QAAM,aAAa,MAAM,wBAAwB;AAAA,IAC/C,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,MACN,WAAW;AAAA,QACT,QAAQ,KAAK,OAAO,EAAE,IAAI,KAAK,OAAO,GAAG,MAAM,KAAK,OAAO,EAAE,CAAC;AAAA,QAC9D,OAAO,CAAC,IAAI;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,QAAQ,KAAK,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QACpE,OAAO,CAAC,aAAa;AAAA,MACvB;AAAA,MACA,WAAW;AAAA,QACT,QAAQ,KAAK,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,cAAc,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QACjG,OAAO,CAAC,eAAe,cAAc;AAAA,MACvC;AAAA,MACA,mBAAmB;AAAA,QACjB,QAAQ,KAAK,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,cAAc,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QACjG,OAAO,CAAC,eAAe,cAAc;AAAA,MACvC;AAAA,MACA,uBAAuB;AAAA,QACrB,QAAQ,KAAK,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,cAAc,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QACjG,OAAO,CAAC,eAAe,cAAc;AAAA,MACvC;AAAA,MACA,WAAW;AAAA,QACT,QAAQ,KAAK,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,cAAc,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QACjG,OAAO,CAAC,eAAe,cAAc;AAAA,MACvC;AAAA,MACA,iBAAiB;AAAA,QACf,QAAQ,KAAK,OAAO,EAAE,aAAa,KAAK,OAAO,GAAG,cAAc,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC;AAAA,QACjG,OAAO,CAAC,eAAe,cAAc;AAAA,MACvC;AAAA,IACF;AAAA,EACF,CAAC;AAGD,QAAM,iBAAiB,WAAW,IAAI,WAAW;AACjD,QAAM,YAAY,WAAW,IAAI,MAAM;AACvC,QAAM,iBAAiB,WAAW,IAAI,WAAW;AACjD,QAAM,wBAAwB,WAAW,IAAI,mBAAmB;AAChE,QAAM,4BAA4B,WAAW,IAAI,uBAAuB;AACxE,QAAM,iBAAiB,WAAW,IAAI,WAAW;AACjD,QAAM,uBAAuB,WAAW,IAAI,iBAAiB;AAG7D,SAAO;AAAA,IACL,OAAO,MAAM;AACX,iBAAW,cAAc;AAAA,IAC3B;AAAA,IACA,MAAM;AAAA;AAAA;AAAA;AAAA,MAIJ,SAAS,OAAO,aAAqB,SAAwB;AAC3D,cAAM,UAAU,QAAQ,EAAE,YAAY,GAAG,EAAE,KAAK,CAAC;AAAA,MACnD;AAAA,IACF;AAAA,IACA,WAAW;AAAA;AAAA;AAAA;AAAA,MAIT,SAAS,OAAO,aAAqB,cAAsB,SAAiD;AAC1G,cAAM,eAAe,QAAQ,EAAE,aAAa,aAAa,GAAG,EAAE,KAAK,CAAC;AAAA,MACtE;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA;AAAA;AAAA,MAIjB,SAAS,OACP,aACA,cACA,SACG;AACH,cAAM,sBAAsB,QAAQ,EAAE,aAAa,aAAa,GAAG,EAAE,KAAK,CAAC;AAAA,MAC7E;AAAA,IACF;AAAA,IACA,uBAAuB;AAAA;AAAA;AAAA;AAAA,MAIrB,SAAS,OACP,aACA,cACA,SACG;AACH,cAAM,0BAA0B,QAAQ,EAAE,aAAa,aAAa,GAAG,EAAE,KAAK,CAAC;AAAA,MACjF;AAAA,IACF;AAAA,IACA,WAAW;AAAA;AAAA;AAAA;AAAA,MAIT,SAAS,OAAO,aAAqB,cAAsB,SAAiD;AAC1G,cAAM,eAAe,QAAQ,EAAE,aAAa,aAAa,GAAG,EAAE,KAAK,CAAC;AAAA,MACtE;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA;AAAA;AAAA;AAAA,MAIf,SAAS,OACP,aACA,cACA,SACG;AACH,cAAM,qBAAqB,QAAQ,EAAE,aAAa,aAAa,GAAG,EAAE,KAAK,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,IACA,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMT,SAAS,OAAO,OAA4E;AAC1F,cAAM,YAAY,MAAM,eAAe,QAAQ,EAAE,GAAG,CAAC;AAErD,YAAI,CAAC,WAAW;AACd,iBAAO;AAAA,QACT;AAGA,cAAM,qBAAqB,MAAM,eAAe,SAAS,CAAC,EAAE,CAAC;AAC7D,cAAM,6BAA6B,MAAM,sBAAsB,SAAS,CAAC,EAAE,CAAC;AAC5E,cAAM,iCAAiC,MAAM,0BAA0B,SAAS,CAAC,EAAE,CAAC;AACpF,cAAM,qBAAqB,MAAM,eAAe,SAAS,CAAC,EAAE,CAAC;AAC7D,cAAM,gBAAgB,MAAM,UAAU,QAAQ,EAAE,aAAa,GAAG,CAAC;AACjE,cAAM,2BAA2B,MAAM,qBAAqB,SAAS,CAAC,EAAE,CAAC;AAGzE,eAAO;AAAA,UACL;AAAA,UACA,MAAM,UAAU;AAAA,UAChB,WAAW;AAAA,YACT,WAAW,OAAO,YAAY,mBAAmB,IAAI,CAAC,SAAS,CAAC,KAAK,cAAc,KAAK,IAAI,CAAC,CAAC;AAAA,YAC9F,mBAAmB,OAAO;AAAA,cACxB,2BAA2B,IAAI,CAAC,SAAS,CAAC,KAAK,cAAc,KAAK,IAAI,CAAC;AAAA,YACzE;AAAA,YACA,uBAAuB,OAAO;AAAA,cAC5B,+BAA+B,IAAI,CAAC,SAAS,CAAC,KAAK,cAAc,KAAK,IAAI,CAAC;AAAA,YAC7E;AAAA,YACA,WAAW,OAAO,YAAY,mBAAmB,IAAI,CAAC,SAAS,CAAC,KAAK,cAAc,KAAK,IAAI,CAAC,CAAC;AAAA,YAC9F,MAAM,eAAe;AAAA,YACrB,iBAAiB,OAAO,YAAY,yBAAyB,IAAI,CAAC,SAAS,CAAC,KAAK,cAAc,KAAK,IAAI,CAAC,CAAC;AAAA,UAC5G;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,QAAQ,YAAY;AAClB,eAAO,MAAM,eAAe,OAAO;AAAA,MACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,SAAS,OAAO,IAAY,UAA8C;AACxE,cAAM,eAAe,QAAQ,EAAE,GAAG,GAAG,EAAE,MAAM,MAAM,KAAK,CAAC;AAGzD,cAAM,UAAU,QAAQ,EAAE,aAAa,GAAG,GAAG,EAAE,MAAM,MAAM,UAAU,KAAK,CAAC;AAG3E,cAAM,QAAQ;AAAA,UACZ,OAAO,QAAQ,MAAM,UAAU,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM;AACpE,mBAAO,eAAe,QAAQ,EAAE,aAAa,IAAI,cAAc,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,UACjF,CAAC;AAAA,QACH;AAGA,cAAM,QAAQ;AAAA,UACZ,OAAO,QAAQ,MAAM,UAAU,qBAAqB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM;AAC5E,mBAAO,sBAAsB,QAAQ,EAAE,aAAa,IAAI,cAAc,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,UACxF,CAAC;AAAA,QACH;AAGA,cAAM,QAAQ;AAAA,UACZ,OAAO,QAAQ,MAAM,UAAU,yBAAyB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM;AAChF,mBAAO,0BAA0B,QAAQ,EAAE,aAAa,IAAI,cAAc,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,UAC5F,CAAC;AAAA,QACH;AAGA,cAAM,QAAQ;AAAA,UACZ,OAAO,QAAQ,MAAM,UAAU,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM;AACpE,mBAAO,eAAe,QAAQ,EAAE,aAAa,IAAI,cAAc,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,UACjF,CAAC;AAAA,QACH;AAGA,cAAM,QAAQ;AAAA,UACZ,OAAO,QAAQ,MAAM,UAAU,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM;AAC1E,mBAAO,qBAAqB,QAAQ,EAAE,aAAa,IAAI,cAAc,KAAK,GAAG,EAAE,KAAK,CAAC;AAAA,UACvF,CAAC;AAAA,QACH;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,YAAY,OAAO,OAA8B;AAC/C,cAAM,eAAe,WAAW,EAAE,GAAG,CAAC;AAGtC,cAAM,QAAQ,IAAI;AAAA;AAAA,UAEhB,UAAU,WAAW,EAAE,aAAa,GAAG,CAAC;AAAA;AAAA,UAGxC,eAAe,YAAY,CAAC,EAAE,CAAC;AAAA,UAC/B,sBAAsB,YAAY,CAAC,EAAE,CAAC;AAAA,UACtC,0BAA0B,YAAY,CAAC,EAAE,CAAC;AAAA,UAC1C,eAAe,YAAY,CAAC,EAAE,CAAC;AAAA,UAC/B,qBAAqB,YAAY,CAAC,EAAE,CAAC;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,87 @@
1
+ import type { Static, TObject } from '@scalar/typebox';
2
+ type TableEntry<S extends TObject, K extends readonly (keyof Static<S>)[]> = {
3
+ schema: S;
4
+ index: K;
5
+ };
6
+ /**
7
+ * Initializes and manages an IndexedDB database connection for table-based persistence.
8
+ *
9
+ * @param name - The database name. Defaults to 'scalar-workspace-store'.
10
+ * @param tables - Table definitions: the tables to create and their key schemas.
11
+ * @param version - The database version. Bump this to trigger upgrades (default: 1).
12
+ * @param migrations - Optional migration steps to run for version upgrades.
13
+ * @returns An object with the following methods:
14
+ * - `get(tableName)` — Get a wrapper to interact with the object store for the given table name.
15
+ * - `closeDatabase()` — Closes the database connection.
16
+ *
17
+ * Example usage:
18
+ * ```ts
19
+ * import { Type } from '@scalar/typebox'
20
+ * import { createIndexDbConnection } from './indexdb.js'
21
+ *
22
+ * // Define a schema for a user
23
+ * const UserSchema = Type.Object({
24
+ * id: Type.String(),
25
+ * name: Type.String(),
26
+ * age: Type.Number(),
27
+ * })
28
+ *
29
+ * // Define tables in the database
30
+ * const dbConfig = {
31
+ * users: {
32
+ * schema: UserSchema,
33
+ * index: ['id'] as const,
34
+ * },
35
+ * }
36
+ *
37
+ * // Open the database connection and get table API
38
+ * const { get, closeDatabase } = await createIndexDbConnection({
39
+ * name: 'my-app-db',
40
+ * tables: dbConfig,
41
+ * version: 1,
42
+ * })
43
+ *
44
+ * // Get a strongly-typed users table API
45
+ * const usersTable = get('users')
46
+ *
47
+ * // Add a user
48
+ * await usersTable.addItem({ id: 'user-1' }, { name: 'Alice', age: 25 })
49
+ *
50
+ * // Retrieve a user by id
51
+ * const user = await usersTable.getItem({ id: 'user-1' })
52
+ *
53
+ * // Don't forget to close the database when done!
54
+ * closeDatabase()
55
+ * ```
56
+ */
57
+ export declare const createIndexDbConnection: <T extends Record<string, TableEntry<any, readonly (keyof any)[]>>>({ name, tables, version, migrations, }: {
58
+ name: string;
59
+ tables: T;
60
+ version: number;
61
+ migrations?: {
62
+ version: number;
63
+ exec: (db: IDBDatabase, event: IDBVersionChangeEvent) => {};
64
+ }[];
65
+ }) => Promise<{
66
+ get: <Name extends keyof T>(name: Name) => {
67
+ addItem: (key: Record<T[Name]["index"][number], IDBValidKey>, value: Omit<(T[Name]["schema"] & {
68
+ params: [];
69
+ })["static"], T[Name]["index"][number]>) => Promise<(T[Name]["schema"] & {
70
+ params: [];
71
+ })["static"]>;
72
+ getItem: (key: Record<T[Name]["index"][number], IDBValidKey>) => Promise<(T[Name]["schema"] & {
73
+ params: [];
74
+ })["static"] | undefined>;
75
+ getRange: (partialKey: IDBValidKey[]) => Promise<(T[Name]["schema"] & {
76
+ params: [];
77
+ })["static"][]>;
78
+ deleteItem: (key: Record<T[Name]["index"][number], IDBValidKey>) => Promise<void>;
79
+ deleteRange: (partialKey: IDBValidKey[]) => Promise<number>;
80
+ getAll: () => Promise<(T[Name]["schema"] & {
81
+ params: [];
82
+ })["static"][]>;
83
+ };
84
+ closeDatabase: () => void;
85
+ }>;
86
+ export {};
87
+ //# sourceMappingURL=indexdb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexdb.d.ts","sourceRoot":"","sources":["../../src/persistence/indexdb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAW,MAAM,iBAAiB,CAAA;AAE/D,KAAK,UAAU,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,SAAS,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI;IAC3E,MAAM,EAAE,CAAC,CAAA;IACT,KAAK,EAAE,CAAC,CAAA;CACT,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,eAAO,MAAM,uBAAuB,GAAU,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,wCAK9G;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,CAAC,CAAA;IACT,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,qBAAqB,KAAK,EAAE,CAAA;KAAE,EAAE,CAAA;CAChG;UAgCS,IAAI,SAAS,MAAM,CAAC,QAAQ,IAAI;;;;;;;;;+BA+FV,WAAW,EAAE;;;4EA6Ba,OAAO,CAAC,IAAI,CAAC;kCAmBpC,WAAW,EAAE,KAAG,OAAO,CAAC,MAAM,CAAC;;;;;;EAxIjE,CAAA"}
@@ -0,0 +1,125 @@
1
+ const createIndexDbConnection = async ({
2
+ name = "scalar-workspace-store",
3
+ tables,
4
+ version = 1,
5
+ migrations = []
6
+ }) => {
7
+ const db = indexedDB.open(name, version);
8
+ db.onupgradeneeded = (e) => {
9
+ if (e.oldVersion < 1) {
10
+ const database = db.result;
11
+ Object.entries(tables).forEach(([name2, options]) => {
12
+ if (!database.objectStoreNames.contains(name2)) {
13
+ database.createObjectStore(name2, {
14
+ keyPath: options.index.length === 1 ? options.index[0] : options.index
15
+ });
16
+ }
17
+ });
18
+ }
19
+ migrations.forEach((migration) => {
20
+ if (e.oldVersion < migration.version) {
21
+ migration.exec(db.result, e);
22
+ }
23
+ });
24
+ };
25
+ await new Promise((resolve, reject) => {
26
+ db.onsuccess = () => resolve(true);
27
+ db.onerror = () => reject(db.error);
28
+ });
29
+ return {
30
+ get: (name2) => {
31
+ return createTableWrapper(name2, db.result);
32
+ },
33
+ closeDatabase: () => {
34
+ db.result.close();
35
+ }
36
+ };
37
+ };
38
+ function createTableWrapper(name, db) {
39
+ const getStore = (mode) => {
40
+ const tx = db.transaction(name, mode);
41
+ return tx.objectStore(name);
42
+ };
43
+ async function addItem(key, value) {
44
+ const store = getStore("readwrite");
45
+ const keyObj = { ...key };
46
+ const finalValue = { ...keyObj, ...value };
47
+ await requestAsPromise(store.put(finalValue));
48
+ return finalValue;
49
+ }
50
+ function getItem(key) {
51
+ const store = getStore("readonly");
52
+ const keyValues = Object.values(key);
53
+ const keyToUse = keyValues.length === 1 ? keyValues[0] : keyValues;
54
+ return requestAsPromise(store.get(keyToUse));
55
+ }
56
+ function getRange(partialKey) {
57
+ const store = getStore("readonly");
58
+ const results = [];
59
+ const upperBound = [...partialKey];
60
+ upperBound.push([]);
61
+ const range = IDBKeyRange.bound(partialKey, upperBound, false, true);
62
+ return new Promise((resolve, reject) => {
63
+ const request = store.openCursor(range);
64
+ request.onerror = () => reject(request.error);
65
+ request.onsuccess = (event) => {
66
+ const cursor = event.target.result;
67
+ if (cursor) {
68
+ results.push(cursor.value);
69
+ cursor.continue();
70
+ } else {
71
+ resolve(results);
72
+ }
73
+ };
74
+ });
75
+ }
76
+ async function deleteItem(key) {
77
+ const store = getStore("readwrite");
78
+ const keyValues = Object.values(key);
79
+ const keyToUse = keyValues.length === 1 ? keyValues[0] : keyValues;
80
+ await requestAsPromise(store.delete(keyToUse));
81
+ }
82
+ function deleteRange(partialKey) {
83
+ const store = getStore("readwrite");
84
+ let deletedCount = 0;
85
+ const upperBound = [...partialKey];
86
+ upperBound.push([]);
87
+ const range = IDBKeyRange.bound(partialKey, upperBound, false, true);
88
+ return new Promise((resolve, reject) => {
89
+ const request = store.openCursor(range);
90
+ request.onerror = () => reject(request.error);
91
+ request.onsuccess = (event) => {
92
+ const cursor = event.target.result;
93
+ if (cursor) {
94
+ cursor.delete();
95
+ deletedCount++;
96
+ cursor.continue();
97
+ } else {
98
+ resolve(deletedCount);
99
+ }
100
+ };
101
+ });
102
+ }
103
+ function getAll() {
104
+ const store = getStore("readonly");
105
+ return requestAsPromise(store.getAll());
106
+ }
107
+ return {
108
+ addItem,
109
+ getItem,
110
+ getRange,
111
+ deleteItem,
112
+ deleteRange,
113
+ getAll
114
+ };
115
+ }
116
+ function requestAsPromise(req) {
117
+ return new Promise((resolve, reject) => {
118
+ req.onsuccess = () => resolve(req.result);
119
+ req.onerror = () => reject(req.error);
120
+ });
121
+ }
122
+ export {
123
+ createIndexDbConnection
124
+ };
125
+ //# sourceMappingURL=indexdb.js.map