@scalar/workspace-store 0.43.0 → 0.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @scalar/workspace-store
2
2
 
3
+ ## 0.43.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#8728](https://github.com/scalar/scalar/pull/8728): fix: correctly merge security schemes with the config security
8
+
3
9
  ## 0.43.0
4
10
 
5
11
  ### Minor Changes
@@ -1,3 +1,4 @@
1
+ import type { AuthenticationConfiguration } from '@scalar/types/api-reference';
1
2
  import type { WorkspaceStore } from '../../client.js';
2
3
  import type { SelectedSecurity } from '../../entities/auth/index.js';
3
4
  import type { AuthMeta, ServerMeta } from '../../events/index.js';
@@ -46,6 +47,8 @@ export declare const getRequestExampleContext: (workspaceStore: WorkspaceStore,
46
47
  layout: Layout;
47
48
  appVersion: string;
48
49
  isElectron: boolean;
50
+ /** User facing authentication configuration */
51
+ authentication: AuthenticationConfiguration;
49
52
  /**
50
53
  * When the document is not in `workspace.documents[documentName]` yet, use this copy (same shape as the
51
54
  * workspace entry). Callers that already hold the resolved document should pass it so behavior matches
@@ -1 +1 @@
1
- {"version":3,"file":"get-request-example-context.d.ts","sourceRoot":"","sources":["../../../src/request-example/context/get-request-example-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAA;AAIjG,OAAO,EAAE,KAAK,MAAM,EAAqB,MAAM,iCAAiC,CAAA;AAIhF,OAAO,EAAE,KAAK,qBAAqB,EAAiB,MAAM,mDAAmD,CAAA;AAE7G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAA;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAA;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,KAAK,0BAA0B,GAAG;IAChC,SAAS,EAAE,eAAe,CAAA;IAC1B,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,WAAW,EAAE,kBAAkB,CAAA;KAChC,CAAA;IACD,OAAO,EAAE;QACP,SAAS,EAAE,aAAa,EAAE,CAAA;QAC1B,QAAQ,EAAE,aAAa,EAAE,CAAA;KAC1B,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,YAAY,EAAE,CAAA;QACpB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;QAC7B,IAAI,EAAE,UAAU,CAAA;KACjB,CAAA;IACD,KAAK,EAAE;QACL,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KACnB,CAAA;IACD,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAChC,CAAA;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,qBAAqB,CAAA;QAC9B,YAAY,EAAE,yBAAyB,EAAE,CAAA;QACzC,QAAQ,EAAE,gBAAgB,CAAA;QAC1B,eAAe,EAAE,0BAA0B,EAAE,CAAA;QAC7C,IAAI,EAAE,QAAQ,CAAA;KACf,CAAA;CACF,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,gBAAgB,cAAc,EAC9B,cAAc,MAAM,EACpB,oBAAoB,kBAAkB,EACtC,UAAS,OAAO,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,gBAAgB,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAC3C,CAAM,KACN,MAAM,CAAC,0BAA0B,CAmInC,CAAA"}
1
+ {"version":3,"file":"get-request-example-context.d.ts","sourceRoot":"","sources":["../../../src/request-example/context/get-request-example-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAA;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAA;AAIjG,OAAO,EAAE,KAAK,MAAM,EAAqB,MAAM,iCAAiC,CAAA;AAIhF,OAAO,EAAE,KAAK,qBAAqB,EAAiB,MAAM,mDAAmD,CAAA;AAE7G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAA;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAA;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,KAAK,0BAA0B,GAAG;IAChC,SAAS,EAAE,eAAe,CAAA;IAC1B,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;QACnB,WAAW,EAAE,kBAAkB,CAAA;KAChC,CAAA;IACD,OAAO,EAAE;QACP,SAAS,EAAE,aAAa,EAAE,CAAA;QAC1B,QAAQ,EAAE,aAAa,EAAE,CAAA;KAC1B,CAAA;IACD,OAAO,EAAE;QACP,IAAI,EAAE,YAAY,EAAE,CAAA;QACpB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;QAC7B,IAAI,EAAE,UAAU,CAAA;KACjB,CAAA;IACD,KAAK,EAAE;QACL,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KACnB,CAAA;IACD,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAChC,CAAA;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,qBAAqB,CAAA;QAC9B,YAAY,EAAE,yBAAyB,EAAE,CAAA;QACzC,QAAQ,EAAE,gBAAgB,CAAA;QAC1B,eAAe,EAAE,0BAA0B,EAAE,CAAA;QAC7C,IAAI,EAAE,QAAQ,CAAA;KACf,CAAA;CACF,CAAA;AAED,eAAO,MAAM,wBAAwB,GACnC,gBAAgB,cAAc,EAC9B,cAAc,MAAM,EACpB,oBAAoB,kBAAkB,EACtC,UAAS,OAAO,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,+CAA+C;IAC/C,cAAc,EAAE,2BAA2B,CAAA;IAC3C;;;;OAIG;IACH,gBAAgB,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAC3C,CAAM,KACN,MAAM,CAAC,0BAA0B,CAoInC,CAAA"}
@@ -63,9 +63,9 @@ export const getRequestExampleContext = (workspaceStore, documentName, requestEx
63
63
  path: path ?? '',
64
64
  method: method ?? 'get',
65
65
  });
66
- const securitySchemes = mergeSecurity(document.components?.securitySchemes ?? {}, {}, workspaceStore.auth, documentName);
66
+ const securitySchemes = mergeSecurity(document.components?.securitySchemes ?? {}, options.authentication?.securitySchemes ?? {}, workspaceStore.auth, documentName);
67
67
  const securityRequirements = getSecurityRequirements(document.security, operation.security);
68
- const selectedSecurity = getSelectedSecurity(documentSelectedSecurity, operationSelectedSecurity, securityRequirements, securitySchemes);
68
+ const selectedSecurity = getSelectedSecurity(documentSelectedSecurity, operationSelectedSecurity, securityRequirements, securitySchemes, options.authentication?.preferredSecurityScheme);
69
69
  /** The above selected requirements in scheme form */
70
70
  const selectedSecuritySchemes = getSecuritySchemes(securitySchemes, selectedSecurity.selectedSchemes);
71
71
  const serverMeta = operation.servers != null ? { type: 'operation', path: path ?? '', method: method ?? 'get' } : { type: 'document' };
@@ -1,3 +1,4 @@
1
+ import type { AuthenticationConfiguration } from '@scalar/types/api-reference';
1
2
  import type { SelectedSecurity } from '@scalar/workspace-store/entities/auth';
2
3
  import type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document';
3
4
  type DefaultScopeScheme = {
@@ -6,10 +7,14 @@ type DefaultScopeScheme = {
6
7
  };
7
8
  /**
8
9
  * Resolves which security selection to use for an operation.
9
- * Priority: operation-level selection, then document-level selection, then a default.
10
- * When neither level has a selection, returns the first security requirement unless
11
- * authentication is optional or there are no requirements, in which case returns no selection.
10
+ *
11
+ * Priority order:
12
+ * 1. Operation-level selection (if set)
13
+ * 2. Document-level selection (if set)
14
+ * 3. Preferred security scheme from configuration (if provided)
15
+ * 4. First security requirement from the OpenAPI spec
16
+ * 5. No selection (if auth is optional or no requirements exist)
12
17
  */
13
- export declare const getSelectedSecurity: (documentSelectedSecurity: SelectedSecurity | undefined, operationSelectedSecurity: SelectedSecurity | undefined, securityRequirements?: NonNullable<OpenApiDocument["security"]>, securitySchemes?: Record<string, DefaultScopeScheme | undefined>) => SelectedSecurity;
18
+ export declare const getSelectedSecurity: (documentSelectedSecurity: SelectedSecurity | undefined, operationSelectedSecurity: SelectedSecurity | undefined, securityRequirements?: NonNullable<OpenApiDocument["security"]>, securitySchemes?: Record<string, DefaultScopeScheme | undefined>, preferredSecurityScheme?: AuthenticationConfiguration["preferredSecurityScheme"]) => SelectedSecurity;
14
19
  export {};
15
20
  //# sourceMappingURL=get-selected-security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-selected-security.d.ts","sourceRoot":"","sources":["../../../../src/request-example/context/security/get-selected-security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAInG,KAAK,kBAAkB,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B,CAAA;AA4BD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,0BAA0B,gBAAgB,GAAG,SAAS,EACtD,2BAA2B,gBAAgB,GAAG,SAAS,EACvD,uBAAsB,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAM,EACnE,kBAAiB,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,CAAM,KACnE,gBA4BF,CAAA"}
1
+ {"version":3,"file":"get-selected-security.d.ts","sourceRoot":"","sources":["../../../../src/request-example/context/security/get-selected-security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAE7E,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,8DAA8D,CAAA;AAIrE,KAAK,kBAAkB,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B,CAAA;AAkED;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC9B,0BAA0B,gBAAgB,GAAG,SAAS,EACtD,2BAA2B,gBAAgB,GAAG,SAAS,EACvD,uBAAsB,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAM,EACnE,kBAAiB,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,CAAM,EACpE,0BAA0B,2BAA2B,CAAC,yBAAyB,CAAC,KAC/E,gBAgDF,CAAA"}
@@ -1,5 +1,12 @@
1
1
  import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
2
2
  import { isAuthOptional } from './is-auth-optional.js';
3
+ /** Extracts the default scopes for a security scheme (only OAuth2 schemes support this) */
4
+ const getDefaultScopes = (scheme) => {
5
+ if (!scheme || scheme.type !== 'oauth2') {
6
+ return [];
7
+ }
8
+ return scheme['x-default-scopes'] ?? [];
9
+ };
3
10
  const applyDefaultScopes = (requirement, securitySchemes) => {
4
11
  let didApplyDefaultScopes = false;
5
12
  const hydratedRequirement = Object.fromEntries(Object.entries(requirement).map(([name, scopes]) => {
@@ -16,25 +23,68 @@ const applyDefaultScopes = (requirement, securitySchemes) => {
16
23
  }));
17
24
  return didApplyDefaultScopes ? hydratedRequirement : requirement;
18
25
  };
26
+ /**
27
+ * Builds a security requirement from the preferred security scheme configuration.
28
+ * Handles both string and array formats for complex auth scenarios.
29
+ */
30
+ const buildSecurityRequirementFromPreferred = (preferredSecurityScheme, securitySchemes) => {
31
+ if (!Array.isArray(preferredSecurityScheme)) {
32
+ const scheme = getResolvedRef(securitySchemes[preferredSecurityScheme]);
33
+ return { [preferredSecurityScheme]: getDefaultScopes(scheme) };
34
+ }
35
+ const requirement = {};
36
+ for (const item of preferredSecurityScheme) {
37
+ if (Array.isArray(item)) {
38
+ for (const schemeName of item) {
39
+ const scheme = getResolvedRef(securitySchemes[schemeName]);
40
+ requirement[schemeName] = getDefaultScopes(scheme);
41
+ }
42
+ }
43
+ else {
44
+ const scheme = getResolvedRef(securitySchemes[item]);
45
+ requirement[item] = getDefaultScopes(scheme);
46
+ }
47
+ }
48
+ return requirement;
49
+ };
19
50
  /**
20
51
  * Resolves which security selection to use for an operation.
21
- * Priority: operation-level selection, then document-level selection, then a default.
22
- * When neither level has a selection, returns the first security requirement unless
23
- * authentication is optional or there are no requirements, in which case returns no selection.
52
+ *
53
+ * Priority order:
54
+ * 1. Operation-level selection (if set)
55
+ * 2. Document-level selection (if set)
56
+ * 3. Preferred security scheme from configuration (if provided)
57
+ * 4. First security requirement from the OpenAPI spec
58
+ * 5. No selection (if auth is optional or no requirements exist)
24
59
  */
25
- export const getSelectedSecurity = (documentSelectedSecurity, operationSelectedSecurity, securityRequirements = [], securitySchemes = {}) => {
26
- // Operation level security
60
+ export const getSelectedSecurity = (documentSelectedSecurity, operationSelectedSecurity, securityRequirements = [], securitySchemes = {}, preferredSecurityScheme) => {
61
+ // Operation level security takes highest priority
27
62
  if (operationSelectedSecurity) {
28
63
  return operationSelectedSecurity;
29
64
  }
30
- // Document level security
65
+ // Document level security is next
31
66
  if (documentSelectedSecurity) {
32
67
  return documentSelectedSecurity;
33
68
  }
34
69
  const isOptional = isAuthOptional(securityRequirements);
70
+ // No need to default if auth is optional and no preferred scheme
71
+ if (isOptional && !preferredSecurityScheme) {
72
+ return {
73
+ selectedIndex: -1,
74
+ selectedSchemes: [],
75
+ };
76
+ }
77
+ // Use preferred security scheme if configured
78
+ if (preferredSecurityScheme) {
79
+ const requirement = buildSecurityRequirementFromPreferred(preferredSecurityScheme, securitySchemes);
80
+ return {
81
+ selectedIndex: 0,
82
+ selectedSchemes: [requirement],
83
+ };
84
+ }
35
85
  const firstRequirement = securityRequirements[0];
36
- // No need to default if auth is optional
37
- if (isOptional || !firstRequirement) {
86
+ // No requirements and no preferred scheme
87
+ if (!firstRequirement) {
38
88
  return {
39
89
  selectedIndex: -1,
40
90
  selectedSchemes: [],
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "openapi",
17
17
  "scalar"
18
18
  ],
19
- "version": "0.43.0",
19
+ "version": "0.43.1",
20
20
  "engines": {
21
21
  "node": ">=22"
22
22
  },
@@ -147,8 +147,8 @@
147
147
  "@scalar/helpers": "0.4.3",
148
148
  "@scalar/json-magic": "0.12.5",
149
149
  "@scalar/openapi-upgrader": "0.2.4",
150
- "@scalar/types": "0.7.6",
151
150
  "@scalar/snippetz": "0.7.8",
151
+ "@scalar/types": "0.7.6",
152
152
  "@scalar/validation": "0.3.0"
153
153
  },
154
154
  "devDependencies": {