@pd4castr/cli 1.0.1 → 1.2.0

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.
Files changed (2) hide show
  1. package/dist/index.js +31 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ var AUTH0_CLIENT_ID = "Q5tQNF57cQlVXnVsqnU0hhgy92rVb03W";
51
51
  var AUTH0_AUDIENCE = "https://api.pd4castr.com.au";
52
52
  var GLOBAL_CONFIG_FILE = ".pd4castr";
53
53
  var PROJECT_CONFIG_FILE = ".pd4castrrc.json";
54
- var DEFAULT_API_URL = "https://pd4castr-api.pipelabs.app";
54
+ var DEFAULT_API_URL = "https://api.v2.pd4castr.com.au";
55
55
  var DEFAULT_INPUT_SOURCE_ID = "0bdfd52b-efaa-455e-9a3b-1a6d2b879b73";
56
56
  var TEST_INPUT_DATA_DIR = "test_input";
57
57
  var TEST_OUTPUT_DATA_DIR = "test_output";
@@ -75,6 +75,14 @@ import { ZodError } from "zod";
75
75
 
76
76
  // src/schemas/project-config-schema.ts
77
77
  import { z } from "zod";
78
+
79
+ // src/utils/is-iana-timezone.ts
80
+ var timezones = /* @__PURE__ */ new Set([...Intl.supportedValuesOf("timeZone"), "UTC"]);
81
+ function isIanaTimeZone(value) {
82
+ return typeof value === "string" && timezones.has(value);
83
+ }
84
+
85
+ // src/schemas/project-config-schema.ts
78
86
  var fileFormatSchema = z.enum(["csv", "json", "parquet"]);
