@scalar/workspace-store 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"inmemory-workspace.d.ts","sourceRoot":"","sources":["../../src/schemas/inmemory-workspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAErD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMlC,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAA"}
1
+ {"version":3,"file":"inmemory-workspace.d.ts","sourceRoot":"","sources":["../../src/schemas/inmemory-workspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAErD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOlC,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { PartialDeep } from "../schemas/typebox-types.js";
1
2
  import { WorkspaceDocumentSchema, WorkspaceMetaSchema } from "../schemas/workspace.js";
2
3
  import { ConfigSchema } from "../schemas/workspace-specification/config.js";
3
4
  import { Type } from "@sinclair/typebox";
@@ -6,7 +7,8 @@ const InMemoryWorkspaceSchema = Type.Object({
6
7
  documentConfigs: Type.Record(Type.String(), ConfigSchema),
7
8
  documents: Type.Record(Type.String(), WorkspaceDocumentSchema),
8
9
  originalDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema),
9
- intermediateDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema)
10
+ intermediateDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema),
11
+ overrides: Type.Record(Type.String(), PartialDeep(WorkspaceDocumentSchema))
10
12
  });
11
13
  export {
12
14
  InMemoryWorkspaceSchema
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/schemas/inmemory-workspace.ts"],
4
- "sourcesContent": ["import { WorkspaceDocumentSchema, WorkspaceMetaSchema } from '@/schemas/workspace'\nimport { ConfigSchema } from '@/schemas/workspace-specification/config'\nimport { Type, type Static } from '@sinclair/typebox'\n\nexport const InMemoryWorkspaceSchema = Type.Object({\n meta: WorkspaceMetaSchema,\n documentConfigs: Type.Record(Type.String(), ConfigSchema),\n documents: Type.Record(Type.String(), WorkspaceDocumentSchema),\n originalDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema),\n intermediateDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema),\n})\n\nexport type InMemoryWorkspace = Static<typeof InMemoryWorkspaceSchema>\n"],
5
- "mappings": "AAAA,SAAS,yBAAyB,2BAA2B;AAC7D,SAAS,oBAAoB;AAC7B,SAAS,YAAyB;AAE3B,MAAM,0BAA0B,KAAK,OAAO;AAAA,EACjD,MAAM;AAAA,EACN,iBAAiB,KAAK,OAAO,KAAK,OAAO,GAAG,YAAY;AAAA,EACxD,WAAW,KAAK,OAAO,KAAK,OAAO,GAAG,uBAAuB;AAAA,EAC7D,mBAAmB,KAAK,OAAO,KAAK,OAAO,GAAG,uBAAuB;AAAA,EACrE,uBAAuB,KAAK,OAAO,KAAK,OAAO,GAAG,uBAAuB;AAC3E,CAAC;",
4
+ "sourcesContent": ["import { PartialDeep } from '@/schemas/typebox-types'\nimport { WorkspaceDocumentSchema, WorkspaceMetaSchema } from '@/schemas/workspace'\nimport { ConfigSchema } from '@/schemas/workspace-specification/config'\nimport { Type, type Static } from '@sinclair/typebox'\n\nexport const InMemoryWorkspaceSchema = Type.Object({\n meta: WorkspaceMetaSchema,\n documentConfigs: Type.Record(Type.String(), ConfigSchema),\n documents: Type.Record(Type.String(), WorkspaceDocumentSchema),\n originalDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema),\n intermediateDocuments: Type.Record(Type.String(), WorkspaceDocumentSchema),\n overrides: Type.Record(Type.String(), PartialDeep(WorkspaceDocumentSchema)),\n})\n\nexport type InMemoryWorkspace = Static<typeof InMemoryWorkspaceSchema>\n"],
5
+ "mappings": "AAAA,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB,2BAA2B;AAC7D,SAAS,oBAAoB;AAC7B,SAAS,YAAyB;AAE3B,MAAM,0BAA0B,KAAK,OAAO;AAAA,EACjD,MAAM;AAAA,EACN,iBAAiB,KAAK,OAAO,KAAK,OAAO,GAAG,YAAY;AAAA,EACxD,WAAW,KAAK,OAAO,KAAK,OAAO,GAAG,uBAAuB;AAAA,EAC7D,mBAAmB,KAAK,OAAO,KAAK,OAAO,GAAG,uBAAuB;AAAA,EACrE,uBAAuB,KAAK,OAAO,KAAK,OAAO,GAAG,uBAAuB;AAAA,EACzE,WAAW,KAAK,OAAO,KAAK,OAAO,GAAG,YAAY,uBAAuB,CAAC;AAC5E,CAAC;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * See: https://github.com/sinclairzx81/typebox/discussions/835
3
+ */
4
+ import { type TSchema, type TIntersect, type TUnion, type TObject, type TPartial, type TProperties, type Evaluate } from '@sinclair/typebox';
5
+ export type TPartialDeepProperties<T extends TProperties> = {
6
+ [K in keyof T]: TPartialDeep<T[K]>;
7
+ };
8
+ export type TPartialDeepRest<T extends TSchema[], Acc extends TSchema[] = []> = T extends [
9
+ infer L extends TSchema,
10
+ ...infer R extends TSchema[]
11
+ ] ? TPartialDeepRest<R, [...Acc, TPartialDeep<L>]> : Acc;
12
+ export type TPartialDeep<T extends TSchema> = T extends TIntersect<infer S> ? TIntersect<TPartialDeepRest<S>> : T extends TUnion<infer S> ? TUnion<TPartialDeepRest<S>> : T extends TObject<infer S> ? TPartial<TObject<Evaluate<TPartialDeepProperties<S>>>> : T;
13
+ export declare function PartialDeep<T extends TSchema>(schema: T): TPartialDeep<T>;
14
+ //# sourceMappingURL=typebox-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox-types.d.ts","sourceRoot":"","sources":["../../src/schemas/typebox-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,QAAQ,EACd,MAAM,mBAAmB,CAAA;AAK1B,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,WAAW,IAAI;KACzD,CAAC,IAAI,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACnC,CAAA;AASD,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,GAAG,SAAS,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS;IACxF,MAAM,CAAC,SAAS,OAAO;IACvB,GAAG,MAAM,CAAC,SAAS,OAAO,EAAE;CAC7B,GACG,gBAAgB,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,GAC9C,GAAG,CAAA;AAOP,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GACvE,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAC/B,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,CAAC,GACvB,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAC3B,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GACxB,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GACtD,CAAC,CAAA;AACT,wBAAgB,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAUzE"}
@@ -0,0 +1,19 @@
1
+ import {
2
+ TypeGuard,
3
+ Type
4
+ } from "@sinclair/typebox";
5
+ function PartialDeepProperties(properties) {
6
+ return Object.getOwnPropertyNames(properties).reduce((acc, key) => {
7
+ return { ...acc, [key]: PartialDeep(properties[key]) };
8
+ }, {});
9
+ }
10
+ function PartialDeepRest(rest) {
11
+ return rest.map((schema) => PartialDeep(schema));
12
+ }
13
+ function PartialDeep(schema) {
14
+ return TypeGuard.IsIntersect(schema) ? Type.Intersect(PartialDeepRest(schema.allOf)) : TypeGuard.IsUnion(schema) ? Type.Union(PartialDeepRest(schema.anyOf)) : TypeGuard.IsObject(schema) ? Type.Partial(Type.Object(PartialDeepProperties(schema.properties))) : schema;
15
+ }
16
+ export {
17
+ PartialDeep
18
+ };
19
+ //# sourceMappingURL=typebox-types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/schemas/typebox-types.ts"],
4
+ "sourcesContent": ["/**\n * See: https://github.com/sinclairzx81/typebox/discussions/835\n */\n\nimport {\n TypeGuard,\n Type,\n type TSchema,\n type TIntersect,\n type TUnion,\n type TObject,\n type TPartial,\n type TProperties,\n type Evaluate,\n} from '@sinclair/typebox'\n\n// -------------------------------------------------------------------------------------\n// TPartialDeepProperties\n// -------------------------------------------------------------------------------------\nexport type TPartialDeepProperties<T extends TProperties> = {\n [K in keyof T]: TPartialDeep<T[K]>\n}\nfunction PartialDeepProperties<T extends TProperties>(properties: T): TPartialDeepProperties<T> {\n return Object.getOwnPropertyNames(properties).reduce((acc, key) => {\n return { ...acc, [key]: PartialDeep(properties[key] as any) }\n }, {}) as never\n}\n// -------------------------------------------------------------------------------------\n// TPartialDeepRest\n// -------------------------------------------------------------------------------------\nexport type TPartialDeepRest<T extends TSchema[], Acc extends TSchema[] = []> = T extends [\n infer L extends TSchema,\n ...infer R extends TSchema[],\n]\n ? TPartialDeepRest<R, [...Acc, TPartialDeep<L>]>\n : Acc\nfunction PartialDeepRest<T extends TSchema[]>(rest: [...T]): TPartialDeepRest<T> {\n return rest.map((schema) => PartialDeep(schema)) as never\n}\n// -------------------------------------------------------------------------------------\n// TPartialDeep\n// -------------------------------------------------------------------------------------\nexport type TPartialDeep<T extends TSchema> = T extends TIntersect<infer S>\n ? TIntersect<TPartialDeepRest<S>>\n : T extends TUnion<infer S>\n ? TUnion<TPartialDeepRest<S>>\n : T extends TObject<infer S>\n ? TPartial<TObject<Evaluate<TPartialDeepProperties<S>>>>\n : T\nexport function PartialDeep<T extends TSchema>(schema: T): TPartialDeep<T> {\n return (\n TypeGuard.IsIntersect(schema)\n ? Type.Intersect(PartialDeepRest(schema.allOf))\n : TypeGuard.IsUnion(schema)\n ? Type.Union(PartialDeepRest(schema.anyOf))\n : TypeGuard.IsObject(schema)\n ? Type.Partial(Type.Object(PartialDeepProperties(schema.properties)))\n : schema\n ) as never\n}\n"],
5
+ "mappings": "AAIA;AAAA,EACE;AAAA,EACA;AAAA,OAQK;AAQP,SAAS,sBAA6C,YAA0C;AAC9F,SAAO,OAAO,oBAAoB,UAAU,EAAE,OAAO,CAAC,KAAK,QAAQ;AACjE,WAAO,EAAE,GAAG,KAAK,CAAC,GAAG,GAAG,YAAY,WAAW,GAAG,CAAQ,EAAE;AAAA,EAC9D,GAAG,CAAC,CAAC;AACP;AAUA,SAAS,gBAAqC,MAAmC;AAC/E,SAAO,KAAK,IAAI,CAAC,WAAW,YAAY,MAAM,CAAC;AACjD;AAWO,SAAS,YAA+B,QAA4B;AACzE,SACE,UAAU,YAAY,MAAM,IACxB,KAAK,UAAU,gBAAgB,OAAO,KAAK,CAAC,IAC5C,UAAU,QAAQ,MAAM,IACtB,KAAK,MAAM,gBAAgB,OAAO,KAAK,CAAC,IACxC,UAAU,SAAS,MAAM,IACvB,KAAK,QAAQ,KAAK,OAAO,sBAAsB,OAAO,UAAU,CAAC,CAAC,IAClE;AAEZ;",
6
+ "names": []
7
+ }
package/dist/server.js CHANGED
@@ -6,7 +6,7 @@ import { createNavigation } from "./navigation/index.js";
6
6
  import { extensions } from "./schemas/extensions.js";
