@lukoweb/apitogo 0.1.92 → 0.1.93
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 +23 -35
- 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/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) {
|
|
@@ -12545,7 +12533,7 @@ import {
|
|
|
12545
12533
|
// package.json
|
|
12546
12534
|
var package_default = {
|
|
12547
12535
|
name: "@lukoweb/apitogo",
|
|
12548
|
-
version: "0.1.
|
|
12536
|
+
version: "0.1.93",
|
|
12549
12537
|
type: "module",
|
|
12550
12538
|
sideEffects: [
|
|
12551
12539
|
"**/*.css",
|
|
@@ -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<{
|
|
@@ -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(),
|