@lukoweb/apitogo 0.1.92 → 0.1.94
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/dist/cli/cli.js +32 -41
- package/dist/declarations/cli/platform/helpers/dev-portal-manifest.d.ts +3 -0
- package/dist/declarations/config/local-manifest.d.ts +4 -0
- package/docs/cli/commands.md +2 -1
- package/docs/cli/overview.md +1 -1
- package/docs/cli/setup.md +19 -5
- package/docs/cli/shape.md +2 -2
- package/docs/configuration/make-config.mdx +1 -1
- package/docs/configuration/manifest.md +41 -4
- package/package.json +1 -1
- package/src/config/apitogo-config-core.ts +11 -25
- package/src/config/local-manifest.ts +6 -0
package/dist/cli/cli.js
CHANGED
|
@@ -301,23 +301,15 @@ function firstApiInput(config2) {
|
|
|
301
301
|
}
|
|
302
302
|
return void 0;
|
|
303
303
|
}
|
|
304
|
-
function
|
|
304
|
+
function normalizeGatewayPlacement(config2) {
|
|
305
305
|
const authentication = asRecord2(config2.authentication);
|
|
306
306
|
if (!authentication) {
|
|
307
|
-
return
|
|
307
|
+
return;
|
|
308
308
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
return authentication;
|
|
309
|
+
if ("gateway" in authentication) {
|
|
310
|
+
delete authentication.gateway;
|
|
311
|
+
config2.authentication = authentication;
|
|
313
312
|
}
|
|
314
|
-
return {
|
|
315
|
-
...authentication,
|
|
316
|
-
gateway: {
|
|
317
|
-
...rootGateway,
|
|
318
|
-
...authGateway
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
313
|
}
|
|
322
314
|
function ensureModules(config2) {
|
|
323
315
|
const modules = asRecord2(config2.modules) ?? {};
|
|
@@ -378,11 +370,10 @@ function normalizeApitogoConfig(config2) {
|
|
|
378
370
|
};
|
|
379
371
|
}
|
|
380
372
|
normalized.site = site;
|
|
381
|
-
const authentication =
|
|
373
|
+
const authentication = asRecord2(normalized.authentication);
|
|
382
374
|
if (authentication) {
|
|
383
|
-
normalized
|
|
375
|
+
normalizeGatewayPlacement(normalized);
|
|
384
376
|
}
|
|
385
|
-
delete normalized.gateway;
|
|
386
377
|
const modules = ensureModules(normalized);
|
|
387
378
|
const legacyDocs = asRecord2(normalized.docs);
|
|
388
379
|
const moduleDocs = asRecord2(modules.docs) ?? {};
|
|
@@ -533,13 +524,16 @@ function deriveManifestFields(config2) {
|
|
|
533
524
|
continue;
|
|
534
525
|
}
|
|
535
526
|
if (key === "authentication") {
|
|
536
|
-
const
|
|
537
|
-
if (
|
|
538
|
-
manifest.authentication = stripAuthenticationSecrets2(
|
|
527
|
+
const authentication = asRecord2(normalized.authentication);
|
|
528
|
+
if (authentication) {
|
|
529
|
+
manifest.authentication = stripAuthenticationSecrets2(authentication);
|
|
539
530
|
}
|
|
540
531
|
continue;
|
|
541
532
|
}
|
|
542
533
|
if (key === "gateway") {
|
|
534
|
+
if (normalized.gateway !== void 0) {
|
|
535
|
+
manifest.gateway = normalized.gateway;
|
|
536
|
+
}
|
|
543
537
|
continue;
|
|
544
538
|
}
|
|
545
539
|
if (key === "pricing") {
|
|
@@ -570,10 +564,6 @@ function deriveManifestFields(config2) {
|
|
|
570
564
|
manifest[key] = normalized[key];
|
|
571
565
|
}
|
|
572
566
|
}
|
|
573
|
-
const authentication = asRecord2(normalized.authentication);
|
|
574
|
-
if (authentication?.gateway) {
|
|
575
|
-
manifest.gateway = authentication.gateway;
|
|
576
|
-
}
|
|
577
567
|
return manifest;
|
|
578
568
|
}
|
|
579
569
|
function extractManifest(config2) {
|
|
@@ -1158,7 +1148,11 @@ var init_local_manifest = __esm({
|
|
|
1158
1148
|
oidcAllowedIssuers: z4.array(z4.string()).optional(),
|
|
1159
1149
|
oidcAudiences: z4.array(z4.string()).optional(),
|
|
1160
1150
|
limitsJson: z4.string().optional(),
|
|
1161
|
-
publicHealthActionKey: z4.string().optional()
|
|
1151
|
+
publicHealthActionKey: z4.string().optional(),
|
|
1152
|
+
publicRoutes: z4.array(z4.string()).optional(),
|
|
1153
|
+
cors: z4.object({
|
|
1154
|
+
allowedOrigins: z4.array(z4.string()).optional()
|
|
1155
|
+
}).optional()
|
|
1162
1156
|
}).optional(),
|
|
1163
1157
|
projectId: z4.string().optional(),
|
|
1164
1158
|
landing: z4.object({
|
|
@@ -6034,6 +6028,7 @@ function manifestFilePath(siteDirectory) {
|
|
|
6034
6028
|
var STORED_MANIFEST_KEYS = [
|
|
6035
6029
|
"authentication",
|
|
6036
6030
|
"backend",
|
|
6031
|
+
"gateway",
|
|
6037
6032
|
"projectId"
|
|
6038
6033
|
];
|
|
6039
6034
|
function readPlanItemsFromConfig(config2) {
|
|
@@ -6189,12 +6184,6 @@ function extractManifestFromConfig(config2) {
|
|
|
6189
6184
|
if (readPricingEnabledFromConfig(config2)) {
|
|
6190
6185
|
manifest.pricing = { enabled: true };
|
|
6191
6186
|
}
|
|
6192
|
-
const authConfig = config2.authentication;
|
|
6193
|
-
if (authConfig?.gateway) {
|
|
6194
|
-
manifest.gateway = authConfig.gateway;
|
|
6195
|
-
} else if (config2.gateway) {
|
|
6196
|
-
manifest.gateway = config2.gateway;
|
|
6197
|
-
}
|
|
6198
6187
|
const landing = readLandingFromConfig(config2);
|
|
6199
6188
|
if (landing) {
|
|
6200
6189
|
manifest.landing = landing;
|
|
@@ -6234,15 +6223,14 @@ function applyManifestToConfig(config2, manifest) {
|
|
|
6234
6223
|
}
|
|
6235
6224
|
delete next.plans;
|
|
6236
6225
|
delete next.pricing;
|
|
6237
|
-
if (
|
|
6238
|
-
const authentication = next.authentication
|
|
6239
|
-
authentication.gateway
|
|
6226
|
+
if (next.authentication && typeof next.authentication === "object") {
|
|
6227
|
+
const authentication = { ...next.authentication };
|
|
6228
|
+
delete authentication.gateway;
|
|
6240
6229
|
next.authentication = authentication;
|
|
6241
6230
|
}
|
|
6242
6231
|
delete next.siteName;
|
|
6243
6232
|
delete next.branding;
|
|
6244
6233
|
delete next.projectName;
|
|
6245
|
-
delete next.gateway;
|
|
6246
6234
|
return next;
|
|
6247
6235
|
}
|
|
6248
6236
|
async function readLegacyManifest(_siteDirectory) {
|
|
@@ -9407,7 +9395,8 @@ var PLATFORM_PLAN_CATALOG = [
|
|
|
9407
9395
|
"Paid end-user gateway plans (Stripe checkout for API subscribers)",
|
|
9408
9396
|
"1 custom domain on the dev portal",
|
|
9409
9397
|
"100k requests included; up to 1M requests / month",
|
|
9410
|
-
"Stripe subscription billing with promotion codes at checkout"
|
|
9398
|
+
"Stripe subscription billing with promotion codes at checkout",
|
|
9399
|
+
"Standard support"
|
|
9411
9400
|
],
|
|
9412
9401
|
limitations: [
|
|
9413
9402
|
"Requires Stripe checkout to activate",
|
|
@@ -9427,7 +9416,8 @@ var PLATFORM_PLAN_CATALOG = [
|
|
|
9427
9416
|
"3 custom domains",
|
|
9428
9417
|
"1M requests included; up to 10M requests / month",
|
|
9429
9418
|
"Advanced analytics and CDN for your API",
|
|
9430
|
-
"Extended monitoring history and alerts"
|
|
9419
|
+
"Extended monitoring history and alerts",
|
|
9420
|
+
"Enterprise support"
|
|
9431
9421
|
],
|
|
9432
9422
|
limitations: [
|
|
9433
9423
|
"Requires Stripe checkout to activate",
|
|
@@ -9446,8 +9436,8 @@ function buildPlatformPlanSelectionAgentInstruction(quota) {
|
|
|
9446
9436
|
const lines = [
|
|
9447
9437
|
"Before calling ensure_platform_plan, explain the platform hosting tiers to the user using platformPlanCatalog from the bootstrap response or list_platform_plans.",
|
|
9448
9438
|
"Free: $0/month, dev portal + API hub, no custom domain, free ($0) gateway/API plans only.",
|
|
9449
|
-
"Starter: $99/month via Stripe, custom domain, paid gateway plans, production hosting.",
|
|
9450
|
-
"Professional: $999/month via Stripe, higher limits, multiple domains, advanced analytics.",
|
|
9439
|
+
"Starter: $99/month via Stripe, custom domain, paid gateway plans, production hosting, standard support.",
|
|
9440
|
+
"Professional: $999/month via Stripe, higher limits, multiple domains, advanced analytics, enterprise support.",
|
|
9451
9441
|
"This is separate from gateway/API plans (what end users pay for API access) configured in apitogo.config.json.",
|
|
9452
9442
|
"If apitogo.config.json already has paid gateway plans (priceAmount > 0), warn before they pick Free: Free cannot publish paid API plans \u2014 they must choose Starter/Professional, or remove/zero those paid plans first. Never silently strip paid plans."
|
|
9453
9443
|
];
|
|
@@ -12545,7 +12535,7 @@ import {
|
|
|
12545
12535
|
// package.json
|
|
12546
12536
|
var package_default = {
|
|
12547
12537
|
name: "@lukoweb/apitogo",
|
|
12548
|
-
version: "0.1.
|
|
12538
|
+
version: "0.1.94",
|
|
12549
12539
|
type: "module",
|
|
12550
12540
|
sideEffects: [
|
|
12551
12541
|
"**/*.css",
|
|
@@ -18516,12 +18506,13 @@ function buildCreateApitogoCliArgs(invocationArgs, projectName, options) {
|
|
|
18516
18506
|
const cliArgs = [
|
|
18517
18507
|
...invocationArgs,
|
|
18518
18508
|
projectName,
|
|
18519
|
-
"--
|
|
18509
|
+
"--typescript",
|
|
18510
|
+
"--eslint",
|
|
18520
18511
|
"--skip-install",
|
|
18521
18512
|
"--use-npm"
|
|
18522
18513
|
];
|
|
18523
18514
|
if (options?.withExamples) {
|
|
18524
|
-
cliArgs.push("--
|
|
18515
|
+
cliArgs.push("--include-examples");
|
|
18525
18516
|
}
|
|
18526
18517
|
return cliArgs;
|
|
18527
18518
|
}
|
|
@@ -89,6 +89,10 @@ export declare const DevPortalLocalManifestSchema: z.ZodObject<{
|
|
|
89
89
|
oidcAudiences: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
90
90
|
limitsJson: z.ZodOptional<z.ZodString>;
|
|
91
91
|
publicHealthActionKey: z.ZodOptional<z.ZodString>;
|
|
92
|
+
publicRoutes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
93
|
+
cors: z.ZodOptional<z.ZodObject<{
|
|
94
|
+
allowedOrigins: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
95
|
+
}, z.core.$strip>>;
|
|
92
96
|
}, z.core.$strip>>;
|
|
93
97
|
projectId: z.ZodOptional<z.ZodString>;
|
|
94
98
|
landing: z.ZodOptional<z.ZodObject<{
|
package/docs/cli/commands.md
CHANGED
|
@@ -29,7 +29,8 @@ same commands so agents and humans get identical behavior.
|
|
|
29
29
|
| `init [dir]` | Named folder; `--install` (default), `--overwrite`, `--json`, `--openapi-search` |
|
|
30
30
|
| `config` | Interactive on TTY; flags: `--openapi`, `--page-*`, `--plan`, `--backend`, `--theme`, `--patch`, `--json` |
|
|
31
31
|
|
|
32
|
-
`
|
|
32
|
+
`npx @lukoweb/create-apitogo@latest` remains an interactive alternative for new folders.
|
|
33
|
+
Pass `--typescript --eslint` to skip those prompts. See [Install the CLI](./setup.md#scaffold-options).
|
|
33
34
|
|
|
34
35
|
See [Make config (CLI)](../configuration/make-config.mdx) for all `config` flags.
|
|
35
36
|
|
package/docs/cli/overview.md
CHANGED
|
@@ -13,7 +13,7 @@ local files, preview with `apitogo dev`, and publish to APItoGo hosting with `ap
|
|
|
13
13
|
|
|
14
14
|
## What you get
|
|
15
15
|
|
|
16
|
-
- Scaffold a local portal site (`
|
|
16
|
+
- Scaffold a local portal site (`npx @lukoweb/create-apitogo@latest` or `apitogo init`)
|
|
17
17
|
- Shape backend, OpenAPI, plans, and docs pages via `apitogo config` and file edits
|
|
18
18
|
- Preview locally (`apitogo dev`)
|
|
19
19
|
- Publish to APItoGo hosting (`apitogo apply`) with platform plans **Free**, **Starter**, or
|
package/docs/cli/setup.md
CHANGED
|
@@ -23,10 +23,10 @@ need a global install — scaffold commands add it to your project and `npm inst
|
|
|
23
23
|
|
|
24
24
|
### New project (recommended)
|
|
25
25
|
|
|
26
|
-
`
|
|
26
|
+
`npx @lukoweb/create-apitogo` scaffolds the site **and** installs `@lukoweb/apitogo` locally:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
|
|
29
|
+
npx @lukoweb/create-apitogo@latest
|
|
30
30
|
cd your-project-name
|
|
31
31
|
npx apitogo config # interactive: backend, OpenAPI, pages, plans
|
|
32
32
|
npm run dev
|
|
@@ -35,14 +35,28 @@ npm run dev
|
|
|
35
35
|
Also works with `pnpm create @lukoweb/apitogo`, `yarn create @lukoweb/apitogo`, or
|
|
36
36
|
`bunx @lukoweb/create-apitogo`.
|
|
37
37
|
|
|
38
|
-
Non-interactive
|
|
38
|
+
Non-interactive:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
|
|
41
|
+
npx @lukoweb/create-apitogo@latest my-portal --typescript --eslint
|
|
42
42
|
cd my-portal
|
|
43
43
|
npx apitogo config
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
#### Scaffold options
|
|
47
|
+
|
|
48
|
+
| Flag | Effect |
|
|
49
|
+
| ---- | ------ |
|
|
50
|
+
| `--typescript` / `--ts` | TypeScript project |
|
|
51
|
+
| `--javascript` / `--js` | JavaScript project |
|
|
52
|
+
| `--eslint` | Add ESLint config |
|
|
53
|
+
| `--no-eslint` | Skip ESLint |
|
|
54
|
+
| `--include-examples` | Add starter docs and a sample OpenAPI spec (off unless passed) |
|
|
55
|
+
|
|
56
|
+
Omit flags to be prompted for TypeScript and ESLint. Example files are never prompted.
|
|
57
|
+
|
|
58
|
+
See `@lukoweb/create-apitogo --help` for package manager and install flags.
|
|
59
|
+
|
|
46
60
|
### Scaffold into an existing folder
|
|
47
61
|
|
|
48
62
|
`apitogo init` writes `package.json` with `@lukoweb/apitogo` as a dependency. Run **`npm install`**
|
|
@@ -63,7 +77,7 @@ to preview, then `apitogo apply` when ready to go live.
|
|
|
63
77
|
|
|
64
78
|
| Situation | Command |
|
|
65
79
|
| --------- | ------- |
|
|
66
|
-
| After `
|
|
80
|
+
| After `npx @lukoweb/create-apitogo` or `npm install` in the project | `npx apitogo <command>` (e.g. `npx apitogo config`) |
|
|
67
81
|
| Same, if `node_modules/.bin` is on your PATH | `apitogo <command>` |
|
|
68
82
|
| One-off, no project yet | `npx @lukoweb/apitogo <command>` |
|
|
69
83
|
| Optional global install | `npm install -g @lukoweb/apitogo` then `apitogo <command>` anywhere |
|
package/docs/cli/shape.md
CHANGED
|
@@ -13,10 +13,10 @@ Requires the **`apitogo`** CLI (`@lukoweb/apitogo`). If you have not installed i
|
|
|
13
13
|
|
|
14
14
|
## Happy path
|
|
15
15
|
|
|
16
|
-
`
|
|
16
|
+
`npx @lukoweb/create-apitogo` installs `@lukoweb/apitogo` into the new project. Then run config via `npx`:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
|
|
19
|
+
npx @lukoweb/create-apitogo@latest my-portal --typescript --eslint
|
|
20
20
|
cd my-portal
|
|
21
21
|
npx apitogo config # backend, OpenAPI, pages, plans (apply each immediately)
|
|
22
22
|
npm run dev # http://localhost:3000
|
|
@@ -20,7 +20,7 @@ on new scaffolds. The command does **not** change `redirects`.
|
|
|
20
20
|
|
|
21
21
|
Install the CLI first — see [Install the CLI](../cli/setup.md). In short:
|
|
22
22
|
|
|
23
|
-
- **New site:** `
|
|
23
|
+
- **New site:** `npx @lukoweb/create-apitogo@latest` (installs `@lukoweb/apitogo` into the project)
|
|
24
24
|
- **Existing folder:** `npx @lukoweb/apitogo init .` then `npm install`
|
|
25
25
|
|
|
26
26
|
Run config from the project root with `npx apitogo config` (or `apitogo config` if
|
|
@@ -25,10 +25,17 @@ metadata, with optional `.env` overrides for secrets and local tweaks.
|
|
|
25
25
|
"authentication": {
|
|
26
26
|
"enabled": true,
|
|
27
27
|
"type": "dev-portal",
|
|
28
|
-
"apiBaseUrl": "https://your-dev-portal-api.example.com"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
"apiBaseUrl": "https://your-dev-portal-api.example.com"
|
|
29
|
+
},
|
|
30
|
+
"gateway": {
|
|
31
|
+
"authMode": "bringYourOwnOidc",
|
|
32
|
+
"oidcMetadataUrl": "https://login.example.com/.well-known/openid-configuration",
|
|
33
|
+
"publicRoutes": ["/health"],
|
|
34
|
+
"cors": {
|
|
35
|
+
"allowedOrigins": [
|
|
36
|
+
"https://myapp.example.com",
|
|
37
|
+
"http://localhost:5173"
|
|
38
|
+
]
|
|
32
39
|
}
|
|
33
40
|
},
|
|
34
41
|
"modules": {
|
|
@@ -60,6 +67,36 @@ metadata, with optional `.env` overrides for secrets and local tweaks.
|
|
|
60
67
|
`modules.userPanel.plans.items`. Add plans with `apitogo config` or edit the manifest by hand.
|
|
61
68
|
See [Gateway plans](./plans.md). Legacy root `plans` is migrated on load.
|
|
62
69
|
- **Docs / API keys:** configure under `modules.docs` and `modules.userPanel.apiKeys` only.
|
|
70
|
+
- **Gateway:** top-level `gateway` (not under `authentication`). See [Gateway CORS](#gateway-cors)
|
|
71
|
+
and [Gateway plans](./plans.md).
|
|
72
|
+
|
|
73
|
+
## Gateway CORS
|
|
74
|
+
|
|
75
|
+
Browser calls from your developer portal (and any other SPA) to the API gateway are cross-origin.
|
|
76
|
+
APItoGo always allows the portal site origin. Add extra origins under `gateway.cors.allowedOrigins`
|
|
77
|
+
when tenant apps or local frontends call the gateway:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"gateway": {
|
|
82
|
+
"cors": {
|
|
83
|
+
"allowedOrigins": [
|
|
84
|
+
"https://myapp.example.com",
|
|
85
|
+
"http://localhost:5173"
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| Rule | Detail |
|
|
93
|
+
| ---- | ------ |
|
|
94
|
+
| Portal origin | Always allowed by the platform (`https://{your-portal-host}`). Do not list it here. |
|
|
95
|
+
| Extra origins | Absolute `http://` or `https://` origins only — no path, query, or fragment. |
|
|
96
|
+
| Wildcard | `"*"` is allowed (replaces the list; credentials stay off). |
|
|
97
|
+
| Empty / omitted | Portal playground still works; only extras are missing. |
|
|
98
|
+
|
|
99
|
+
Apply with `apitogo apply` / `publish_dev_portal` so APIM policies pick up the change.
|
|
63
100
|
|
|
64
101
|
## Environment variables
|
|
65
102
|
|
package/package.json
CHANGED
|
@@ -297,28 +297,17 @@ function firstApiInput(config: ApitogoJsonConfig): string | undefined {
|
|
|
297
297
|
return undefined;
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
): Record<string, unknown> | undefined {
|
|
300
|
+
/** Keep gateway at config root; strip any nested authentication.gateway. */
|
|
301
|
+
function normalizeGatewayPlacement(config: ApitogoJsonConfig): void {
|
|
303
302
|
const authentication = asRecord(config.authentication);
|
|
304
303
|
if (!authentication) {
|
|
305
|
-
return
|
|
304
|
+
return;
|
|
306
305
|
}
|
|
307
306
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (!authGateway && !rootGateway) {
|
|
312
|
-
return authentication;
|
|
307
|
+
if ("gateway" in authentication) {
|
|
308
|
+
delete authentication.gateway;
|
|
309
|
+
config.authentication = authentication;
|
|
313
310
|
}
|
|
314
|
-
|
|
315
|
-
return {
|
|
316
|
-
...authentication,
|
|
317
|
-
gateway: {
|
|
318
|
-
...rootGateway,
|
|
319
|
-
...authGateway,
|
|
320
|
-
},
|
|
321
|
-
};
|
|
322
311
|
}
|
|
323
312
|
|
|
324
313
|
function ensureModules(config: ApitogoJsonConfig): Record<string, unknown> {
|
|
@@ -403,11 +392,10 @@ export function normalizeApitogoConfig(
|
|
|
403
392
|
}
|
|
404
393
|
normalized.site = site;
|
|
405
394
|
|
|
406
|
-
const authentication =
|
|
395
|
+
const authentication = asRecord(normalized.authentication);
|
|
407
396
|
if (authentication) {
|
|
408
|
-
normalized
|
|
397
|
+
normalizeGatewayPlacement(normalized);
|
|
409
398
|
}
|
|
410
|
-
delete normalized.gateway;
|
|
411
399
|
|
|
412
400
|
const modules = ensureModules(normalized);
|
|
413
401
|
const legacyDocs = asRecord(normalized.docs);
|
|
@@ -654,6 +642,9 @@ export function deriveManifestFields(
|
|
|
654
642
|
continue;
|
|
655
643
|
}
|
|
656
644
|
if (key === "gateway") {
|
|
645
|
+
if (normalized.gateway !== undefined) {
|
|
646
|
+
manifest.gateway = normalized.gateway;
|
|
647
|
+
}
|
|
657
648
|
continue;
|
|
658
649
|
}
|
|
659
650
|
if (key === "pricing") {
|
|
@@ -686,11 +677,6 @@ export function deriveManifestFields(
|
|
|
686
677
|
}
|
|
687
678
|
}
|
|
688
679
|
|
|
689
|
-
const authentication = asRecord(normalized.authentication);
|
|
690
|
-
if (authentication?.gateway) {
|
|
691
|
-
manifest.gateway = authentication.gateway;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
680
|
return manifest;
|
|
695
681
|
}
|
|
696
682
|
|
|
@@ -140,6 +140,12 @@ export const DevPortalLocalManifestSchema = z.object({
|
|
|
140
140
|
oidcAudiences: z.array(z.string()).optional(),
|
|
141
141
|
limitsJson: z.string().optional(),
|
|
142
142
|
publicHealthActionKey: z.string().optional(),
|
|
143
|
+
publicRoutes: z.array(z.string()).optional(),
|
|
144
|
+
cors: z
|
|
145
|
+
.object({
|
|
146
|
+
allowedOrigins: z.array(z.string()).optional(),
|
|
147
|
+
})
|
|
148
|
+
.optional(),
|
|
143
149
|
})
|
|
144
150
|
.optional(),
|
|
145
151
|
projectId: z.string().optional(),
|