@pikku/openapi-parser 0.12.13 → 0.12.14
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 +6 -0
- package/dist/auth-config.d.ts +1 -0
- package/dist/auth-config.js +7 -0
- package/dist/codegen.js +9 -1
- package/package.json +1 -1
- package/src/auth-config.ts +7 -0
- package/src/codegen.test.ts +23 -0
- package/src/codegen.ts +11 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @pikku/openapi-parser
|
|
2
2
|
|
|
3
|
+
## 0.12.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a10e88d: auth-config: new `extraHeaders` field — static headers baked into every generated request (the delegated login call and all proxied service calls), for upstreams that route on a header such as multi-tenant APIs resolving the tenant from `Origin`.
|
|
8
|
+
|
|
3
9
|
## 0.12.13
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/auth-config.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ export declare const AuthConfigSchema: z.ZodObject<{
|
|
|
39
39
|
raw: "raw";
|
|
40
40
|
bearer: "bearer";
|
|
41
41
|
}>>;
|
|
42
|
+
extraHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
42
43
|
delegated: z.ZodOptional<z.ZodObject<{
|
|
43
44
|
loginPath: z.ZodString;
|
|
44
45
|
loginMethod: z.ZodDefault<z.ZodString>;
|
package/dist/auth-config.js
CHANGED
|
@@ -38,6 +38,13 @@ export const AuthConfigSchema = z.object({
|
|
|
38
38
|
headerName: z.string().optional(),
|
|
39
39
|
/** 'raw' sends the bare token; 'bearer' prefixes it. Default: bearer for Authorization, raw for custom headers. */
|
|
40
40
|
headerFormat: z.enum(['raw', 'bearer']).optional(),
|
|
41
|
+
/**
|
|
42
|
+
* Static headers sent on EVERY request — the delegated login call and all
|
|
43
|
+
* proxied API calls. Needed for upstreams that route on a header, e.g. a
|
|
44
|
+
* multi-tenant API that resolves the tenant from an `Origin` header and
|
|
45
|
+
* rejects requests without it.
|
|
46
|
+
*/
|
|
47
|
+
extraHeaders: z.record(z.string(), z.string()).optional(),
|
|
41
48
|
/** Present when end-users sign in with their existing upstream credentials (delegated login). */
|
|
42
49
|
delegated: DelegatedLoginSchema.optional(),
|
|
43
50
|
});
|
package/dist/codegen.js
CHANGED
|
@@ -839,7 +839,12 @@ function generateUpstreamAuthFile(vars, authConfig) {
|
|
|
839
839
|
lines.push(` credentials: ${pascalName}UpstreamCredentials,`);
|
|
840
840
|
lines.push(' baseUrl: string');
|
|
841
841
|
lines.push(`): Promise<${pascalName}UpstreamIdentity | null> => {`);
|
|
842
|
-
lines.push(
|
|
842
|
+
lines.push(' const headers: Record<string, string> = {');
|
|
843
|
+
lines.push(" 'Content-Type': 'application/json',");
|
|
844
|
+
for (const [header, value] of Object.entries(authConfig.extraHeaders ?? {})) {
|
|
845
|
+
lines.push(` ${JSON.stringify(header)}: ${JSON.stringify(value)},`);
|
|
846
|
+
}
|
|
847
|
+
lines.push(' }');
|
|
843
848
|
lines.push(' const body: Record<string, string> = {}');
|
|
844
849
|
if (delegated.credentials.includes('email')) {
|
|
845
850
|
lines.push(' if (credentials.email) body.email = credentials.email');
|
|
@@ -1041,6 +1046,9 @@ function generateServiceFile(spec, opPairs, vars, flags) {
|
|
|
1041
1046
|
lines.push(' const query: Record<string, string> = {}');
|
|
1042
1047
|
lines.push(' const headers: Record<string, string> = {');
|
|
1043
1048
|
lines.push(" 'Content-Type': 'application/json',");
|
|
1049
|
+
for (const [header, value] of Object.entries(flags.authConfig?.extraHeaders ?? {})) {
|
|
1050
|
+
lines.push(` ${JSON.stringify(header)}: ${JSON.stringify(value)},`);
|
|
1051
|
+
}
|
|
1044
1052
|
lines.push(' }');
|
|
1045
1053
|
lines.push('');
|
|
1046
1054
|
// When camelCase flag is on, use rawData (snake_case converted) for route matching
|
package/package.json
CHANGED
package/src/auth-config.ts
CHANGED
|
@@ -41,6 +41,13 @@ export const AuthConfigSchema = z.object({
|
|
|
41
41
|
headerName: z.string().optional(),
|
|
42
42
|
/** 'raw' sends the bare token; 'bearer' prefixes it. Default: bearer for Authorization, raw for custom headers. */
|
|
43
43
|
headerFormat: z.enum(['raw', 'bearer']).optional(),
|
|
44
|
+
/**
|
|
45
|
+
* Static headers sent on EVERY request — the delegated login call and all
|
|
46
|
+
* proxied API calls. Needed for upstreams that route on a header, e.g. a
|
|
47
|
+
* multi-tenant API that resolves the tenant from an `Origin` header and
|
|
48
|
+
* rejects requests without it.
|
|
49
|
+
*/
|
|
50
|
+
extraHeaders: z.record(z.string(), z.string()).optional(),
|
|
44
51
|
/** Present when end-users sign in with their existing upstream credentials (delegated login). */
|
|
45
52
|
delegated: DelegatedLoginSchema.optional(),
|
|
46
53
|
})
|
package/src/codegen.test.ts
CHANGED
|
@@ -932,6 +932,29 @@ describe('auth config', () => {
|
|
|
932
932
|
)
|
|
933
933
|
})
|
|
934
934
|
|
|
935
|
+
test('extraHeaders are baked into the service and the upstream-auth login', () => {
|
|
936
|
+
const spec = makeSpec({ operations: [makeOp()] })
|
|
937
|
+
const files = generateAddonFromOpenAPI(spec, makeVars(), {
|
|
938
|
+
oauth: false,
|
|
939
|
+
secret: false,
|
|
940
|
+
credential: 'bearer',
|
|
941
|
+
authConfig: {
|
|
942
|
+
...delegatedConfig,
|
|
943
|
+
extraHeaders: { Origin: 'https://tenant.example.com' },
|
|
944
|
+
},
|
|
945
|
+
})
|
|
946
|
+
const service = files['src/test-api-api.service.ts']
|
|
947
|
+
assert.ok(
|
|
948
|
+
service.includes('"Origin": "https://tenant.example.com",'),
|
|
949
|
+
'service headers init should carry the static header'
|
|
950
|
+
)
|
|
951
|
+
const authFile = files['src/test-api-upstream-auth.ts']
|
|
952
|
+
assert.ok(
|
|
953
|
+
authFile.includes('"Origin": "https://tenant.example.com",'),
|
|
954
|
+
'login fetch should carry the static header'
|
|
955
|
+
)
|
|
956
|
+
})
|
|
957
|
+
|
|
935
958
|
test('no delegated config → no upstream-auth file', () => {
|
|
936
959
|
const spec = makeSpec({ operations: [makeOp()] })
|
|
937
960
|
const files = generateAddonFromOpenAPI(spec, makeVars(), {
|
package/src/codegen.ts
CHANGED
|
@@ -1132,9 +1132,12 @@ function generateUpstreamAuthFile(
|
|
|
1132
1132
|
lines.push(` credentials: ${pascalName}UpstreamCredentials,`)
|
|
1133
1133
|
lines.push(' baseUrl: string')
|
|
1134
1134
|
lines.push(`): Promise<${pascalName}UpstreamIdentity | null> => {`)
|
|
1135
|
-
lines.push(
|
|
1136
|
-
|
|
1137
|
-
)
|
|
1135
|
+
lines.push(' const headers: Record<string, string> = {')
|
|
1136
|
+
lines.push(" 'Content-Type': 'application/json',")
|
|
1137
|
+
for (const [header, value] of Object.entries(authConfig.extraHeaders ?? {})) {
|
|
1138
|
+
lines.push(` ${JSON.stringify(header)}: ${JSON.stringify(value)},`)
|
|
1139
|
+
}
|
|
1140
|
+
lines.push(' }')
|
|
1138
1141
|
lines.push(' const body: Record<string, string> = {}')
|
|
1139
1142
|
if (delegated.credentials.includes('email')) {
|
|
1140
1143
|
lines.push(' if (credentials.email) body.email = credentials.email')
|
|
@@ -1405,6 +1408,11 @@ function generateServiceFile(
|
|
|
1405
1408
|
lines.push(' const query: Record<string, string> = {}')
|
|
1406
1409
|
lines.push(' const headers: Record<string, string> = {')
|
|
1407
1410
|
lines.push(" 'Content-Type': 'application/json',")
|
|
1411
|
+
for (const [header, value] of Object.entries(
|
|
1412
|
+
flags.authConfig?.extraHeaders ?? {}
|
|
1413
|
+
)) {
|
|
1414
|
+
lines.push(` ${JSON.stringify(header)}: ${JSON.stringify(value)},`)
|
|
1415
|
+
}
|
|
1408
1416
|
lines.push(' }')
|
|
1409
1417
|
lines.push('')
|
|
1410
1418
|
// When camelCase flag is on, use rawData (snake_case converted) for route matching
|