@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.
- package/dist/index.js +31 -19
- 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://
|
|
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
|
|
132
|
-
const configExists = await isExistingPath(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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",
|