@lukoweb/apitogo 0.1.61 → 0.1.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/cli.js CHANGED
@@ -852,7 +852,7 @@ var init_ModulesSchema = __esm({
852
852
  sku: z3.string(),
853
853
  displayName: z3.string(),
854
854
  priceAmount: z3.number().default(0),
855
- priceCurrency: z3.string().optional(),
855
+ priceCurrency: z3.string().trim().toLowerCase().regex(/^[a-z]{3}$/, "priceCurrency must be a 3-letter ISO 4217 code (lowercase)").optional(),
856
856
  billingPeriod: z3.string().optional(),
857
857
  limitsJson: z3.string().optional(),
858
858
  includedActionKeys: z3.array(z3.string()).optional()
@@ -993,17 +993,30 @@ async function readEffectiveManifest(rootDir, _env) {
993
993
  return null;
994
994
  }
995
995
  }
996
- var BillingPeriodSchema, ManifestPlanInputSchema, DevPortalLocalManifestSchema;
996
+ var BillingPeriodSchema, PriceCurrencySchema, ALLOWED_RUNTIME_VERSIONS, ManifestPlanInputSchema, DevPortalLocalManifestSchema;
997
997
  var init_local_manifest = __esm({
998
998
  "src/config/local-manifest.ts"() {
999
999
  init_apitogo_config_loader();
1000
1000
  init_landing_manifest();
1001
1001
  BillingPeriodSchema = z4.enum(["month", "year", "monthly", "annual"]);
1002
+ PriceCurrencySchema = z4.string().trim().toLowerCase().regex(/^[a-z]{3}$/, "priceCurrency must be a 3-letter ISO 4217 code (lowercase)");
1003
+ ALLOWED_RUNTIME_VERSIONS = [
1004
+ "DOTNET_10",
1005
+ "DOTNET_9",
1006
+ "DOTNET_8",
1007
+ "NODE_24_LTS",
1008
+ "NODE_22_LTS",
1009
+ "PYTHON_314",
1010
+ "PYTHON_313",
1011
+ "PYTHON_312",
1012
+ "PYTHON_311",
1013
+ "PYTHON_310"
1014
+ ];
1002
1015
  ManifestPlanInputSchema = z4.object({
1003
1016
  sku: z4.string().min(1),
1004
1017
  displayName: z4.string().min(1),
1005
1018
  priceAmount: z4.number().default(0),
1006
- priceCurrency: z4.string().optional(),
1019
+ priceCurrency: PriceCurrencySchema.optional(),
1007
1020
  billingPeriod: BillingPeriodSchema.optional(),
1008
1021
  limitsJson: z4.string().optional(),
1009
1022
  includedActionKeys: z4.array(z4.string()).optional()
@@ -1042,8 +1055,15 @@ var init_local_manifest = __esm({
1042
1055
  sourceDirectory: z4.string().optional(),
1043
1056
  publishDirectory: z4.string().optional(),
1044
1057
  openApiPath: z4.string().optional(),
1045
- runtime: z4.string().optional(),
1046
- runtimeVersion: z4.string().optional(),
1058
+ runtime: z4.enum(["dotnet", "nodejs", "python"]).or(z4.string()).optional(),
1059
+ runtimeVersion: z4.string().optional().refine(
1060
+ (value) => value === void 0 || ALLOWED_RUNTIME_VERSIONS.includes(value.toUpperCase()) || /^(8(\.0)?|9(\.0)?|10(\.0)?|net8\.0|net9\.0|net10\.0|24|22|3\.(10|11|12|13|14))$/i.test(
1061
+ value
1062
+ ),
1063
+ {
1064
+ message: `runtimeVersion must be a platform slug (${ALLOWED_RUNTIME_VERSIONS.join(", ")}) or a known alias such as 8.0`
1065
+ }
1066
+ ),
1047
1067
  deployed: z4.boolean().optional()
1048
1068
  }).optional(),
1049
1069
  gateway: z4.object({
@@ -4772,6 +4792,18 @@ import {
4772
4792
  runnerImport,
4773
4793
  loadEnv as viteLoadEnv
4774
4794
  } from "vite";
4795
+ function mergeJsonConfigWithRuntimeOverrides(fileConfig, importedConfig) {
4796
+ const jsonConfig = buildApitogoConfig({
4797
+ ...fileConfig,
4798
+ plugins: importedConfig.plugins
4799
+ });
4800
+ return {
4801
+ ...jsonConfig,
4802
+ // Custom pages carry React elements and therefore only exist in the
4803
+ // imported TSX config. They cannot be read from or cloned through JSON.
4804
+ navigation: importedConfig.navigation ?? jsonConfig.navigation
4805
+ };
4806
+ }
4775
4807
  async function getConfigFilePath(rootDir) {
4776
4808
  for (const fileName of zudokuConfigFiles) {
4777
4809
  const filepath = path5.join(rootDir, fileName);
@@ -4806,10 +4838,7 @@ async function loadZudokuConfigWithMeta(rootDir) {
4806
4838
  let config2;
4807
4839
  try {
4808
4840
  const fileConfig = loadApitogoConfig(rootDir);
4809
- config2 = buildApitogoConfig({
4810
- ...fileConfig,
4811
- plugins: importedConfig.plugins
4812
- });
4841
+ config2 = mergeJsonConfigWithRuntimeOverrides(fileConfig, importedConfig);
4813
4842
  } catch {
4814
4843
  config2 = importedConfig;
4815
4844
  }
@@ -4906,6 +4935,7 @@ async function loadZudokuConfig(configEnv, rootDir) {
4906
4935
  return { config, envPrefix, publicEnv };
4907
4936
  }
4908
4937
  ({ publicEnv, envPrefix } = loadEnv(configEnv, rootDir));
4938
+ let loadSucceeded = false;
4909
4939
  try {
4910
4940
  const loadedConfig = await loadZudokuConfigWithMeta(rootDir);
4911
4941
  const manifestEnv = resolveManifestEnv(configEnv.mode);
@@ -4943,6 +4973,7 @@ async function loadZudokuConfig(configEnv, rootDir) {
4943
4973
  { timestamp: true }
4944
4974
  );
4945
4975
  }
4976
+ loadSucceeded = true;
4946
4977
  return { config, envPrefix, publicEnv };
4947
4978
  } catch (error) {
4948
4979
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -4951,7 +4982,11 @@ async function loadZudokuConfig(configEnv, rootDir) {
4951
4982
  }
4952
4983
  throw new Error(errorMessage, { cause: error });
4953
4984
  } finally {
4954
- await updateModifiedTimes();
4985
+ if (loadSucceeded) {
4986
+ await updateModifiedTimes();
4987
+ } else {
4988
+ modifiedTimes = void 0;
4989
+ }
4955
4990
  }
4956
4991
  }
4957
4992
  var config, envPrefix, publicEnv, modifiedTimes, zudokuConfigFiles, serverConfigOutputFiles, virtualModuleStubPlugin, getCurrentConfig;
@@ -5238,7 +5273,7 @@ import {
5238
5273
  // package.json
5239
5274
  var package_default = {
5240
5275
  name: "@lukoweb/apitogo",
5241
- version: "0.1.61",
5276
+ version: "0.1.63",
5242
5277
  type: "module",
5243
5278
  sideEffects: [
5244
5279
  "**/*.css",
@@ -7583,9 +7618,7 @@ var viteConfigReloadPlugin = () => ({
7583
7618
  if (file !== currentConfig.__meta.configPath && file.endsWith(".tsx"))
7584
7619
  return;
7585
7620
  invalidate(server);
7586
- Object.values(server.environments).forEach((env) => {
7587
- env.moduleGraph.invalidateAll();
7588
- });
7621
+ reload(server);
7589
7622
  logger.info(
7590
7623
  colors3.blue(
7591
7624
  `Config ${path13.basename(currentConfig.__meta.configPath)} changed. Reloading...`
@@ -16,6 +16,7 @@ export type ConfigWithMeta = ZudokuConfig & {
16
16
  };
17
17
  __resolvedModules: ResolvedModulesConfig;
18
18
  };
19
+ export declare function mergeJsonConfigWithRuntimeOverrides(fileConfig: Record<string, unknown>, importedConfig: ZudokuConfig): ZudokuConfig;
19
20
  export declare function findOutputPathOfServerConfig(output: RollupOutput | RollupOutput[] | RollupWatcher): string;
20
21
  export declare const getCurrentConfig: () => ConfigWithMeta;
21
22
  export declare const setCurrentConfig: (newConfig: ConfigWithMeta) => void;
@@ -8,6 +8,7 @@ export declare const APITOGO_MANIFEST_ENV_FILES: {
8
8
  };
9
9
  export { APITOGO_CONFIG_FILENAME };
10
10
  export type ApitogoManifestEnv = keyof typeof APITOGO_MANIFEST_ENV_FILES;
11
+ export declare const ALLOWED_RUNTIME_VERSIONS: readonly ["DOTNET_10", "DOTNET_9", "DOTNET_8", "NODE_24_LTS", "NODE_22_LTS", "PYTHON_314", "PYTHON_313", "PYTHON_312", "PYTHON_311", "PYTHON_310"];
11
12
  export declare const ManifestPlanInputSchema: z.ZodObject<{
12
13
  sku: z.ZodString;
13
14
  displayName: z.ZodString;
@@ -70,7 +71,11 @@ export declare const DevPortalLocalManifestSchema: z.ZodObject<{
70
71
  sourceDirectory: z.ZodOptional<z.ZodString>;
71
72
  publishDirectory: z.ZodOptional<z.ZodString>;
72
73
  openApiPath: z.ZodOptional<z.ZodString>;
73
- runtime: z.ZodOptional<z.ZodString>;
74
+ runtime: z.ZodOptional<z.ZodUnion<[z.ZodEnum<{
75
+ python: "python";
76
+ dotnet: "dotnet";
77
+ nodejs: "nodejs";
78
+ }>, z.ZodString]>>;
74
79
  runtimeVersion: z.ZodOptional<z.ZodString>;
75
80
  deployed: z.ZodOptional<z.ZodBoolean>;
76
81
  }, z.core.$strip>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo",
3
- "version": "0.1.61",
3
+ "version": "0.1.63",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -69,6 +69,23 @@ const zudokuConfigFiles = [
69
69
 
70
70
  const serverConfigOutputFiles = ["apitogo.config.js", "zudoku.config.js"];
71
71
 
72
+ export function mergeJsonConfigWithRuntimeOverrides(
73
+ fileConfig: Record<string, unknown>,
74
+ importedConfig: ZudokuConfig,
75
+ ): ZudokuConfig {
76
+ const jsonConfig = buildApitogoConfig({
77
+ ...fileConfig,
78
+ plugins: importedConfig.plugins,
79
+ });
80
+
81
+ return {
82
+ ...jsonConfig,
83
+ // Custom pages carry React elements and therefore only exist in the
84
+ // imported TSX config. They cannot be read from or cloned through JSON.
85
+ navigation: importedConfig.navigation ?? jsonConfig.navigation,
86
+ };
87
+ }
88
+
72
89
  async function getConfigFilePath(rootDir: string) {
73
90
  for (const fileName of zudokuConfigFiles) {
74
91
  const filepath = path.join(rootDir, fileName);
@@ -123,10 +140,7 @@ async function loadZudokuConfigWithMeta(
123
140
  let config: ZudokuConfig;
124
141
  try {
125
142
  const fileConfig = loadApitogoConfig(rootDir);
126
- config = buildApitogoConfig({
127
- ...fileConfig,
128
- plugins: importedConfig.plugins,
129
- });
143
+ config = mergeJsonConfigWithRuntimeOverrides(fileConfig, importedConfig);
130
144
  } catch {
131
145
  config = importedConfig;
132
146
  }
@@ -271,6 +285,7 @@ export async function loadZudokuConfig(
271
285
 
272
286
  ({ publicEnv, envPrefix } = loadEnv(configEnv, rootDir));
273
287
 
288
+ let loadSucceeded = false;
274
289
  try {
275
290
  const loadedConfig = await loadZudokuConfigWithMeta(rootDir);
276
291
  const manifestEnv = resolveManifestEnv(configEnv.mode);
@@ -313,6 +328,7 @@ export async function loadZudokuConfig(
313
328
  );
314
329
  }
315
330
 
331
+ loadSucceeded = true;
316
332
  return { config, envPrefix, publicEnv };
317
333
  } catch (error) {
318
334
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -324,7 +340,13 @@ export async function loadZudokuConfig(
324
340
 
325
341
  throw new Error(errorMessage, { cause: error });
326
342
  } finally {
327
- await updateModifiedTimes();
343
+ if (loadSucceeded) {
344
+ await updateModifiedTimes();
345
+ } else {
346
+ // A watcher may have observed a file while it was being replaced.
347
+ // Retry on the next request instead of caching the failed file mtimes.
348
+ modifiedTimes = undefined;
349
+ }
328
350
  }
329
351
  }
330
352
 
@@ -28,11 +28,30 @@ export type ApitogoManifestEnv = keyof typeof APITOGO_MANIFEST_ENV_FILES;
28
28
 
29
29
  const BillingPeriodSchema = z.enum(["month", "year", "monthly", "annual"]);
30
30
 
31
+ const PriceCurrencySchema = z
32
+ .string()
33
+ .trim()
34
+ .toLowerCase()
35
+ .regex(/^[a-z]{3}$/, "priceCurrency must be a 3-letter ISO 4217 code (lowercase)");
36
+
37
+ export const ALLOWED_RUNTIME_VERSIONS = [
38
+ "DOTNET_10",
39
+ "DOTNET_9",
40
+ "DOTNET_8",
41
+ "NODE_24_LTS",
42
+ "NODE_22_LTS",
43
+ "PYTHON_314",
44
+ "PYTHON_313",
45
+ "PYTHON_312",
46
+ "PYTHON_311",
47
+ "PYTHON_310",
48
+ ] as const;
49
+
31
50
  export const ManifestPlanInputSchema = z.object({
32
51
  sku: z.string().min(1),
33
52
  displayName: z.string().min(1),
34
53
  priceAmount: z.number().default(0),
35
- priceCurrency: z.string().optional(),
54
+ priceCurrency: PriceCurrencySchema.optional(),
36
55
  billingPeriod: BillingPeriodSchema.optional(),
37
56
  limitsJson: z.string().optional(),
38
57
  includedActionKeys: z.array(z.string()).optional(),
@@ -90,8 +109,21 @@ export const DevPortalLocalManifestSchema = z.object({
90
109
  sourceDirectory: z.string().optional(),
91
110
  publishDirectory: z.string().optional(),
92
111
  openApiPath: z.string().optional(),
93
- runtime: z.string().optional(),
94
- runtimeVersion: z.string().optional(),
112
+ runtime: z.enum(["dotnet", "nodejs", "python"]).or(z.string()).optional(),
113
+ runtimeVersion: z
114
+ .string()
115
+ .optional()
116
+ .refine(
117
+ (value) =>
118
+ value === undefined ||
119
+ (ALLOWED_RUNTIME_VERSIONS as readonly string[]).includes(value.toUpperCase()) ||
120
+ /^(8(\.0)?|9(\.0)?|10(\.0)?|net8\.0|net9\.0|net10\.0|24|22|3\.(10|11|12|13|14))$/i.test(
121
+ value,
122
+ ),
123
+ {
124
+ message: `runtimeVersion must be a platform slug (${ALLOWED_RUNTIME_VERSIONS.join(", ")}) or a known alias such as 8.0`,
125
+ },
126
+ ),
95
127
  deployed: z.boolean().optional(),
96
128
  })
97
129
  .optional(),
@@ -262,7 +262,12 @@ const PlanCatalogItemSchema = z.object({
262
262
  sku: z.string(),
263
263
  displayName: z.string(),
264
264
  priceAmount: z.number().default(0),
265
- priceCurrency: z.string().optional(),
265
+ priceCurrency: z
266
+ .string()
267
+ .trim()
268
+ .toLowerCase()
269
+ .regex(/^[a-z]{3}$/, "priceCurrency must be a 3-letter ISO 4217 code (lowercase)")
270
+ .optional(),
266
271
  billingPeriod: z.string().optional(),
267
272
  limitsJson: z.string().optional(),
268
273
  includedActionKeys: z.array(z.string()).optional(),
@@ -34,9 +34,7 @@ export const viteConfigReloadPlugin = (): Plugin => ({
34
34
  return;
35
35
 
36
36
  invalidateNavigation(server);
37
- Object.values(server.environments).forEach((env) => {
38
- env.moduleGraph.invalidateAll();
39
- });
37
+ reload(server);
40
38
 
41
39
  logger.info(
42
40
  colors.blue(