@pd4castr/cli 0.0.11 → 0.0.12

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 (3) hide show
  1. package/README.md +20 -27
  2. package/dist/index.js +72 -45
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pd4castr CLI
2
2
 
3
- CLI tool for creating, testing, and publishing pd4castr models.
3
+ CLI tool for creating, testing, and publishing [pd4castr](https://pdview.com.au/services/pd4castr/) models.
4
4
 
5
5
  Install via:
6
6
 
@@ -8,41 +8,34 @@ Install via:
8
8
  npm install -g @pd4castr/cli
9
9
  ```
10
10
 
11
- ## Contributing
11
+ Read the [full documentation here](https://github.com/pipelabs/pd4castr-model-examples/)
12
12
 
13
- ### Quick Start
13
+ ## Quick Usage
14
14
 
15
- ```bash
16
- # set this repository up for linking during develpment
17
- yarn link
15
+ Authenticate with the pd4castr API
18
16
 
19
- # run the project in watch mode
20
- yarn dev
17
+ ```sh
18
+ pd4castr login
19
+ ```
21
20
 
22
- # from a model project, link the module
23
- # ex. https://github.com/pipelabs/pd4castr-model-examples/tree/main/examples/python-demo
24
- yarn link @pd4castr/cli
21
+ Run model input data fetchers and generate test input data
25
22
 
26
- # from that project, execute a command
27
- yarn pd4castr <command>
23
+ ```sh
24
+ pd4castr fetch
28
25
  ```
29
26
 
30
- ### Scripts
27
+ Run your model locally and verify it reads inputs & uploads output as expected
31
28
 
32
- - `yarn build` - Build the project
33
- - `yarn dev` - Watch mode for development
34
- - `yarn cli <command>` - Run CLI commands against local build
35
- - `yarn test` - Run tests once
36
- - `yarn test:watch` - Run tests in watch mode
37
- - `yarn lint` - Check for linting issues
38
- - `yarn format` - Format code with Prettier
39
- - `yarn type-check` - TypeScript type checking
29
+ ```sh
30
+ pd4castr test
31
+ ```
40
32
 
41
- ### Testing
33
+ Publish your model to the pd4castr platform
42
34
 
43
- As this project requires a lot of disk I/O and network reqeuests, we opt for 2 mocking solutions that keep us as close to the metal as possible:
35
+ ```sh
36
+ pd4castr publish
37
+ ```
44
38
 
45
- - network requests are mocked uses [msw](https://mswjs.io/) - request handlers live in the [mocks/handlers](./src/mocks/handlers/) folder
46
- - disk I/O (`fs`) is mocked using [`memfs`](https://github.com/streamich/memfs) which is handled by Vitest in our [`__mocks__/`](./src/__mocks__) folder
39
+ ## Contributing
47
40
 
48
- Both of these mocks are initialised globally via our [setup script](./vitest.setup.ts).
41
+ For development docs, check [CONTRIBUTING.MD](./CONTRIBUTING.md)
package/dist/index.js CHANGED
@@ -626,7 +626,7 @@ async function startWebServer(app, port) {
626
626
 
627
627
  // src/commands/publish/handle-create-model-flow.ts
628
628
  import * as inquirer2 from "@inquirer/prompts";
629
- import chalk2 from "chalk";
629
+ import chalk3 from "chalk";
630
630
 
631
631
  // src/api/create-model.ts
632
632
  async function createModel(config, authCtx) {
@@ -667,10 +667,14 @@ async function updateProjectConfig(updateFn) {
667
667
  import { execa } from "execa";
668
668
  async function buildDockerImage(dockerImage, ctx) {
669
669
  try {
670
- await execa("docker", ["build", "-t", dockerImage, "."], {
671
- cwd: ctx.projectRoot,
672
- stdio: "pipe"
673
- });
670
+ await execa(
671
+ "docker",
672
+ ["build", "--platform=linux/amd64", "-t", dockerImage, "."],
673
+ {
674
+ cwd: ctx.projectRoot,
675
+ stdio: "pipe"
676
+ }
677
+ );
674
678
  } catch (error) {
675
679
  throw new Error("Failed to build docker image", { cause: error });
676
680
  }
@@ -771,19 +775,27 @@ function logEmptyLine() {
771
775
  console.log("");
772
776
  }
773
777
 
774
- // src/commands/publish/utils/get-model-summary-lines.ts
778
+ // src/commands/publish/constants.ts
775
779
  import chalk from "chalk";
780
+ var MODEL_RUN_TRIGGER_MESSAGE = `${chalk.whiteBright.bold("NOTE!")} If you do not see your model output in the pd4castr UI:
781
+
782
+ \u2022 If you are using static inputs - check you have uploaded your input data to your input bucket
783
+ \u2022 If you are using inputs with data fetchers - wait a few minutes and check again
784
+ `;
785
+
786
+ // src/commands/publish/utils/get-model-summary-lines.ts
787
+ import chalk2 from "chalk";
776
788
  function getModelSummaryLines(ctx) {
777
789
  return [
778
- ` ${chalk.bold("Model name:")} ${ctx.config.name}`,
779
- ` ${chalk.bold("Revision:")} ${ctx.config.$$revision}`,
780
- ` ${chalk.bold("Forecast variable:")} ${ctx.config.forecastVariable}`,
781
- ` ${chalk.bold("Time horizon:")} ${ctx.config.timeHorizon}`,
782
- ` ${chalk.bold("Inputs:")}`,
790
+ ` ${chalk2.bold("Model name:")} ${ctx.config.name}`,
791
+ ` ${chalk2.bold("Revision:")} ${ctx.config.$$revision}`,
792
+ ` ${chalk2.bold("Forecast variable:")} ${ctx.config.forecastVariable}`,
793
+ ` ${chalk2.bold("Time horizon:")} ${ctx.config.timeHorizon}`,
794
+ ` ${chalk2.bold("Inputs:")}`,
783
795
  ...ctx.config.inputs.map(
784
796
  (input2) => ` \u2022 ${input2.key} - ${getInputType(input2)}`
785
797
  ),
786
- ` ${chalk.bold("Outputs:")}`,
798
+ ` ${chalk2.bold("Outputs:")}`,
787
799
  ...ctx.config.outputs.map((output) => ` \u2022 ${output.name} - ${output.type}`),
788
800
  ""
789
801
  ];
@@ -973,7 +985,7 @@ async function runModelIOTests(dockerImage, options, app, ctx) {
973
985
 
974
986
  // src/commands/publish/handle-create-model-flow.ts
975
987
  async function handleCreateModelFlow(options, app, spinner, ctx, authCtx) {
976
- spinner.info(`You are publishing a ${chalk2.bold("new")} model:
988
+ spinner.info(`You are publishing a ${chalk3.bold("new")} model:
977
989
  `);
978
990
  getModelSummaryLines(ctx).map((line) => console.log(line));
979
991
  const confirm4 = await inquirer2.confirm({
@@ -1009,29 +1021,34 @@ async function handleCreateModelFlow(options, app, spinner, ctx, authCtx) {
1009
1021
  await pushDockerImage(dockerImage, model.dockerImage);
1010
1022
  spinner.succeed("Model image pushed to reogistry successfully");
1011
1023
  spinner.start("Triggering model run...");
1012
- try {
1013
- await triggerModelRun(model.id, authCtx);
1014
- spinner.succeed("Model run triggered successfully");
1015
- } catch {
1016
- spinner.warn(`Failed to trigger model run
1017
- If you use static inputs, make sure you have uploaded it to your input bucket
1018
- If you use inputs with data fetchers, your model will run when they have fetched new data`);
1024
+ let modelRunTriggered = false;
1025
+ if (!options.skipTrigger) {
1026
+ try {
1027
+ await triggerModelRun(model.id, authCtx);
1028
+ spinner.succeed("Model run triggered successfully");
1029
+ modelRunTriggered = true;
1030
+ } catch {
1031
+ spinner.info("Model run did not trigger");
1032
+ }
1019
1033
  }
1020
1034
  spinner.stopAndPersist({
1021
1035
  symbol: "\u{1F680} ",
1022
1036
  prefixText: "\n",
1023
1037
  suffixText: "\n",
1024
- text: chalk2.bold(`${model.name} r${model.revision} published successfully`)
1038
+ text: chalk3.bold(`${model.name} r${model.revision} published successfully`)
1025
1039
  });
1040
+ if (!modelRunTriggered && !options.skipTrigger) {
1041
+ console.log(MODEL_RUN_TRIGGER_MESSAGE);
1042
+ }
1026
1043
  }
1027
1044
 
1028
1045
  // src/commands/publish/handle-update-existing-model-flow.ts
1029
1046
  import * as inquirer5 from "@inquirer/prompts";
1030
- import chalk5 from "chalk";
1047
+ import chalk6 from "chalk";
1031
1048
 
1032
1049
  // src/commands/publish/handle-model-revision-create-flow.ts
1033
1050
  import * as inquirer3 from "@inquirer/prompts";
1034
- import chalk3 from "chalk";
1051
+ import chalk4 from "chalk";
1035
1052
 
1036
1053
  // src/commands/publish/utils/validate-local-model-state.ts
1037
1054
  import invariant2 from "tiny-invariant";
@@ -1060,7 +1077,7 @@ async function validateLocalModelState(ctx, authCtx) {
1060
1077
  }
1061
1078
 
1062
1079
  // src/commands/publish/handle-model-revision-create-flow.ts
1063
- var WARNING_LABEL = chalk3.yellowBright.bold("WARNING!");
1080
+ var WARNING_LABEL = chalk4.yellowBright.bold("WARNING!");
1064
1081
  var CONFIRMATION_MESSAGE = `${WARNING_LABEL} Creating a new revision will preserve existing revisions.
1065
1082
  Previous revisions will still be available in the pd4castr UI.
1066
1083
  `;
@@ -1102,27 +1119,32 @@ async function handleModelRevisionCreateFlow(options, app, spinner, ctx, authCtx
1102
1119
  await pushDockerImage(dockerImage, model.dockerImage);
1103
1120
  spinner.succeed("New model revision image pushed to registry successfully");
1104
1121
  spinner.start("Triggering model run...");
1105
- try {
1106
- await triggerModelRun(model.id, authCtx);
1107
- spinner.succeed("Model run triggered successfully");
1108
- } catch {
1109
- spinner.warn(`Failed to trigger model run
1110
- If you use static inputs, make sure you have uploaded it to your input bucket
1111
- If you use inputs with data fetchers, your model will run when they have fetched new data`);
1122
+ let modelRunTriggered = false;
1123
+ if (!options.skipTrigger) {
1124
+ try {
1125
+ await triggerModelRun(model.id, authCtx);
1126
+ spinner.succeed("Model run triggered successfully");
1127
+ modelRunTriggered = true;
1128
+ } catch {
1129
+ spinner.info("Model run did not trigger");
1130
+ }
1112
1131
  }
1113
1132
  spinner.stopAndPersist({
1114
1133
  symbol: "\u{1F680} ",
1115
1134
  prefixText: "\n",
1116
1135
  suffixText: "\n",
1117
- text: chalk3.bold(
1136
+ text: chalk4.bold(
1118
1137
  `New model revision (r${model.revision}) published successfully`
1119
1138
  )
1120
1139
  });
1140
+ if (!modelRunTriggered && !options.skipTrigger) {
1141
+ console.log(MODEL_RUN_TRIGGER_MESSAGE);
1142
+ }
1121
1143
  }
1122
1144
 
1123
1145
  // src/commands/publish/handle-model-revision-update-flow.ts
1124
1146
  import * as inquirer4 from "@inquirer/prompts";
1125
- import chalk4 from "chalk";
1147
+ import chalk5 from "chalk";
1126
1148
 
1127
1149
  // src/api/update-model.ts
1128
1150
  async function updateModel(config, authCtx) {
@@ -1132,7 +1154,7 @@ async function updateModel(config, authCtx) {
1132
1154
  }
1133
1155
 
1134
1156
  // src/commands/publish/handle-model-revision-update-flow.ts
1135
- var WARNING_LABEL2 = chalk4.yellowBright.bold("WARNING!");
1157
+ var WARNING_LABEL2 = chalk5.yellowBright.bold("WARNING!");
1136
1158
  var CONFIRMATION_MESSAGE2 = `${WARNING_LABEL2} Updating a model revision recreates the associated inputs and outputs.
1137
1159
  Historical data is preserved, but it will no longer be displayed in the pd4castr UI.
1138
1160
  `;
@@ -1174,25 +1196,30 @@ async function handleModelRevisionUpdateFlow(options, app, spinner, ctx, authCtx
1174
1196
  await pushDockerImage(dockerImage, model.dockerImage);
1175
1197
  spinner.succeed("Updated model image pushed to registry successfully");
1176
1198
  spinner.start("Triggering model run...");
1177
- try {
1178
- await triggerModelRun(model.id, authCtx);
1179
- spinner.succeed("Model run triggered successfully");
1180
- } catch {
1181
- spinner.warn(`Failed to trigger model run
1182
- If you use static inputs, make sure you have uploaded it to your input bucket
1183
- If you use inputs with data fetchers, your model will run when they have fetched new data`);
1199
+ let modelRunTriggered = false;
1200
+ if (!options.skipTrigger) {
1201
+ try {
1202
+ await triggerModelRun(model.id, authCtx);
1203
+ spinner.succeed("Model run triggered successfully");
1204
+ modelRunTriggered = true;
1205
+ } catch {
1206
+ spinner.info("Model run did not trigger");
1207
+ }
1184
1208
  }
1185
1209
  spinner.stopAndPersist({
1186
1210
  symbol: "\u{1F680} ",
1187
1211
  prefixText: "\n",
1188
1212
  suffixText: "\n",
1189
- text: chalk4.bold(`${model.name} (r${model.revision}) updated successfully`)
1213
+ text: chalk5.bold(`${model.name} (r${model.revision}) updated successfully`)
1190
1214
  });
1215
+ if (!modelRunTriggered && !options.skipTrigger) {
1216
+ console.log(MODEL_RUN_TRIGGER_MESSAGE);
1217
+ }
1191
1218
  }
1192
1219
 
1193
1220
  // src/commands/publish/handle-update-existing-model-flow.ts
1194
1221
  async function handleUpdateExistingModelFlow(options, app, spinner, ctx, authCtx) {
1195
- spinner.info(`You are publishing an ${chalk5.bold("existing")} model:
1222
+ spinner.info(`You are publishing an ${chalk6.bold("existing")} model:
1196
1223
  `);
1197
1224
  getModelSummaryLines(ctx).map((line) => console.log(line));
1198
1225
  const revision = ctx.config.$$revision ?? 0;
@@ -1266,7 +1293,7 @@ function registerPublishCommand(program2) {
1266
1293
  "-p, --port <port>",
1267
1294
  "The port to run the IO testing webserver on",
1268
1295
  TEST_WEBSERVER_PORT.toString()
1269
- ).option("-s, --skip-checks", "Skip the model I/O checks", false).action(handleAction5);
1296
+ ).option("--sc, --skip-checks", "Skip the model I/O checks", false).option("--st, --skip-trigger", "Skip the model trigger", false).action(handleAction5);
1270
1297
  }
1271
1298
 
1272
1299
  // src/commands/test/handle-action.ts
@@ -1367,7 +1394,7 @@ import { Command } from "commander";
1367
1394
  // package.json
1368
1395
  var package_default = {
1369
1396
  name: "@pd4castr/cli",
1370
- version: "0.0.11",
1397
+ version: "0.0.12",
1371
1398
  description: "CLI tool for creating, testing, and publishing pd4castr models",
1372
1399
  main: "dist/index.js",
1373
1400
  type: "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pd4castr/cli",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "CLI tool for creating, testing, and publishing pd4castr models",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",