7
7
  import { OpenAPIDocumentSchema } from "./schemas/v3.1/strict/openapi-document.js";
8
8
  import { keyOf } from "./helpers/general.js";
9
- import { fetchUrls, readFiles } from "@scalar/openapi-parser/plugins";
9
+ import { fetchUrls, readFiles } from "@scalar/json-magic/bundle/plugins/node";
10
10
  import { coerceValue } from "./schemas/typebox-coerce.js";
11
11
  const DEFAULT_ASSETS_FOLDER = "assets";
12
12
  const WORKSPACE_FILE_NAME = "scalar-workspace.json";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/server.ts"],
4
- "sourcesContent": ["import { escapeJsonPointer, upgrade } from '@scalar/openapi-parser'\nimport { getValueByPath, parseJsonPointer } from './helpers/json-path-utils'\nimport type { WorkspaceDocumentMeta, WorkspaceMeta } from './schemas/workspace'\nimport fs from 'node:fs/promises'\nimport { cwd } from 'node:process'\nimport { createNavigation, type createNavigationOptions } from '@/navigation'\nimport { extensions } from '@/schemas/extensions'\nimport { OpenAPIDocumentSchema, type OpenApiDocument } from '@/schemas/v3.1/strict/openapi-document'\nimport type { PathsObject } from '@/schemas/v3.1/strict/paths'\nimport { keyOf } from '@/helpers/general'\nimport type { OperationObject } from '@/schemas/v3.1/strict/path-operations'\nimport { fetchUrls, readFiles } from '@scalar/openapi-parser/plugins'\nimport { coerceValue } from '@/schemas/typebox-coerce'\nimport type { ComponentsObject } from '@/schemas/v3.1/strict/components'\nimport type { TraversedEntry } from '@/schemas/navigation'\n\nconst DEFAULT_ASSETS_FOLDER = 'assets'\nexport const WORKSPACE_FILE_NAME = 'scalar-workspace.json'\n\ntype WorkspaceDocumentMetaInput = {\n name: string\n meta?: WorkspaceDocumentMeta\n}\n\ntype UrlDoc = { url: string } & WorkspaceDocumentMetaInput\ntype FileDoc = { path: string } & WorkspaceDocumentMetaInput\ntype ObjectDoc = { document: Record<string, unknown> } & WorkspaceDocumentMetaInput\n\ntype WorkspaceDocumentInput = UrlDoc | ObjectDoc | FileDoc\n\ntype CreateServerWorkspaceStoreBase = {\n documents: WorkspaceDocumentInput[]\n meta?: WorkspaceMeta\n config?: createNavigationOptions\n}\ntype CreateServerWorkspaceStore =\n | ({\n directory?: string\n mode: 'static'\n } & CreateServerWorkspaceStoreBase)\n | ({\n baseUrl: string\n mode: 'ssr'\n } & CreateServerWorkspaceStoreBase)\n\nconst httpMethods = new Set(['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'])\n\n/**\n * Filters an OpenAPI PathsObject to only include standard HTTP methods.\n * Removes any vendor extensions or other non-HTTP properties.\n *\n * @param paths - The OpenAPI PathsObject to filter\n * @returns A new PathsObject containing only standard HTTP methods\n *\n * @example\n * Input: {\n * \"/users\": {\n * \"get\": {...},\n * \"x-custom\": {...},\n * \"post\": {...}\n * }\n * }\n * Output: {\n * \"/users\": {\n * \"get\": {...},\n * \"post\": {...}\n * }\n * }\n */\nexport function filterHttpMethodsOnly(paths: PathsObject) {\n const result: Record<string, Record<string, OperationObject>> = {}\n\n // Todo: skip extension properties\n for (const [path, methods] of Object.entries(paths)) {\n if (!methods) {\n continue\n }\n\n const filteredMethods: Record<string, any> = {}\n\n for (const [method, operation] of Object.entries(methods)) {\n if (httpMethods.has(method.toLowerCase())) {\n filteredMethods[method] = operation\n }\n }\n\n if (Object.keys(filteredMethods).length > 0) {\n result[path] = filteredMethods\n }\n }\n\n return result\n}\n\n/**\n * Escapes path keys in an OpenAPI PathsObject to be JSON Pointer compatible.\n * This is necessary because OpenAPI paths can contain characters that need to be escaped\n * when used as JSON Pointer references (like '/' and '~').\n *\n * @example\n * Input: { \"/users/{id}\": { ... } }\n * Output: { \"/users~1{id}\": { ... } }\n */\nexport function escapePaths(paths: Record<string, Record<string, OperationObject>>) {\n const result: Record<string, Record<string, OperationObject>> = {}\n\n Object.keys(paths).forEach((path) => {\n if (paths[path]) {\n result[escapeJsonPointer(path)] = paths[path]\n }\n })\n\n return result\n}\n\n/**\n * Externalizes components by turning them into refs.\n */\nexport function externalizeComponentReferences(\n document: OpenApiDocument,\n meta: { mode: 'ssr'; name: string; baseUrl: string } | { mode: 'static'; name: string; directory: string },\n) {\n const result: Record<string, any> = {}\n\n if (!document.components) {\n return result\n }\n\n Object.entries(document.components).forEach(([type, component]) => {\n if (!component || typeof component !== 'object') {\n return\n }\n\n result[type] = {}\n Object.keys(component).forEach((name) => {\n const ref =\n meta.mode === 'ssr'\n ? `${meta.baseUrl}/${meta.name}/components/${type}/${name}#`\n : `./chunks/${meta.name}/components/${type}/${name}.json#`\n\n result[type][name] = { '$ref': ref, $global: true }\n })\n })\n\n return result\n}\n\n/**\n * Externalizes paths operations by turning them into refs.\n */\nexport function externalizePathReferences(\n document: OpenApiDocument,\n meta: { mode: 'ssr'; name: string; baseUrl: string } | { mode: 'static'; name: string; directory: string },\n) {\n const result: Record<string, any> = {}\n\n if (!document.paths) {\n return result\n }\n\n Object.entries(document.paths).forEach(([path, pathItem]) => {\n if (!pathItem || typeof pathItem !== 'object') {\n return\n }\n\n const pathItemRecord = pathItem as Record<string, unknown>\n\n result[path] = {}\n\n const escapedPath = escapeJsonPointer(path)\n\n keyOf(pathItemRecord).forEach((type) => {\n if (httpMethods.has(type)) {\n const ref =\n meta.mode === 'ssr'\n ? `${meta.baseUrl}/${meta.name}/operations/${escapedPath}/${type}#`\n : `./chunks/${meta.name}/operations/${escapedPath}/${type}.json#`\n\n result[path][type] = { '$ref': ref, $global: true }\n } else {\n result[path][type] = pathItemRecord[type]\n }\n })\n })\n\n return result\n}\n\n/**\n * Resolves a workspace document from various input sources (URL, local file, or direct document object).\n *\n * @param workspaceDocument - The document input to resolve, which can be:\n * - A URL to fetch the document from\n * - A local file path to read the document from\n * - A direct document object\n * @returns A promise that resolves to an object containing:\n * - ok: boolean indicating if the resolution was successful\n * - data: The resolved document data\n *\n * @example\n * // Resolve from URL\n * const urlDoc = await loadDocument({ name: 'api', url: 'https://api.example.com/openapi.json' })\n *\n * // Resolve direct document\n * const directDoc = await loadDocument({\n * name: 'inline',\n * document: { openapi: '3.0.0', paths: {} }\n * })\n */\nasync function loadDocument(workspaceDocument: WorkspaceDocumentInput) {\n if ('url' in workspaceDocument) {\n return fetchUrls().exec(workspaceDocument.url)\n }\n\n if ('path' in workspaceDocument) {\n return readFiles().exec(workspaceDocument.path)\n }\n\n return {\n ok: true as const,\n data: workspaceDocument.document,\n }\n}\n\n/**\n * Create server state workspace store\n */\nexport async function createServerWorkspaceStore(workspaceProps: CreateServerWorkspaceStore) {\n /**\n * Base workspace document containing essential metadata and document references.\n *\n * This workspace document provides the minimal information needed for initial rendering.\n * All components and path operations are replaced with references to enable lazy loading.\n *\n * In SSR mode, references point to API endpoints.\n * In static mode, references point to filesystem chunks.\n */\n const workspace = {\n ...workspaceProps.meta,\n documents: {} as Record<string, OpenApiDocument & { [extensions.document.navigation]: TraversedEntry[] }>,\n }\n\n /**\n * A map of document chunks that can be loaded asynchronously by the client.\n * Each document is split into components and operations to enable lazy loading.\n * The keys are document names and values contain the components and operations\n * for that document.\n */\n const assets = {} as Record<\n string,\n { components?: ComponentsObject; operations?: Record<string, Record<string, OperationObject>> }\n >\n\n /**\n * Adds a new document to the workspace.\n *\n * This function processes an OpenAPI document by:\n * 1. Converting it to OpenAPI 3.1 format if needed\n * 2. Separating it into reusable components and path operations\n * 3. Externalizing references based on the workspace mode (SSR or static)\n * 4. Adding the processed document to the workspace with its metadata\n *\n * The resulting document contains minimal information with externalized references\n * that will be resolved on-demand through the workspace's get() method.\n *\n * @param document - The OpenAPI document to process and add\n * @param meta - Document metadata containing the required name and optional settings\n */\n const addDocumentSync = (document: Record<string, unknown>, meta: { name: string } & WorkspaceDocumentMeta) => {\n const { name, ...documentMeta } = meta\n\n const documentV3 = coerceValue(OpenAPIDocumentSchema, upgrade(document).specification)\n\n // add the assets\n assets[meta.name] = {\n components: documentV3.components,\n operations: documentV3.paths && escapePaths(filterHttpMethodsOnly(documentV3.paths)),\n }\n\n const options =\n workspaceProps.mode === 'ssr'\n ? { mode: workspaceProps.mode, name, baseUrl: workspaceProps.baseUrl }\n : { mode: workspaceProps.mode, name, directory: workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER }\n\n const components = externalizeComponentReferences(documentV3, options)\n const paths = externalizePathReferences(documentV3, options)\n\n // Build the sidebar entries\n const { entries } = createNavigation(documentV3, workspaceProps.config ?? {})\n\n // The document is now a minimal version with externalized references to components and operations.\n // These references will be resolved asynchronously when needed through the workspace's get() method.\n workspace.documents[meta.name] = {\n ...documentMeta,\n ...documentV3,\n components,\n paths,\n [extensions.document.navigation]: entries,\n }\n }\n\n /**\n * Adds a new document to the workspace asynchronously.\n *\n * This function:\n * 1. Loads the document using the provided input\n * 2. Checks if the document loaded successfully\n * 3. If successful, adds the document to the workspace using addDocumentSync\n *\n * @param input - The document input containing the document source and metadata\n */\n const addDocument = async (input: WorkspaceDocumentInput) => {\n const document = await loadDocument(input)\n\n if (!document.ok) {\n console.warn(`Failed to load document \"${input.name}`)\n return\n }\n\n addDocumentSync(document.data as Record<string, unknown>, { name: input.name, ...input.meta })\n }\n\n // Load and process all initial documents in parallel\n await Promise.all(workspaceProps.documents.map(addDocument))\n\n return {\n /**\n * Generates workspace chunks by writing components and operations to the filesystem.\n *\n * This method is only available in static mode. It creates a directory structure containing:\n * - A workspace file with metadata and document references\n * - Component chunks split by type (schemas, parameters, etc)\n * - Operation chunks split by path and HTTP method\n *\n * The generated workspace references will be relative file paths pointing to these chunks.\n *\n * @throws {Error} If called when mode is not 'static'\n */\n generateWorkspaceChunks: async () => {\n if (workspaceProps.mode !== 'static') {\n throw 'Mode has to be set to `static` to generate filesystem workspace chunks'\n }\n\n // Write the workspace document\n const basePath = `${cwd()}/${workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER}`\n await fs.mkdir(basePath, { recursive: true })\n\n // Write the workspace contents on the file system\n await fs.writeFile(`${basePath}/${WORKSPACE_FILE_NAME}`, JSON.stringify(workspace))\n\n // Write the chunks\n for (const [name, { components, operations }] of Object.entries(assets)) {\n // Write the components chunks\n if (components) {\n for (const [type, component] of Object.entries(components as Record<string, Record<string, unknown>>)) {\n const componentPath = `${basePath}/chunks/${name}/components/${type}`\n await fs.mkdir(componentPath, { recursive: true })\n\n for (const [key, value] of Object.entries(component)) {\n await fs.writeFile(`${componentPath}/${key}.json`, JSON.stringify(value))\n }\n }\n }\n\n // Write the operations chunks\n if (operations) {\n for (const [path, methods] of Object.entries(operations)) {\n const operationPath = `${basePath}/chunks/${name}/operations/${path}`\n await fs.mkdir(operationPath, { recursive: true })\n\n for (const [method, operation] of Object.entries(methods)) {\n await fs.writeFile(`${operationPath}/${method}.json`, JSON.stringify(operation))\n }\n }\n }\n }\n },\n /**\n * Returns the workspace document containing metadata and all sparse documents.\n *\n * The workspace document includes:\n * - Global workspace metadata (theme, active document, etc)\n * - Document metadata and sparse document\n * - In SSR mode: References point to in-memory chunks\n * - In static mode: References point to filesystem chunks\n *\n * @returns The complete workspace document\n */\n getWorkspace: () => {\n return workspace\n },\n /**\n * Retrieves a chunk of data from the workspace using a JSON Pointer\n *\n * A JSON Pointer is a string that references a specific location in a JSON document.\n * Only components and operations chunks can be retrieved.\n *\n * @example\n * ```ts\n * // Get a component\n * get('#/document-name/components/schemas/User')\n *\n * // Get an operation\n * get('#/document-name/operations/pets/get')\n * ```\n *\n * @param pointer - The JSON Pointer string to locate the chunk\n * @returns The chunk data if found, undefined otherwise\n */\n get: (pointer: string) => {\n return getValueByPath(assets, parseJsonPointer(pointer))\n },\n /**\n * Adds a new document to the workspace asynchronously.\n *\n * This function:\n * 1. Loads the document using the provided input\n * 2. Checks if the document loaded successfully\n * 3. If successful, adds the document to the workspace using addDocumentSync\n *\n * @param input - The document input containing the document source and metadata\n */\n addDocument,\n }\n}\n"],
4
+ "sourcesContent": ["import { escapeJsonPointer, upgrade } from '@scalar/openapi-parser'\nimport { getValueByPath, parseJsonPointer } from './helpers/json-path-utils'\nimport type { WorkspaceDocumentMeta, WorkspaceMeta } from './schemas/workspace'\nimport fs from 'node:fs/promises'\nimport { cwd } from 'node:process'\nimport { createNavigation, type createNavigationOptions } from '@/navigation'\nimport { extensions } from '@/schemas/extensions'\nimport { OpenAPIDocumentSchema, type OpenApiDocument } from '@/schemas/v3.1/strict/openapi-document'\nimport type { PathsObject } from '@/schemas/v3.1/strict/paths'\nimport { keyOf } from '@/helpers/general'\nimport type { OperationObject } from '@/schemas/v3.1/strict/path-operations'\nimport { fetchUrls, readFiles } from '@scalar/json-magic/bundle/plugins/node'\nimport { coerceValue } from '@/schemas/typebox-coerce'\nimport type { ComponentsObject } from '@/schemas/v3.1/strict/components'\nimport type { TraversedEntry } from '@/schemas/navigation'\n\nconst DEFAULT_ASSETS_FOLDER = 'assets'\nexport const WORKSPACE_FILE_NAME = 'scalar-workspace.json'\n\ntype WorkspaceDocumentMetaInput = {\n name: string\n meta?: WorkspaceDocumentMeta\n}\n\ntype UrlDoc = { url: string } & WorkspaceDocumentMetaInput\ntype FileDoc = { path: string } & WorkspaceDocumentMetaInput\ntype ObjectDoc = { document: Record<string, unknown> } & WorkspaceDocumentMetaInput\n\ntype WorkspaceDocumentInput = UrlDoc | ObjectDoc | FileDoc\n\ntype CreateServerWorkspaceStoreBase = {\n documents: WorkspaceDocumentInput[]\n meta?: WorkspaceMeta\n config?: createNavigationOptions\n}\ntype CreateServerWorkspaceStore =\n | ({\n directory?: string\n mode: 'static'\n } & CreateServerWorkspaceStoreBase)\n | ({\n baseUrl: string\n mode: 'ssr'\n } & CreateServerWorkspaceStoreBase)\n\nconst httpMethods = new Set(['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'])\n\n/**\n * Filters an OpenAPI PathsObject to only include standard HTTP methods.\n * Removes any vendor extensions or other non-HTTP properties.\n *\n * @param paths - The OpenAPI PathsObject to filter\n * @returns A new PathsObject containing only standard HTTP methods\n *\n * @example\n * Input: {\n * \"/users\": {\n * \"get\": {...},\n * \"x-custom\": {...},\n * \"post\": {...}\n * }\n * }\n * Output: {\n * \"/users\": {\n * \"get\": {...},\n * \"post\": {...}\n * }\n * }\n */\nexport function filterHttpMethodsOnly(paths: PathsObject) {\n const result: Record<string, Record<string, OperationObject>> = {}\n\n // Todo: skip extension properties\n for (const [path, methods] of Object.entries(paths)) {\n if (!methods) {\n continue\n }\n\n const filteredMethods: Record<string, any> = {}\n\n for (const [method, operation] of Object.entries(methods)) {\n if (httpMethods.has(method.toLowerCase())) {\n filteredMethods[method] = operation\n }\n }\n\n if (Object.keys(filteredMethods).length > 0) {\n result[path] = filteredMethods\n }\n }\n\n return result\n}\n\n/**\n * Escapes path keys in an OpenAPI PathsObject to be JSON Pointer compatible.\n * This is necessary because OpenAPI paths can contain characters that need to be escaped\n * when used as JSON Pointer references (like '/' and '~').\n *\n * @example\n * Input: { \"/users/{id}\": { ... } }\n * Output: { \"/users~1{id}\": { ... } }\n */\nexport function escapePaths(paths: Record<string, Record<string, OperationObject>>) {\n const result: Record<string, Record<string, OperationObject>> = {}\n\n Object.keys(paths).forEach((path) => {\n if (paths[path]) {\n result[escapeJsonPointer(path)] = paths[path]\n }\n })\n\n return result\n}\n\n/**\n * Externalizes components by turning them into refs.\n */\nexport function externalizeComponentReferences(\n document: OpenApiDocument,\n meta: { mode: 'ssr'; name: string; baseUrl: string } | { mode: 'static'; name: string; directory: string },\n) {\n const result: Record<string, any> = {}\n\n if (!document.components) {\n return result\n }\n\n Object.entries(document.components).forEach(([type, component]) => {\n if (!component || typeof component !== 'object') {\n return\n }\n\n result[type] = {}\n Object.keys(component).forEach((name) => {\n const ref =\n meta.mode === 'ssr'\n ? `${meta.baseUrl}/${meta.name}/components/${type}/${name}#`\n : `./chunks/${meta.name}/components/${type}/${name}.json#`\n\n result[type][name] = { '$ref': ref, $global: true }\n })\n })\n\n return result\n}\n\n/**\n * Externalizes paths operations by turning them into refs.\n */\nexport function externalizePathReferences(\n document: OpenApiDocument,\n meta: { mode: 'ssr'; name: string; baseUrl: string } | { mode: 'static'; name: string; directory: string },\n) {\n const result: Record<string, any> = {}\n\n if (!document.paths) {\n return result\n }\n\n Object.entries(document.paths).forEach(([path, pathItem]) => {\n if (!pathItem || typeof pathItem !== 'object') {\n return\n }\n\n const pathItemRecord = pathItem as Record<string, unknown>\n\n result[path] = {}\n\n const escapedPath = escapeJsonPointer(path)\n\n keyOf(pathItemRecord).forEach((type) => {\n if (httpMethods.has(type)) {\n const ref =\n meta.mode === 'ssr'\n ? `${meta.baseUrl}/${meta.name}/operations/${escapedPath}/${type}#`\n : `./chunks/${meta.name}/operations/${escapedPath}/${type}.json#`\n\n result[path][type] = { '$ref': ref, $global: true }\n } else {\n result[path][type] = pathItemRecord[type]\n }\n })\n })\n\n return result\n}\n\n/**\n * Resolves a workspace document from various input sources (URL, local file, or direct document object).\n *\n * @param workspaceDocument - The document input to resolve, which can be:\n * - A URL to fetch the document from\n * - A local file path to read the document from\n * - A direct document object\n * @returns A promise that resolves to an object containing:\n * - ok: boolean indicating if the resolution was successful\n * - data: The resolved document data\n *\n * @example\n * // Resolve from URL\n * const urlDoc = await loadDocument({ name: 'api', url: 'https://api.example.com/openapi.json' })\n *\n * // Resolve direct document\n * const directDoc = await loadDocument({\n * name: 'inline',\n * document: { openapi: '3.0.0', paths: {} }\n * })\n */\nasync function loadDocument(workspaceDocument: WorkspaceDocumentInput) {\n if ('url' in workspaceDocument) {\n return fetchUrls().exec(workspaceDocument.url)\n }\n\n if ('path' in workspaceDocument) {\n return readFiles().exec(workspaceDocument.path)\n }\n\n return {\n ok: true as const,\n data: workspaceDocument.document,\n }\n}\n\n/**\n * Create server state workspace store\n */\nexport async function createServerWorkspaceStore(workspaceProps: CreateServerWorkspaceStore) {\n /**\n * Base workspace document containing essential metadata and document references.\n *\n * This workspace document provides the minimal information needed for initial rendering.\n * All components and path operations are replaced with references to enable lazy loading.\n *\n * In SSR mode, references point to API endpoints.\n * In static mode, references point to filesystem chunks.\n */\n const workspace = {\n ...workspaceProps.meta,\n documents: {} as Record<string, OpenApiDocument & { [extensions.document.navigation]: TraversedEntry[] }>,\n }\n\n /**\n * A map of document chunks that can be loaded asynchronously by the client.\n * Each document is split into components and operations to enable lazy loading.\n * The keys are document names and values contain the components and operations\n * for that document.\n */\n const assets = {} as Record<\n string,\n { components?: ComponentsObject; operations?: Record<string, Record<string, OperationObject>> }\n >\n\n /**\n * Adds a new document to the workspace.\n *\n * This function processes an OpenAPI document by:\n * 1. Converting it to OpenAPI 3.1 format if needed\n * 2. Separating it into reusable components and path operations\n * 3. Externalizing references based on the workspace mode (SSR or static)\n * 4. Adding the processed document to the workspace with its metadata\n *\n * The resulting document contains minimal information with externalized references\n * that will be resolved on-demand through the workspace's get() method.\n *\n * @param document - The OpenAPI document to process and add\n * @param meta - Document metadata containing the required name and optional settings\n */\n const addDocumentSync = (document: Record<string, unknown>, meta: { name: string } & WorkspaceDocumentMeta) => {\n const { name, ...documentMeta } = meta\n\n const documentV3 = coerceValue(OpenAPIDocumentSchema, upgrade(document).specification)\n\n // add the assets\n assets[meta.name] = {\n components: documentV3.components,\n operations: documentV3.paths && escapePaths(filterHttpMethodsOnly(documentV3.paths)),\n }\n\n const options =\n workspaceProps.mode === 'ssr'\n ? { mode: workspaceProps.mode, name, baseUrl: workspaceProps.baseUrl }\n : { mode: workspaceProps.mode, name, directory: workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER }\n\n const components = externalizeComponentReferences(documentV3, options)\n const paths = externalizePathReferences(documentV3, options)\n\n // Build the sidebar entries\n const { entries } = createNavigation(documentV3, workspaceProps.config ?? {})\n\n // The document is now a minimal version with externalized references to components and operations.\n // These references will be resolved asynchronously when needed through the workspace's get() method.\n workspace.documents[meta.name] = {\n ...documentMeta,\n ...documentV3,\n components,\n paths,\n [extensions.document.navigation]: entries,\n }\n }\n\n /**\n * Adds a new document to the workspace asynchronously.\n *\n * This function:\n * 1. Loads the document using the provided input\n * 2. Checks if the document loaded successfully\n * 3. If successful, adds the document to the workspace using addDocumentSync\n *\n * @param input - The document input containing the document source and metadata\n */\n const addDocument = async (input: WorkspaceDocumentInput) => {\n const document = await loadDocument(input)\n\n if (!document.ok) {\n console.warn(`Failed to load document \"${input.name}`)\n return\n }\n\n addDocumentSync(document.data as Record<string, unknown>, { name: input.name, ...input.meta })\n }\n\n // Load and process all initial documents in parallel\n await Promise.all(workspaceProps.documents.map(addDocument))\n\n return {\n /**\n * Generates workspace chunks by writing components and operations to the filesystem.\n *\n * This method is only available in static mode. It creates a directory structure containing:\n * - A workspace file with metadata and document references\n * - Component chunks split by type (schemas, parameters, etc)\n * - Operation chunks split by path and HTTP method\n *\n * The generated workspace references will be relative file paths pointing to these chunks.\n *\n * @throws {Error} If called when mode is not 'static'\n */\n generateWorkspaceChunks: async () => {\n if (workspaceProps.mode !== 'static') {\n throw 'Mode has to be set to `static` to generate filesystem workspace chunks'\n }\n\n // Write the workspace document\n const basePath = `${cwd()}/${workspaceProps.directory ?? DEFAULT_ASSETS_FOLDER}`\n await fs.mkdir(basePath, { recursive: true })\n\n // Write the workspace contents on the file system\n await fs.writeFile(`${basePath}/${WORKSPACE_FILE_NAME}`, JSON.stringify(workspace))\n\n // Write the chunks\n for (const [name, { components, operations }] of Object.entries(assets)) {\n // Write the components chunks\n if (components) {\n for (const [type, component] of Object.entries(components as Record<string, Record<string, unknown>>)) {\n const componentPath = `${basePath}/chunks/${name}/components/${type}`\n await fs.mkdir(componentPath, { recursive: true })\n\n for (const [key, value] of Object.entries(component)) {\n await fs.writeFile(`${componentPath}/${key}.json`, JSON.stringify(value))\n }\n }\n }\n\n // Write the operations chunks\n if (operations) {\n for (const [path, methods] of Object.entries(operations)) {\n const operationPath = `${basePath}/chunks/${name}/operations/${path}`\n await fs.mkdir(operationPath, { recursive: true })\n\n for (const [method, operation] of Object.entries(methods)) {\n await fs.writeFile(`${operationPath}/${method}.json`, JSON.stringify(operation))\n }\n }\n }\n }\n },\n /**\n * Returns the workspace document containing metadata and all sparse documents.\n *\n * The workspace document includes:\n * - Global workspace metadata (theme, active document, etc)\n * - Document metadata and sparse document\n * - In SSR mode: References point to in-memory chunks\n * - In static mode: References point to filesystem chunks\n *\n * @returns The complete workspace document\n */\n getWorkspace: () => {\n return workspace\n },\n /**\n * Retrieves a chunk of data from the workspace using a JSON Pointer\n *\n * A JSON Pointer is a string that references a specific location in a JSON document.\n * Only components and operations chunks can be retrieved.\n *\n * @example\n * ```ts\n * // Get a component\n * get('#/document-name/components/schemas/User')\n *\n * // Get an operation\n * get('#/document-name/operations/pets/get')\n * ```\n *\n * @param pointer - The JSON Pointer string to locate the chunk\n * @returns The chunk data if found, undefined otherwise\n */\n get: (pointer: string) => {\n return getValueByPath(assets, parseJsonPointer(pointer))\n },\n /**\n * Adds a new document to the workspace asynchronously.\n *\n * This function:\n * 1. Loads the document using the provided input\n * 2. Checks if the document loaded successfully\n * 3. If successful, adds the document to the workspace using addDocumentSync\n *\n * @param input - The document input containing the document source and metadata\n */\n addDocument,\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "openapi",
17
17
  "scalar"
18
18
  ],
