@scalar/workspace-store 0.28.2 → 0.28.4

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":"environment.d.ts","sourceRoot":"","sources":["../../src/mutators/environment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7D,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EAGxB,MAAM,qDAAqD,CAAA;AAG5D,KAAK,KAAK,CAAC,CAAC,SAAS,MAAM,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAA;AAE5F;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC5B,WAAW,SAAS,GAAG,IAAI,EAC3B,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,kDAAkD,KAAK,CAAC,gCAAgC,CAAC,KACxF,kBAAkB,GAAG,SAoCvB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,SAAS,GAAG,IAAI,EAC3B,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,qBAAqB,KAAK,CAAC,gCAAgC,CAAC,SAO7D,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GACpC,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,sCAAsC,KAAK,CAAC,yCAAyC,CAAC,KACrF,aAAa,GAAG,SA0BlB,CAAA;AAED,eAAO,MAAM,yBAAyB,GACpC,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,4BAA4B,KAAK,CAAC,yCAAyC,CAAC,SAO7E,CAAA;AAED,eAAO,MAAM,0BAA0B,GAAI,4BAGxC;IACD,SAAS,EAAE,SAAS,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAAA;CACjD;iCAEgC,KAAK,CAAC,gCAAgC,CAAC;iCAEvC,KAAK,CAAC,gCAAgC,CAAC;yCAE/B,KAAK,CAAC,yCAAyC,CAAC;yCAEhD,KAAK,CAAC,yCAAyC,CAAC;CAGxF,CAAA"}
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/mutators/environment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7D,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EAGxB,MAAM,qDAAqD,CAAA;AAG5D,KAAK,KAAK,CAAC,CAAC,SAAS,MAAM,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAA;AAE5F;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC5B,WAAW,SAAS,GAAG,IAAI,EAC3B,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,kDAAkD,KAAK,CAAC,gCAAgC,CAAC,KACxF,kBAAkB,GAAG,SAoCvB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,SAAS,GAAG,IAAI,EAC3B,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,qBAAqB,KAAK,CAAC,gCAAgC,CAAC,SAO7D,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GACpC,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,sCAAsC,KAAK,CAAC,yCAAyC,CAAC,KACrF,aAAa,GAAG,SA0BlB,CAAA;AAED,eAAO,MAAM,yBAAyB,GACpC,YAAY,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAChD,4BAA4B,KAAK,CAAC,yCAAyC,CAAC,SAO7E,CAAA;AAED,eAAO,MAAM,0BAA0B,GAAI,4BAGxC;IACD,SAAS,EAAE,SAAS,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,CAAA;CACjD;iCAEgC,KAAK,CAAC,gCAAgC,CAAC;iCAEvC,KAAK,CAAC,gCAAgC,CAAC;yCAE/B,KAAK,CAAC,yCAAyC,CAAC;yCAEhD,KAAK,CAAC,yCAAyC,CAAC;CAGxF,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { unpackProxyObject } from "../helpers/unpack-proxy.js";
1
2
  import {
2
3
  xScalarEnvVarSchema,
3
4
  xScalarEnvironmentSchema
@@ -12,7 +13,7 @@ const upsertEnvironment = (workspace, collection, { environmentName, payload, ol
12
13
  }
13
14
  const isNewEnvironment = !collection["x-scalar-environments"][oldEnvironmentName ?? environmentName];
14
15
  const parsed = coerceValue(xScalarEnvironmentSchema, {
15
- ...collection["x-scalar-environments"][oldEnvironmentName ?? environmentName],
16
+ ...unpackProxyObject(collection["x-scalar-environments"][oldEnvironmentName ?? environmentName], { depth: 1 }),
16
17
  ...payload
17
18
  });
18
19
  collection["x-scalar-environments"][environmentName] = parsed;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/mutators/environment.ts"],
4
- "sourcesContent": ["import type { EnvironmentEvents } from '@/events/definitions/environment'\nimport type { Workspace, WorkspaceDocument } from '@/schemas'\nimport {\n type XScalarEnvVar,\n type XScalarEnvironment,\n xScalarEnvVarSchema,\n xScalarEnvironmentSchema,\n} from '@/schemas/extensions/document/x-scalar-environments'\nimport { coerceValue } from '@/schemas/typebox-coerce'\n\ntype Event<T extends keyof EnvironmentEvents> = Omit<EnvironmentEvents[T], 'collectionType'>\n\n/**\n * Adds OR updates an environment to the document or workspace.\n *\n * @param document - current document if available\n * @param workspace - current workspace if available\n * @param environmentName - Name of the environment to add\n * @param payload - The environment configuration to add\n * @param oldEnvironmentName - Only needed when renaming the environment\n * @returns the parsed environment that was added or updated or undefined if the collection is not found\n */\nexport const upsertEnvironment = (\n workspace: Workspace | null,\n collection: WorkspaceDocument | Workspace | null,\n { environmentName, payload, oldEnvironmentName }: Event<'environment:upsert:environment'>,\n): XScalarEnvironment | undefined => {\n /** Discriminating between document and workspace */\n if (!collection || !workspace) {\n return\n }\n\n if (!collection['x-scalar-environments']) {\n collection['x-scalar-environments'] = {}\n }\n\n // Check if this is a new environment before we create it\n const isNewEnvironment = !collection['x-scalar-environments'][oldEnvironmentName ?? environmentName]\n\n // Ensure we parse the payload but keep the old variables\n const parsed = coerceValue(xScalarEnvironmentSchema, {\n ...collection['x-scalar-environments'][oldEnvironmentName ?? environmentName],\n ...payload,\n })\n collection['x-scalar-environments'][environmentName] = parsed\n\n // If we are renaming the environment, we need to delete the old one\n if (oldEnvironmentName && oldEnvironmentName !== environmentName) {\n delete collection['x-scalar-environments'][oldEnvironmentName]\n\n // If the old environment was active, we need to set the new environment as active\n if (workspace['x-scalar-active-environment'] === oldEnvironmentName) {\n workspace['x-scalar-active-environment'] = environmentName\n }\n }\n\n // Set the newly created workspace environment as active\n if (isNewEnvironment) {\n workspace['x-scalar-active-environment'] = environmentName\n }\n\n return parsed\n}\n\nexport const deleteEnvironment = (\n workspace: Workspace | null,\n collection: WorkspaceDocument | Workspace | null,\n { environmentName }: Event<'environment:delete:environment'>,\n) => {\n if (!collection || !workspace) {\n return\n }\n\n delete collection['x-scalar-environments']?.[environmentName]\n}\n\n/**\n * Adds OR updates an environment variable to the document or workspace.\n *\n * @param collection - Workspace OR document\n * @param environmentName - Name of the environment to add the variable to\n * @param variableName - Name of the variable to add\n * @param value - Value of the variable to add\n * @returns the parsed variable that was added or updated or undefined if the collection is not found\n */\nexport const upsertEnvironmentVariable = (\n collection: WorkspaceDocument | Workspace | null,\n { environmentName, variable, index }: Event<'environment:upsert:environment-variable'>,\n): XScalarEnvVar | undefined => {\n // The environment should exist by now if we are upserting a variable\n if (!collection?.['x-scalar-environments']?.[environmentName]) {\n console.error('Environment not found', environmentName)\n return\n }\n\n // Ensure we parse the variable for type safety\n const parsed = coerceValue(xScalarEnvVarSchema, variable)\n\n if (index !== undefined) {\n // Delete the row if the name is empty\n if (parsed.name === '') {\n collection['x-scalar-environments'][environmentName].variables.splice(index, 1)\n return\n }\n\n // Update\n collection['x-scalar-environments'][environmentName].variables[index] = parsed\n }\n // Add\n else {\n collection['x-scalar-environments'][environmentName].variables.push(parsed)\n }\n\n return parsed\n}\n\nexport const deleteEnvironmentVariable = (\n collection: WorkspaceDocument | Workspace | null,\n { environmentName, index }: Event<'environment:delete:environment-variable'>,\n) => {\n if (!collection?.['x-scalar-environments']?.[environmentName]) {\n console.error('Environment not found', environmentName)\n return\n }\n collection['x-scalar-environments']?.[environmentName]?.variables?.splice(index, 1)\n}\n\nexport const environmentMutatorsFactory = ({\n workspace,\n collection,\n}: {\n workspace: Workspace | null\n collection: WorkspaceDocument | Workspace | null\n}) => {\n return {\n upsertEnvironment: (payload: Event<'environment:upsert:environment'>) =>\n upsertEnvironment(workspace, collection, payload),\n deleteEnvironment: (payload: Event<'environment:delete:environment'>) =>\n deleteEnvironment(workspace, collection, payload),\n upsertEnvironmentVariable: (payload: Event<'environment:upsert:environment-variable'>) =>\n upsertEnvironmentVariable(collection, payload),\n deleteEnvironmentVariable: (payload: Event<'environment:delete:environment-variable'>) =>\n deleteEnvironmentVariable(collection, payload),\n }\n}\n"],
5
- "mappings": "AAEA;AAAA,EAGE;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAcrB,MAAM,oBAAoB,CAC/B,WACA,YACA,EAAE,iBAAiB,SAAS,mBAAmB,MACZ;AAEnC,MAAI,CAAC,cAAc,CAAC,WAAW;AAC7B;AAAA,EACF;AAEA,MAAI,CAAC,WAAW,uBAAuB,GAAG;AACxC,eAAW,uBAAuB,IAAI,CAAC;AAAA,EACzC;AAGA,QAAM,mBAAmB,CAAC,WAAW,uBAAuB,EAAE,sBAAsB,eAAe;AAGnG,QAAM,SAAS,YAAY,0BAA0B;AAAA,IACnD,GAAG,WAAW,uBAAuB,EAAE,sBAAsB,eAAe;AAAA,IAC5E,GAAG;AAAA,EACL,CAAC;AACD,aAAW,uBAAuB,EAAE,eAAe,IAAI;AAGvD,MAAI,sBAAsB,uBAAuB,iBAAiB;AAChE,WAAO,WAAW,uBAAuB,EAAE,kBAAkB;AAG7D,QAAI,UAAU,6BAA6B,MAAM,oBAAoB;AACnE,gBAAU,6BAA6B,IAAI;AAAA,IAC7C;AAAA,EACF;AAGA,MAAI,kBAAkB;AACpB,cAAU,6BAA6B,IAAI;AAAA,EAC7C;AAEA,SAAO;AACT;AAEO,MAAM,oBAAoB,CAC/B,WACA,YACA,EAAE,gBAAgB,MACf;AACH,MAAI,CAAC,cAAc,CAAC,WAAW;AAC7B;AAAA,EACF;AAEA,SAAO,WAAW,uBAAuB,IAAI,eAAe;AAC9D;AAWO,MAAM,4BAA4B,CACvC,YACA,EAAE,iBAAiB,UAAU,MAAM,MACL;AAE9B,MAAI,CAAC,aAAa,uBAAuB,IAAI,eAAe,GAAG;AAC7D,YAAQ,MAAM,yBAAyB,eAAe;AACtD;AAAA,EACF;AAGA,QAAM,SAAS,YAAY,qBAAqB,QAAQ;AAExD,MAAI,UAAU,QAAW;AAEvB,QAAI,OAAO,SAAS,IAAI;AACtB,iBAAW,uBAAuB,EAAE,eAAe,EAAE,UAAU,OAAO,OAAO,CAAC;AAC9E;AAAA,IACF;AAGA,eAAW,uBAAuB,EAAE,eAAe,EAAE,UAAU,KAAK,IAAI;AAAA,EAC1E,OAEK;AACH,eAAW,uBAAuB,EAAE,eAAe,EAAE,UAAU,KAAK,MAAM;AAAA,EAC5E;AAEA,SAAO;AACT;AAEO,MAAM,4BAA4B,CACvC,YACA,EAAE,iBAAiB,MAAM,MACtB;AACH,MAAI,CAAC,aAAa,uBAAuB,IAAI,eAAe,GAAG;AAC7D,YAAQ,MAAM,yBAAyB,eAAe;AACtD;AAAA,EACF;AACA,aAAW,uBAAuB,IAAI,eAAe,GAAG,WAAW,OAAO,OAAO,CAAC;AACpF;AAEO,MAAM,6BAA6B,CAAC;AAAA,EACzC;AAAA,EACA;AACF,MAGM;AACJ,SAAO;AAAA,IACL,mBAAmB,CAAC,YAClB,kBAAkB,WAAW,YAAY,OAAO;AAAA,IAClD,mBAAmB,CAAC,YAClB,kBAAkB,WAAW,YAAY,OAAO;AAAA,IAClD,2BAA2B,CAAC,YAC1B,0BAA0B,YAAY,OAAO;AAAA,IAC/C,2BAA2B,CAAC,YAC1B,0BAA0B,YAAY,OAAO;AAAA,EACjD;AACF;",
4
+ "sourcesContent": ["import type { EnvironmentEvents } from '@/events/definitions/environment'\nimport { unpackProxyObject } from '@/helpers/unpack-proxy'\nimport type { Workspace, WorkspaceDocument } from '@/schemas'\nimport {\n type XScalarEnvVar,\n type XScalarEnvironment,\n xScalarEnvVarSchema,\n xScalarEnvironmentSchema,\n} from '@/schemas/extensions/document/x-scalar-environments'\nimport { coerceValue } from '@/schemas/typebox-coerce'\n\ntype Event<T extends keyof EnvironmentEvents> = Omit<EnvironmentEvents[T], 'collectionType'>\n\n/**\n * Adds OR updates an environment to the document or workspace.\n *\n * @param document - current document if available\n * @param workspace - current workspace if available\n * @param environmentName - Name of the environment to add\n * @param payload - The environment configuration to add\n * @param oldEnvironmentName - Only needed when renaming the environment\n * @returns the parsed environment that was added or updated or undefined if the collection is not found\n */\nexport const upsertEnvironment = (\n workspace: Workspace | null,\n collection: WorkspaceDocument | Workspace | null,\n { environmentName, payload, oldEnvironmentName }: Event<'environment:upsert:environment'>,\n): XScalarEnvironment | undefined => {\n /** Discriminating between document and workspace */\n if (!collection || !workspace) {\n return\n }\n\n if (!collection['x-scalar-environments']) {\n collection['x-scalar-environments'] = {}\n }\n\n // Check if this is a new environment before we create it\n const isNewEnvironment = !collection['x-scalar-environments'][oldEnvironmentName ?? environmentName]\n\n // Ensure we parse the payload but keep the old variables\n const parsed = coerceValue(xScalarEnvironmentSchema, {\n ...unpackProxyObject(collection['x-scalar-environments'][oldEnvironmentName ?? environmentName], { depth: 1 }),\n ...payload,\n })\n collection['x-scalar-environments'][environmentName] = parsed\n\n // If we are renaming the environment, we need to delete the old one\n if (oldEnvironmentName && oldEnvironmentName !== environmentName) {\n delete collection['x-scalar-environments'][oldEnvironmentName]\n\n // If the old environment was active, we need to set the new environment as active\n if (workspace['x-scalar-active-environment'] === oldEnvironmentName) {\n workspace['x-scalar-active-environment'] = environmentName\n }\n }\n\n // Set the newly created workspace environment as active\n if (isNewEnvironment) {\n workspace['x-scalar-active-environment'] = environmentName\n }\n\n return parsed\n}\n\nexport const deleteEnvironment = (\n workspace: Workspace | null,\n collection: WorkspaceDocument | Workspace | null,\n { environmentName }: Event<'environment:delete:environment'>,\n) => {\n if (!collection || !workspace) {\n return\n }\n\n delete collection['x-scalar-environments']?.[environmentName]\n}\n\n/**\n * Adds OR updates an environment variable to the document or workspace.\n *\n * @param collection - Workspace OR document\n * @param environmentName - Name of the environment to add the variable to\n * @param variableName - Name of the variable to add\n * @param value - Value of the variable to add\n * @returns the parsed variable that was added or updated or undefined if the collection is not found\n */\nexport const upsertEnvironmentVariable = (\n collection: WorkspaceDocument | Workspace | null,\n { environmentName, variable, index }: Event<'environment:upsert:environment-variable'>,\n): XScalarEnvVar | undefined => {\n // The environment should exist by now if we are upserting a variable\n if (!collection?.['x-scalar-environments']?.[environmentName]) {\n console.error('Environment not found', environmentName)\n return\n }\n\n // Ensure we parse the variable for type safety\n const parsed = coerceValue(xScalarEnvVarSchema, variable)\n\n if (index !== undefined) {\n // Delete the row if the name is empty\n if (parsed.name === '') {\n collection['x-scalar-environments'][environmentName].variables.splice(index, 1)\n return\n }\n\n // Update\n collection['x-scalar-environments'][environmentName].variables[index] = parsed\n }\n // Add\n else {\n collection['x-scalar-environments'][environmentName].variables.push(parsed)\n }\n\n return parsed\n}\n\nexport const deleteEnvironmentVariable = (\n collection: WorkspaceDocument | Workspace | null,\n { environmentName, index }: Event<'environment:delete:environment-variable'>,\n) => {\n if (!collection?.['x-scalar-environments']?.[environmentName]) {\n console.error('Environment not found', environmentName)\n return\n }\n collection['x-scalar-environments']?.[environmentName]?.variables?.splice(index, 1)\n}\n\nexport const environmentMutatorsFactory = ({\n workspace,\n collection,\n}: {\n workspace: Workspace | null\n collection: WorkspaceDocument | Workspace | null\n}) => {\n return {\n upsertEnvironment: (payload: Event<'environment:upsert:environment'>) =>\n upsertEnvironment(workspace, collection, payload),\n deleteEnvironment: (payload: Event<'environment:delete:environment'>) =>\n deleteEnvironment(workspace, collection, payload),\n upsertEnvironmentVariable: (payload: Event<'environment:upsert:environment-variable'>) =>\n upsertEnvironmentVariable(collection, payload),\n deleteEnvironmentVariable: (payload: Event<'environment:delete:environment-variable'>) =>\n deleteEnvironmentVariable(collection, payload),\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,yBAAyB;AAElC;AAAA,EAGE;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;AAcrB,MAAM,oBAAoB,CAC/B,WACA,YACA,EAAE,iBAAiB,SAAS,mBAAmB,MACZ;AAEnC,MAAI,CAAC,cAAc,CAAC,WAAW;AAC7B;AAAA,EACF;AAEA,MAAI,CAAC,WAAW,uBAAuB,GAAG;AACxC,eAAW,uBAAuB,IAAI,CAAC;AAAA,EACzC;AAGA,QAAM,mBAAmB,CAAC,WAAW,uBAAuB,EAAE,sBAAsB,eAAe;AAGnG,QAAM,SAAS,YAAY,0BAA0B;AAAA,IACnD,GAAG,kBAAkB,WAAW,uBAAuB,EAAE,sBAAsB,eAAe,GAAG,EAAE,OAAO,EAAE,CAAC;AAAA,IAC7G,GAAG;AAAA,EACL,CAAC;AACD,aAAW,uBAAuB,EAAE,eAAe,IAAI;AAGvD,MAAI,sBAAsB,uBAAuB,iBAAiB;AAChE,WAAO,WAAW,uBAAuB,EAAE,kBAAkB;AAG7D,QAAI,UAAU,6BAA6B,MAAM,oBAAoB;AACnE,gBAAU,6BAA6B,IAAI;AAAA,IAC7C;AAAA,EACF;AAGA,MAAI,kBAAkB;AACpB,cAAU,6BAA6B,IAAI;AAAA,EAC7C;AAEA,SAAO;AACT;AAEO,MAAM,oBAAoB,CAC/B,WACA,YACA,EAAE,gBAAgB,MACf;AACH,MAAI,CAAC,cAAc,CAAC,WAAW;AAC7B;AAAA,EACF;AAEA,SAAO,WAAW,uBAAuB,IAAI,eAAe;AAC9D;AAWO,MAAM,4BAA4B,CACvC,YACA,EAAE,iBAAiB,UAAU,MAAM,MACL;AAE9B,MAAI,CAAC,aAAa,uBAAuB,IAAI,eAAe,GAAG;AAC7D,YAAQ,MAAM,yBAAyB,eAAe;AACtD;AAAA,EACF;AAGA,QAAM,SAAS,YAAY,qBAAqB,QAAQ;AAExD,MAAI,UAAU,QAAW;AAEvB,QAAI,OAAO,SAAS,IAAI;AACtB,iBAAW,uBAAuB,EAAE,eAAe,EAAE,UAAU,OAAO,OAAO,CAAC;AAC9E;AAAA,IACF;AAGA,eAAW,uBAAuB,EAAE,eAAe,EAAE,UAAU,KAAK,IAAI;AAAA,EAC1E,OAEK;AACH,eAAW,uBAAuB,EAAE,eAAe,EAAE,UAAU,KAAK,MAAM;AAAA,EAC5E;AAEA,SAAO;AACT;AAEO,MAAM,4BAA4B,CACvC,YACA,EAAE,iBAAiB,MAAM,MACtB;AACH,MAAI,CAAC,aAAa,uBAAuB,IAAI,eAAe,GAAG;AAC7D,YAAQ,MAAM,yBAAyB,eAAe;AACtD;AAAA,EACF;AACA,aAAW,uBAAuB,IAAI,eAAe,GAAG,WAAW,OAAO,OAAO,CAAC;AACpF;AAEO,MAAM,6BAA6B,CAAC;AAAA,EACzC;AAAA,EACA;AACF,MAGM;AACJ,SAAO;AAAA,IACL,mBAAmB,CAAC,YAClB,kBAAkB,WAAW,YAAY,OAAO;AAAA,IAClD,mBAAmB,CAAC,YAClB,kBAAkB,WAAW,YAAY,OAAO;AAAA,IAClD,2BAA2B,CAAC,YAC1B,0BAA0B,YAAY,OAAO;AAAA,IAC/C,2BAA2B,CAAC,YAC1B,0BAA0B,YAAY,OAAO;AAAA,EACjD;AACF;",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mutators/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAE/D,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,wCAAwC,CAAA;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,UAAU,iBAAiB,GAAG,IAAI,KAAG,YAAY,GAAG,SAc7E,CAAA;AAgFD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,iBAAiB,GAAG,IAAI,EAClC,mBAAmB,YAAY,CAAC,sBAAsB,CAAC,KACtD,YAAY,GAAG,SA+BjB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,UAAU,iBAAiB,GAAG,IAAI,EAAE,WAAW,YAAY,CAAC,sBAAsB,CAAC,SAY/G,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,UAAU,iBAAiB,GAAG,IAAI,EAClC,uBAAuB,YAAY,CAAC,yBAAyB,CAAC,sFAkB/D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,iBAAiB,GAAG,IAAI,EAClC,SAAS,YAAY,CAAC,wBAAwB,CAAC,KAC9C,MAAM,GAAG,SAsBX,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,cAAc;IAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAAE;;4BAG9D,YAAY,CAAC,sBAAsB,CAAC;4BACpC,YAAY,CAAC,sBAAsB,CAAC;qCAC3B,YAAY,CAAC,yBAAyB,CAAC;oCAExC,YAAY,CAAC,wBAAwB,CAAC;CAEzE,CAAA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mutators/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAE/D,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,wCAAwC,CAAA;AAC9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,UAAU,iBAAiB,GAAG,IAAI,KAAG,YAAY,GAAG,SAc7E,CAAA;AAgFD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,iBAAiB,GAAG,IAAI,EAClC,mBAAmB,YAAY,CAAC,sBAAsB,CAAC,KACtD,YAAY,GAAG,SA+BjB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,UAAU,iBAAiB,GAAG,IAAI,EAAE,WAAW,YAAY,CAAC,sBAAsB,CAAC,SAY/G,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,UAAU,iBAAiB,GAAG,IAAI,EAClC,uBAAuB,YAAY,CAAC,yBAAyB,CAAC,sFAkB/D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,iBAAiB,GAAG,IAAI,EAClC,SAAS,YAAY,CAAC,wBAAwB,CAAC,KAC9C,MAAM,GAAG,SAiBX,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,cAAc;IAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAAE;;4BAG9D,YAAY,CAAC,sBAAsB,CAAC;4BACpC,YAAY,CAAC,sBAAsB,CAAC;qCAC3B,YAAY,CAAC,yBAAyB,CAAC;oCAExC,YAAY,CAAC,wBAAwB,CAAC;CAEzE,CAAA"}
@@ -107,9 +107,6 @@ const updateSelectedServer = (document, { url }) => {
107
107
  document["x-scalar-selected-server"] = "";
108
108
  return "";
109
109
  }
110
- if (!document.servers?.some((server) => server.url === url)) {
111
- return;
112
- }
113
110
  document["x-scalar-selected-server"] = document["x-scalar-selected-server"] === url ? "" : url;
114
111
  return document["x-scalar-selected-server"];
115
112
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/mutators/server.ts"],
4
- "sourcesContent": ["import { findVariables } from '@scalar/helpers/regex/find-variables'\n\nimport type { ServerEvents } from '@/events/definitions/server'\nimport { coerceValue } from '@/schemas/typebox-coerce'\nimport { type ServerObject, ServerObjectSchema } from '@/schemas/v3.1/strict/openapi-document'\nimport type { WorkspaceDocument } from '@/schemas/workspace'\n\n/**\n * Adds a new ServerObject to the document.\n *\n * @param document - The document to add the server to\n * @returns the new server object or undefined if the document is not found\n */\nexport const addServer = (document: WorkspaceDocument | null): ServerObject | undefined => {\n if (!document) {\n return undefined\n }\n\n const parsed = coerceValue(ServerObjectSchema, {})\n\n // Initialize the servers array if it doesn't exist\n if (!document.servers) {\n document.servers = []\n }\n\n document.servers.push(parsed)\n return parsed\n}\n\n/**\n * Creates a map of variable names to their character positions in a URL.\n * Used to detect renamed variables by position matching.\n */\nconst getVariablePositions = (url: string, variables: readonly string[]): Record<string, number> => {\n const positions: Record<string, number> = {}\n\n for (const varName of variables) {\n const position = url.indexOf(`{${varName}}`)\n if (position !== -1) {\n positions[varName] = position\n }\n }\n\n return positions\n}\n\ntype VariableConfig = {\n description?: string\n default?: string\n enum?: string[]\n}\n\n/**\n * Syncs server variables when the URL changes.\n *\n * Preserves variable configurations by:\n * 1. Keeping variables with matching names\n * 2. Renaming variables at the same position\n * 3. Creating new variables with empty defaults\n */\nconst syncVariablesForUrlChange = (\n newUrl: string,\n oldUrl: string,\n existingVariables: Record<string, VariableConfig>,\n): Record<string, VariableConfig> => {\n // Filter out undefined values from findVariables results\n const oldVariables = findVariables(oldUrl, { includePath: true, includeEnv: false }).filter(\n (v): v is string => v !== undefined,\n )\n const newVariables = findVariables(newUrl, { includePath: true, includeEnv: false }).filter(\n (v): v is string => v !== undefined,\n )\n\n const oldPositions = getVariablePositions(oldUrl, oldVariables)\n const newPositions = getVariablePositions(newUrl, newVariables)\n\n const usedOldVariables = new Set<string>()\n const syncedVariables: Record<string, VariableConfig> = {}\n\n for (const newVar of newVariables) {\n // Case 1: Variable with same name exists - preserve its config\n if (existingVariables[newVar]) {\n syncedVariables[newVar] = existingVariables[newVar]\n usedOldVariables.add(newVar)\n continue\n }\n\n // Case 2: Check for variable at same position (likely a rename)\n const newVarPosition = newPositions[newVar]\n const oldVarAtPosition = oldVariables.find(\n (oldVar) => oldPositions[oldVar] === newVarPosition && !usedOldVariables.has(oldVar),\n )\n\n if (oldVarAtPosition && existingVariables[oldVarAtPosition]) {\n // Rename: transfer the old variable's config to the new name\n syncedVariables[newVar] = existingVariables[oldVarAtPosition]\n usedOldVariables.add(oldVarAtPosition)\n continue\n }\n\n // Case 3: New variable - create with empty default\n syncedVariables[newVar] = { default: '' }\n }\n\n return syncedVariables\n}\n\n/**\n * Updates a ServerObject in the document.\n * When the URL changes, intelligently syncs variables by preserving configurations\n * for renamed variables (detected by position) and existing variables.\n *\n * @param document - The document containing the server to update\n * @param index - The index of the server to update\n * @param server - The partial server object with fields to update\n * @returns the updated server object or undefined if the server is not found\n */\nexport const updateServer = (\n document: WorkspaceDocument | null,\n { index, server }: ServerEvents['server:update:server'],\n): ServerObject | undefined => {\n const oldServer = document?.servers?.[index]\n\n if (!oldServer) {\n console.error('Server not found at index:', index)\n return undefined\n }\n\n const oldUrl = oldServer.url\n const updatedServer = coerceValue(ServerObjectSchema, { ...oldServer, ...server })\n\n // Sync variables if the URL changed\n const hasUrlChanged = oldUrl && oldUrl !== updatedServer.url\n if (hasUrlChanged) {\n const existingVariables = updatedServer.variables ?? {}\n updatedServer.variables = syncVariablesForUrlChange(updatedServer.url, oldUrl, existingVariables)\n\n // If the selected server is the one being updated, set the selected server to the new server\n if (document['x-scalar-selected-server'] === oldUrl) {\n document['x-scalar-selected-server'] = updatedServer.url\n }\n }\n\n // Ensure servers array exists and update the server at the specified index\n if (!document.servers) {\n document.servers = [updatedServer]\n } else {\n document.servers[index] = updatedServer\n }\n\n return updatedServer\n}\n\n/**\n * Deletes a ServerObject at the specified index from the target array.\n *\n * @param document - The document to delete the server from\n * @param index - The index of the server to delete.\n */\nexport const deleteServer = (document: WorkspaceDocument | null, { index }: ServerEvents['server:delete:server']) => {\n if (!document?.servers) {\n return\n }\n\n const url = document.servers[index]?.url\n document.servers.splice(index, 1)\n\n // If the selected server is the one being deleted, set the selected server to the first one after removal\n if (document['x-scalar-selected-server'] === url) {\n document['x-scalar-selected-server'] = document.servers[0]?.url ?? undefined\n }\n}\n\n/**\n * Updates a server variable for the selected server\n *\n * @param document - The document to update the server variables in\n * @param index - The index of the server to update\n * @param key - The key of the variable to update\n * @param value - The new value of the variable\n * @returns the updated variable or undefined if the variable is not found\n */\nexport const updateServerVariables = (\n document: WorkspaceDocument | null,\n { index, key, value }: ServerEvents['server:update:variables'],\n) => {\n const variable = document?.servers?.[index]?.variables?.[key]\n if (!variable) {\n console.error('Variable not found', key, index)\n return\n }\n\n variable.default = value\n\n // Now we need to make the url reflect the new variable value\n const url = document?.servers?.[index]?.url\n if (!url) {\n console.error('URL not found', index)\n return\n }\n\n return variable\n}\n\n/**\n * Updates the selected server for the document\n *\n * @param document - The document to update the selected server in\n * @param index - The index of the server to update\n * @returns the url of the selected server or undefined if the server is not found\n */\nexport const updateSelectedServer = (\n document: WorkspaceDocument | null,\n { url }: ServerEvents['server:update:selected'],\n): string | undefined => {\n if (!document) {\n return\n }\n\n // We are explicitly de-selecting the server\n if (url === '') {\n document['x-scalar-selected-server'] = ''\n return ''\n }\n\n // If no servers match then return undefined\n if (!document.servers?.some((server) => server.url === url)) {\n return\n }\n\n /**\n * [un]set it and return the url,\n * we specifically use en empty string to indicate that the user has unset the selected server\n */\n document['x-scalar-selected-server'] = document['x-scalar-selected-server'] === url ? '' : url\n return document['x-scalar-selected-server']\n}\n\nexport const serverMutatorsFactory = ({ document }: { document: WorkspaceDocument | null }) => {\n return {\n addServer: () => addServer(document),\n updateServer: (payload: ServerEvents['server:update:server']) => updateServer(document, payload),\n deleteServer: (payload: ServerEvents['server:delete:server']) => deleteServer(document, payload),\n updateServerVariables: (payload: ServerEvents['server:update:variables']) =>\n updateServerVariables(document, payload),\n updateSelectedServer: (payload: ServerEvents['server:update:selected']) => updateSelectedServer(document, payload),\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { findVariables } from '@scalar/helpers/regex/find-variables'\n\nimport type { ServerEvents } from '@/events/definitions/server'\nimport { coerceValue } from '@/schemas/typebox-coerce'\nimport { type ServerObject, ServerObjectSchema } from '@/schemas/v3.1/strict/openapi-document'\nimport type { WorkspaceDocument } from '@/schemas/workspace'\n\n/**\n * Adds a new ServerObject to the document.\n *\n * @param document - The document to add the server to\n * @returns the new server object or undefined if the document is not found\n */\nexport const addServer = (document: WorkspaceDocument | null): ServerObject | undefined => {\n if (!document) {\n return undefined\n }\n\n const parsed = coerceValue(ServerObjectSchema, {})\n\n // Initialize the servers array if it doesn't exist\n if (!document.servers) {\n document.servers = []\n }\n\n document.servers.push(parsed)\n return parsed\n}\n\n/**\n * Creates a map of variable names to their character positions in a URL.\n * Used to detect renamed variables by position matching.\n */\nconst getVariablePositions = (url: string, variables: readonly string[]): Record<string, number> => {\n const positions: Record<string, number> = {}\n\n for (const varName of variables) {\n const position = url.indexOf(`{${varName}}`)\n if (position !== -1) {\n positions[varName] = position\n }\n }\n\n return positions\n}\n\ntype VariableConfig = {\n description?: string\n default?: string\n enum?: string[]\n}\n\n/**\n * Syncs server variables when the URL changes.\n *\n * Preserves variable configurations by:\n * 1. Keeping variables with matching names\n * 2. Renaming variables at the same position\n * 3. Creating new variables with empty defaults\n */\nconst syncVariablesForUrlChange = (\n newUrl: string,\n oldUrl: string,\n existingVariables: Record<string, VariableConfig>,\n): Record<string, VariableConfig> => {\n // Filter out undefined values from findVariables results\n const oldVariables = findVariables(oldUrl, { includePath: true, includeEnv: false }).filter(\n (v): v is string => v !== undefined,\n )\n const newVariables = findVariables(newUrl, { includePath: true, includeEnv: false }).filter(\n (v): v is string => v !== undefined,\n )\n\n const oldPositions = getVariablePositions(oldUrl, oldVariables)\n const newPositions = getVariablePositions(newUrl, newVariables)\n\n const usedOldVariables = new Set<string>()\n const syncedVariables: Record<string, VariableConfig> = {}\n\n for (const newVar of newVariables) {\n // Case 1: Variable with same name exists - preserve its config\n if (existingVariables[newVar]) {\n syncedVariables[newVar] = existingVariables[newVar]\n usedOldVariables.add(newVar)\n continue\n }\n\n // Case 2: Check for variable at same position (likely a rename)\n const newVarPosition = newPositions[newVar]\n const oldVarAtPosition = oldVariables.find(\n (oldVar) => oldPositions[oldVar] === newVarPosition && !usedOldVariables.has(oldVar),\n )\n\n if (oldVarAtPosition && existingVariables[oldVarAtPosition]) {\n // Rename: transfer the old variable's config to the new name\n syncedVariables[newVar] = existingVariables[oldVarAtPosition]\n usedOldVariables.add(oldVarAtPosition)\n continue\n }\n\n // Case 3: New variable - create with empty default\n syncedVariables[newVar] = { default: '' }\n }\n\n return syncedVariables\n}\n\n/**\n * Updates a ServerObject in the document.\n * When the URL changes, intelligently syncs variables by preserving configurations\n * for renamed variables (detected by position) and existing variables.\n *\n * @param document - The document containing the server to update\n * @param index - The index of the server to update\n * @param server - The partial server object with fields to update\n * @returns the updated server object or undefined if the server is not found\n */\nexport const updateServer = (\n document: WorkspaceDocument | null,\n { index, server }: ServerEvents['server:update:server'],\n): ServerObject | undefined => {\n const oldServer = document?.servers?.[index]\n\n if (!oldServer) {\n console.error('Server not found at index:', index)\n return undefined\n }\n\n const oldUrl = oldServer.url\n const updatedServer = coerceValue(ServerObjectSchema, { ...oldServer, ...server })\n\n // Sync variables if the URL changed\n const hasUrlChanged = oldUrl && oldUrl !== updatedServer.url\n if (hasUrlChanged) {\n const existingVariables = updatedServer.variables ?? {}\n updatedServer.variables = syncVariablesForUrlChange(updatedServer.url, oldUrl, existingVariables)\n\n // If the selected server is the one being updated, set the selected server to the new server\n if (document['x-scalar-selected-server'] === oldUrl) {\n document['x-scalar-selected-server'] = updatedServer.url\n }\n }\n\n // Ensure servers array exists and update the server at the specified index\n if (!document.servers) {\n document.servers = [updatedServer]\n } else {\n document.servers[index] = updatedServer\n }\n\n return updatedServer\n}\n\n/**\n * Deletes a ServerObject at the specified index from the target array.\n *\n * @param document - The document to delete the server from\n * @param index - The index of the server to delete.\n */\nexport const deleteServer = (document: WorkspaceDocument | null, { index }: ServerEvents['server:delete:server']) => {\n if (!document?.servers) {\n return\n }\n\n const url = document.servers[index]?.url\n document.servers.splice(index, 1)\n\n // If the selected server is the one being deleted, set the selected server to the first one after removal\n if (document['x-scalar-selected-server'] === url) {\n document['x-scalar-selected-server'] = document.servers[0]?.url ?? undefined\n }\n}\n\n/**\n * Updates a server variable for the selected server\n *\n * @param document - The document to update the server variables in\n * @param index - The index of the server to update\n * @param key - The key of the variable to update\n * @param value - The new value of the variable\n * @returns the updated variable or undefined if the variable is not found\n */\nexport const updateServerVariables = (\n document: WorkspaceDocument | null,\n { index, key, value }: ServerEvents['server:update:variables'],\n) => {\n const variable = document?.servers?.[index]?.variables?.[key]\n if (!variable) {\n console.error('Variable not found', key, index)\n return\n }\n\n variable.default = value\n\n // Now we need to make the url reflect the new variable value\n const url = document?.servers?.[index]?.url\n if (!url) {\n console.error('URL not found', index)\n return\n }\n\n return variable\n}\n\n/**\n * Updates the selected server for the document\n *\n * @param document - The document to update the selected server in\n * @param index - The index of the server to update\n * @returns the url of the selected server or undefined if the server is not found\n */\nexport const updateSelectedServer = (\n document: WorkspaceDocument | null,\n { url }: ServerEvents['server:update:selected'],\n): string | undefined => {\n if (!document) {\n return\n }\n\n // We are explicitly de-selecting the server\n if (url === '') {\n document['x-scalar-selected-server'] = ''\n return ''\n }\n\n /**\n * [un]set it and return the url,\n * we specifically use en empty string to indicate that the user has unset the selected server\n */\n document['x-scalar-selected-server'] = document['x-scalar-selected-server'] === url ? '' : url\n return document['x-scalar-selected-server']\n}\n\nexport const serverMutatorsFactory = ({ document }: { document: WorkspaceDocument | null }) => {\n return {\n addServer: () => addServer(document),\n updateServer: (payload: ServerEvents['server:update:server']) => updateServer(document, payload),\n deleteServer: (payload: ServerEvents['server:delete:server']) => deleteServer(document, payload),\n updateServerVariables: (payload: ServerEvents['server:update:variables']) =>\n updateServerVariables(document, payload),\n updateSelectedServer: (payload: ServerEvents['server:update:selected']) => updateSelectedServer(document, payload),\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -84,4 +84,11 @@ export declare const restoreOriginalRefs: () => LifecyclePlugin;
84
84
  * ```
85
85
  */
86
86
  export declare const normalizeAuthSchemes: () => LifecyclePlugin;
87
+ /**
88
+ * Lifecycle plugin to normalize $ref nodes:
89
+ * Ensures that for any non-schema object containing a $ref, only $ref,
90
+ * summary, description, and $status properties are preserved.
91
+ * This keeps $ref references clean and predictable for downstream consumers.
92
+ */
93
+ export declare const normalizeRefs: () => LifecyclePlugin;
87
94
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/bundler/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAKhE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAO,eAahC,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,QAAO,eA+BxC,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,QAAO,eAwCjC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,mBAAmB,QAAO,eAuBtC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB,QAAO,eAuBvC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/bundler/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAKhE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAO,eAahC,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,QAAO,eA+BxC,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,QAAO,eAwCjC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,mBAAmB,QAAO,eAuBtC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,oBAAoB,QAAO,eAuBvC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,QAAO,eAmBhC,CAAA"}
@@ -95,10 +95,27 @@ const normalizeAuthSchemes = () => {
95
95
  }
96
96
  };
97
97
  };
98
+ const normalizeRefs = () => {
99
+ return {
100
+ type: "lifecycle",
101
+ onBeforeNodeProcess: (node, context) => {
102
+ const { path } = context;
103
+ if (typeof node["$ref"] === "string" && !(path[0] === "components" && path[1] === "schemas")) {
104
+ const keepProperties = /* @__PURE__ */ new Set(["$ref", "summary", "description", "$status"]);
105
+ Object.keys(node).forEach((key) => {
106
+ if (!keepProperties.has(key)) {
107
+ delete node[key];
108
+ }
109
+ });
110
+ }
111
+ }
112
+ };
113
+ };
98
114
  export {
99
115
  externalValueResolver,
100
116
  loadingStatus,
101
117
  normalizeAuthSchemes,
118
+ normalizeRefs,
102
119
  refsEverywhere,
103
120
  restoreOriginalRefs
104
121
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/bundler/index.ts"],
4
- "sourcesContent": ["/**\n * This file contains a collection of plugins used for the bundler.\n * Plugins defined here can extend or modify the behavior of the bundling process,\n * such as adding lifecycle hooks or custom processing logic.\n */\n\nimport type { LifecyclePlugin } from '@scalar/json-magic/bundle'\n\nimport { isLocalRef } from '@/helpers/general'\nimport { getResolvedRef } from '@/plugins/bundler/helpers'\n\n/**\n * A lifecycle plugin that adds a `$status` property to nodes during resolution.\n * - Sets `$status` to 'loading' when resolution starts.\n * - Sets `$status` to 'error' if resolution fails.\n * - Removes `$status` when resolution succeeds.\n */\nexport const loadingStatus = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onResolveStart: (node) => {\n node['$status'] = 'loading'\n },\n onResolveError: (node) => {\n node['$status'] = 'error'\n },\n onResolveSuccess: (node) => {\n delete node['$status']\n },\n }\n}\n\n/**\n * Lifecycle plugin to resolve and embed external content referenced by an 'externalValue' property in a node.\n *\n * When a node contains an 'externalValue' property (as a string), this plugin will:\n * - Fetch the external resource (such as a URL or file) using the fetchUrls plugin.\n * - If the fetch is successful, assign the fetched data to the node's 'value' property.\n *\n * This is useful for inlining external content (like examples or schemas) into the OpenAPI document during bundling.\n *\n * @param node - The node being processed, which may contain an 'externalValue' property.\n */\nexport const externalValueResolver = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onAfterNodeProcess: async (node, context) => {\n const externalValue = node['externalValue']\n const cache = context.resolutionCache\n\n // Only process if 'externalValue' is a string\n if (typeof externalValue !== 'string') {\n return\n }\n\n const loader = context.loaders.find((it) => it.validate(externalValue))\n\n // We can not process the external value\n if (!loader) {\n return\n }\n\n if (!cache.has(externalValue)) {\n cache.set(externalValue, loader.exec(externalValue))\n }\n\n const result = await cache.get(externalValue)\n\n // If fetch is successful, assign the data to the node's 'value' property\n if (result?.ok) {\n node['value'] = result.data\n }\n },\n }\n}\n\n/**\n * Lifecycle plugin to resolve $ref on any object, including non-standard locations like the info object.\n *\n * This plugin will:\n * - Detect if a node contains a $ref property (as a string).\n * - If the node is under the 'info' path, attempt to resolve the reference using fetchUrls.\n * - Replace the node's properties with the resolved data if successful.\n *\n * Note: This currently only supports refs on the 'info' object and does not handle primitive types.\n */\nexport const refsEverywhere = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onBeforeNodeProcess: async (node, context) => {\n const { path, resolutionCache, parentNode } = context\n const ref = node['$ref']\n\n // Only process nodes that have a $ref property as a string\n if (typeof ref !== 'string') {\n return\n }\n\n // Can not resolve top level refs\n if (!parentNode || !path.length) {\n return\n }\n\n const loader = context.loaders.find((it) => it.validate(ref))\n\n // Can not load the external ref\n if (!loader) {\n return\n }\n\n // Support resolving $ref on the info object\n if (path[0] === 'info') {\n // Use the cache to avoid duplicate fetches\n if (!resolutionCache.has(ref)) {\n resolutionCache.set(ref, loader.exec(ref))\n }\n\n const result = await resolutionCache.get(ref)\n\n if (result?.ok) {\n // Replace the ref with the resolved data\n parentNode[path.at(-1)!] = result.data\n }\n }\n },\n }\n}\n\n/**\n * Lifecycle plugin to restore original $ref values after processing.\n *\n * This plugin is intended to be used as a \"lifecycle\" plugin in the bundling process.\n * It operates in the `onAfterNodeProcess` hook, and its main purpose is to restore\n * the original $ref values for external references that may have been replaced or\n * rewritten during the bundling process.\n *\n * How it works:\n * - For each node processed, if the node contains a $ref property (as a string),\n * and the root document contains an \"x-ext-urls\" mapping object,\n * the plugin will attempt to restore the original $ref value.\n * - The \"x-ext-urls\" object is expected to be a mapping from the rewritten $ref\n * (e.g., a hashed or compressed reference) back to the original external URL or path.\n * - If a mapping exists for the current $ref, the plugin replaces the $ref value\n * with the original value from the mapping. If no mapping exists (e.g., for local refs),\n * the $ref value is left unchanged.\n *\n * This is useful for scenarios where you want to present or export the bundled document\n * with the original external $ref values, rather than the internal or rewritten ones.\n *\n * @returns {LifecyclePlugin} The plugin object for use in the bundler.\n */\nexport const restoreOriginalRefs = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onBeforeNodeProcess: (node, context) => {\n const ref = node['$ref']\n const root = context.rootNode\n const extUrls = root['x-ext-urls']\n\n // Only process if $ref is a string and x-ext-urls is a valid object\n if (typeof ref !== 'string' || typeof extUrls !== 'object' || extUrls === null || !isLocalRef(ref)) {\n return\n }\n\n // Working with local refs\n\n const segments = ref.split('/')\n const key = segments.at(-1) ?? ''\n\n // Replace the $ref with the original version from the mapping,\n // or keep the current version if there is no mapping (e.g., for local refs)\n node['$ref'] = (extUrls as Record<string, string>)[key] ?? ref\n },\n }\n}\n\n/**\n * Lifecycle plugin to normalize the `scheme` property in securitySchemes to lowercase.\n *\n * Our typebox schemas require the `scheme` property to be a lowercase string.\n * This plugin ensures that any `scheme` field under `components.securitySchemes` is normalized to lowercase, fixing\n * potential user input errors such as \"Bearer\" or \"BASIC\".\n *\n * Example:\n * ```yaml\n * Before normalization:\n * components:\n * securitySchemes:\n * bearerAuth:\n * type: http\n * scheme: Bearer\n * ```\n * After normalization:\n * ```yaml\n * components:\n * securitySchemes:\n * bearerAuth:\n * type: http\n * scheme: bearer\n * ```\n */\nexport const normalizeAuthSchemes = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onAfterNodeProcess: (node, context) => {\n const { path } = context\n\n // Check if we're at components.securitySchemes.{schemeName}\n if (path.length === 3 && path[0] === 'components' && path[1] === 'securitySchemes') {\n const targetNode = getResolvedRef(node, context)\n\n // If the scheme exists and is a string, normalize to lowercase if not already\n if (\n typeof targetNode === 'object' &&\n targetNode !== null &&\n 'scheme' in targetNode &&\n typeof targetNode['scheme'] === 'string' &&\n targetNode['scheme'].toLowerCase() !== targetNode['scheme']\n ) {\n targetNode['scheme'] = targetNode['scheme'].toLowerCase()\n }\n }\n },\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * This file contains a collection of plugins used for the bundler.\n * Plugins defined here can extend or modify the behavior of the bundling process,\n * such as adding lifecycle hooks or custom processing logic.\n */\n\nimport type { LifecyclePlugin } from '@scalar/json-magic/bundle'\n\nimport { isLocalRef } from '@/helpers/general'\nimport { getResolvedRef } from '@/plugins/bundler/helpers'\n\n/**\n * A lifecycle plugin that adds a `$status` property to nodes during resolution.\n * - Sets `$status` to 'loading' when resolution starts.\n * - Sets `$status` to 'error' if resolution fails.\n * - Removes `$status` when resolution succeeds.\n */\nexport const loadingStatus = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onResolveStart: (node) => {\n node['$status'] = 'loading'\n },\n onResolveError: (node) => {\n node['$status'] = 'error'\n },\n onResolveSuccess: (node) => {\n delete node['$status']\n },\n }\n}\n\n/**\n * Lifecycle plugin to resolve and embed external content referenced by an 'externalValue' property in a node.\n *\n * When a node contains an 'externalValue' property (as a string), this plugin will:\n * - Fetch the external resource (such as a URL or file) using the fetchUrls plugin.\n * - If the fetch is successful, assign the fetched data to the node's 'value' property.\n *\n * This is useful for inlining external content (like examples or schemas) into the OpenAPI document during bundling.\n *\n * @param node - The node being processed, which may contain an 'externalValue' property.\n */\nexport const externalValueResolver = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onAfterNodeProcess: async (node, context) => {\n const externalValue = node['externalValue']\n const cache = context.resolutionCache\n\n // Only process if 'externalValue' is a string\n if (typeof externalValue !== 'string') {\n return\n }\n\n const loader = context.loaders.find((it) => it.validate(externalValue))\n\n // We can not process the external value\n if (!loader) {\n return\n }\n\n if (!cache.has(externalValue)) {\n cache.set(externalValue, loader.exec(externalValue))\n }\n\n const result = await cache.get(externalValue)\n\n // If fetch is successful, assign the data to the node's 'value' property\n if (result?.ok) {\n node['value'] = result.data\n }\n },\n }\n}\n\n/**\n * Lifecycle plugin to resolve $ref on any object, including non-standard locations like the info object.\n *\n * This plugin will:\n * - Detect if a node contains a $ref property (as a string).\n * - If the node is under the 'info' path, attempt to resolve the reference using fetchUrls.\n * - Replace the node's properties with the resolved data if successful.\n *\n * Note: This currently only supports refs on the 'info' object and does not handle primitive types.\n */\nexport const refsEverywhere = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onBeforeNodeProcess: async (node, context) => {\n const { path, resolutionCache, parentNode } = context\n const ref = node['$ref']\n\n // Only process nodes that have a $ref property as a string\n if (typeof ref !== 'string') {\n return\n }\n\n // Can not resolve top level refs\n if (!parentNode || !path.length) {\n return\n }\n\n const loader = context.loaders.find((it) => it.validate(ref))\n\n // Can not load the external ref\n if (!loader) {\n return\n }\n\n // Support resolving $ref on the info object\n if (path[0] === 'info') {\n // Use the cache to avoid duplicate fetches\n if (!resolutionCache.has(ref)) {\n resolutionCache.set(ref, loader.exec(ref))\n }\n\n const result = await resolutionCache.get(ref)\n\n if (result?.ok) {\n // Replace the ref with the resolved data\n parentNode[path.at(-1)!] = result.data\n }\n }\n },\n }\n}\n\n/**\n * Lifecycle plugin to restore original $ref values after processing.\n *\n * This plugin is intended to be used as a \"lifecycle\" plugin in the bundling process.\n * It operates in the `onAfterNodeProcess` hook, and its main purpose is to restore\n * the original $ref values for external references that may have been replaced or\n * rewritten during the bundling process.\n *\n * How it works:\n * - For each node processed, if the node contains a $ref property (as a string),\n * and the root document contains an \"x-ext-urls\" mapping object,\n * the plugin will attempt to restore the original $ref value.\n * - The \"x-ext-urls\" object is expected to be a mapping from the rewritten $ref\n * (e.g., a hashed or compressed reference) back to the original external URL or path.\n * - If a mapping exists for the current $ref, the plugin replaces the $ref value\n * with the original value from the mapping. If no mapping exists (e.g., for local refs),\n * the $ref value is left unchanged.\n *\n * This is useful for scenarios where you want to present or export the bundled document\n * with the original external $ref values, rather than the internal or rewritten ones.\n *\n * @returns {LifecyclePlugin} The plugin object for use in the bundler.\n */\nexport const restoreOriginalRefs = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onBeforeNodeProcess: (node, context) => {\n const ref = node['$ref']\n const root = context.rootNode\n const extUrls = root['x-ext-urls']\n\n // Only process if $ref is a string and x-ext-urls is a valid object\n if (typeof ref !== 'string' || typeof extUrls !== 'object' || extUrls === null || !isLocalRef(ref)) {\n return\n }\n\n // Working with local refs\n\n const segments = ref.split('/')\n const key = segments.at(-1) ?? ''\n\n // Replace the $ref with the original version from the mapping,\n // or keep the current version if there is no mapping (e.g., for local refs)\n node['$ref'] = (extUrls as Record<string, string>)[key] ?? ref\n },\n }\n}\n\n/**\n * Lifecycle plugin to normalize the `scheme` property in securitySchemes to lowercase.\n *\n * Our typebox schemas require the `scheme` property to be a lowercase string.\n * This plugin ensures that any `scheme` field under `components.securitySchemes` is normalized to lowercase, fixing\n * potential user input errors such as \"Bearer\" or \"BASIC\".\n *\n * Example:\n * ```yaml\n * Before normalization:\n * components:\n * securitySchemes:\n * bearerAuth:\n * type: http\n * scheme: Bearer\n * ```\n * After normalization:\n * ```yaml\n * components:\n * securitySchemes:\n * bearerAuth:\n * type: http\n * scheme: bearer\n * ```\n */\nexport const normalizeAuthSchemes = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onAfterNodeProcess: (node, context) => {\n const { path } = context\n\n // Check if we're at components.securitySchemes.{schemeName}\n if (path.length === 3 && path[0] === 'components' && path[1] === 'securitySchemes') {\n const targetNode = getResolvedRef(node, context)\n\n // If the scheme exists and is a string, normalize to lowercase if not already\n if (\n typeof targetNode === 'object' &&\n targetNode !== null &&\n 'scheme' in targetNode &&\n typeof targetNode['scheme'] === 'string' &&\n targetNode['scheme'].toLowerCase() !== targetNode['scheme']\n ) {\n targetNode['scheme'] = targetNode['scheme'].toLowerCase()\n }\n }\n },\n }\n}\n\n/**\n * Lifecycle plugin to normalize $ref nodes:\n * Ensures that for any non-schema object containing a $ref, only $ref,\n * summary, description, and $status properties are preserved.\n * This keeps $ref references clean and predictable for downstream consumers.\n */\nexport const normalizeRefs = (): LifecyclePlugin => {\n return {\n type: 'lifecycle',\n onBeforeNodeProcess: (node, context) => {\n const { path } = context\n\n // If the node is a $ref and we are not on the schema object, we need to normalize the $ref\n if (typeof node['$ref'] === 'string' && !(path[0] === 'components' && path[1] === 'schemas')) {\n // Remove any other properties from the node and only keep the '$ref', 'summary', 'description' and '$status'\n const keepProperties = new Set(['$ref', 'summary', 'description', '$status'])\n\n Object.keys(node).forEach((key) => {\n if (!keepProperties.has(key)) {\n delete node[key]\n }\n })\n }\n },\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,9 @@
1
+ import type { MaybeRefSchemaObject, SchemaObject } from './schemas/v3.1/strict/schema.js';
2
+ type ResolvedSchema<T> = T extends undefined ? undefined : SchemaObject & {
3
+ $ref?: string;
4
+ };
5
+ export declare const resolve: {
6
+ schema: <T extends MaybeRefSchemaObject | undefined>(schema: T) => ResolvedSchema<T>;
7
+ };
8
+ export {};
9
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAUtF,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3F,eAAO,MAAM,OAAO;aACT,CAAC,SAAS,oBAAoB,GAAG,SAAS,UAAU,CAAC,KAAG,cAAc,CAAC,CAAC,CAAC;CAWnF,CAAA"}
@@ -0,0 +1,28 @@
1
+ import { Type } from "@scalar/typebox";
2
+ import { getResolvedRef } from "./helpers/get-resolved-ref.js";
3
+ import { compose } from "./schemas/compose.js";
4
+ import { coerceValue } from "./schemas/typebox-coerce.js";
5
+ import { SchemaObjectSchema } from "./schemas/v3.1/strict/openapi-document.js";
6
+ const mergeSiblingReferences = (node) => {
7
+ const { "$ref-value": value, ...rest } = node;
8
+ return {
9
+ ...value,
10
+ ...rest
11
+ };
12
+ };
13
+ const resolve = {
14
+ schema: (schema) => {
15
+ if (schema === void 0) {
16
+ return void 0;
17
+ }
18
+ const resoled = getResolvedRef(schema, mergeSiblingReferences);
19
+ return coerceValue(
20
+ compose(SchemaObjectSchema, Type.Object({ $ref: Type.Optional(Type.String()) })),
21
+ resoled
22
+ );
23
+ }
24
+ };
25
+ export {
26
+ resolve
27
+ };
28
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/resolve.ts"],
4
+ "sourcesContent": ["import { Type } from '@scalar/typebox'\n\nimport { type RefNode, getResolvedRef } from '@/helpers/get-resolved-ref'\nimport { compose } from '@/schemas/compose'\nimport { coerceValue } from '@/schemas/typebox-coerce'\nimport { SchemaObjectSchema } from '@/schemas/v3.1/strict/openapi-document'\nimport type { MaybeRefSchemaObject, SchemaObject } from '@/schemas/v3.1/strict/schema'\n\nconst mergeSiblingReferences = <Node>(node: RefNode<Node>) => {\n const { '$ref-value': value, ...rest } = node\n return {\n ...value,\n ...rest,\n }\n}\n\ntype ResolvedSchema<T> = T extends undefined ? undefined : SchemaObject & { $ref?: string }\n\nexport const resolve = {\n schema: <T extends MaybeRefSchemaObject | undefined>(schema: T): ResolvedSchema<T> => {\n if (schema === undefined) {\n return undefined as ResolvedSchema<T>\n }\n\n const resoled = getResolvedRef(schema, mergeSiblingReferences)\n return coerceValue(\n compose(SchemaObjectSchema, Type.Object({ $ref: Type.Optional(Type.String()) })),\n resoled,\n ) as ResolvedSchema<T>\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,YAAY;AAErB,SAAuB,sBAAsB;AAC7C,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAGnC,MAAM,yBAAyB,CAAO,SAAwB;AAC5D,QAAM,EAAE,cAAc,OAAO,GAAG,KAAK,IAAI;AACzC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;AAIO,MAAM,UAAU;AAAA,EACrB,QAAQ,CAA6C,WAAiC;AACpF,QAAI,WAAW,QAAW;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,eAAe,QAAQ,sBAAsB;AAC7D,WAAO;AAAA,MACL,QAAQ,oBAAoB,KAAK,OAAO,EAAE,MAAM,KAAK,SAAS,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }