@lukoweb/apitogo 0.1.121 → 0.1.126
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/LICENSE.md +18 -0
- package/dist/cli/cli.js +606 -396
- package/dist/declarations/config/local-manifest.d.ts +1 -1
- package/dist/declarations/lib/authentication/auth-header-nav.d.ts +5 -1
- package/dist/declarations/lib/authentication/hook.d.ts +25 -3
- package/dist/declarations/lib/authentication/state.d.ts +39 -3
- package/dist/declarations/lib/plugins/openapi/processors/injectApitogoGatewayServer.d.ts +1 -1
- package/docs/cli/go-live.md +21 -20
- package/docs/components/slot.mdx +2 -2
- package/docs/components.mdx +34 -34
- package/docs/concepts/auth-provider-api-identities.md +2 -2
- package/docs/configuration/authentication.md +16 -14
- package/docs/configuration/build-configuration.mdx +2 -2
- package/docs/configuration/make-config.mdx +5 -5
- package/docs/configuration/manifest.md +8 -14
- package/docs/configuration/navigation.mdx +4 -4
- package/docs/configuration/overview.md +6 -7
- package/docs/configuration/plans.md +19 -16
- package/docs/deploy/vercel.md +3 -4
- package/docs/deployment.md +5 -4
- package/docs/guides/custom-pages.md +2 -2
- package/docs/guides/environment-variables.md +19 -17
- package/docs/guides/managing-api-keys-and-identities.md +10 -18
- package/docs/mcp/go-live.md +12 -12
- package/docs/mcp/overview.md +10 -10
- package/docs/mcp/setup.md +9 -9
- package/docs/mcp/shape.md +4 -3
- package/docs/mcp/tools.md +61 -61
- package/docs/plugins.md +2 -2
- package/docs/quickstart.md +5 -6
- package/package.json +10 -155
- package/src/config/apitogo-config-core.ts +5 -1
- package/src/config/gateway-limits.ts +7 -2
- package/src/config/loader.ts +5 -7
- package/src/config/local-manifest.ts +7 -7
- package/src/config/resolve-modules.ts +5 -7
- package/src/lib/authentication/auth-header-nav.ts +3 -3
- package/src/lib/authentication/providers/dev-portal-auth-pages.tsx +2 -5
- package/src/lib/authentication/state.ts +1 -1
- package/src/lib/components/Layout.tsx +1 -4
- package/src/lib/components/SiteTitle.tsx +3 -1
- package/src/lib/plugins/openapi/processors/injectApitogoGatewayServer.ts +9 -3
- package/src/vite/config.ts +0 -21
- package/src/vite/plugin-api.ts +1 -1
- package/src/vite/plugin-modules.ts +1 -2
- package/src/vite/plugin-offroot-resolve.ts +2 -6
package/dist/cli/cli.js
CHANGED
|
@@ -212,7 +212,9 @@ function mergeLimitsSource(prior, patch) {
|
|
|
212
212
|
return planForConfig(merged);
|
|
213
213
|
}
|
|
214
214
|
function planLimitsForPlatform(plan) {
|
|
215
|
-
return stringifyGatewayLimits(
|
|
215
|
+
return stringifyGatewayLimits(
|
|
216
|
+
coerceGatewayLimits(plan)
|
|
217
|
+
);
|
|
216
218
|
}
|
|
217
219
|
function validateLimitsField(value, field) {
|
|
218
220
|
if (value == null || value === "") {
|
|
@@ -1176,8 +1178,8 @@ async function readEffectiveManifest(rootDir, _env) {
|
|
|
1176
1178
|
var BillingPeriodSchema, GatewayLimitsSchema, PriceCurrencySchema, ALLOWED_RUNTIME_VERSIONS, ManifestPlanInputSchema, DevPortalLocalManifestSchema;
|
|
1177
1179
|
var init_local_manifest = __esm({
|
|
1178
1180
|
"src/config/local-manifest.ts"() {
|
|
1179
|
-
init_gateway_limits();
|
|
1180
1181
|
init_apitogo_config_loader();
|
|
1182
|
+
init_gateway_limits();
|
|
1181
1183
|
init_landing_manifest();
|
|
1182
1184
|
BillingPeriodSchema = z4.enum(["month", "year", "monthly", "annual"]);
|
|
1183
1185
|
GatewayLimitsSchema = z4.object({
|
|
@@ -1503,10 +1505,7 @@ var init_resolve_modules = __esm({
|
|
|
1503
1505
|
codeExample: content?.hero?.codeExample ?? defaults.hero?.codeExample,
|
|
1504
1506
|
titleAccent: content?.hero?.titleAccent ?? (content?.hero?.title ? void 0 : defaults.hero?.titleAccent)
|
|
1505
1507
|
},
|
|
1506
|
-
featuresSection:
|
|
1507
|
-
defaults.featuresSection,
|
|
1508
|
-
content?.featuresSection
|
|
1509
|
-
),
|
|
1508
|
+
featuresSection: defaults.featuresSection || content?.featuresSection ? { ...defaults.featuresSection, ...content?.featuresSection } : void 0,
|
|
1510
1509
|
features: content?.features ?? defaults.features,
|
|
1511
1510
|
primaryAction: content?.primaryAction ?? defaults.primaryAction,
|
|
1512
1511
|
secondaryAction: content?.secondaryAction ?? defaults.secondaryAction,
|
|
@@ -1534,7 +1533,7 @@ var init_resolve_modules = __esm({
|
|
|
1534
1533
|
...content.hero,
|
|
1535
1534
|
title: content.hero?.title ?? siteTitle
|
|
1536
1535
|
},
|
|
1537
|
-
featuresSection: content.featuresSection
|
|
1536
|
+
featuresSection: content.featuresSection,
|
|
1538
1537
|
features: content.features,
|
|
1539
1538
|
primaryAction: content.primaryAction,
|
|
1540
1539
|
secondaryAction: content.secondaryAction,
|
|
@@ -5063,7 +5062,7 @@ async function loadZudokuConfigWithMeta(rootDir) {
|
|
|
5063
5062
|
dependencies,
|
|
5064
5063
|
configPath
|
|
5065
5064
|
},
|
|
5066
|
-
__resolvedModules: resolveModulesConfig(config2
|
|
5065
|
+
__resolvedModules: resolveModulesConfig(config2)
|
|
5067
5066
|
};
|
|
5068
5067
|
return configWithMetadata;
|
|
5069
5068
|
}
|
|
@@ -5094,9 +5093,7 @@ function isWatchableConfigDependency(depPath) {
|
|
|
5094
5093
|
return !depPath.startsWith("\0virtual:") && !depPath.startsWith("virtual:");
|
|
5095
5094
|
}
|
|
5096
5095
|
function getWatchableConfigDependencies(config2) {
|
|
5097
|
-
const manifestEnv = resolveManifestEnv(
|
|
5098
|
-
config2.__meta.mode === "production" ? "production" : "development"
|
|
5099
|
-
);
|
|
5096
|
+
const manifestEnv = resolveManifestEnv("development");
|
|
5100
5097
|
const { watchPaths } = manifestPathsForEnv(
|
|
5101
5098
|
config2.__meta.rootDir,
|
|
5102
5099
|
manifestEnv
|
|
@@ -5175,9 +5172,7 @@ async function loadZudokuConfig(configEnv, rootDir) {
|
|
|
5175
5172
|
...transformedConfig.__meta,
|
|
5176
5173
|
...configWithManifestMeta.__meta
|
|
5177
5174
|
},
|
|
5178
|
-
__resolvedModules: resolveModulesConfig(transformedConfig
|
|
5179
|
-
rootDir: transformedConfig.__meta.rootDir
|
|
5180
|
-
})
|
|
5175
|
+
__resolvedModules: resolveModulesConfig(transformedConfig)
|
|
5181
5176
|
};
|
|
5182
5177
|
if (!process.env.APITOGO_JSON_ONLY) {
|
|
5183
5178
|
logger.info(
|
|
@@ -5802,7 +5797,7 @@ import {
|
|
|
5802
5797
|
// package.json
|
|
5803
5798
|
var package_default = {
|
|
5804
5799
|
name: "@lukoweb/apitogo",
|
|
5805
|
-
version: "0.1.
|
|
5800
|
+
version: "0.1.126",
|
|
5806
5801
|
type: "module",
|
|
5807
5802
|
sideEffects: [
|
|
5808
5803
|
"**/*.css",
|
|
@@ -9864,10 +9859,6 @@ function vitePlugin() {
|
|
|
9864
9859
|
}
|
|
9865
9860
|
|
|
9866
9861
|
// src/vite/config.ts
|
|
9867
|
-
var browserConfigLoaderPath2 = path26.join(
|
|
9868
|
-
getZudokuRootDir(),
|
|
9869
|
-
"src/config/apitogo-config-loader.browser.ts"
|
|
9870
|
-
);
|
|
9871
9862
|
var resolveMergedPublicDir = (rootDir, merged) => {
|
|
9872
9863
|
if (merged.publicDir === false) return void 0;
|
|
9873
9864
|
const rel = typeof merged.publicDir === "string" ? merged.publicDir : "public";
|
|
@@ -9925,22 +9916,6 @@ async function getViteConfig(dir, configEnv) {
|
|
|
9925
9916
|
"@mdx-js/react": import.meta.resolve("@mdx-js/react")
|
|
9926
9917
|
}
|
|
9927
9918
|
},
|
|
9928
|
-
environments: {
|
|
9929
|
-
client: {
|
|
9930
|
-
resolve: {
|
|
9931
|
-
alias: {
|
|
9932
|
-
[path26.join(
|
|
9933
|
-
getZudokuRootDir(),
|
|
9934
|
-
"src/config/apitogo-config-loader.node.ts"
|
|
9935
|
-
)]: browserConfigLoaderPath2,
|
|
9936
|
-
[path26.join(
|
|
9937
|
-
getZudokuRootDir(),
|
|
9938
|
-
"src/config/apitogo-config-loader.node.js"
|
|
9939
|
-
)]: browserConfigLoaderPath2
|
|
9940
|
-
}
|
|
9941
|
-
}
|
|
9942
|
-
}
|
|
9943
|
-
},
|
|
9944
9919
|
define: {
|
|
9945
9920
|
"process.env.ZUDOKU_VERSION": JSON.stringify(package_default.version),
|
|
9946
9921
|
"process.env.IS_ZUPLO": ZuploEnv.isZuplo,
|
|
@@ -10689,7 +10664,9 @@ async function build(argv) {
|
|
|
10689
10664
|
const packageJson3 = getZudokuPackageJson();
|
|
10690
10665
|
const jsonOnly = argv.jsonOnly === true || process.env.APITOGO_JSON_ONLY === "1";
|
|
10691
10666
|
if (!jsonOnly) {
|
|
10692
|
-
printDiagnosticsToConsole(
|
|
10667
|
+
printDiagnosticsToConsole(
|
|
10668
|
+
`Starting API ToGo build v${packageJson3.version}`
|
|
10669
|
+
);
|
|
10693
10670
|
printDiagnosticsToConsole("");
|
|
10694
10671
|
printDiagnosticsToConsole("");
|
|
10695
10672
|
}
|
|
@@ -11795,11 +11772,16 @@ function applyManifestToConfig(config2, manifest) {
|
|
|
11795
11772
|
const site = next.site ?? {};
|
|
11796
11773
|
site.title = title;
|
|
11797
11774
|
if (manifest.branding?.logoUrl) {
|
|
11775
|
+
const existingLogo = site.logo ?? {};
|
|
11776
|
+
const existingSrc = existingLogo.src ?? {};
|
|
11798
11777
|
site.logo = {
|
|
11799
|
-
...
|
|
11778
|
+
...existingLogo,
|
|
11779
|
+
// Platform branding only stores a single logo — only override the
|
|
11780
|
+
// light slot so an existing dark-mode asset (e.g. logo-dark.svg)
|
|
11781
|
+
// isn't clobbered.
|
|
11800
11782
|
src: {
|
|
11801
|
-
|
|
11802
|
-
|
|
11783
|
+
...existingSrc,
|
|
11784
|
+
light: manifest.branding.logoUrl
|
|
11803
11785
|
}
|
|
11804
11786
|
};
|
|
11805
11787
|
}
|
|
@@ -12176,7 +12158,14 @@ async function writeManifest(siteDirectory, manifest) {
|
|
|
12176
12158
|
}
|
|
12177
12159
|
|
|
12178
12160
|
// src/cli/platform/helpers/dev-portal-secrets.ts
|
|
12179
|
-
import {
|
|
12161
|
+
import {
|
|
12162
|
+
access as access2,
|
|
12163
|
+
appendFile,
|
|
12164
|
+
mkdir as mkdir7,
|
|
12165
|
+
readFile as readFile7,
|
|
12166
|
+
unlink,
|
|
12167
|
+
writeFile as writeFile8
|
|
12168
|
+
} from "node:fs/promises";
|
|
12180
12169
|
import path37 from "node:path";
|
|
12181
12170
|
var ENV_FILENAME = ".env";
|
|
12182
12171
|
var COLLAPSED_UPPERCASE_ALIASES2 = {
|
|
@@ -12236,7 +12225,7 @@ function parseEnvValue2(raw) {
|
|
|
12236
12225
|
return trimmed;
|
|
12237
12226
|
}
|
|
12238
12227
|
function resolveExistingKey2(target, key) {
|
|
12239
|
-
if (Object.
|
|
12228
|
+
if (Object.hasOwn(target, key)) {
|
|
12240
12229
|
return key;
|
|
12241
12230
|
}
|
|
12242
12231
|
const lower = key.toLowerCase();
|
|
@@ -12299,7 +12288,10 @@ async function loadSiteEnv(siteDirectory) {
|
|
|
12299
12288
|
const resolvedDirectory = path37.resolve(siteDirectory);
|
|
12300
12289
|
const merged = { ...process.env };
|
|
12301
12290
|
for (const fileName of [ENV_FILENAME, ".env.local"]) {
|
|
12302
|
-
Object.assign(
|
|
12291
|
+
Object.assign(
|
|
12292
|
+
merged,
|
|
12293
|
+
await readEnvFile(path37.join(resolvedDirectory, fileName))
|
|
12294
|
+
);
|
|
12303
12295
|
}
|
|
12304
12296
|
return merged;
|
|
12305
12297
|
}
|
|
@@ -12385,7 +12377,11 @@ function getSecretsStatus(siteDirectory, manifest, secrets, envExists) {
|
|
|
12385
12377
|
};
|
|
12386
12378
|
}
|
|
12387
12379
|
function validateSecretsForPublish(manifest, secrets, emailOptions) {
|
|
12388
|
-
const prerequisites = getPublishPrerequisites(
|
|
12380
|
+
const prerequisites = getPublishPrerequisites(
|
|
12381
|
+
manifest,
|
|
12382
|
+
secrets,
|
|
12383
|
+
emailOptions
|
|
12384
|
+
);
|
|
12389
12385
|
if (prerequisites.readyToPublish) {
|
|
12390
12386
|
return;
|
|
12391
12387
|
}
|
|
@@ -12411,7 +12407,11 @@ async function resolvePublishConfig(siteDirectory, emailOptions) {
|
|
|
12411
12407
|
const env = await loadSiteEnv(resolvedDirectory);
|
|
12412
12408
|
const secrets = readAuthenticationSecretsFromEnv(env);
|
|
12413
12409
|
const envExists = await siteEnvFileHasEntries(resolvedDirectory);
|
|
12414
|
-
const publishPrerequisites = getPublishPrerequisites(
|
|
12410
|
+
const publishPrerequisites = getPublishPrerequisites(
|
|
12411
|
+
manifestRaw,
|
|
12412
|
+
secrets,
|
|
12413
|
+
emailOptions
|
|
12414
|
+
);
|
|
12415
12415
|
const secretsStatus = getSecretsStatus(
|
|
12416
12416
|
resolvedDirectory,
|
|
12417
12417
|
manifestRaw,
|
|
@@ -12487,13 +12487,15 @@ var writeScaffoldSecretsArtifacts = writeScaffoldEnv;
|
|
|
12487
12487
|
var SECRETS_COLLECTION_INSTRUCTION = "For go-live, plans must already be in apitogo.config.json \u2014 ask the user what plans they want before calling update_dev_portal_manifest; never add Free+Pro defaults unless they explicitly request them. The user must save auth secrets (OIDC provider secrets, and Stripe if paid plans) in .env using APITOGO_CONFIG_AUTHENTICATION__* keys. Native auth email is provisioned by the platform \u2014 do not ask for an ACS connection string. Share .env and required fields from publishPrerequisites.missingFields. Never ask for or accept secret values in chat. When the user confirms secrets are saved locally, call check_dev_portal_publish_readiness, then publish_dev_portal.";
|
|
12488
12488
|
|
|
12489
12489
|
// src/cli/platform/helpers/dev-portal-site-validation.ts
|
|
12490
|
+
init_gateway_limits();
|
|
12490
12491
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
12491
12492
|
import { createRequire as createRequire2 } from "node:module";
|
|
12492
12493
|
import path38 from "node:path";
|
|
12493
|
-
init_gateway_limits();
|
|
12494
12494
|
var cachedFallbackTs;
|
|
12495
12495
|
async function loadTypeScriptForSite(sourceDirectory) {
|
|
12496
|
-
const require2 = createRequire2(
|
|
12496
|
+
const require2 = createRequire2(
|
|
12497
|
+
path38.join(path38.resolve(sourceDirectory), "package.json")
|
|
12498
|
+
);
|
|
12497
12499
|
try {
|
|
12498
12500
|
return require2("typescript");
|
|
12499
12501
|
} catch {
|
|
@@ -12520,11 +12522,12 @@ function checkTsxSyntax(ts, fileName, content) {
|
|
|
12520
12522
|
}
|
|
12521
12523
|
});
|
|
12522
12524
|
return (result.diagnostics ?? []).filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error).map((diagnostic) => {
|
|
12523
|
-
const message = ts.flattenDiagnosticMessageText(
|
|
12525
|
+
const message = ts.flattenDiagnosticMessageText(
|
|
12526
|
+
diagnostic.messageText,
|
|
12527
|
+
" "
|
|
12528
|
+
);
|
|
12524
12529
|
if (diagnostic.file && diagnostic.start !== void 0) {
|
|
12525
|
-
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
|
|
12526
|
-
diagnostic.start
|
|
12527
|
-
);
|
|
12530
|
+
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
12528
12531
|
return `${message} (line ${line + 1}, column ${character + 1})`;
|
|
12529
12532
|
}
|
|
12530
12533
|
return message;
|
|
@@ -12537,7 +12540,9 @@ async function referencedFileExists(sourceDirectory, reference) {
|
|
|
12537
12540
|
if (/^https?:\/\//i.test(reference)) {
|
|
12538
12541
|
return true;
|
|
12539
12542
|
}
|
|
12540
|
-
return pathExists(
|
|
12543
|
+
return pathExists(
|
|
12544
|
+
path38.resolve(sourceDirectory, reference.replace(/^\.\//, ""))
|
|
12545
|
+
);
|
|
12541
12546
|
}
|
|
12542
12547
|
async function validateSiteConfigStructure(config2, sourceDirectory) {
|
|
12543
12548
|
const errors = [];
|
|
@@ -12561,7 +12566,9 @@ async function validateSiteConfigStructure(config2, sourceDirectory) {
|
|
|
12561
12566
|
if (!item) {
|
|
12562
12567
|
errors.push(`"navigation[${index}]" must be an object.`);
|
|
12563
12568
|
} else if (typeof item.type !== "string" || !item.type.trim()) {
|
|
12564
|
-
errors.push(
|
|
12569
|
+
errors.push(
|
|
12570
|
+
`"navigation[${index}].type" must be a non-empty string.`
|
|
12571
|
+
);
|
|
12565
12572
|
}
|
|
12566
12573
|
});
|
|
12567
12574
|
}
|
|
@@ -12580,7 +12587,9 @@ async function validateSiteConfigStructure(config2, sourceDirectory) {
|
|
|
12580
12587
|
if (typeof api.input !== "string" || !api.input.trim()) {
|
|
12581
12588
|
errors.push(`"apis[${index}].input" must be a non-empty string.`);
|
|
12582
12589
|
} else if (api.type === "file" && !await referencedFileExists(sourceDirectory, api.input)) {
|
|
12583
|
-
errors.push(
|
|
12590
|
+
errors.push(
|
|
12591
|
+
`"apis[${index}].input" points to a missing file: ${api.input}`
|
|
12592
|
+
);
|
|
12584
12593
|
}
|
|
12585
12594
|
if (typeof api.path !== "string" || !api.path.trim()) {
|
|
12586
12595
|
errors.push(`"apis[${index}].path" must be a non-empty string.`);
|
|
@@ -12593,7 +12602,9 @@ async function validateSiteConfigStructure(config2, sourceDirectory) {
|
|
|
12593
12602
|
const modules = asRecord2(root.modules);
|
|
12594
12603
|
const landing = asRecord2(modules?.landing);
|
|
12595
12604
|
if (typeof landing?.page === "string" && landing.page.trim() && !await referencedFileExists(sourceDirectory, landing.page)) {
|
|
12596
|
-
errors.push(
|
|
12605
|
+
errors.push(
|
|
12606
|
+
`"modules.landing.page" points to a missing file: ${landing.page}`
|
|
12607
|
+
);
|
|
12597
12608
|
}
|
|
12598
12609
|
const plansModule = asRecord2(asRecord2(modules?.userPanel)?.plans);
|
|
12599
12610
|
if (plansModule?.items !== void 0) {
|
|
@@ -12603,7 +12614,9 @@ async function validateSiteConfigStructure(config2, sourceDirectory) {
|
|
|
12603
12614
|
plansModule.items.forEach((entry, index) => {
|
|
12604
12615
|
const plan = asRecord2(entry);
|
|
12605
12616
|
if (!plan) {
|
|
12606
|
-
errors.push(
|
|
12617
|
+
errors.push(
|
|
12618
|
+
`"modules.userPanel.plans.items[${index}]" must be an object.`
|
|
12619
|
+
);
|
|
12607
12620
|
return;
|
|
12608
12621
|
}
|
|
12609
12622
|
if (typeof plan.sku !== "string" || !plan.sku.trim()) {
|
|
@@ -12662,7 +12675,10 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
|
|
|
12662
12675
|
});
|
|
12663
12676
|
}
|
|
12664
12677
|
if (!parseFailed) {
|
|
12665
|
-
const structureErrors = await validateSiteConfigStructure(
|
|
12678
|
+
const structureErrors = await validateSiteConfigStructure(
|
|
12679
|
+
parsed,
|
|
12680
|
+
resolvedDir
|
|
12681
|
+
);
|
|
12666
12682
|
issues.push(
|
|
12667
12683
|
...structureErrors.map((message) => ({
|
|
12668
12684
|
file: APITOGO_CONFIG_FILENAME2,
|
|
@@ -12689,7 +12705,10 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
|
|
|
12689
12705
|
} else {
|
|
12690
12706
|
for (const relativeFile of existingTsxFiles) {
|
|
12691
12707
|
checkedFiles.push(relativeFile);
|
|
12692
|
-
const content = await readFile8(
|
|
12708
|
+
const content = await readFile8(
|
|
12709
|
+
path38.join(resolvedDir, relativeFile),
|
|
12710
|
+
"utf8"
|
|
12711
|
+
);
|
|
12693
12712
|
issues.push(
|
|
12694
12713
|
...checkTsxSyntax(ts, relativeFile, content).map((message) => ({
|
|
12695
12714
|
file: relativeFile,
|
|
@@ -12745,7 +12764,9 @@ function parseNodeMajor(version) {
|
|
|
12745
12764
|
function assertNodeVersion(required) {
|
|
12746
12765
|
const major = parseNodeMajor(process.version);
|
|
12747
12766
|
if (Number.isNaN(major) || major < MIN_NODE_MAJOR) {
|
|
12748
|
-
throw new Error(
|
|
12767
|
+
throw new Error(
|
|
12768
|
+
`Node.js ${MIN_NODE_MAJOR}+ is required (current: ${process.version}).`
|
|
12769
|
+
);
|
|
12749
12770
|
}
|
|
12750
12771
|
if (required) {
|
|
12751
12772
|
const requiredMajor = parseNodeMajor(required);
|
|
@@ -13011,7 +13032,9 @@ function normalizeRuntime(runtime) {
|
|
|
13011
13032
|
if (raw === "dotnet" || raw === ".net" || raw === "net") return "dotnet";
|
|
13012
13033
|
if (raw === "nodejs" || raw === "node") return "nodejs";
|
|
13013
13034
|
if (raw === "python") return "python";
|
|
13014
|
-
throw new Error(
|
|
13035
|
+
throw new Error(
|
|
13036
|
+
`runtime must be one of: dotnet, nodejs, python; got '${runtime}'.`
|
|
13037
|
+
);
|
|
13015
13038
|
}
|
|
13016
13039
|
function normalizePlanForGatewayApi(plan) {
|
|
13017
13040
|
return {
|
|
@@ -13069,7 +13092,10 @@ function normalizeManifestForPlatform(manifest) {
|
|
|
13069
13092
|
}
|
|
13070
13093
|
}
|
|
13071
13094
|
if (backend.runtimeVersion) {
|
|
13072
|
-
const slug = normalizeRuntimeVersionSlug(
|
|
13095
|
+
const slug = normalizeRuntimeVersionSlug(
|
|
13096
|
+
backend.runtime,
|
|
13097
|
+
backend.runtimeVersion
|
|
13098
|
+
);
|
|
13073
13099
|
if (slug !== backend.runtimeVersion) {
|
|
13074
13100
|
corrections.push({
|
|
13075
13101
|
field: "backend.runtimeVersion",
|
|
@@ -13094,7 +13120,10 @@ function validateManifestForPlatformPublish(manifest) {
|
|
|
13094
13120
|
} else {
|
|
13095
13121
|
for (const [index, plan] of manifest.plans.entries()) {
|
|
13096
13122
|
if (!plan.sku?.trim()) {
|
|
13097
|
-
issues.push({
|
|
13123
|
+
issues.push({
|
|
13124
|
+
field: `plans[${index}].sku`,
|
|
13125
|
+
message: "sku is required."
|
|
13126
|
+
});
|
|
13098
13127
|
}
|
|
13099
13128
|
if (!plan.displayName?.trim()) {
|
|
13100
13129
|
issues.push({
|
|
@@ -13110,7 +13139,10 @@ function validateManifestForPlatformPublish(manifest) {
|
|
|
13110
13139
|
}
|
|
13111
13140
|
const currencyResult = tryNormalizePriceCurrency(plan.priceCurrency);
|
|
13112
13141
|
if (!currencyResult.ok) {
|
|
13113
|
-
issues.push({
|
|
13142
|
+
issues.push({
|
|
13143
|
+
field: `plans[${index}].priceCurrency`,
|
|
13144
|
+
message: currencyResult.message
|
|
13145
|
+
});
|
|
13114
13146
|
} else if ((plan.priceCurrency ?? "usd") !== currencyResult.value) {
|
|
13115
13147
|
corrections.push({
|
|
13116
13148
|
field: `plans[${index}].priceCurrency`,
|
|
@@ -13152,7 +13184,10 @@ function validateManifestForPlatformPublish(manifest) {
|
|
|
13152
13184
|
manifest.backend.runtimeVersion
|
|
13153
13185
|
);
|
|
13154
13186
|
if (!runtimeResult.ok) {
|
|
13155
|
-
issues.push({
|
|
13187
|
+
issues.push({
|
|
13188
|
+
field: "backend.runtimeVersion",
|
|
13189
|
+
message: runtimeResult.message
|
|
13190
|
+
});
|
|
13156
13191
|
} else if (runtimeResult.value !== manifest.backend.runtimeVersion) {
|
|
13157
13192
|
corrections.push({
|
|
13158
13193
|
field: "backend.runtimeVersion",
|
|
@@ -13320,9 +13355,143 @@ import path52 from "node:path";
|
|
|
13320
13355
|
import { stdin as input2 } from "node:process";
|
|
13321
13356
|
import { glob as glob5 } from "glob";
|
|
13322
13357
|
|
|
13358
|
+
// src/cli/platform/helpers/openapi-action-keys.ts
|
|
13359
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
13360
|
+
import path42 from "node:path";
|
|
13361
|
+
import YAML from "yaml";
|
|
13362
|
+
var HTTP_METHODS = [
|
|
13363
|
+
"get",
|
|
13364
|
+
"post",
|
|
13365
|
+
"put",
|
|
13366
|
+
"patch",
|
|
13367
|
+
"delete",
|
|
13368
|
+
"head",
|
|
13369
|
+
"options"
|
|
13370
|
+
];
|
|
13371
|
+
function normalizeOpenApiPathTemplate(pathTemplate) {
|
|
13372
|
+
if (!pathTemplate.trim()) {
|
|
13373
|
+
return "/";
|
|
13374
|
+
}
|
|
13375
|
+
let value = pathTemplate.trim();
|
|
13376
|
+
if (!value.startsWith("/")) {
|
|
13377
|
+
value = `/${value}`;
|
|
13378
|
+
}
|
|
13379
|
+
if (value.length > 1 && value.endsWith("/")) {
|
|
13380
|
+
value = value.replace(/\/+$/, "");
|
|
13381
|
+
}
|
|
13382
|
+
return value;
|
|
13383
|
+
}
|
|
13384
|
+
function resolveRelativeServerBasePath(document) {
|
|
13385
|
+
const serverUrl = document.servers?.[0]?.url;
|
|
13386
|
+
if (!serverUrl || serverUrl === "/") {
|
|
13387
|
+
return null;
|
|
13388
|
+
}
|
|
13389
|
+
return serverUrl.startsWith("/") ? serverUrl.replace(/\/+$/, "") : null;
|
|
13390
|
+
}
|
|
13391
|
+
function combineBasePath(basePath, pathKey) {
|
|
13392
|
+
const normalizedPath = normalizeOpenApiPathTemplate(pathKey);
|
|
13393
|
+
if (!basePath || basePath === "/") {
|
|
13394
|
+
return normalizedPath;
|
|
13395
|
+
}
|
|
13396
|
+
const baseNorm = normalizeOpenApiPathTemplate(basePath);
|
|
13397
|
+
if (normalizedPath === "/") {
|
|
13398
|
+
return baseNorm;
|
|
13399
|
+
}
|
|
13400
|
+
return `${baseNorm.replace(/\/+$/, "")}${normalizedPath}`;
|
|
13401
|
+
}
|
|
13402
|
+
function extractGatewayActionKeysFromOpenApiDocument(document) {
|
|
13403
|
+
if (!document || typeof document !== "object") {
|
|
13404
|
+
return [];
|
|
13405
|
+
}
|
|
13406
|
+
const spec = document;
|
|
13407
|
+
if (!spec.paths || typeof spec.paths !== "object") {
|
|
13408
|
+
return [];
|
|
13409
|
+
}
|
|
13410
|
+
const basePath = resolveRelativeServerBasePath(spec);
|
|
13411
|
+
const keys = /* @__PURE__ */ new Set();
|
|
13412
|
+
for (const [pathKey, pathItem] of Object.entries(spec.paths)) {
|
|
13413
|
+
if (!pathItem || typeof pathItem !== "object") {
|
|
13414
|
+
continue;
|
|
13415
|
+
}
|
|
13416
|
+
const pathTemplate = combineBasePath(basePath, pathKey);
|
|
13417
|
+
for (const method of HTTP_METHODS) {
|
|
13418
|
+
if (!pathItem[method] || typeof pathItem[method] !== "object") {
|
|
13419
|
+
continue;
|
|
13420
|
+
}
|
|
13421
|
+
keys.add(`${method}:${pathTemplate}`);
|
|
13422
|
+
}
|
|
13423
|
+
}
|
|
13424
|
+
return [...keys].sort((a, b) => a.localeCompare(b));
|
|
13425
|
+
}
|
|
13426
|
+
function extractGatewayActionKeysFromOpenApiFile(filePath) {
|
|
13427
|
+
try {
|
|
13428
|
+
const raw = readFileSync3(filePath, "utf8");
|
|
13429
|
+
const ext = path42.extname(filePath).toLowerCase();
|
|
13430
|
+
const parsed = ext === ".json" ? JSON.parse(raw) : YAML.parse(raw);
|
|
13431
|
+
return extractGatewayActionKeysFromOpenApiDocument(parsed);
|
|
13432
|
+
} catch {
|
|
13433
|
+
return [];
|
|
13434
|
+
}
|
|
13435
|
+
}
|
|
13436
|
+
function resolveConfigOpenApiFilePath(siteDirectory, config2) {
|
|
13437
|
+
const backend = config2.backend;
|
|
13438
|
+
const candidates = [];
|
|
13439
|
+
if (typeof backend?.openApiPath === "string" && backend.openApiPath.trim()) {
|
|
13440
|
+
candidates.push(backend.openApiPath.trim());
|
|
13441
|
+
}
|
|
13442
|
+
const apis = config2.apis;
|
|
13443
|
+
const entries = Array.isArray(apis) ? apis : apis ? [apis] : [];
|
|
13444
|
+
for (const entry of entries) {
|
|
13445
|
+
if (entry && typeof entry === "object" && entry.type === "file" && typeof entry.input === "string") {
|
|
13446
|
+
candidates.push(entry.input);
|
|
13447
|
+
}
|
|
13448
|
+
}
|
|
13449
|
+
for (const candidate of candidates) {
|
|
13450
|
+
const resolved = path42.isAbsolute(candidate) ? candidate : path42.resolve(siteDirectory, candidate);
|
|
13451
|
+
if (existsSync5(resolved)) {
|
|
13452
|
+
return resolved;
|
|
13453
|
+
}
|
|
13454
|
+
}
|
|
13455
|
+
return void 0;
|
|
13456
|
+
}
|
|
13457
|
+
function loadOpenApiActionKeysForSite(siteDirectory, config2) {
|
|
13458
|
+
const filePath = resolveConfigOpenApiFilePath(siteDirectory, config2);
|
|
13459
|
+
if (!filePath) {
|
|
13460
|
+
return [];
|
|
13461
|
+
}
|
|
13462
|
+
return extractGatewayActionKeysFromOpenApiFile(filePath);
|
|
13463
|
+
}
|
|
13464
|
+
function loadOpenApiActionKeysFromSiteDirectory(siteDirectory) {
|
|
13465
|
+
const configPath = path42.join(siteDirectory, "apitogo.config.json");
|
|
13466
|
+
if (!existsSync5(configPath)) {
|
|
13467
|
+
return [];
|
|
13468
|
+
}
|
|
13469
|
+
try {
|
|
13470
|
+
const parsed = JSON.parse(readFileSync3(configPath, "utf8"));
|
|
13471
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
13472
|
+
return [];
|
|
13473
|
+
}
|
|
13474
|
+
return loadOpenApiActionKeysForSite(
|
|
13475
|
+
siteDirectory,
|
|
13476
|
+
parsed
|
|
13477
|
+
);
|
|
13478
|
+
} catch {
|
|
13479
|
+
return [];
|
|
13480
|
+
}
|
|
13481
|
+
}
|
|
13482
|
+
function withDefaultIncludedActionKeys(plan, actionKeys) {
|
|
13483
|
+
if (plan.includedActionKeys && plan.includedActionKeys.length > 0) {
|
|
13484
|
+
return plan;
|
|
13485
|
+
}
|
|
13486
|
+
if (actionKeys.length === 0) {
|
|
13487
|
+
return plan;
|
|
13488
|
+
}
|
|
13489
|
+
return { ...plan, includedActionKeys: actionKeys };
|
|
13490
|
+
}
|
|
13491
|
+
|
|
13323
13492
|
// src/cli/scaffold/dev-portal-config-pages.ts
|
|
13324
13493
|
import { access as access4, readFile as readFile10, rename as rename2, rm as rm3, writeFile as writeFile9 } from "node:fs/promises";
|
|
13325
|
-
import
|
|
13494
|
+
import path43 from "node:path";
|
|
13326
13495
|
async function writeConfigAtomically(filePath, content) {
|
|
13327
13496
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
13328
13497
|
try {
|
|
@@ -13335,7 +13504,7 @@ async function writeConfigAtomically(filePath, content) {
|
|
|
13335
13504
|
}
|
|
13336
13505
|
async function resolveApitogoConfigPath(sourceDirectory) {
|
|
13337
13506
|
for (const filename of ["apitogo.config.tsx", "apitogo.config.jsx"]) {
|
|
13338
|
-
const configPath =
|
|
13507
|
+
const configPath = path43.join(sourceDirectory, filename);
|
|
13339
13508
|
try {
|
|
13340
13509
|
await access4(configPath);
|
|
13341
13510
|
return configPath;
|
|
@@ -13391,7 +13560,7 @@ function inlineMarkdownToJsx(text) {
|
|
|
13391
13560
|
const link = /^\[([^\]]+)\]\(([^)]+)\)$/.exec(token);
|
|
13392
13561
|
if (link) {
|
|
13393
13562
|
parts.push(
|
|
13394
|
-
`<a href={${JSON.stringify(link[2])}} className="text-primary underline">${jsxTextExpr(link[1])}</a>`
|
|
13563
|
+
`<a href={${JSON.stringify(link[2])}} className="text-primary underline">${jsxTextExpr(link[1] ?? "")}</a>`
|
|
13395
13564
|
);
|
|
13396
13565
|
} else {
|
|
13397
13566
|
parts.push(jsxTextExpr(token));
|
|
@@ -13476,9 +13645,9 @@ ${indent}</Callout>`
|
|
|
13476
13645
|
}
|
|
13477
13646
|
const tipQuote = /^>\s*\*\*(Tip|Note|Info|Caution|Danger):\*\*\s*(.*)$/i.exec(line.trim());
|
|
13478
13647
|
if (tipQuote) {
|
|
13479
|
-
const rawType = tipQuote[1].toLowerCase();
|
|
13648
|
+
const rawType = (tipQuote[1] ?? "").toLowerCase();
|
|
13480
13649
|
const type = CALLOUT_TYPES.has(rawType) ? rawType : "tip";
|
|
13481
|
-
const rest = tipQuote[2].trim();
|
|
13650
|
+
const rest = (tipQuote[2] ?? "").trim();
|
|
13482
13651
|
i += 1;
|
|
13483
13652
|
const more = rest ? [rest] : [];
|
|
13484
13653
|
while (i < lines.length && /^>\s*/.test(lines[i] ?? "")) {
|
|
@@ -13514,10 +13683,10 @@ ${indent}</pre>`
|
|
|
13514
13683
|
}
|
|
13515
13684
|
const heading = /^(#{1,3})\s+(.+)$/.exec(line);
|
|
13516
13685
|
if (heading) {
|
|
13517
|
-
const level = heading[1].length;
|
|
13686
|
+
const level = (heading[1] ?? "").length;
|
|
13518
13687
|
const className = level === 1 ? "text-foreground" : level === 2 ? "text-foreground" : "text-foreground";
|
|
13519
13688
|
blocks.push(
|
|
13520
|
-
`${indent}<Heading level={${level}} className="${className}">${inlineMarkdownToJsx(heading[2].trim())}</Heading>`
|
|
13689
|
+
`${indent}<Heading level={${level}} className="${className}">${inlineMarkdownToJsx((heading[2] ?? "").trim())}</Heading>`
|
|
13521
13690
|
);
|
|
13522
13691
|
i += 1;
|
|
13523
13692
|
continue;
|
|
@@ -13619,7 +13788,7 @@ function splitMarkdownByH2(content) {
|
|
|
13619
13788
|
if (current) {
|
|
13620
13789
|
sections.push(current);
|
|
13621
13790
|
}
|
|
13622
|
-
current = { title: h2[1].trim(), body: "" };
|
|
13791
|
+
current = { title: (h2[1] ?? "").trim(), body: "" };
|
|
13623
13792
|
continue;
|
|
13624
13793
|
}
|
|
13625
13794
|
if (current) {
|
|
@@ -13901,7 +14070,10 @@ function appendEntryToArrayRange(content, range, entry) {
|
|
|
13901
14070
|
const after = content.slice(range.close);
|
|
13902
14071
|
const trimmedBefore = before.trimEnd();
|
|
13903
14072
|
const needsComma = !trimmedBefore.endsWith("[") && !trimmedBefore.endsWith(",");
|
|
13904
|
-
const closeIndent = range.indent.slice(
|
|
14073
|
+
const closeIndent = range.indent.slice(
|
|
14074
|
+
0,
|
|
14075
|
+
Math.max(0, range.indent.length - 2)
|
|
14076
|
+
);
|
|
13905
14077
|
return `${trimmedBefore}${needsComma ? "," : ""}
|
|
13906
14078
|
${entry}
|
|
13907
14079
|
${closeIndent}${after}`;
|
|
@@ -13909,7 +14081,10 @@ ${closeIndent}${after}`;
|
|
|
13909
14081
|
function prependEntryToArrayRange(content, range, entry) {
|
|
13910
14082
|
const inner = content.slice(range.open + 1, range.close);
|
|
13911
14083
|
const trimmedInner = inner.trim();
|
|
13912
|
-
const closeIndent = range.indent.slice(
|
|
14084
|
+
const closeIndent = range.indent.slice(
|
|
14085
|
+
0,
|
|
14086
|
+
Math.max(0, range.indent.length - 2)
|
|
14087
|
+
);
|
|
13913
14088
|
const normalizedEntry = entry.trimEnd().endsWith(",") ? entry.trimEnd() : `${entry.trimEnd()},`;
|
|
13914
14089
|
if (!trimmedInner) {
|
|
13915
14090
|
return `${content.slice(0, range.open + 1)}
|
|
@@ -14027,7 +14202,11 @@ function appendCustomPageToNavigation(content, slug, label, _options) {
|
|
|
14027
14202
|
if (content.includes(`path: ${pagePath}`)) {
|
|
14028
14203
|
return content;
|
|
14029
14204
|
}
|
|
14030
|
-
const rewrittenBuildExport = appendCustomPageToDirectBuildExport(
|
|
14205
|
+
const rewrittenBuildExport = appendCustomPageToDirectBuildExport(
|
|
14206
|
+
content,
|
|
14207
|
+
slug,
|
|
14208
|
+
label
|
|
14209
|
+
);
|
|
14031
14210
|
if (rewrittenBuildExport) {
|
|
14032
14211
|
return rewrittenBuildExport;
|
|
14033
14212
|
}
|
|
@@ -14035,12 +14214,24 @@ function appendCustomPageToNavigation(content, slug, label, _options) {
|
|
|
14035
14214
|
if (!range) {
|
|
14036
14215
|
return content;
|
|
14037
14216
|
}
|
|
14038
|
-
const docsItems = findDocumentationCategoryItemsRange(
|
|
14217
|
+
const docsItems = findDocumentationCategoryItemsRange(
|
|
14218
|
+
content,
|
|
14219
|
+
range.open,
|
|
14220
|
+
range.close
|
|
14221
|
+
);
|
|
14039
14222
|
if (docsItems) {
|
|
14040
|
-
const entry = formatCustomPageNavigationEntry(
|
|
14223
|
+
const entry = formatCustomPageNavigationEntry(
|
|
14224
|
+
slug,
|
|
14225
|
+
label,
|
|
14226
|
+
docsItems.indent
|
|
14227
|
+
);
|
|
14041
14228
|
return appendEntryToArrayRange(content, docsItems, entry);
|
|
14042
14229
|
}
|
|
14043
|
-
const category = formatDocumentationCategoryWithPage(
|
|
14230
|
+
const category = formatDocumentationCategoryWithPage(
|
|
14231
|
+
slug,
|
|
14232
|
+
label,
|
|
14233
|
+
`${range.indent} `
|
|
14234
|
+
);
|
|
14044
14235
|
return prependEntryToArrayRange(
|
|
14045
14236
|
content,
|
|
14046
14237
|
{ open: range.open, close: range.close, indent: `${range.indent} ` },
|
|
@@ -14048,7 +14239,12 @@ function appendCustomPageToNavigation(content, slug, label, _options) {
|
|
|
14048
14239
|
);
|
|
14049
14240
|
}
|
|
14050
14241
|
function patchApitogoConfigForNewPage(content, slug, label, options) {
|
|
14051
|
-
const withNavigation = appendCustomPageToNavigation(
|
|
14242
|
+
const withNavigation = appendCustomPageToNavigation(
|
|
14243
|
+
content,
|
|
14244
|
+
slug,
|
|
14245
|
+
label,
|
|
14246
|
+
options
|
|
14247
|
+
);
|
|
14052
14248
|
if (withNavigation === content) {
|
|
14053
14249
|
return content;
|
|
14054
14250
|
}
|
|
@@ -14072,17 +14268,17 @@ async function wireNewDevPortalPageInConfig(sourceDirectory, slug, label) {
|
|
|
14072
14268
|
|
|
14073
14269
|
// src/cli/scaffold/wire-openapi.ts
|
|
14074
14270
|
import { access as access6, readFile as readFile12, writeFile as writeFile11 } from "node:fs/promises";
|
|
14075
|
-
import
|
|
14271
|
+
import path48 from "node:path";
|
|
14076
14272
|
|
|
14077
14273
|
// src/cli/platform/helpers/openapi.ts
|
|
14078
14274
|
import { promises as fs6 } from "node:fs";
|
|
14079
|
-
import
|
|
14275
|
+
import path45 from "node:path";
|
|
14080
14276
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
14081
|
-
import
|
|
14277
|
+
import YAML2 from "yaml";
|
|
14082
14278
|
|
|
14083
14279
|
// src/cli/scaffold/discover-openapi-files.ts
|
|
14084
14280
|
import { promises as fs5 } from "node:fs";
|
|
14085
|
-
import
|
|
14281
|
+
import path44 from "node:path";
|
|
14086
14282
|
var OPENAPI_BASENAMES = [
|
|
14087
14283
|
"openapi.yaml",
|
|
14088
14284
|
"openapi.yml",
|
|
@@ -14104,13 +14300,13 @@ var SKIP_OPENAPI_SEARCH_DIRS = /* @__PURE__ */ new Set([
|
|
|
14104
14300
|
".apitogo"
|
|
14105
14301
|
]);
|
|
14106
14302
|
async function collectFromDir(dir, searchedDirectories, candidates) {
|
|
14107
|
-
const resolved =
|
|
14303
|
+
const resolved = path44.resolve(dir);
|
|
14108
14304
|
if (searchedDirectories.includes(resolved)) {
|
|
14109
14305
|
return;
|
|
14110
14306
|
}
|
|
14111
14307
|
searchedDirectories.push(resolved);
|
|
14112
14308
|
for (const name of OPENAPI_BASENAMES) {
|
|
14113
|
-
const candidate =
|
|
14309
|
+
const candidate = path44.join(resolved, name);
|
|
14114
14310
|
try {
|
|
14115
14311
|
await fs5.access(candidate);
|
|
14116
14312
|
candidates.push(candidate);
|
|
@@ -14125,8 +14321,8 @@ async function collectSiteOpenApiFiles(siteDirectory) {
|
|
|
14125
14321
|
return { candidates: [...new Set(candidates)], searchedDirectories };
|
|
14126
14322
|
}
|
|
14127
14323
|
async function collectNearbyOpenApiFiles(siteDirectory) {
|
|
14128
|
-
const site =
|
|
14129
|
-
const parent =
|
|
14324
|
+
const site = path44.resolve(siteDirectory);
|
|
14325
|
+
const parent = path44.dirname(site);
|
|
14130
14326
|
const searchedDirectories = [];
|
|
14131
14327
|
const candidates = [];
|
|
14132
14328
|
if (parent && parent !== site) {
|
|
@@ -14137,8 +14333,8 @@ async function collectNearbyOpenApiFiles(siteDirectory) {
|
|
|
14137
14333
|
if (!entry.isDirectory() || SKIP_OPENAPI_SEARCH_DIRS.has(entry.name)) {
|
|
14138
14334
|
continue;
|
|
14139
14335
|
}
|
|
14140
|
-
const sibling =
|
|
14141
|
-
if (
|
|
14336
|
+
const sibling = path44.join(parent, entry.name);
|
|
14337
|
+
if (path44.resolve(sibling) === site) {
|
|
14142
14338
|
continue;
|
|
14143
14339
|
}
|
|
14144
14340
|
await collectFromDir(sibling, searchedDirectories, candidates);
|
|
@@ -14166,7 +14362,7 @@ function parseOpenApiObject(doc) {
|
|
|
14166
14362
|
};
|
|
14167
14363
|
}
|
|
14168
14364
|
function liteParseOpenApi(content, filePath) {
|
|
14169
|
-
const ext =
|
|
14365
|
+
const ext = path44.extname(filePath).toLowerCase();
|
|
14170
14366
|
if (ext === ".json") {
|
|
14171
14367
|
try {
|
|
14172
14368
|
const parsed = JSON.parse(content);
|
|
@@ -14231,12 +14427,12 @@ async function discoverNearbyOpenApi(siteDirectory) {
|
|
|
14231
14427
|
};
|
|
14232
14428
|
}
|
|
14233
14429
|
async function validateOpenApiFile(filePath) {
|
|
14234
|
-
const resolved =
|
|
14430
|
+
const resolved = path45.resolve(filePath);
|
|
14235
14431
|
const content = await fs6.readFile(resolved, "utf8");
|
|
14236
|
-
const ext =
|
|
14432
|
+
const ext = path45.extname(resolved).toLowerCase();
|
|
14237
14433
|
let parsed;
|
|
14238
14434
|
try {
|
|
14239
|
-
parsed = ext === ".json" ? JSON.parse(content) :
|
|
14435
|
+
parsed = ext === ".json" ? JSON.parse(content) : YAML2.parse(content);
|
|
14240
14436
|
} catch (err) {
|
|
14241
14437
|
return {
|
|
14242
14438
|
valid: false,
|
|
@@ -14276,12 +14472,7 @@ async function validateOpenApiFile(filePath) {
|
|
|
14276
14472
|
|
|
14277
14473
|
// src/cli/scaffold/scaffold-dev-portal-site.ts
|
|
14278
14474
|
import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile10 } from "node:fs/promises";
|
|
14279
|
-
import
|
|
14280
|
-
|
|
14281
|
-
// src/cli/scaffold/create-apitogo-cli.ts
|
|
14282
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
14283
|
-
import { access as access5, rm as rm4 } from "node:fs/promises";
|
|
14284
|
-
import path45 from "node:path";
|
|
14475
|
+
import path47 from "node:path";
|
|
14285
14476
|
|
|
14286
14477
|
// src/cli/scaffold/apitogo-npm-packages.ts
|
|
14287
14478
|
var DEFAULT_CREATE_APITOGO_PACKAGE2 = "@lukoweb/create-apitogo@latest";
|
|
@@ -14367,6 +14558,9 @@ var DOC_TOOL_LOCAL_PACKAGE_PATHS = {
|
|
|
14367
14558
|
};
|
|
14368
14559
|
|
|
14369
14560
|
// src/cli/scaffold/create-apitogo-cli.ts
|
|
14561
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
14562
|
+
import { access as access5, rm as rm4 } from "node:fs/promises";
|
|
14563
|
+
import path46 from "node:path";
|
|
14370
14564
|
var CreateApitogoCliError = class extends Error {
|
|
14371
14565
|
exitCode;
|
|
14372
14566
|
log;
|
|
@@ -14382,9 +14576,9 @@ function resolveDocToolPath(explicit) {
|
|
|
14382
14576
|
return value || void 0;
|
|
14383
14577
|
}
|
|
14384
14578
|
function splitOutputDirectory(outputDirectory) {
|
|
14385
|
-
const resolvedOutputDirectory =
|
|
14386
|
-
const projectName =
|
|
14387
|
-
const parentDirectory =
|
|
14579
|
+
const resolvedOutputDirectory = path46.resolve(outputDirectory);
|
|
14580
|
+
const projectName = path46.basename(resolvedOutputDirectory);
|
|
14581
|
+
const parentDirectory = path46.dirname(resolvedOutputDirectory);
|
|
14388
14582
|
if (!projectName || projectName === "." || projectName === "..") {
|
|
14389
14583
|
throw new Error(
|
|
14390
14584
|
"outputDirectory must be a named folder (e.g. ./dev-portal-site), not the current directory."
|
|
@@ -14410,7 +14604,7 @@ async function directoryHasEntries(dir) {
|
|
|
14410
14604
|
}
|
|
14411
14605
|
}
|
|
14412
14606
|
function resolveLocalCreateApitogoEntry(docToolPath) {
|
|
14413
|
-
return
|
|
14607
|
+
return path46.resolve(docToolPath, "packages/create-zudoku/dist/index.js");
|
|
14414
14608
|
}
|
|
14415
14609
|
async function resolveCreateApitogoInvocation(options) {
|
|
14416
14610
|
const docToolPath = resolveDocToolPath(options.docToolPath);
|
|
@@ -14492,7 +14686,7 @@ async function runCreateApitogoDevPortal(options) {
|
|
|
14492
14686
|
result.exitCode
|
|
14493
14687
|
);
|
|
14494
14688
|
}
|
|
14495
|
-
if (!await pathExists3(
|
|
14689
|
+
if (!await pathExists3(path46.join(resolvedOutputDirectory, "package.json"))) {
|
|
14496
14690
|
throw new CreateApitogoCliError(
|
|
14497
14691
|
`create-apitogo completed but package.json was not found at ${resolvedOutputDirectory}`,
|
|
14498
14692
|
result.output,
|
|
@@ -14541,14 +14735,17 @@ function ensureRequiredApitogoModules(pkg, options) {
|
|
|
14541
14735
|
const moduleAliasVersion = resolveApitogoModuleVersionFromCore(coreVersion);
|
|
14542
14736
|
for (const [moduleName, localPath] of [
|
|
14543
14737
|
[landing, DOC_TOOL_LOCAL_PACKAGE_PATHS["@lukoweb/apitogo-module-landing"]],
|
|
14544
|
-
[
|
|
14738
|
+
[
|
|
14739
|
+
userPanel,
|
|
14740
|
+
DOC_TOOL_LOCAL_PACKAGE_PATHS["@lukoweb/apitogo-module-user-panel"]
|
|
14741
|
+
],
|
|
14545
14742
|
[
|
|
14546
14743
|
billing,
|
|
14547
14744
|
DOC_TOOL_LOCAL_PACKAGE_PATHS["@lukoweb/apitogo-plugin-dev-portal-billing"]
|
|
14548
14745
|
]
|
|
14549
14746
|
]) {
|
|
14550
14747
|
if (options.docToolPath) {
|
|
14551
|
-
deps[moduleName] = `file:${
|
|
14748
|
+
deps[moduleName] = `file:${path47.join(options.docToolPath, localPath)}`;
|
|
14552
14749
|
continue;
|
|
14553
14750
|
}
|
|
14554
14751
|
deps[moduleName] = `npm:${moduleName}@${moduleAliasVersion}`;
|
|
@@ -14575,9 +14772,11 @@ function rewritePackageJson(raw, options) {
|
|
|
14575
14772
|
for (const section of ["dependencies", "devDependencies"]) {
|
|
14576
14773
|
const deps = pkg[section];
|
|
14577
14774
|
if (!deps) continue;
|
|
14578
|
-
for (const [dep, relativePath] of Object.entries(
|
|
14775
|
+
for (const [dep, relativePath] of Object.entries(
|
|
14776
|
+
DOC_TOOL_LOCAL_PACKAGE_PATHS
|
|
14777
|
+
)) {
|
|
14579
14778
|
if (dep in deps) {
|
|
14580
|
-
deps[dep] = `file:${
|
|
14779
|
+
deps[dep] = `file:${path47.join(options.docToolPath, relativePath)}`;
|
|
14581
14780
|
linkedWorkspacePackage = true;
|
|
14582
14781
|
}
|
|
14583
14782
|
}
|
|
@@ -14634,7 +14833,10 @@ function patchApisConfig(content, config2) {
|
|
|
14634
14833
|
return insertApisConfig(content, config2);
|
|
14635
14834
|
}
|
|
14636
14835
|
const asArray = match[0].includes("apis: [");
|
|
14637
|
-
return content.replace(
|
|
14836
|
+
return content.replace(
|
|
14837
|
+
APIS_CONFIG_PATTERN,
|
|
14838
|
+
renderApisConfig(config2, asArray)
|
|
14839
|
+
);
|
|
14638
14840
|
}
|
|
14639
14841
|
function patchApitogoConfigOpenApiToFile(content, input5 = "./openapi.json") {
|
|
14640
14842
|
return patchApisConfig(content, {
|
|
@@ -14674,23 +14876,23 @@ function patchDashboardPageConfig(content) {
|
|
|
14674
14876
|
);
|
|
14675
14877
|
}
|
|
14676
14878
|
async function ensureAccountPlansPage(outputDirectory) {
|
|
14677
|
-
const pagePath =
|
|
14879
|
+
const pagePath = path47.join(outputDirectory, ACCOUNT_PLANS_PAGE_PATH);
|
|
14678
14880
|
try {
|
|
14679
14881
|
await readFile11(pagePath, "utf8");
|
|
14680
14882
|
return void 0;
|
|
14681
14883
|
} catch {
|
|
14682
|
-
await mkdir8(
|
|
14884
|
+
await mkdir8(path47.dirname(pagePath), { recursive: true });
|
|
14683
14885
|
await writeFile10(pagePath, ACCOUNT_PLANS_PAGE);
|
|
14684
14886
|
return ACCOUNT_PLANS_PAGE_PATH;
|
|
14685
14887
|
}
|
|
14686
14888
|
}
|
|
14687
14889
|
async function ensureDashboardPage(outputDirectory) {
|
|
14688
|
-
const pagePath =
|
|
14890
|
+
const pagePath = path47.join(outputDirectory, DASHBOARD_PAGE_PATH);
|
|
14689
14891
|
try {
|
|
14690
14892
|
await readFile11(pagePath, "utf8");
|
|
14691
14893
|
return void 0;
|
|
14692
14894
|
} catch {
|
|
14693
|
-
await mkdir8(
|
|
14895
|
+
await mkdir8(path47.dirname(pagePath), { recursive: true });
|
|
14694
14896
|
await writeFile10(pagePath, DASHBOARD_PAGE);
|
|
14695
14897
|
return DASHBOARD_PAGE_PATH;
|
|
14696
14898
|
}
|
|
@@ -14716,13 +14918,20 @@ function patchApitogoConfig(content, options) {
|
|
|
14716
14918
|
});
|
|
14717
14919
|
}
|
|
14718
14920
|
if (options.logoUrl) {
|
|
14719
|
-
|
|
14720
|
-
|
|
14921
|
+
const logoBlockRegex = /logo:\s*\{[\s\S]*?\},/m;
|
|
14922
|
+
const existingBlock = patched.match(logoBlockRegex)?.[0];
|
|
14923
|
+
if (existingBlock) {
|
|
14924
|
+
const darkMatch = existingBlock.match(/dark:\s*"([^"]*)"/);
|
|
14925
|
+
const darkLine = darkMatch ? `
|
|
14926
|
+
dark: "${darkMatch[1]}",` : "";
|
|
14927
|
+
patched = patched.replace(
|
|
14928
|
+
logoBlockRegex,
|
|
14929
|
+
`logo: {
|
|
14721
14930
|
src: {
|
|
14722
|
-
light: "${options.logoUrl}"
|
|
14723
|
-
dark: "${options.logoUrl}",
|
|
14931
|
+
light: "${options.logoUrl}",${darkLine}
|
|
14724
14932
|
},
|
|
14725
|
-
},`
|
|
14933
|
+
},`
|
|
14934
|
+
);
|
|
14726
14935
|
} else {
|
|
14727
14936
|
patched = patched.replace(
|
|
14728
14937
|
/site:\s*\{/,
|
|
@@ -14730,7 +14939,6 @@ function patchApitogoConfig(content, options) {
|
|
|
14730
14939
|
logo: {
|
|
14731
14940
|
src: {
|
|
14732
14941
|
light: "${options.logoUrl}",
|
|
14733
|
-
dark: "${options.logoUrl}",
|
|
14734
14942
|
},
|
|
14735
14943
|
},`
|
|
14736
14944
|
);
|
|
@@ -14741,7 +14949,7 @@ function patchApitogoConfig(content, options) {
|
|
|
14741
14949
|
async function patchScaffoldedSite(outputDirectory, options) {
|
|
14742
14950
|
const title = options.branding?.title ?? options.siteName;
|
|
14743
14951
|
const filesWritten = [];
|
|
14744
|
-
const packageJsonPath =
|
|
14952
|
+
const packageJsonPath = path47.join(outputDirectory, "package.json");
|
|
14745
14953
|
if (options.patchPackageJson !== false) {
|
|
14746
14954
|
const packageJson3 = await readFile11(packageJsonPath, "utf8");
|
|
14747
14955
|
await writeFile10(
|
|
@@ -14754,7 +14962,7 @@ async function patchScaffoldedSite(outputDirectory, options) {
|
|
|
14754
14962
|
);
|
|
14755
14963
|
filesWritten.push("package.json");
|
|
14756
14964
|
}
|
|
14757
|
-
const configPath =
|
|
14965
|
+
const configPath = path47.join(outputDirectory, "apitogo.config.tsx");
|
|
14758
14966
|
const configContent = await readFile11(configPath, "utf8");
|
|
14759
14967
|
await writeFile10(
|
|
14760
14968
|
configPath,
|
|
@@ -14849,8 +15057,8 @@ async function discoverOpenApiByMode(siteDirectory, mode) {
|
|
|
14849
15057
|
return discoverNearbyOpenApi(siteDirectory);
|
|
14850
15058
|
}
|
|
14851
15059
|
async function wireDevPortalOpenApi(sourceDirectory, openApiPath) {
|
|
14852
|
-
const resolvedSource =
|
|
14853
|
-
const resolvedOpenApi =
|
|
15060
|
+
const resolvedSource = path48.resolve(sourceDirectory);
|
|
15061
|
+
const resolvedOpenApi = path48.resolve(openApiPath);
|
|
14854
15062
|
const input5 = toSiteRelativeOpenApiInput(resolvedSource, resolvedOpenApi);
|
|
14855
15063
|
const validation = await validateOpenApiFile(resolvedOpenApi);
|
|
14856
15064
|
if (!validation.valid) {
|
|
@@ -14875,7 +15083,7 @@ async function wireDevPortalOpenApi(sourceDirectory, openApiPath) {
|
|
|
14875
15083
|
"utf8"
|
|
14876
15084
|
);
|
|
14877
15085
|
} else {
|
|
14878
|
-
const tsxConfigPath =
|
|
15086
|
+
const tsxConfigPath = path48.join(resolvedSource, "apitogo.config.tsx");
|
|
14879
15087
|
const configContent = await readFile12(tsxConfigPath, "utf8");
|
|
14880
15088
|
try {
|
|
14881
15089
|
const patched = patchApitogoConfigOpenApiToFile(configContent, input5);
|
|
@@ -14961,12 +15169,12 @@ async function discoverAndWireOpenApi(siteDirectory, mode) {
|
|
|
14961
15169
|
}
|
|
14962
15170
|
|
|
14963
15171
|
// src/cli/make-config/interactive.ts
|
|
14964
|
-
import
|
|
15172
|
+
import path50 from "node:path";
|
|
14965
15173
|
import { stdin as input, stdout as output } from "node:process";
|
|
14966
|
-
import
|
|
15174
|
+
import { createInterface } from "node:readline/promises";
|
|
14967
15175
|
|
|
14968
15176
|
// src/cli/make-config/json-config.ts
|
|
14969
|
-
import
|
|
15177
|
+
import path49 from "node:path";
|
|
14970
15178
|
|
|
14971
15179
|
// src/cli/make-config/branding-assets.ts
|
|
14972
15180
|
var LOGO_LIGHT = '<svg xmlns="http://www.w3.org/2000/svg" width="201.57" height="72.66" viewBox="-0.09 -46.99 201.57 72.66">\n <path d="M13.5 0.39Q8.03 0.39 4.76 -2.09Q1.48 -4.57 1.41 -9.61H8.03Q8.14 -7.48 9.6 -6.41Q11.05 -5.33 13.42 -5.33Q15.57 -5.33 16.8 -6.2Q18.03 -7.07 18.03 -8.46Q18.03 -9.71 16.87 -10.44Q15.7 -11.17 13.32 -11.72L10.23 -12.44Q6.46 -13.3 4.32 -15.25Q2.17 -17.21 2.17 -20.49Q2.17 -23.18 3.62 -25.21Q5.08 -27.23 7.64 -28.36Q10.2 -29.49 13.5 -29.49Q16.88 -29.49 19.36 -28.35Q21.84 -27.21 23.2 -25.17Q24.57 -23.12 24.61 -20.43H17.99Q17.85 -22.01 16.7 -22.89Q15.55 -23.77 13.48 -23.77Q11.41 -23.77 10.35 -22.97Q9.3 -22.17 9.3 -20.96Q9.3 -19.61 10.47 -18.88Q11.64 -18.14 13.59 -17.71L16.11 -17.13Q20.33 -16.19 22.67 -14.06Q25 -11.93 25 -8.44Q25 -4.3 21.95 -1.95Q18.91 0.39 13.5 0.39Z M32.97 0.39Q29.82 0.39 27.8 -1.21Q25.78 -2.81 25.78 -6.05Q25.78 -8.48 26.89 -9.9Q28 -11.33 29.85 -12.01Q31.7 -12.7 33.9 -12.89Q36.68 -13.12 37.88 -13.47Q39.08 -13.81 39.08 -14.82V-14.9Q39.08 -16.04 38.29 -16.65Q37.5 -17.27 36.11 -17.27Q34.68 -17.27 33.77 -16.66Q32.85 -16.05 32.58 -15.02L26.4 -15.82Q27.05 -18.61 29.56 -20.36Q32.07 -22.11 36.17 -22.11Q38.88 -22.11 41.08 -21.27Q43.28 -20.43 44.58 -18.8Q45.88 -17.17 45.88 -14.82V0H39.47V-3.07H39.29Q37.48 0.39 32.97 0.39ZM35.04 -4.12Q36.75 -4.12 37.95 -5.14Q39.14 -6.15 39.14 -7.77V-9.86Q38.55 -9.55 37.44 -9.34Q36.33 -9.12 35.37 -8.96Q32.22 -8.5 32.22 -6.37Q32.22 -5.27 33.01 -4.7Q33.81 -4.12 35.04 -4.12Z M48.59 0V-21.84H54.86L55.17 -17.5Q56.07 -19.96 57.78 -21.04Q59.49 -22.13 61.46 -22.13Q63.53 -22.13 64.91 -20.94Q66.28 -19.75 67.08 -17.07Q68.08 -19.77 70.02 -20.95Q71.97 -22.13 74.17 -22.13Q77.24 -22.13 79.2 -20.16Q81.17 -18.18 81.17 -14.73V0H74.37V-13.18Q74.37 -14.84 73.5 -15.7Q72.63 -16.56 71.28 -16.56Q69.84 -16.56 69 -15.62Q68.16 -14.67 68.16 -13.11V0H61.61V-13.28Q61.61 -14.79 60.77 -15.67Q59.92 -16.56 58.57 -16.56Q57.18 -16.56 56.29 -15.62Q55.4 -14.69 55.4 -12.97V0Z M83.88 8.16V-21.84H90.62V-18.09H90.85Q91.26 -19.06 92.04 -19.99Q92.82 -20.92 94.05 -21.51Q95.28 -22.11 97.02 -22.11Q99.33 -22.11 101.31 -20.9Q103.29 -19.69 104.51 -17.21Q105.73 -14.73 105.73 -10.9Q105.73 -7.19 104.55 -4.7Q103.37 -2.21 101.39 -0.95Q99.4 0.31 96.98 0.31Q94.48 0.31 92.99 -0.87Q91.49 -2.05 90.85 -3.54H90.69V8.16ZM94.66 -5Q96.63 -5 97.68 -6.62Q98.72 -8.24 98.72 -10.9Q98.72 -13.55 97.68 -15.17Q96.63 -16.78 94.66 -16.78Q92.71 -16.78 91.62 -15.2Q90.54 -13.61 90.54 -10.9Q90.54 -8.22 91.62 -6.61Q92.71 -5 94.66 -5Z M114.4 -29.1V0H107.59V-29.1Z M127.29 0.41Q122.15 0.41 119.21 -2.59Q116.27 -5.59 116.27 -10.84Q116.27 -14.2 117.59 -16.74Q118.91 -19.28 121.33 -20.69Q123.75 -22.11 127.04 -22.11Q130.1 -22.11 132.47 -20.83Q134.85 -19.55 136.21 -17.06Q137.56 -14.57 137.56 -10.98V-9.26H122.97Q123.07 -6.89 124.27 -5.71Q125.47 -4.53 127.41 -4.53Q128.77 -4.53 129.77 -5.11Q130.77 -5.68 131.18 -6.78L137.25 -5.78Q136.43 -2.95 133.84 -1.27Q131.25 0.41 127.29 0.41ZM123.01 -13.22H131.1Q130.9 -15.08 129.89 -16.12Q128.87 -17.17 127.09 -17.17Q125.3 -17.17 124.25 -16.1Q123.21 -15.04 123.01 -13.22Z" fill="#202633"/>\n <path d="M138.48 0 148.19 -29.1H157.43L167.43 0H159.69L157.72 -6.19H148.03L146.14 0ZM149.65 -11.46H156.04L155.65 -12.71Q154.89 -15.21 154.16 -17.95Q153.44 -20.68 152.74 -23.61Q152.07 -20.66 151.42 -17.93Q150.77 -15.2 150.04 -12.71Z M168.81 0V-29.1H180.72Q184 -29.1 186.39 -27.83Q188.77 -26.56 190.05 -24.3Q191.33 -22.03 191.33 -19.04Q191.33 -16.04 190.02 -13.8Q188.71 -11.56 186.29 -10.32Q183.87 -9.08 180.53 -9.08H175.7V0ZM175.7 -14.53H179.28Q181.7 -14.53 182.94 -15.77Q184.18 -17.01 184.18 -19.04Q184.18 -21.09 182.93 -22.3Q181.68 -23.52 179.26 -23.52H175.7Z M199.98 -29.1V0H193.08V-29.1Z" fill="#008A7D"/>\n</svg>\n';
|
|
@@ -15345,9 +15553,9 @@ function openapiInputForConfig(specRelativePosix) {
|
|
|
15345
15553
|
return `./${specRelativePosix}`;
|
|
15346
15554
|
}
|
|
15347
15555
|
function toRelativeOpenApiInput(projectDir, inputPath) {
|
|
15348
|
-
const resolved =
|
|
15349
|
-
const relative =
|
|
15350
|
-
const posix = relative.split(
|
|
15556
|
+
const resolved = path49.isAbsolute(inputPath) ? inputPath : path49.resolve(projectDir, inputPath);
|
|
15557
|
+
const relative = path49.relative(projectDir, resolved);
|
|
15558
|
+
const posix = relative.split(path49.sep).join(path49.posix.sep);
|
|
15351
15559
|
if (!posix) {
|
|
15352
15560
|
throw new Error("OpenAPI path must point to a file.");
|
|
15353
15561
|
}
|
|
@@ -15550,11 +15758,11 @@ ${customPages}
|
|
|
15550
15758
|
// src/cli/make-config/wrap-up.ts
|
|
15551
15759
|
var DOCS = "https://docs.apitogo.com";
|
|
15552
15760
|
function printPageAddedHint(relativePath, routePath) {
|
|
15553
|
-
printDiagnosticsToConsole(`Page created: ${relativePath} (route ${routePath})`);
|
|
15554
|
-
printDiagnosticsToConsole("Edit that file to change the content.");
|
|
15555
15761
|
printDiagnosticsToConsole(
|
|
15556
|
-
`
|
|
15762
|
+
`Page created: ${relativePath} (route ${routePath})`
|
|
15557
15763
|
);
|
|
15764
|
+
printDiagnosticsToConsole("Edit that file to change the content.");
|
|
15765
|
+
printDiagnosticsToConsole(`Predefined components: ${DOCS}/docs/components`);
|
|
15558
15766
|
}
|
|
15559
15767
|
function printPlanAddedHint(displayName) {
|
|
15560
15768
|
printDiagnosticsToConsole(
|
|
@@ -15584,9 +15792,13 @@ function printInteractiveWrapUp(hasPaidPlans) {
|
|
|
15584
15792
|
printDiagnosticsToConsole("");
|
|
15585
15793
|
printDiagnosticsToConsole("Configure more:");
|
|
15586
15794
|
printDiagnosticsToConsole(`- Overview: ${DOCS}/docs/configuration/overview`);
|
|
15587
|
-
printDiagnosticsToConsole(
|
|
15795
|
+
printDiagnosticsToConsole(
|
|
15796
|
+
`- Gateway plans: ${DOCS}/docs/configuration/plans`
|
|
15797
|
+
);
|
|
15588
15798
|
printDiagnosticsToConsole(`- Custom pages: ${DOCS}/docs/guides/custom-pages`);
|
|
15589
|
-
printDiagnosticsToConsole(
|
|
15799
|
+
printDiagnosticsToConsole(
|
|
15800
|
+
`- API reference: ${DOCS}/docs/configuration/api-reference`
|
|
15801
|
+
);
|
|
15590
15802
|
printDiagnosticsToConsole(`- Theme: ${DOCS}/docs/customization/colors-theme`);
|
|
15591
15803
|
printDiagnosticsToConsole(`- Fonts: ${DOCS}/docs/customization/fonts`);
|
|
15592
15804
|
printDiagnosticsToConsole(`- CLI shape: ${DOCS}/docs/cli/shape`);
|
|
@@ -15672,9 +15884,7 @@ async function promptMakeConfigInteractive(options) {
|
|
|
15672
15884
|
);
|
|
15673
15885
|
runtimeVersion = parseRuntimeVersion(runtime, versionRaw);
|
|
15674
15886
|
if (!runtimeVersion) {
|
|
15675
|
-
printDiagnosticsToConsole(
|
|
15676
|
-
`Choose one of: ${versions.join(", ")}.`
|
|
15677
|
-
);
|
|
15887
|
+
printDiagnosticsToConsole(`Choose one of: ${versions.join(", ")}.`);
|
|
15678
15888
|
}
|
|
15679
15889
|
}
|
|
15680
15890
|
const backend = {
|
|
@@ -15720,7 +15930,7 @@ async function promptMakeConfigInteractive(options) {
|
|
|
15720
15930
|
continue;
|
|
15721
15931
|
}
|
|
15722
15932
|
const routePath = `/${slug}`;
|
|
15723
|
-
const relativePath =
|
|
15933
|
+
const relativePath = path50.posix.join(options.pagesDir, `${slug}.tsx`);
|
|
15724
15934
|
const page = {
|
|
15725
15935
|
slug,
|
|
15726
15936
|
title: pageTitle.trim(),
|
|
@@ -15813,7 +16023,7 @@ export default function ${componentName}() {
|
|
|
15813
16023
|
init_package_json();
|
|
15814
16024
|
import { constants } from "node:fs";
|
|
15815
16025
|
import { access as access7, mkdir as mkdir9, readFile as readFile13, writeFile as writeFile12 } from "node:fs/promises";
|
|
15816
|
-
import
|
|
16026
|
+
import path51 from "node:path";
|
|
15817
16027
|
import { glob as glob4 } from "glob";
|
|
15818
16028
|
|
|
15819
16029
|
// src/cli/make-config/favicon-png.ts
|
|
@@ -15828,9 +16038,9 @@ var OPENAPI_GLOBS = [
|
|
|
15828
16038
|
"openapi.yaml",
|
|
15829
16039
|
"openapi.yml"
|
|
15830
16040
|
];
|
|
15831
|
-
var toPosix = (p) => p.split(
|
|
16041
|
+
var toPosix = (p) => p.split(path51.sep).join("/");
|
|
15832
16042
|
var sanitizePackageName = (dir) => {
|
|
15833
|
-
const base =
|
|
16043
|
+
const base = path51.basename(path51.resolve(dir));
|
|
15834
16044
|
const s = base.toLowerCase().replace(/[^a-z0-9-_.]/g, "-").replace(/^-+|-+$/g, "");
|
|
15835
16045
|
return s || "apitogo-site";
|
|
15836
16046
|
};
|
|
@@ -15840,7 +16050,7 @@ var apitogoVersionRange = () => {
|
|
|
15840
16050
|
};
|
|
15841
16051
|
async function findOpenApiSpecPath(dir) {
|
|
15842
16052
|
for (const rel of OPENAPI_GLOBS) {
|
|
15843
|
-
const full =
|
|
16053
|
+
const full = path51.join(dir, rel);
|
|
15844
16054
|
try {
|
|
15845
16055
|
await access7(full, constants.R_OK);
|
|
15846
16056
|
return toPosix(rel);
|
|
@@ -15855,7 +16065,7 @@ async function findOpenApiSpecPath(dir) {
|
|
|
15855
16065
|
return extra[0] ? toPosix(extra[0]) : null;
|
|
15856
16066
|
}
|
|
15857
16067
|
async function ensurePackageJson(dir) {
|
|
15858
|
-
const pkgPath =
|
|
16068
|
+
const pkgPath = path51.join(dir, "package.json");
|
|
15859
16069
|
const apitogoVer = apitogoVersionRange();
|
|
15860
16070
|
const baseDeps = {
|
|
15861
16071
|
react: ">=19.0.0",
|
|
@@ -15922,7 +16132,7 @@ async function ensurePackageJson(dir) {
|
|
|
15922
16132
|
return false;
|
|
15923
16133
|
}
|
|
15924
16134
|
async function ensureTsconfigJson(dir) {
|
|
15925
|
-
const tsPath =
|
|
16135
|
+
const tsPath = path51.join(dir, "tsconfig.json");
|
|
15926
16136
|
try {
|
|
15927
16137
|
await access7(tsPath, constants.R_OK);
|
|
15928
16138
|
return false;
|
|
@@ -15971,40 +16181,40 @@ var fileExists2 = async (filePath) => {
|
|
|
15971
16181
|
}
|
|
15972
16182
|
};
|
|
15973
16183
|
async function ensurePortalStubFiles(dir) {
|
|
15974
|
-
const landingPath =
|
|
16184
|
+
const landingPath = path51.join(dir, "landing", "LandingPage.tsx");
|
|
15975
16185
|
if (!await fileExists2(landingPath)) {
|
|
15976
|
-
await mkdir9(
|
|
16186
|
+
await mkdir9(path51.join(dir, "landing"), { recursive: true });
|
|
15977
16187
|
await writeFile12(landingPath, LANDING_PAGE_SOURCE, "utf8");
|
|
15978
16188
|
}
|
|
15979
|
-
const plansPath =
|
|
16189
|
+
const plansPath = path51.join(dir, "user-panel", "AccountPlansPage.tsx");
|
|
15980
16190
|
if (!await fileExists2(plansPath)) {
|
|
15981
|
-
await mkdir9(
|
|
16191
|
+
await mkdir9(path51.join(dir, "user-panel"), { recursive: true });
|
|
15982
16192
|
await writeFile12(plansPath, ACCOUNT_PLANS_PAGE_SOURCE, "utf8");
|
|
15983
16193
|
}
|
|
15984
|
-
const dashboardPath =
|
|
16194
|
+
const dashboardPath = path51.join(dir, "user-panel", "DashboardPage.tsx");
|
|
15985
16195
|
if (!await fileExists2(dashboardPath)) {
|
|
15986
|
-
await mkdir9(
|
|
16196
|
+
await mkdir9(path51.join(dir, "user-panel"), { recursive: true });
|
|
15987
16197
|
await writeFile12(dashboardPath, DASHBOARD_PAGE_SOURCE, "utf8");
|
|
15988
16198
|
}
|
|
15989
16199
|
await ensurePublicBrandingFiles(dir);
|
|
15990
16200
|
}
|
|
15991
16201
|
async function ensurePublicBrandingFiles(dir) {
|
|
15992
|
-
const destDir =
|
|
16202
|
+
const destDir = path51.join(dir, "public");
|
|
15993
16203
|
await mkdir9(destDir, { recursive: true });
|
|
15994
16204
|
for (const { name, content } of BRANDING_ASSETS) {
|
|
15995
|
-
const dest =
|
|
16205
|
+
const dest = path51.join(destDir, name);
|
|
15996
16206
|
if (await fileExists2(dest)) {
|
|
15997
16207
|
continue;
|
|
15998
16208
|
}
|
|
15999
16209
|
await writeFile12(dest, content, "utf8");
|
|
16000
16210
|
}
|
|
16001
|
-
const faviconDest =
|
|
16211
|
+
const faviconDest = path51.join(destDir, "Icon.png");
|
|
16002
16212
|
if (!await fileExists2(faviconDest)) {
|
|
16003
16213
|
await writeFile12(faviconDest, Buffer.from(FAVICON_PNG_BASE64, "base64"));
|
|
16004
16214
|
}
|
|
16005
16215
|
}
|
|
16006
16216
|
async function ensureThinConfigTsx(dir) {
|
|
16007
|
-
const tsxPath =
|
|
16217
|
+
const tsxPath = path51.join(dir, "apitogo.config.tsx");
|
|
16008
16218
|
if (await fileExists2(tsxPath)) {
|
|
16009
16219
|
return false;
|
|
16010
16220
|
}
|
|
@@ -16012,137 +16222,6 @@ async function ensureThinConfigTsx(dir) {
|
|
|
16012
16222
|
return true;
|
|
16013
16223
|
}
|
|
16014
16224
|
|
|
16015
|
-
// src/cli/platform/helpers/openapi-action-keys.ts
|
|
16016
|
-
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "node:fs";
|
|
16017
|
-
import path51 from "node:path";
|
|
16018
|
-
import YAML2 from "yaml";
|
|
16019
|
-
var HTTP_METHODS = [
|
|
16020
|
-
"get",
|
|
16021
|
-
"post",
|
|
16022
|
-
"put",
|
|
16023
|
-
"patch",
|
|
16024
|
-
"delete",
|
|
16025
|
-
"head",
|
|
16026
|
-
"options"
|
|
16027
|
-
];
|
|
16028
|
-
function normalizeOpenApiPathTemplate(pathTemplate) {
|
|
16029
|
-
if (!pathTemplate.trim()) {
|
|
16030
|
-
return "/";
|
|
16031
|
-
}
|
|
16032
|
-
let value = pathTemplate.trim();
|
|
16033
|
-
if (!value.startsWith("/")) {
|
|
16034
|
-
value = `/${value}`;
|
|
16035
|
-
}
|
|
16036
|
-
if (value.length > 1 && value.endsWith("/")) {
|
|
16037
|
-
value = value.replace(/\/+$/, "");
|
|
16038
|
-
}
|
|
16039
|
-
return value;
|
|
16040
|
-
}
|
|
16041
|
-
function resolveRelativeServerBasePath(document) {
|
|
16042
|
-
const serverUrl = document.servers?.[0]?.url;
|
|
16043
|
-
if (!serverUrl || serverUrl === "/") {
|
|
16044
|
-
return null;
|
|
16045
|
-
}
|
|
16046
|
-
return serverUrl.startsWith("/") ? serverUrl.replace(/\/+$/, "") : null;
|
|
16047
|
-
}
|
|
16048
|
-
function combineBasePath(basePath, pathKey) {
|
|
16049
|
-
const normalizedPath = normalizeOpenApiPathTemplate(pathKey);
|
|
16050
|
-
if (!basePath || basePath === "/") {
|
|
16051
|
-
return normalizedPath;
|
|
16052
|
-
}
|
|
16053
|
-
const baseNorm = normalizeOpenApiPathTemplate(basePath);
|
|
16054
|
-
if (normalizedPath === "/") {
|
|
16055
|
-
return baseNorm;
|
|
16056
|
-
}
|
|
16057
|
-
return `${baseNorm.replace(/\/+$/, "")}${normalizedPath}`;
|
|
16058
|
-
}
|
|
16059
|
-
function extractGatewayActionKeysFromOpenApiDocument(document) {
|
|
16060
|
-
if (!document || typeof document !== "object") {
|
|
16061
|
-
return [];
|
|
16062
|
-
}
|
|
16063
|
-
const spec = document;
|
|
16064
|
-
if (!spec.paths || typeof spec.paths !== "object") {
|
|
16065
|
-
return [];
|
|
16066
|
-
}
|
|
16067
|
-
const basePath = resolveRelativeServerBasePath(spec);
|
|
16068
|
-
const keys = /* @__PURE__ */ new Set();
|
|
16069
|
-
for (const [pathKey, pathItem] of Object.entries(spec.paths)) {
|
|
16070
|
-
if (!pathItem || typeof pathItem !== "object") {
|
|
16071
|
-
continue;
|
|
16072
|
-
}
|
|
16073
|
-
const pathTemplate = combineBasePath(basePath, pathKey);
|
|
16074
|
-
for (const method of HTTP_METHODS) {
|
|
16075
|
-
if (!pathItem[method] || typeof pathItem[method] !== "object") {
|
|
16076
|
-
continue;
|
|
16077
|
-
}
|
|
16078
|
-
keys.add(`${method}:${pathTemplate}`);
|
|
16079
|
-
}
|
|
16080
|
-
}
|
|
16081
|
-
return [...keys].sort((a, b) => a.localeCompare(b));
|
|
16082
|
-
}
|
|
16083
|
-
function extractGatewayActionKeysFromOpenApiFile(filePath) {
|
|
16084
|
-
try {
|
|
16085
|
-
const raw = readFileSync3(filePath, "utf8");
|
|
16086
|
-
const ext = path51.extname(filePath).toLowerCase();
|
|
16087
|
-
const parsed = ext === ".json" ? JSON.parse(raw) : YAML2.parse(raw);
|
|
16088
|
-
return extractGatewayActionKeysFromOpenApiDocument(parsed);
|
|
16089
|
-
} catch {
|
|
16090
|
-
return [];
|
|
16091
|
-
}
|
|
16092
|
-
}
|
|
16093
|
-
function resolveConfigOpenApiFilePath(siteDirectory, config2) {
|
|
16094
|
-
const backend = config2.backend;
|
|
16095
|
-
const candidates = [];
|
|
16096
|
-
if (typeof backend?.openApiPath === "string" && backend.openApiPath.trim()) {
|
|
16097
|
-
candidates.push(backend.openApiPath.trim());
|
|
16098
|
-
}
|
|
16099
|
-
const apis = config2.apis;
|
|
16100
|
-
const entries = Array.isArray(apis) ? apis : apis ? [apis] : [];
|
|
16101
|
-
for (const entry of entries) {
|
|
16102
|
-
if (entry && typeof entry === "object" && entry.type === "file" && typeof entry.input === "string") {
|
|
16103
|
-
candidates.push(entry.input);
|
|
16104
|
-
}
|
|
16105
|
-
}
|
|
16106
|
-
for (const candidate of candidates) {
|
|
16107
|
-
const resolved = path51.isAbsolute(candidate) ? candidate : path51.resolve(siteDirectory, candidate);
|
|
16108
|
-
if (existsSync5(resolved)) {
|
|
16109
|
-
return resolved;
|
|
16110
|
-
}
|
|
16111
|
-
}
|
|
16112
|
-
return void 0;
|
|
16113
|
-
}
|
|
16114
|
-
function loadOpenApiActionKeysForSite(siteDirectory, config2) {
|
|
16115
|
-
const filePath = resolveConfigOpenApiFilePath(siteDirectory, config2);
|
|
16116
|
-
if (!filePath) {
|
|
16117
|
-
return [];
|
|
16118
|
-
}
|
|
16119
|
-
return extractGatewayActionKeysFromOpenApiFile(filePath);
|
|
16120
|
-
}
|
|
16121
|
-
function loadOpenApiActionKeysFromSiteDirectory(siteDirectory) {
|
|
16122
|
-
const configPath = path51.join(siteDirectory, "apitogo.config.json");
|
|
16123
|
-
if (!existsSync5(configPath)) {
|
|
16124
|
-
return [];
|
|
16125
|
-
}
|
|
16126
|
-
try {
|
|
16127
|
-
const parsed = JSON.parse(readFileSync3(configPath, "utf8"));
|
|
16128
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16129
|
-
return [];
|
|
16130
|
-
}
|
|
16131
|
-
return loadOpenApiActionKeysForSite(siteDirectory, parsed);
|
|
16132
|
-
} catch {
|
|
16133
|
-
return [];
|
|
16134
|
-
}
|
|
16135
|
-
}
|
|
16136
|
-
function withDefaultIncludedActionKeys(plan, actionKeys) {
|
|
16137
|
-
if (plan.includedActionKeys && plan.includedActionKeys.length > 0) {
|
|
16138
|
-
return plan;
|
|
16139
|
-
}
|
|
16140
|
-
if (actionKeys.length === 0) {
|
|
16141
|
-
return plan;
|
|
16142
|
-
}
|
|
16143
|
-
return { ...plan, includedActionKeys: actionKeys };
|
|
16144
|
-
}
|
|
16145
|
-
|
|
16146
16225
|
// src/cli/make-config/handler.ts
|
|
16147
16226
|
var toPosixPath2 = (value) => value.split(path52.sep).join(path52.posix.sep);
|
|
16148
16227
|
var fileExists3 = async (filePath) => {
|
|
@@ -16272,7 +16351,10 @@ async function makeConfig(argv) {
|
|
|
16272
16351
|
const flagPatches = {
|
|
16273
16352
|
site: parseJsonObjectFlag(argv.site, "site"),
|
|
16274
16353
|
theme: parseJsonObjectFlag(argv.theme, "theme"),
|
|
16275
|
-
authentication: parseJsonObjectFlag(
|
|
16354
|
+
authentication: parseJsonObjectFlag(
|
|
16355
|
+
argv.authentication,
|
|
16356
|
+
"authentication"
|
|
16357
|
+
),
|
|
16276
16358
|
title: argv.title
|
|
16277
16359
|
};
|
|
16278
16360
|
const persistCtx = {
|
|
@@ -16747,7 +16829,9 @@ async function sha256File(filePath) {
|
|
|
16747
16829
|
}
|
|
16748
16830
|
async function hashDirectoryContents(rootDirectory) {
|
|
16749
16831
|
const resolved = path54.resolve(rootDirectory);
|
|
16750
|
-
const files = (await collectPackageableFiles(resolved)).sort(
|
|
16832
|
+
const files = (await collectPackageableFiles(resolved)).sort(
|
|
16833
|
+
(a, b) => a.localeCompare(b)
|
|
16834
|
+
);
|
|
16751
16835
|
const hash2 = createHash2("sha256");
|
|
16752
16836
|
for (const rel of files) {
|
|
16753
16837
|
hash2.update(rel);
|
|
@@ -16820,7 +16904,9 @@ async function syncDevPortalPlanCatalog(options) {
|
|
|
16820
16904
|
signal: controller.signal
|
|
16821
16905
|
});
|
|
16822
16906
|
if (!response.ok) {
|
|
16823
|
-
throw new Error(
|
|
16907
|
+
throw new Error(
|
|
16908
|
+
`GET /api/v1/plans?refresh=true&force=true returned ${response.status}.`
|
|
16909
|
+
);
|
|
16824
16910
|
}
|
|
16825
16911
|
const catalog = await response.json();
|
|
16826
16912
|
if (options.expectedPlanCount !== void 0 && catalog.plans.length < options.expectedPlanCount) {
|
|
@@ -16954,7 +17040,10 @@ function arraysEquivalentForAuth(existing, desired) {
|
|
|
16954
17040
|
if (isPlatformManagedAuthMode(desired.authMode)) {
|
|
16955
17041
|
return true;
|
|
16956
17042
|
}
|
|
16957
|
-
return (existing.oidcMetadataUrl ?? "").trim() === (desired.oidcMetadataUrl ?? "").trim() && sameStringList(
|
|
17043
|
+
return (existing.oidcMetadataUrl ?? "").trim() === (desired.oidcMetadataUrl ?? "").trim() && sameStringList(
|
|
17044
|
+
existing.oidcAllowedIssuers,
|
|
17045
|
+
desired.oidcAllowedIssuers ?? void 0
|
|
17046
|
+
) && sameStringList(existing.oidcAudiences, desired.oidcAudiences ?? void 0);
|
|
16958
17047
|
}
|
|
16959
17048
|
async function ensureGatewayAuthConfigured(client, projectId, desired) {
|
|
16960
17049
|
let existing = null;
|
|
@@ -17003,7 +17092,7 @@ function normalizeActionKey(actionKey) {
|
|
|
17003
17092
|
if (trimmed.includes(":")) {
|
|
17004
17093
|
const [method2, ...pathParts] = trimmed.split(":");
|
|
17005
17094
|
const path73 = pathParts.join(":").trim();
|
|
17006
|
-
return `${method2
|
|
17095
|
+
return `${method2?.toLowerCase()}:${path73.startsWith("/") ? path73 : `/${path73}`}`;
|
|
17007
17096
|
}
|
|
17008
17097
|
const spaceIndex = trimmed.indexOf(" ");
|
|
17009
17098
|
if (spaceIndex <= 0) {
|
|
@@ -17024,12 +17113,16 @@ async function applyGatewayPublicRoutes(client, projectId, routes, options) {
|
|
|
17024
17113
|
}
|
|
17025
17114
|
let knownKeys = null;
|
|
17026
17115
|
if (options?.knownActions) {
|
|
17027
|
-
knownKeys = new Set(
|
|
17116
|
+
knownKeys = new Set(
|
|
17117
|
+
options.knownActions.map((action) => action.actionKey.toLowerCase())
|
|
17118
|
+
);
|
|
17028
17119
|
} else {
|
|
17029
17120
|
try {
|
|
17030
17121
|
const listed = await listAllGatewayActions(client, projectId);
|
|
17031
17122
|
if (listed.length > 0) {
|
|
17032
|
-
knownKeys = new Set(
|
|
17123
|
+
knownKeys = new Set(
|
|
17124
|
+
listed.map((action) => action.actionKey.toLowerCase())
|
|
17125
|
+
);
|
|
17033
17126
|
}
|
|
17034
17127
|
} catch {
|
|
17035
17128
|
knownKeys = null;
|
|
@@ -17054,7 +17147,11 @@ async function applyGatewayPublicRoutes(client, projectId, routes, options) {
|
|
|
17054
17147
|
continue;
|
|
17055
17148
|
}
|
|
17056
17149
|
try {
|
|
17057
|
-
const action = await client.setGatewayActionPublic(
|
|
17150
|
+
const action = await client.setGatewayActionPublic(
|
|
17151
|
+
projectId,
|
|
17152
|
+
actionKey,
|
|
17153
|
+
true
|
|
17154
|
+
);
|
|
17058
17155
|
applied.push(action);
|
|
17059
17156
|
} catch (error) {
|
|
17060
17157
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -17170,7 +17267,11 @@ async function handleConfigureGatewayBaseline(client, config2, args) {
|
|
|
17170
17267
|
oidcAudiences: args.oidcAudiences ?? null
|
|
17171
17268
|
};
|
|
17172
17269
|
try {
|
|
17173
|
-
ensured = await ensureGatewayAuthConfigured(
|
|
17270
|
+
ensured = await ensureGatewayAuthConfigured(
|
|
17271
|
+
client,
|
|
17272
|
+
projectId,
|
|
17273
|
+
desiredAuth
|
|
17274
|
+
);
|
|
17174
17275
|
} catch (error) {
|
|
17175
17276
|
const message = error instanceof Error ? error.message : String(error);
|
|
17176
17277
|
if (/EntraGateway|not configured|Graph permissions/i.test(message)) {
|
|
@@ -17197,7 +17298,11 @@ async function handleConfigureGatewayBaseline(client, config2, args) {
|
|
|
17197
17298
|
});
|
|
17198
17299
|
auth = entraWait.auth;
|
|
17199
17300
|
} else if (provisionStatus2 === "failed") {
|
|
17200
|
-
ensured = await ensureGatewayAuthConfigured(
|
|
17301
|
+
ensured = await ensureGatewayAuthConfigured(
|
|
17302
|
+
client,
|
|
17303
|
+
projectId,
|
|
17304
|
+
desiredAuth
|
|
17305
|
+
);
|
|
17201
17306
|
entraWait = await waitForGatewayEntraProvision(client, projectId, {
|
|
17202
17307
|
timeoutMs: args.timeoutMs,
|
|
17203
17308
|
pollIntervalMs: args.pollIntervalMs
|
|
@@ -17247,13 +17352,21 @@ async function handleConfigureGatewayBaseline(client, config2, args) {
|
|
|
17247
17352
|
if (normalizeLimits(settings.limitsJson) === normalizeLimits(limitsJson)) {
|
|
17248
17353
|
skippedSettings = true;
|
|
17249
17354
|
} else {
|
|
17250
|
-
settingsUpdated = await client.updateGatewaySettings(projectId, {
|
|
17355
|
+
settingsUpdated = await client.updateGatewaySettings(projectId, {
|
|
17356
|
+
limitsJson
|
|
17357
|
+
});
|
|
17251
17358
|
}
|
|
17252
17359
|
const healthKey = args.publicHealthActionKey ?? "get:/health";
|
|
17253
17360
|
const publicRoutes = [
|
|
17254
|
-
...new Set(
|
|
17361
|
+
...new Set(
|
|
17362
|
+
[...args.publicRoutes ?? [], healthKey].map((route) => route.trim()).filter(Boolean)
|
|
17363
|
+
)
|
|
17255
17364
|
];
|
|
17256
|
-
const publicRoutesResult = await applyGatewayPublicRoutes(
|
|
17365
|
+
const publicRoutesResult = await applyGatewayPublicRoutes(
|
|
17366
|
+
client,
|
|
17367
|
+
projectId,
|
|
17368
|
+
publicRoutes
|
|
17369
|
+
);
|
|
17257
17370
|
const healthAction = publicRoutesResult.applied.find(
|
|
17258
17371
|
(action) => action.actionKey.toLowerCase() === normalizeActionKey(healthKey).toLowerCase()
|
|
17259
17372
|
) ?? null;
|
|
@@ -17291,7 +17404,9 @@ async function handleConfigureGatewayBaseline(client, config2, args) {
|
|
|
17291
17404
|
// src/cli/platform/helpers/gateway-plan-sync.ts
|
|
17292
17405
|
function resolveIncludedActionKeysForUpsert(manifestPlan, existingPlan) {
|
|
17293
17406
|
if (manifestPlan.includedActionKeys !== void 0) {
|
|
17294
|
-
return manifestPlan.includedActionKeys.map(
|
|
17407
|
+
return manifestPlan.includedActionKeys.map(
|
|
17408
|
+
(key) => normalizeActionKey(key)
|
|
17409
|
+
);
|
|
17295
17410
|
}
|
|
17296
17411
|
if (existingPlan) {
|
|
17297
17412
|
return existingPlan.includedActions.map((action) => action.actionKey);
|
|
@@ -17299,7 +17414,10 @@ function resolveIncludedActionKeysForUpsert(manifestPlan, existingPlan) {
|
|
|
17299
17414
|
return [];
|
|
17300
17415
|
}
|
|
17301
17416
|
async function resolveActionKeysOrAllProjectActions(manifestPlan, existingPlan, getAllKeys) {
|
|
17302
|
-
const resolved = resolveIncludedActionKeysForUpsert(
|
|
17417
|
+
const resolved = resolveIncludedActionKeysForUpsert(
|
|
17418
|
+
manifestPlan,
|
|
17419
|
+
existingPlan
|
|
17420
|
+
);
|
|
17303
17421
|
if (resolved.length > 0) {
|
|
17304
17422
|
return resolved;
|
|
17305
17423
|
}
|
|
@@ -17313,7 +17431,9 @@ function buildGatewayPlanSortTargetsFromIds(manifestPlans, planIdsBySku, skuById
|
|
|
17313
17431
|
const key = input5.sku.toLowerCase();
|
|
17314
17432
|
const planId = planIdsBySku.get(key);
|
|
17315
17433
|
if (!planId) {
|
|
17316
|
-
throw new Error(
|
|
17434
|
+
throw new Error(
|
|
17435
|
+
`Gateway plan '${input5.sku}' was not found; upsert plans before reordering.`
|
|
17436
|
+
);
|
|
17317
17437
|
}
|
|
17318
17438
|
const sku = skuById?.get(key)?.sku ?? input5.sku;
|
|
17319
17439
|
targets.push({ planId, sku, sortOrder: index });
|
|
@@ -17399,7 +17519,11 @@ async function upsertGatewayPlansFromManifest(client, config2, projectId, plans,
|
|
|
17399
17519
|
projectActionKeys
|
|
17400
17520
|
);
|
|
17401
17521
|
}
|
|
17402
|
-
const patchedJson = await handlePatchGatewayPlan(
|
|
17522
|
+
const patchedJson = await handlePatchGatewayPlan(
|
|
17523
|
+
client,
|
|
17524
|
+
config2,
|
|
17525
|
+
patchArgs
|
|
17526
|
+
);
|
|
17403
17527
|
results.push(JSON.parse(patchedJson));
|
|
17404
17528
|
planIdsBySku.set(input5.sku.toLowerCase(), found.id);
|
|
17405
17529
|
continue;
|
|
@@ -17415,7 +17539,11 @@ async function upsertGatewayPlansFromManifest(client, config2, projectId, plans,
|
|
|
17415
17539
|
priceCurrency: input5.priceCurrency ?? "usd",
|
|
17416
17540
|
billingPeriod: normalizeBillingPeriod2(input5.billingPeriod),
|
|
17417
17541
|
limitsJson: planLimitsForPlatform(input5),
|
|
17418
|
-
includedActionKeys: options?.deferActionKeys ? [] : await resolveActionKeysOrAllProjectActions(
|
|
17542
|
+
includedActionKeys: options?.deferActionKeys ? [] : await resolveActionKeysOrAllProjectActions(
|
|
17543
|
+
input5,
|
|
17544
|
+
void 0,
|
|
17545
|
+
projectActionKeys
|
|
17546
|
+
),
|
|
17419
17547
|
skipDefaultActions: true,
|
|
17420
17548
|
sortOrder: index
|
|
17421
17549
|
});
|
|
@@ -17426,8 +17554,17 @@ async function upsertGatewayPlansFromManifest(client, config2, projectId, plans,
|
|
|
17426
17554
|
results.push(created);
|
|
17427
17555
|
}
|
|
17428
17556
|
if (!options?.syncActionsOnly && plans.length > 0 && plans.every((plan) => planIdsBySku.has(plan.sku.toLowerCase()))) {
|
|
17429
|
-
const sortTargets = buildGatewayPlanSortTargetsFromIds(
|
|
17430
|
-
|
|
17557
|
+
const sortTargets = buildGatewayPlanSortTargetsFromIds(
|
|
17558
|
+
plans,
|
|
17559
|
+
planIdsBySku,
|
|
17560
|
+
bySku
|
|
17561
|
+
);
|
|
17562
|
+
const sortResults = await applyGatewayPlanSortOrders(
|
|
17563
|
+
client,
|
|
17564
|
+
config2,
|
|
17565
|
+
projectId,
|
|
17566
|
+
sortTargets
|
|
17567
|
+
);
|
|
17431
17568
|
results.push(...sortResults);
|
|
17432
17569
|
}
|
|
17433
17570
|
return results;
|
|
@@ -17482,12 +17619,19 @@ async function materializePublishOpenApiWithGateway(siteDirectory, sourceOpenApi
|
|
|
17482
17619
|
const doc = await readOpenApiDocument(source);
|
|
17483
17620
|
const rewritten = withGatewayServers(doc, gatewayUrl);
|
|
17484
17621
|
await mkdir11(path55.dirname(outputPath), { recursive: true });
|
|
17485
|
-
await writeFile14(
|
|
17486
|
-
|
|
17622
|
+
await writeFile14(
|
|
17623
|
+
outputPath,
|
|
17624
|
+
`${JSON.stringify(rewritten, null, 2)}
|
|
17625
|
+
`,
|
|
17626
|
+
"utf8"
|
|
17627
|
+
);
|
|
17487
17628
|
return { outputPath, relativeInput };
|
|
17488
17629
|
}
|
|
17489
17630
|
async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
|
|
17490
|
-
const configPath = path55.join(
|
|
17631
|
+
const configPath = path55.join(
|
|
17632
|
+
path55.resolve(siteDirectory),
|
|
17633
|
+
APITOGO_CONFIG_FILENAME2
|
|
17634
|
+
);
|
|
17491
17635
|
const raw = await readFile15(configPath, "utf8");
|
|
17492
17636
|
const config2 = JSON.parse(raw);
|
|
17493
17637
|
const previousApis = config2.apis;
|
|
@@ -17517,20 +17661,30 @@ async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
|
|
|
17517
17661
|
} else {
|
|
17518
17662
|
current.backend = previousBackend;
|
|
17519
17663
|
}
|
|
17520
|
-
await writeFile14(
|
|
17521
|
-
|
|
17664
|
+
await writeFile14(
|
|
17665
|
+
configPath,
|
|
17666
|
+
`${JSON.stringify(current, null, 2)}
|
|
17667
|
+
`,
|
|
17668
|
+
"utf8"
|
|
17669
|
+
);
|
|
17522
17670
|
}
|
|
17523
17671
|
};
|
|
17524
17672
|
}
|
|
17525
17673
|
async function prepareOpenApiServersForGatewayBuild(options) {
|
|
17526
17674
|
const siteDirectory = path55.resolve(options.siteDirectory);
|
|
17527
|
-
let openApiPath = resolveBackendOpenApiPath(
|
|
17528
|
-
|
|
17529
|
-
|
|
17530
|
-
|
|
17675
|
+
let openApiPath = resolveBackendOpenApiPath(
|
|
17676
|
+
options.manifest?.backend?.openApiPath,
|
|
17677
|
+
{
|
|
17678
|
+
siteDirectory,
|
|
17679
|
+
backendSourceDirectory: options.manifest?.backend?.sourceDirectory
|
|
17680
|
+
}
|
|
17681
|
+
);
|
|
17531
17682
|
if (!openApiPath) {
|
|
17532
17683
|
try {
|
|
17533
|
-
const raw = await readFile15(
|
|
17684
|
+
const raw = await readFile15(
|
|
17685
|
+
path55.join(siteDirectory, APITOGO_CONFIG_FILENAME2),
|
|
17686
|
+
"utf8"
|
|
17687
|
+
);
|
|
17534
17688
|
const config2 = JSON.parse(raw);
|
|
17535
17689
|
const input5 = Array.isArray(config2.apis) ? config2.apis[0]?.input?.trim() : void 0;
|
|
17536
17690
|
openApiPath = resolveBackendOpenApiPath(input5, { siteDirectory });
|
|
@@ -17545,7 +17699,10 @@ async function prepareOpenApiServersForGatewayBuild(options) {
|
|
|
17545
17699
|
openApiPath,
|
|
17546
17700
|
options.gatewayUrl
|
|
17547
17701
|
);
|
|
17548
|
-
const { restore } = await pointSiteApisAtPublishOpenApi(
|
|
17702
|
+
const { restore } = await pointSiteApisAtPublishOpenApi(
|
|
17703
|
+
siteDirectory,
|
|
17704
|
+
relativeInput
|
|
17705
|
+
);
|
|
17549
17706
|
return { relativeInput, outputPath, restore };
|
|
17550
17707
|
}
|
|
17551
17708
|
|
|
@@ -17880,7 +18037,9 @@ async function validateDevPortalReadiness(client, projectId, options) {
|
|
|
17880
18037
|
})
|
|
17881
18038
|
);
|
|
17882
18039
|
checks.push(checkSwaAlignment(options.project, urls.swaUrl));
|
|
17883
|
-
checks.push(
|
|
18040
|
+
checks.push(
|
|
18041
|
+
await checkGatewayPlans(client, projectId, options.postDeploy ?? false)
|
|
18042
|
+
);
|
|
17884
18043
|
checks.push({
|
|
17885
18044
|
name: "oidc_redirect_uri",
|
|
17886
18045
|
severity: "info",
|
|
@@ -18154,10 +18313,10 @@ async function createProjectWithWarmPoolRetry(client, body, options) {
|
|
|
18154
18313
|
}
|
|
18155
18314
|
|
|
18156
18315
|
// src/cli/platform/helpers/backend-packaging.ts
|
|
18316
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
18157
18317
|
import { mkdtemp, readdir, rm as rm5 } from "node:fs/promises";
|
|
18158
18318
|
import { tmpdir } from "node:os";
|
|
18159
18319
|
import path57 from "node:path";
|
|
18160
|
-
import { spawn as spawn3 } from "node:child_process";
|
|
18161
18320
|
async function directoryHasRuntimeConfig(dir) {
|
|
18162
18321
|
if (!await pathExists(dir)) {
|
|
18163
18322
|
return false;
|
|
@@ -18224,7 +18383,9 @@ async function prepareBackendPackagingDirectory(args) {
|
|
|
18224
18383
|
if (!csproj) {
|
|
18225
18384
|
return { directory: sourceDirectory, packagingMode: "source" };
|
|
18226
18385
|
}
|
|
18227
|
-
const tempRoot = await mkdtemp(
|
|
18386
|
+
const tempRoot = await mkdtemp(
|
|
18387
|
+
path57.join(tmpdir(), "apitogo-dotnet-publish-")
|
|
18388
|
+
);
|
|
18228
18389
|
const outputDir = path57.join(tempRoot, "publish");
|
|
18229
18390
|
const result = await runDotnetPublish(sourceDirectory, outputDir);
|
|
18230
18391
|
if (result.exitCode !== 0) {
|
|
@@ -18288,7 +18449,9 @@ async function packageBackendDirectory(sourceDirectory) {
|
|
|
18288
18449
|
output4.on("error", reject);
|
|
18289
18450
|
archive.pipe(output4);
|
|
18290
18451
|
for (const rel of files) {
|
|
18291
|
-
archive.append(createReadStream2(path58.join(resolved, rel)), {
|
|
18452
|
+
archive.append(createReadStream2(path58.join(resolved, rel)), {
|
|
18453
|
+
name: rel.split(path58.sep).join("/")
|
|
18454
|
+
});
|
|
18292
18455
|
}
|
|
18293
18456
|
void archive.finalize();
|
|
18294
18457
|
});
|
|
@@ -18494,7 +18657,10 @@ async function handleWaitForJob(client, config2, args, progress) {
|
|
|
18494
18657
|
return client.getDevPortalDeployStatus(projectId, args.jobId);
|
|
18495
18658
|
}
|
|
18496
18659
|
if (args.jobId) {
|
|
18497
|
-
return client.getAzureInfrastructureDeployStatus(
|
|
18660
|
+
return client.getAzureInfrastructureDeployStatus(
|
|
18661
|
+
projectId,
|
|
18662
|
+
args.jobId
|
|
18663
|
+
);
|
|
18498
18664
|
}
|
|
18499
18665
|
return client.getLatestAzureInfrastructureStatus(projectId);
|
|
18500
18666
|
},
|
|
@@ -18531,7 +18697,10 @@ async function handleDeployBackend(client, config2, args, progress) {
|
|
|
18531
18697
|
const projectId = resolveProjectId(args.projectId, config2);
|
|
18532
18698
|
const deployProgress = progress?.child("Backend deployment");
|
|
18533
18699
|
const runtime = normalizeRuntime(args.runtime);
|
|
18534
|
-
const runtimeVersion = normalizeRuntimeVersionSlug(
|
|
18700
|
+
const runtimeVersion = normalizeRuntimeVersionSlug(
|
|
18701
|
+
runtime,
|
|
18702
|
+
args.runtimeVersion
|
|
18703
|
+
);
|
|
18535
18704
|
const resolvedOpenApiPath = resolveDeployBackendOpenApiPath({
|
|
18536
18705
|
openApiPath: args.openApiPath,
|
|
18537
18706
|
sourceDirectory: args.sourceDirectory,
|
|
@@ -18541,7 +18710,9 @@ async function handleDeployBackend(client, config2, args, progress) {
|
|
|
18541
18710
|
await deployProgress?.onStep("Validating OpenAPI");
|
|
18542
18711
|
const validation = await validateOpenApiFile(resolvedOpenApiPath);
|
|
18543
18712
|
if (!validation.valid) {
|
|
18544
|
-
throw new Error(
|
|
18713
|
+
throw new Error(
|
|
18714
|
+
`OpenAPI validation failed: ${validation.errors.join("; ")}`
|
|
18715
|
+
);
|
|
18545
18716
|
}
|
|
18546
18717
|
}
|
|
18547
18718
|
await deployProgress?.onStep("Packaging backend source");
|
|
@@ -18711,6 +18882,20 @@ function parseToolJsonResult(result) {
|
|
|
18711
18882
|
}
|
|
18712
18883
|
}
|
|
18713
18884
|
|
|
18885
|
+
// src/cli/platform/helpers/project-name.ts
|
|
18886
|
+
function normalizeProjectName(name) {
|
|
18887
|
+
return name.trim().split(/\s+/).filter(Boolean).join(" ").toLowerCase();
|
|
18888
|
+
}
|
|
18889
|
+
function findProjectByNormalizedName(projects, name) {
|
|
18890
|
+
const needle = normalizeProjectName(name);
|
|
18891
|
+
if (!needle) {
|
|
18892
|
+
return void 0;
|
|
18893
|
+
}
|
|
18894
|
+
return projects.find(
|
|
18895
|
+
(project) => normalizeProjectName(project.name) === needle
|
|
18896
|
+
);
|
|
18897
|
+
}
|
|
18898
|
+
|
|
18714
18899
|
// src/cli/platform/helpers/platform-plan-catalog.ts
|
|
18715
18900
|
var PLATFORM_PLAN_CATALOG = [
|
|
18716
18901
|
{
|
|
@@ -18946,7 +19131,11 @@ async function handleEnsurePlatformPlan(client, config2, args, progress) {
|
|
|
18946
19131
|
projectId = resolved.projectId;
|
|
18947
19132
|
} else {
|
|
18948
19133
|
projectId = resolveProjectId(projectId, config2);
|
|
18949
|
-
steps.push({
|
|
19134
|
+
steps.push({
|
|
19135
|
+
step: "resolve_project",
|
|
19136
|
+
status: "succeeded",
|
|
19137
|
+
detail: { projectId }
|
|
19138
|
+
});
|
|
18950
19139
|
}
|
|
18951
19140
|
const existingSubscription = await client.getSubscription(projectId);
|
|
18952
19141
|
if (isPlatformPlanReady(existingSubscription)) {
|
|
@@ -19140,18 +19329,6 @@ async function assertPaidGatewayPlansAllowedForPublish(client, projectId, plans)
|
|
|
19140
19329
|
};
|
|
19141
19330
|
}
|
|
19142
19331
|
|
|
19143
|
-
// src/cli/platform/helpers/project-name.ts
|
|
19144
|
-
function normalizeProjectName(name) {
|
|
19145
|
-
return name.trim().split(/\s+/).filter(Boolean).join(" ").toLowerCase();
|
|
19146
|
-
}
|
|
19147
|
-
function findProjectByNormalizedName(projects, name) {
|
|
19148
|
-
const needle = normalizeProjectName(name);
|
|
19149
|
-
if (!needle) {
|
|
19150
|
-
return void 0;
|
|
19151
|
-
}
|
|
19152
|
-
return projects.find((project) => normalizeProjectName(project.name) === needle);
|
|
19153
|
-
}
|
|
19154
|
-
|
|
19155
19332
|
// src/cli/platform/tools/projects.ts
|
|
19156
19333
|
function tenantDisplayName(tenant) {
|
|
19157
19334
|
return tenant.displayName ?? tenant.name ?? tenant.userName ?? tenant.email;
|
|
@@ -19202,10 +19379,14 @@ async function handleGetProject(client, config2, args) {
|
|
|
19202
19379
|
if (args.includeInfrastructureStatus !== false) {
|
|
19203
19380
|
for (let i = 0; i < enrichedModules.length; i++) {
|
|
19204
19381
|
const mod = enrichedModules[i];
|
|
19382
|
+
if (!mod) continue;
|
|
19205
19383
|
const statusLower = mod.status.toLowerCase();
|
|
19206
19384
|
if (statusLower === "pending" || statusLower === "provisioning") {
|
|
19207
19385
|
try {
|
|
19208
|
-
const infra = await client.getInfrastructureStatus(
|
|
19386
|
+
const infra = await client.getInfrastructureStatus(
|
|
19387
|
+
projectId,
|
|
19388
|
+
mod.type
|
|
19389
|
+
);
|
|
19209
19390
|
enrichedModules[i] = {
|
|
19210
19391
|
...mod,
|
|
19211
19392
|
status: `${mod.status} (infra: ${infra.status})`
|
|
@@ -19317,7 +19498,11 @@ async function resolveBootstrapProjectId(client, args, steps) {
|
|
|
19317
19498
|
});
|
|
19318
19499
|
const created = JSON.parse(createdJson);
|
|
19319
19500
|
const projectId = created.project.id;
|
|
19320
|
-
steps.push({
|
|
19501
|
+
steps.push({
|
|
19502
|
+
step: "create_project",
|
|
19503
|
+
status: "succeeded",
|
|
19504
|
+
detail: { projectId }
|
|
19505
|
+
});
|
|
19321
19506
|
return { projectId, resumed: false };
|
|
19322
19507
|
} catch (error) {
|
|
19323
19508
|
if (!(error instanceof PlatformApiError) || error.status !== 409) {
|
|
@@ -19338,7 +19523,9 @@ var READY_MODULE_STATUSES = /* @__PURE__ */ new Set(["provisioned", "configured"
|
|
|
19338
19523
|
function moduleTypesPendingActivation(project, requestedModules) {
|
|
19339
19524
|
return requestedModules.filter((moduleType) => {
|
|
19340
19525
|
const normalized = normalizeModuleType(moduleType);
|
|
19341
|
-
const mod = project.modules.find(
|
|
19526
|
+
const mod = project.modules.find(
|
|
19527
|
+
(m) => normalizeModuleType(m.type) === normalized
|
|
19528
|
+
);
|
|
19342
19529
|
if (!mod?.status) {
|
|
19343
19530
|
return true;
|
|
19344
19531
|
}
|
|
@@ -19352,11 +19539,15 @@ async function handleBootstrapProject(client, config2, args, progress) {
|
|
|
19352
19539
|
const selectFreePlan = args.selectFreePlan === true;
|
|
19353
19540
|
const bootstrapProgress = progress?.child("Bootstrap project");
|
|
19354
19541
|
await bootstrapProgress?.onStep("Creating project");
|
|
19355
|
-
const { projectId, resumed } = await resolveBootstrapProjectId(
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19542
|
+
const { projectId, resumed } = await resolveBootstrapProjectId(
|
|
19543
|
+
client,
|
|
19544
|
+
{
|
|
19545
|
+
name: args.name,
|
|
19546
|
+
description: args.description,
|
|
19547
|
+
modules
|
|
19548
|
+
},
|
|
19549
|
+
steps
|
|
19550
|
+
);
|
|
19360
19551
|
if (selectFreePlan && !resumed) {
|
|
19361
19552
|
await bootstrapProgress?.onStep("Selecting free plan");
|
|
19362
19553
|
const freeResult = await handleSelectFreePlan(
|
|
@@ -19370,7 +19561,11 @@ async function handleBootstrapProject(client, config2, args, progress) {
|
|
|
19370
19561
|
}
|
|
19371
19562
|
steps.push({ step: "select_free_plan", status: "succeeded" });
|
|
19372
19563
|
} else if (selectFreePlan && resumed) {
|
|
19373
|
-
steps.push({
|
|
19564
|
+
steps.push({
|
|
19565
|
+
step: "select_free_plan",
|
|
19566
|
+
status: "skipped",
|
|
19567
|
+
detail: { reason: "project resumed" }
|
|
19568
|
+
});
|
|
19374
19569
|
}
|
|
19375
19570
|
const projectBeforeModules = await client.getProject(projectId);
|
|
19376
19571
|
const planSelected = !isPlatformPlanUnselected(projectBeforeModules.planTier);
|
|
@@ -19444,7 +19639,11 @@ async function handleBootstrapProject(client, config2, args, progress) {
|
|
|
19444
19639
|
})
|
|
19445
19640
|
);
|
|
19446
19641
|
for (const { moduleType, activated } of activations) {
|
|
19447
|
-
steps.push({
|
|
19642
|
+
steps.push({
|
|
19643
|
+
step: `activate_${moduleType}`,
|
|
19644
|
+
status: "pending",
|
|
19645
|
+
detail: activated
|
|
19646
|
+
});
|
|
19448
19647
|
}
|
|
19449
19648
|
if (wait) {
|
|
19450
19649
|
const waits = await Promise.all(
|
|
@@ -19468,7 +19667,11 @@ async function handleBootstrapProject(client, config2, args, progress) {
|
|
|
19468
19667
|
})
|
|
19469
19668
|
);
|
|
19470
19669
|
for (const { moduleType, waited } of waits) {
|
|
19471
|
-
steps.push({
|
|
19670
|
+
steps.push({
|
|
19671
|
+
step: `wait_${moduleType}`,
|
|
19672
|
+
status: waited.status,
|
|
19673
|
+
detail: waited
|
|
19674
|
+
});
|
|
19472
19675
|
if (waited.status === "failed") {
|
|
19473
19676
|
return JSON.stringify(
|
|
19474
19677
|
{
|
|
@@ -19749,7 +19952,10 @@ var PLACEHOLDER_HOST_MARKERS = [
|
|
|
19749
19952
|
"dp-example.azurecontainerapps.io",
|
|
19750
19953
|
"your-dev-portal-api.example.com"
|
|
19751
19954
|
];
|
|
19752
|
-
var ENV_LINE_GLOBAL_RE = new RegExp(
|
|
19955
|
+
var ENV_LINE_GLOBAL_RE = new RegExp(
|
|
19956
|
+
`^#?\\s*${SITE_API_BASE_URL_ENV_KEY}=(.*)$`,
|
|
19957
|
+
"gm"
|
|
19958
|
+
);
|
|
19753
19959
|
function isPlaceholderDevPortalApiUrl(apiBaseUrl) {
|
|
19754
19960
|
if (!apiBaseUrl?.trim()) {
|
|
19755
19961
|
return true;
|
|
@@ -19902,51 +20108,6 @@ async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiB
|
|
|
19902
20108
|
import { promises as fs11 } from "node:fs";
|
|
19903
20109
|
import path61 from "node:path";
|
|
19904
20110
|
|
|
19905
|
-
// src/cli/platform/helpers/tarball.ts
|
|
19906
|
-
import { createReadStream as createReadStream3, createWriteStream as createWriteStream3, promises as fs10 } from "node:fs";
|
|
19907
|
-
import { tmpdir as tmpdir3 } from "node:os";
|
|
19908
|
-
import path60 from "node:path";
|
|
19909
|
-
import { TarArchive } from "archiver";
|
|
19910
|
-
var DEV_PORTAL_DEPLOY_ARCHIVE_ROOT = "dist";
|
|
19911
|
-
function normalizeArchiveRoot(archiveRoot) {
|
|
19912
|
-
const trimmed = archiveRoot.trim().replace(/^\/+|\/+$/g, "");
|
|
19913
|
-
if (!trimmed) {
|
|
19914
|
-
throw new Error("archiveRoot must not be empty.");
|
|
19915
|
-
}
|
|
19916
|
-
return `${trimmed}/`;
|
|
19917
|
-
}
|
|
19918
|
-
async function packageDirectoryAsTarGz(sourceDirectory, options) {
|
|
19919
|
-
const resolved = path60.resolve(sourceDirectory);
|
|
19920
|
-
const files = await collectPackageableFiles(resolved);
|
|
19921
|
-
const entryPrefix = options?.archiveRoot ? normalizeArchiveRoot(options.archiveRoot) : "";
|
|
19922
|
-
const archivePath = path60.join(
|
|
19923
|
-
tmpdir3(),
|
|
19924
|
-
`apitogo-docs-${Date.now()}-${Math.random().toString(36).slice(2)}.tgz`
|
|
19925
|
-
);
|
|
19926
|
-
await new Promise((resolve, reject) => {
|
|
19927
|
-
const output4 = createWriteStream3(archivePath);
|
|
19928
|
-
const archive = new TarArchive({ gzip: true, gzipOptions: { level: 6 } });
|
|
19929
|
-
output4.on("close", () => resolve());
|
|
19930
|
-
archive.on("error", reject);
|
|
19931
|
-
output4.on("error", reject);
|
|
19932
|
-
archive.pipe(output4);
|
|
19933
|
-
for (const rel of files) {
|
|
19934
|
-
const entryName = entryPrefix + rel.split(path60.sep).join("/");
|
|
19935
|
-
archive.append(createReadStream3(path60.join(resolved, rel)), { name: entryName });
|
|
19936
|
-
}
|
|
19937
|
-
void archive.finalize();
|
|
19938
|
-
});
|
|
19939
|
-
const { size } = await fs10.stat(archivePath);
|
|
19940
|
-
return { archivePath, byteSize: size };
|
|
19941
|
-
}
|
|
19942
|
-
async function cleanupArchive(archivePath) {
|
|
19943
|
-
await fs10.unlink(archivePath).catch(() => void 0);
|
|
19944
|
-
}
|
|
19945
|
-
function isTarGzPath(filePath) {
|
|
19946
|
-
const normalized = filePath.toLowerCase();
|
|
19947
|
-
return normalized.endsWith(".tgz") || normalized.endsWith(".tar.gz");
|
|
19948
|
-
}
|
|
19949
|
-
|
|
19950
20111
|
// src/cli/platform/helpers/dev-portal-backend-job.ts
|
|
19951
20112
|
var DEV_PORTAL_BACKEND_UPDATE_RESOURCE_TYPE = "DevPortalBackendUpdate";
|
|
19952
20113
|
var ACTIVE_JOB_STATUSES = /* @__PURE__ */ new Set(["Pending", "InProgress"]);
|
|
@@ -20049,16 +20210,65 @@ async function pollBackendUpdateJobStatus(client, projectId, jobId, options) {
|
|
|
20049
20210
|
}
|
|
20050
20211
|
async function snapshotBackendUpdateJobIds(client, projectId) {
|
|
20051
20212
|
const result = await client.listProvisioningJobs(projectId);
|
|
20052
|
-
return new Set(
|
|
20053
|
-
|
|
20213
|
+
return new Set(result.jobs.filter(isBackendUpdateJob).map((job) => job.id));
|
|
20214
|
+
}
|
|
20215
|
+
|
|
20216
|
+
// src/cli/platform/helpers/tarball.ts
|
|
20217
|
+
import { createReadStream as createReadStream3, createWriteStream as createWriteStream3, promises as fs10 } from "node:fs";
|
|
20218
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
20219
|
+
import path60 from "node:path";
|
|
20220
|
+
import { TarArchive } from "archiver";
|
|
20221
|
+
var DEV_PORTAL_DEPLOY_ARCHIVE_ROOT = "dist";
|
|
20222
|
+
function normalizeArchiveRoot(archiveRoot) {
|
|
20223
|
+
const trimmed = archiveRoot.trim().replace(/^\/+|\/+$/g, "");
|
|
20224
|
+
if (!trimmed) {
|
|
20225
|
+
throw new Error("archiveRoot must not be empty.");
|
|
20226
|
+
}
|
|
20227
|
+
return `${trimmed}/`;
|
|
20228
|
+
}
|
|
20229
|
+
async function packageDirectoryAsTarGz(sourceDirectory, options) {
|
|
20230
|
+
const resolved = path60.resolve(sourceDirectory);
|
|
20231
|
+
const files = await collectPackageableFiles(resolved);
|
|
20232
|
+
const entryPrefix = options?.archiveRoot ? normalizeArchiveRoot(options.archiveRoot) : "";
|
|
20233
|
+
const archivePath = path60.join(
|
|
20234
|
+
tmpdir3(),
|
|
20235
|
+
`apitogo-docs-${Date.now()}-${Math.random().toString(36).slice(2)}.tgz`
|
|
20054
20236
|
);
|
|
20237
|
+
await new Promise((resolve, reject) => {
|
|
20238
|
+
const output4 = createWriteStream3(archivePath);
|
|
20239
|
+
const archive = new TarArchive({ gzip: true, gzipOptions: { level: 6 } });
|
|
20240
|
+
output4.on("close", () => resolve());
|
|
20241
|
+
archive.on("error", reject);
|
|
20242
|
+
output4.on("error", reject);
|
|
20243
|
+
archive.pipe(output4);
|
|
20244
|
+
for (const rel of files) {
|
|
20245
|
+
const entryName = entryPrefix + rel.split(path60.sep).join("/");
|
|
20246
|
+
archive.append(createReadStream3(path60.join(resolved, rel)), {
|
|
20247
|
+
name: entryName
|
|
20248
|
+
});
|
|
20249
|
+
}
|
|
20250
|
+
void archive.finalize();
|
|
20251
|
+
});
|
|
20252
|
+
const { size } = await fs10.stat(archivePath);
|
|
20253
|
+
return { archivePath, byteSize: size };
|
|
20254
|
+
}
|
|
20255
|
+
async function cleanupArchive(archivePath) {
|
|
20256
|
+
await fs10.unlink(archivePath).catch(() => void 0);
|
|
20257
|
+
}
|
|
20258
|
+
function isTarGzPath(filePath) {
|
|
20259
|
+
const normalized = filePath.toLowerCase();
|
|
20260
|
+
return normalized.endsWith(".tgz") || normalized.endsWith(".tar.gz");
|
|
20055
20261
|
}
|
|
20056
20262
|
|
|
20057
20263
|
// src/cli/platform/tools/dev-portal.ts
|
|
20058
20264
|
async function handleGetDevPortalBackend(client, config2, args) {
|
|
20059
20265
|
const projectId = resolveProjectId(args.projectId, config2);
|
|
20060
20266
|
const backend = await client.getDevPortalBackend(projectId);
|
|
20061
|
-
return JSON.stringify(
|
|
20267
|
+
return JSON.stringify(
|
|
20268
|
+
formatDevPortalBackendResponse(projectId, backend),
|
|
20269
|
+
null,
|
|
20270
|
+
2
|
|
20271
|
+
);
|
|
20062
20272
|
}
|
|
20063
20273
|
async function upsertDevPortalSettings(client, config2, projectId, body, waitOptions, progress) {
|
|
20064
20274
|
const baselineJobIds = waitOptions.wait ? await snapshotBackendUpdateJobIds(client, projectId) : void 0;
|