79
87
  var aemoDataFetcherSchema = z.object({
80
88
  type: z.literal("AEMO_MMS"),
@@ -104,6 +112,7 @@ var projectConfigSchema = z.object({
104
112
  name: z.string(),
105
113
  forecastVariable: z.enum(["price"]),
106
114
  timeHorizon: z.enum(["actual", "day_ahead", "week_ahead", "quarterly"]),
115
+ displayTimezone: z.string().refine(isIanaTimeZone, "invalid IANA time zone").optional().default("Australia/Brisbane"),
107
116
  metadata: z.record(z.string(), z.any()).optional(),
108
117
  inputs: z.array(modelInputSchema),
109
118
  outputs: z.array(modelOutputSchema),
@@ -126,17 +135,17 @@ async function isExistingPath(path15) {
126
135
  }
127
136
 
128
137
  // src/config/load-project-context.ts
129
- async function loadProjectContext() {
138
+ async function loadProjectContext(configPath) {
130
139
  const projectRoot = process.cwd();
131
- const configPath = path.join(projectRoot, PROJECT_CONFIG_FILE);
132
- const configExists = await isExistingPath(configPath);
140
+ const resolvedConfigPath = configPath ? path.resolve(configPath) : path.join(projectRoot, PROJECT_CONFIG_FILE);
141
+ const configExists = await isExistingPath(resolvedConfigPath);
133
142
  if (!configExists) {
134
143
  throw new Error(
135
- "No config found (docs: https://github.com/pipelabs/pd4castr-model-examples/blob/main/docs/005-config.md)."
144
+ `No config found at ${resolvedConfigPath} (docs: https://github.com/pipelabs/pd4castr-model-examples/blob/main/docs/005-config.md).`
136
145
  );
137
146
  }
138
147
  try {
139
- const configFileContents = await fs2.readFile(configPath, "utf8");
148
+ const configFileContents = await fs2.readFile(resolvedConfigPath, "utf8");
140
149
  const rawConfig = JSON.parse(configFileContents);
141
150
  const config = projectConfigSchema.parse(rawConfig);
142
151
  return {
@@ -318,7 +327,7 @@ async function handleAction(options) {
318
327
  const spinner = ora("Starting data fetch...").start();
319
328
  try {
320
329
  const authCtx = await getAuth();
321
- const ctx = await loadProjectContext();
330
+ const ctx = await loadProjectContext(options.config);
322
331
  const inputsWithFetchers = ctx.config.inputs.filter((input2) => input2.fetcher);
323
332
  if (inputsWithFetchers.length === 0) {
324
333
  spinner.info("No inputs with data fetchers found, skipping");
@@ -371,7 +380,7 @@ function registerFetchCommand(program2) {
371
380
  "-i, --input-dir <path>",
372
381
  "The input test data directory",
373
382
  TEST_INPUT_DATA_DIR
374
- ).action(handleAction);
383
+ ).option("-c, --config <path>", "Path to config file", PROJECT_CONFIG_FILE).action(handleAction);
375
384
  }
376
385
 
377
386
  // src/commands/init/handle-action.ts
@@ -663,11 +672,12 @@ async function triggerModelRun(modelId, authCtx) {
663
672
  import fs7 from "fs/promises";
664
673
  import path8 from "path";
665
674
  import { produce as produce2 } from "immer";
666
- async function updateProjectConfig(updateFn) {
667
- const projectConfig = await loadProjectContext();
675
+ async function updateProjectConfig(updateFn, configPath) {
676
+ const projectConfig = await loadProjectContext(configPath);
668
677
  const updatedConfig = produce2(projectConfig.config, updateFn);
678
+ const resolvedConfigPath = configPath ? path8.resolve(configPath) : path8.join(projectConfig.projectRoot, PROJECT_CONFIG_FILE);
669
679
  await fs7.writeFile(
670
- path8.join(projectConfig.projectRoot, PROJECT_CONFIG_FILE),
680
+ resolvedConfigPath,
671
681
  JSON.stringify(updatedConfig, void 0, 2)
672
682
  );
673
683
  }
@@ -1019,7 +1029,8 @@ async function handleCreateModelFlow(options, app, spinner, ctx, authCtx) {
1019
1029
  config.$$modelGroupID = model.modelGroupId;
1020
1030
  config.$$revision = model.revision;
1021
1031
  config.$$dockerImage = model.dockerImage;
1022
- });
1032
+ config.displayTimezone = model.displayTimezone;
1033
+ }, options.config);
1023
1034
  spinner.succeed("Model data published successfully");
1024
1035
  spinner.start(
1025
1036
  "Pushing model image to registry - this may take a few minutes..."
@@ -1117,7 +1128,7 @@ async function handleModelRevisionCreateFlow(options, app, spinner, ctx, authCtx
1117
1128
  config.$$modelGroupID = model.modelGroupId;
1118
1129
  config.$$revision = model.revision;
1119
1130
  config.$$dockerImage = model.dockerImage;
1120
- });
1131
+ }, options.config);
1121
1132
  spinner.succeed("Model revision data published successfully");
1122
1133
  spinner.start(
1123
1134
  "Pushing new model revision image to registry - this may take a few minutes..."
@@ -1194,7 +1205,8 @@ async function handleModelRevisionUpdateFlow(options, app, spinner, ctx, authCtx
1194
1205
  config.$$modelGroupID = model.modelGroupId;
1195
1206
  config.$$revision = model.revision;
1196
1207
  config.$$dockerImage = model.dockerImage;
1197
- });
1208
+ config.displayTimezone = model.displayTimezone;
1209
+ }, options.config);
1198
1210
  spinner.succeed("Model revision data updated successfully");
1199
1211
  spinner.start(
1200
1212
  "Pushing updated model image to registry - this may take a few minutes..."
@@ -1265,7 +1277,7 @@ async function handleAction5(options) {
1265
1277
  app.use(express2.urlencoded({ limit: "100mb", extended: true }));
1266
1278
  const webServer = __using(_stack, await startWebServer(app, options.port));
1267
1279
  try {
1268
- const ctx = await loadProjectContext();
1280
+ const ctx = await loadProjectContext(options.config);
1269
1281
  const authCtx = await getAuth();
1270
1282
  await (ctx.config.$$id ? handleUpdateExistingModelFlow(options, app, spinner, ctx, authCtx) : handleCreateModelFlow(options, app, spinner, ctx, authCtx));
1271
1283
  } catch (error) {
@@ -1302,7 +1314,7 @@ function registerPublishCommand(program2) {
1302
1314
  "-p, --port <port>",
1303
1315
  "The port to run the IO testing webserver on",
1304
1316
  TEST_WEBSERVER_PORT.toString()
1305
- ).option("--sc, --skip-checks", "Skip the model I/O checks", false).option("--st, --skip-trigger", "Skip the model trigger", false).action(handleAction5);
1317
+ ).option("--sc, --skip-checks", "Skip the model I/O checks", false).option("--st, --skip-trigger", "Skip the model trigger", false).option("-c, --config <path>", "Path to config file", PROJECT_CONFIG_FILE).action(handleAction5);
1306
1318
  }
1307
1319
 
1308
1320
  // src/commands/test/handle-action.ts
@@ -1320,7 +1332,7 @@ async function handleAction6(options) {
1320
1332
  app.use(express3.urlencoded({ limit: "100mb", extended: true }));
1321
1333
  const webServer = __using(_stack, await startWebServer(app, options.port));
1322
1334
  try {
1323
- const ctx = await loadProjectContext();
1335
+ const ctx = await loadProjectContext(options.config);
1324
1336
  const inputFiles = getInputFiles(ctx.config);
1325
1337
  spinner.start("Checking test input data files");
1326
1338
  await checkInputFiles(inputFiles, options.inputDir, ctx);
@@ -1394,7 +1406,7 @@ function registerTestCommand(program2) {
1394
1406
  "-p, --port <port>",
1395
1407
  "The port to run the IO testing webserver on",
1396
1408
  TEST_WEBSERVER_PORT.toString()
1397
- ).action(handleAction6);
1409
+ ).option("-c, --config <path>", "Path to config file", PROJECT_CONFIG_FILE).action(handleAction6);
1398
1410
  }
1399
1411
 
1400
1412
  // src/program.ts
@@ -1403,7 +1415,7 @@ import { Command } from "commander";
1403
1415
  // package.json
1404
1416
  var package_default = {
1405
1417
  name: "@pd4castr/cli",
1406
- version: "1.0.1",
1418
+ version: "1.2.0",
1407
1419
  description: "CLI tool for creating, testing, and publishing pd4castr models",
1408
1420
  main: "dist/index.js",
1409
1421
  type: "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pd4castr/cli",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "CLI tool for creating, testing, and publishing pd4castr models",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",