19
- "version": "0.11.0",
19
+ "version": "0.12.0",
20
20
  "engines": {
21
21
  "node": ">=18"
22
22
  },
@@ -37,6 +37,11 @@
37
37
  "types": "./dist/schemas/workspace.d.ts",
38
38
  "default": "./dist/schemas/workspace.js"
39
39
  },
40
+ "./helpers/*": {
41
+ "import": "./dist/helpers/*.js",
42
+ "types": "./dist/helpers/*.d.ts",
43
+ "default": "./dist/helpers/*.js"
44
+ },
40
45
  "./schemas/v3.1/*": {
41
46
  "import": "./dist/schemas/v3.1/*.js",
42
47
  "types": "./dist/schemas/v3.1/*.d.ts",
@@ -62,12 +67,11 @@
62
67
  "github-slugger": "^2.0.0",
63
68
  "vue": "^3.5.17",
64
69
  "yaml": "2.8.0",
65
- "@scalar/code-highlight": "0.1.9",
66
70
  "@scalar/helpers": "0.0.7",
67
- "@scalar/json-diff": "0.0.4",
68
- "@scalar/openapi-parser": "0.18.3",
71
+ "@scalar/json-magic": "0.1.0",
72
+ "@scalar/code-highlight": "0.1.9",
69
73
  "@scalar/types": "0.2.11",
70
- "@scalar/openapi-types": "0.3.7"
74
+ "@scalar/openapi-parser": "0.19.0"
71
75
  },
72
76
  "devDependencies": {
73
77
  "@google-cloud/storage": "7.16.0",
@@ -1,63 +0,0 @@
1
- import type { UnknownObject } from './general.js';
2
- /**
3
- * Creates a proxy that automatically resolves JSON references ($ref) in an object.
4
- * The proxy intercepts property access and automatically resolves any $ref references
5
- * to their target values in the source document.
6
- *
7
- * @param targetObject - The object to create a proxy for
8
- * @param sourceDocument - The source document containing the reference targets (defaults to targetObject)
9
- * @param resolvedProxyCache - Optional cache to store resolved proxies and prevent duplicate proxies
10
- * @returns A proxy that automatically resolves $ref references
11
- *
12
- * @example
13
- * // Basic usage with local references
14
- * const doc = {
15
- * components: {
16
- * schemas: {
17
- * User: { type: 'object', properties: { name: { type: 'string' } } }
18
- * }
19
- * },
20
- * paths: {
21
- * '/users': {
22
- * get: {
23
- * responses: {
24
- * 200: {
25
- * content: {
26
- * 'application/json': {
27
- * schema: { $ref: '#/components/schemas/User' }
28
- * }
29
- * }
30
- * }
31
- * }
32
- * }
33
- * }
34
- * }
35
- * }
36
- *
37
- * const proxy = createMagicProxy(doc)
38
- * // Accessing the schema will automatically resolve the $ref
39
- * console.log(proxy.paths['/users'].get.responses[200].content['application/json'].schema)
40
- * // Output: { type: 'object', properties: { name: { type: 'string' } } }
41
- *
42
- * @example
43
- * // Using with a cache to prevent duplicate proxies
44
- * const cache = new WeakMap()
45
- * const proxy1 = createMagicProxy(doc, doc, cache)
46
- * const proxy2 = createMagicProxy(doc, doc, cache)
47
- * // proxy1 and proxy2 are the same instance due to caching
48
- * console.log(proxy1 === proxy2) // true
49
- */
50
- export declare function createMagicProxy<T extends UnknownObject | UnknownObject[]>(targetObject: T, sourceDocument?: T, resolvedProxyCache?: WeakMap<object, T>): T;
51
- export declare const TARGET_SYMBOL: unique symbol;
52
- /**
53
- * Gets the raw (non-proxied) version of an object created by createMagicProxy.
54
- * This is useful when you need to access the original object without the magic proxy wrapper.
55
- *
56
- * @param obj - The magic proxy object to get the raw version of
57
- * @returns The raw version of the object
58
- * @example
59
- * const proxy = createMagicProxy({ foo: { $ref: '#/bar' } })
60
- * const raw = getRaw(proxy) // { foo: { $ref: '#/bar' } }
61
- */
62
- export declare function getRaw<T extends UnknownObject>(obj: T): T;
63
- //# sourceMappingURL=proxy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/helpers/proxy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AA2H9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EAAE,EACxE,YAAY,EAAE,CAAC,EACf,cAAc,GAAE,CAAgB,EAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GACtC,CAAC,CAyBH;AAED,eAAO,MAAM,aAAa,eAA6B,CAAA;AACvD;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,aAAa,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAMzD"}
@@ -1,107 +0,0 @@
1
- import { isReactive, toRaw } from "vue";
2
- import { getValueByPath, parseJsonPointer } from "./json-path-utils.js";
3
- import { isLocalRef, isObject } from "./general.js";
4
- const isMagicProxy = Symbol("isMagicProxy");
5
- function createProxyHandler(sourceDocument, resolvedProxyCache) {
6
- return {
7
- get(target, property, receiver) {
8
- if (property === TARGET_SYMBOL) {
9
- return target;
10
- }
11
- if (property === isMagicProxy) {
12
- return true;
13
- }
14
- const value = Reflect.get(target, property, receiver);
15
- const deepResolveNestedRefs = (value2, originalRef) => {
16
- if (!isObject(value2) && !Array.isArray(value2)) {
17
- return value2;
18
- }
19
- if ("$ref" in value2) {
20
- const ref = value2.$ref;
21
- if (isLocalRef(ref)) {
22
- const referencePath = parseJsonPointer(ref);
23
- const resolvedValue = getValueByPath(sourceDocument, referencePath);
24
- return deepResolveNestedRefs(resolvedValue, originalRef ?? ref);
25
- }
26
- }
27
- if (originalRef) {
28
- return createMagicProxy({ ...value2, "x-original-ref": originalRef }, sourceDocument, resolvedProxyCache);
29
- }
30
- return createMagicProxy(value2, sourceDocument, resolvedProxyCache);
31
- };
32
- return deepResolveNestedRefs(value);
33
- },
34
- set(target, property, newValue, receiver) {
35
- const rawTarget = isReactive(target) ? toRaw(target) : target;
36
- const currentValue = rawTarget[property];
37
- if (isObject(currentValue) && "$ref" in currentValue && typeof currentValue.$ref === "string" && isLocalRef(currentValue.$ref)) {
38
- const referencePath = parseJsonPointer(currentValue.$ref);
39
- const targetObject = getValueByPath(sourceDocument, referencePath.slice(0, -1));
40
- const lastPathSegment = referencePath[referencePath.length - 1];
41
- if (targetObject && lastPathSegment) {
42
- targetObject[lastPathSegment] = newValue;
43
- }
44
- } else {
45
- Reflect.set(rawTarget, property, newValue, receiver);
46
- }
47
- return true;
48
- },
49
- has(target, key) {
50
- if (typeof key === "string" && key !== "$ref" && typeof target.$ref === "string" && isLocalRef(target.$ref)) {
51
- const referencePath = parseJsonPointer(target["$ref"]);
52
- const resolvedValue = getValueByPath(sourceDocument, referencePath);
53
- return resolvedValue ? key in resolvedValue : false;
54
- }
55
- return key in target;
56
- },
57
- ownKeys(target) {
58
- if ("$ref" in target && typeof target.$ref === "string" && isLocalRef(target.$ref)) {
59
- const referencePath = parseJsonPointer(target["$ref"]);
60
- const resolvedValue = getValueByPath(sourceDocument, referencePath);
61
- return resolvedValue ? Reflect.ownKeys(resolvedValue) : [];
62
- }
63
- return Reflect.ownKeys(target);
64
- },
65
- getOwnPropertyDescriptor(target, key) {
66
- if ("$ref" in target && key !== "$ref" && typeof target.$ref === "string" && isLocalRef(target.$ref)) {
67
- const referencePath = parseJsonPointer(target["$ref"]);
68
- const resolvedValue = getValueByPath(sourceDocument, referencePath);
69
- if (resolvedValue) {
70
- return Object.getOwnPropertyDescriptor(resolvedValue, key);
71
- }
72
- }
73
- return Object.getOwnPropertyDescriptor(target, key);
74
- }
75
- };
76
- }
77
- function createMagicProxy(targetObject, sourceDocument = targetObject, resolvedProxyCache) {
78
- if (!isObject(targetObject) && !Array.isArray(targetObject)) {
79
- return targetObject;
80
- }
81
- const rawTarget = isReactive(targetObject) ? toRaw(targetObject) : targetObject;
82
- if (resolvedProxyCache?.has(rawTarget)) {
83
- const cachedValue = resolvedProxyCache.get(rawTarget);
84
- if (cachedValue) {
85
- return cachedValue;
86
- }
87
- }
88
- const handler = createProxyHandler(sourceDocument, resolvedProxyCache);
89
- const proxy = new Proxy(rawTarget, handler);
90
- if (resolvedProxyCache) {
91
- resolvedProxyCache.set(rawTarget, proxy);
92
- }
93
- return proxy;
94
- }
95
- const TARGET_SYMBOL = Symbol("magicProxyTarget");
96
- function getRaw(obj) {
97
- if (obj[isMagicProxy]) {
98
- return obj[TARGET_SYMBOL];
99
- }
100
- return obj;
101
- }
102
- export {
103
- TARGET_SYMBOL,
104
- createMagicProxy,
105
- getRaw
106
- };
107
- //# sourceMappingURL=proxy.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/helpers/proxy.ts"],
4
- "sourcesContent": ["import { isReactive, toRaw } from 'vue'\nimport { getValueByPath, parseJsonPointer } from './json-path-utils'\nimport { isLocalRef, isObject } from './general'\nimport type { UnknownObject } from './general'\n\nconst isMagicProxy = Symbol('isMagicProxy')\n\n/**\n * Creates a proxy handler that automatically resolves JSON references ($ref) in an object.\n * The handler intercepts property access, assignment, and property enumeration to automatically\n * resolve any $ref references to their target values in the source document.\n *\n * @param sourceDocument - The source document containing the reference targets\n * @param resolvedProxyCache - Optional cache to store resolved proxies and prevent duplicate proxies\n * @returns A proxy handler that automatically resolves $ref references\n */\nfunction createProxyHandler(\n sourceDocument: UnknownObject | UnknownObject[],\n resolvedProxyCache?: WeakMap<object, UnknownObject | UnknownObject[]>,\n): ProxyHandler<UnknownObject | UnknownObject[]> {\n return {\n get(target, property, receiver) {\n if (property === TARGET_SYMBOL) {\n return target\n }\n\n if (property === isMagicProxy) {\n return true\n }\n\n const value = Reflect.get(target, property, receiver)\n\n /**\n * Recursively resolves nested references in an object.\n * If the value is not an object, returns it as is.\n * If the value has a $ref property:\n * - For local references: resolves the reference and continues resolving nested refs\n * - For all other objects: creates a proxy for lazy resolution\n */\n const deepResolveNestedRefs = (value: unknown, originalRef?: string) => {\n if (!isObject(value) && !Array.isArray(value)) {\n return value\n }\n\n if ('$ref' in value) {\n const ref = value.$ref as string\n\n if (isLocalRef(ref)) {\n const referencePath = parseJsonPointer(ref)\n const resolvedValue = getValueByPath(sourceDocument, referencePath)\n\n // preserve the first $ref to maintain the original reference\n return deepResolveNestedRefs(resolvedValue, originalRef ?? ref)\n }\n }\n\n if (originalRef) {\n return createMagicProxy({ ...value, 'x-original-ref': originalRef }, sourceDocument, resolvedProxyCache)\n }\n\n return createMagicProxy(value, sourceDocument, resolvedProxyCache)\n }\n\n return deepResolveNestedRefs(value)\n },\n\n set(target: UnknownObject, property: string, newValue: unknown, receiver: UnknownObject) {\n const rawTarget = isReactive(target) ? toRaw(target) : target\n const currentValue = rawTarget[property]\n\n if (\n isObject(currentValue) &&\n '$ref' in currentValue &&\n typeof currentValue.$ref === 'string' &&\n isLocalRef(currentValue.$ref)\n ) {\n const referencePath = parseJsonPointer(currentValue.$ref)\n const targetObject = getValueByPath(sourceDocument, referencePath.slice(0, -1)) as UnknownObject\n const lastPathSegment = referencePath[referencePath.length - 1]\n\n if (targetObject && lastPathSegment) {\n targetObject[lastPathSegment] = newValue\n }\n } else {\n Reflect.set(rawTarget, property, newValue, receiver)\n }\n return true\n },\n\n has(target: UnknownObject, key: string) {\n if (typeof key === 'string' && key !== '$ref' && typeof target.$ref === 'string' && isLocalRef(target.$ref)) {\n const referencePath = parseJsonPointer(target['$ref'])\n const resolvedValue = getValueByPath(sourceDocument, referencePath) as UnknownObject\n\n return resolvedValue ? key in resolvedValue : false\n }\n\n return key in target\n },\n\n ownKeys(target: UnknownObject) {\n if ('$ref' in target && typeof target.$ref === 'string' && isLocalRef(target.$ref)) {\n const referencePath = parseJsonPointer(target['$ref'])\n const resolvedValue = getValueByPath(sourceDocument, referencePath)\n\n return resolvedValue ? Reflect.ownKeys(resolvedValue) : []\n }\n\n return Reflect.ownKeys(target)\n },\n\n getOwnPropertyDescriptor(target: UnknownObject, key: string) {\n if ('$ref' in target && key !== '$ref' && typeof target.$ref === 'string' && isLocalRef(target.$ref)) {\n const referencePath = parseJsonPointer(target['$ref'])\n const resolvedValue = getValueByPath(sourceDocument, referencePath)\n\n if (resolvedValue) {\n return Object.getOwnPropertyDescriptor(resolvedValue, key)\n }\n }\n\n return Object.getOwnPropertyDescriptor(target, key)\n },\n }\n}\n\n/**\n * Creates a proxy that automatically resolves JSON references ($ref) in an object.\n * The proxy intercepts property access and automatically resolves any $ref references\n * to their target values in the source document.\n *\n * @param targetObject - The object to create a proxy for\n * @param sourceDocument - The source document containing the reference targets (defaults to targetObject)\n * @param resolvedProxyCache - Optional cache to store resolved proxies and prevent duplicate proxies\n * @returns A proxy that automatically resolves $ref references\n *\n * @example\n * // Basic usage with local references\n * const doc = {\n * components: {\n * schemas: {\n * User: { type: 'object', properties: { name: { type: 'string' } } }\n * }\n * },\n * paths: {\n * '/users': {\n * get: {\n * responses: {\n * 200: {\n * content: {\n * 'application/json': {\n * schema: { $ref: '#/components/schemas/User' }\n * }\n * }\n * }\n * }\n * }\n * }\n * }\n * }\n *\n * const proxy = createMagicProxy(doc)\n * // Accessing the schema will automatically resolve the $ref\n * console.log(proxy.paths['/users'].get.responses[200].content['application/json'].schema)\n * // Output: { type: 'object', properties: { name: { type: 'string' } } }\n *\n * @example\n * // Using with a cache to prevent duplicate proxies\n * const cache = new WeakMap()\n * const proxy1 = createMagicProxy(doc, doc, cache)\n * const proxy2 = createMagicProxy(doc, doc, cache)\n * // proxy1 and proxy2 are the same instance due to caching\n * console.log(proxy1 === proxy2) // true\n */\nexport function createMagicProxy<T extends UnknownObject | UnknownObject[]>(\n targetObject: T,\n sourceDocument: T = targetObject,\n resolvedProxyCache?: WeakMap<object, T>,\n): T {\n if (!isObject(targetObject) && !Array.isArray(targetObject)) {\n return targetObject\n }\n\n const rawTarget = isReactive(targetObject) ? toRaw(targetObject) : targetObject\n\n // check for cached results\n if (resolvedProxyCache?.has(rawTarget)) {\n const cachedValue = resolvedProxyCache.get(rawTarget)\n\n if (cachedValue) {\n return cachedValue\n }\n }\n\n // Create a handler with the correct context\n const handler = createProxyHandler(sourceDocument, resolvedProxyCache)\n const proxy = new Proxy<T>(rawTarget, handler)\n\n if (resolvedProxyCache) {\n resolvedProxyCache.set(rawTarget, proxy)\n }\n\n return proxy\n}\n\nexport const TARGET_SYMBOL = Symbol('magicProxyTarget')\n/**\n * Gets the raw (non-proxied) version of an object created by createMagicProxy.\n * This is useful when you need to access the original object without the magic proxy wrapper.\n *\n * @param obj - The magic proxy object to get the raw version of\n * @returns The raw version of the object\n * @example\n * const proxy = createMagicProxy({ foo: { $ref: '#/bar' } })\n * const raw = getRaw(proxy) // { foo: { $ref: '#/bar' } }\n */\nexport function getRaw<T extends UnknownObject>(obj: T): T {\n if ((obj as T & { [isMagicProxy]: boolean | undefined })[isMagicProxy]) {\n return (obj as T & { [TARGET_SYMBOL]: T })[TARGET_SYMBOL]\n }\n\n return obj\n}\n"],
5
- "mappings": "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",
6
- "names": ["value"]
7
- }