wrangler 2.18.0 → 2.20.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 (59) hide show
  1. package/miniflare-dist/index.mjs +1 -1
  2. package/package.json +1 -1
  3. package/src/__tests__/configuration.test.ts +8 -0
  4. package/src/__tests__/constellation.test.ts +371 -0
  5. package/src/__tests__/index.test.ts +2 -0
  6. package/src/__tests__/mtls-certificates.test.ts +1 -0
  7. package/src/__tests__/pages/functions-build.test.ts +76 -0
  8. package/src/__tests__/pages-deployment-tail.test.ts +2 -0
  9. package/src/__tests__/publish.test.ts +3 -3
  10. package/src/__tests__/tail.test.ts +38 -7
  11. package/src/__tests__/tsconfig.tsbuildinfo +1 -1
  12. package/src/__tests__/user.test.ts +1 -1
  13. package/src/api/dev.ts +5 -0
  14. package/src/api/pages/create-worker-bundle-contents.ts +1 -0
  15. package/src/api/pages/publish.tsx +28 -12
  16. package/src/bundle.ts +28 -7
  17. package/src/config/environment.ts +7 -0
  18. package/src/config/validation.ts +27 -0
  19. package/src/constellation/createProject.tsx +51 -0
  20. package/src/constellation/deleteProject.ts +51 -0
  21. package/src/constellation/deleteProjectModel.ts +68 -0
  22. package/src/constellation/index.ts +75 -0
  23. package/src/constellation/listCatalog.tsx +35 -0
  24. package/src/constellation/listModel.tsx +41 -0
  25. package/src/constellation/listProject.tsx +28 -0
  26. package/src/constellation/listRuntime.tsx +28 -0
  27. package/src/constellation/options.ts +17 -0
  28. package/src/constellation/types.ts +17 -0
  29. package/src/constellation/uploadModel.tsx +64 -0
  30. package/src/constellation/utils.ts +90 -0
  31. package/src/create-worker-upload-form.ts +4 -0
  32. package/src/dev/dev.tsx +6 -1
  33. package/src/dev/local.tsx +4 -0
  34. package/src/dev/remote.tsx +3 -0
  35. package/src/dev/start-server.ts +50 -39
  36. package/src/dev/use-esbuild.ts +54 -42
  37. package/src/dev.tsx +9 -4
  38. package/src/entry.ts +8 -1
  39. package/src/environment-variables/factory.ts +2 -1
  40. package/src/index.ts +10 -0
  41. package/src/init.ts +5 -0
  42. package/src/inspect.ts +107 -6
  43. package/src/logger.ts +5 -1
  44. package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -1
  45. package/src/pages/build.ts +30 -17
  46. package/src/pages/dev.ts +24 -6
  47. package/src/pages/functions/buildPlugin.ts +1 -0
  48. package/src/pages/functions/buildWorker.ts +59 -0
  49. package/src/pages/functions/tsconfig.tsbuildinfo +1 -1
  50. package/src/publish/publish.ts +6 -1
  51. package/src/secret/index.ts +1 -0
  52. package/src/tail/createTail.ts +9 -0
  53. package/src/tail/printing.ts +10 -0
  54. package/src/traverse-module-graph.ts +1 -0
  55. package/src/user/user.ts +1 -0
  56. package/src/utils/render.ts +1 -1
  57. package/src/worker.ts +5 -0
  58. package/wrangler-dist/cli.d.ts +13 -2
  59. package/wrangler-dist/cli.js +3879 -3264
@@ -60,7 +60,7 @@ describe("User", () => {
60
60
  expect(counter).toBe(1);
61
61
  expect(std.out).toMatchInlineSnapshot(`
62
62
  "Attempting to login via OAuth...
63
- Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
63
+ Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20constellation%3Awrite%20offline_access&state=MOCK_STATE_PARAM&code_challenge=MOCK_CODE_CHALLENGE&code_challenge_method=S256
64
64
  Successfully logged in."
65
65
  `);
66
66
  expect(readAuthConfigFile()).toEqual<UserAuthConfig>({
package/src/api/dev.ts CHANGED
@@ -3,6 +3,7 @@ import { startApiDev, startDev } from "../dev";
3
3
  import { logger } from "../logger";
4
4
 
5
5
  import type { Environment } from "../config";
6
+ import type { Rule } from "../config/environment";
6
7
  import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli/types";
7
8
  import type { RequestInit, Response, RequestInfo } from "undici";
8
9
 
@@ -42,6 +43,9 @@ export interface UnstableDevOptions {
42
43
  bucket_name: string;
43
44
  preview_bucket_name?: string;
44
45
  }[];
46
+ processEntrypoint?: boolean;
47
+ moduleRoot?: string;
48
+ rules?: Rule[];
45
49
  logLevel?: "none" | "info" | "error" | "log" | "warn" | "debug"; // Specify logging level [choices: "debug", "info", "log", "warn", "error", "none"] [default: "log"]
46
50
  inspect?: boolean;
47
51
  local?: boolean;
@@ -150,6 +154,7 @@ export async function unstable_dev(
150
154
  },
151
155
  config: options?.config,
152
156
  env: options?.env,
157
+ processEntrypoint: !!options?.processEntrypoint,
153
158
  bundle: options?.bundle,
154
159
  compatibilityDate: options?.compatibilityDate,
155
160
  compatibilityFlags: options?.compatibilityFlags,
@@ -70,6 +70,7 @@ function createWorkerBundleFormData(workerBundle: BundleResult): FormData {
70
70
  usage_model: undefined,
71
71
  keepVars: undefined,
72
72
  logpush: undefined,
73
+ placement: undefined,
73
74
  };
74
75
 
75
76
  return createWorkerUploadForm(worker);
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync } from "node:fs";
1
+ import { existsSync, lstatSync, readFileSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join, resolve as resolvePath } from "node:path";
4
4
  import { cwd } from "node:process";
@@ -14,6 +14,7 @@ import {
14
14
  import {
15
15
  buildRawWorker,
16
16
  checkRawWorker,
17
+ traverseAndBuildWorkerJSDirectory,
17
18
  } from "../../pages/functions/buildWorker";
18
19
  import { validateRoutes } from "../../pages/functions/routes-validation";
19
20
  import { upload } from "../../pages/upload";
@@ -65,7 +66,7 @@ interface PagesPublishOptions {
65
66
 
66
67
  /**
67
68
  * Whether to run bundling on `_worker.js` before deploying.
68
- * Default: false
69
+ * Default: true
69
70
  */
70
71
  bundle?: boolean;
71
72
 
@@ -95,9 +96,12 @@ export async function publish({
95
96
  _redirects: string | undefined,
96
97
  _routesGenerated: string | undefined,
97
98
  _routesCustom: string | undefined,
99
+ _workerJSIsDirectory = false,
98
100
  _workerJS: string | undefined;
99
101
 
100
- const workerScriptPath = resolvePath(directory, "_worker.js");
102
+ bundle = bundle ?? true;
103
+
104
+ const _workerPath = resolvePath(directory, "_worker.js");
101
105
 
102
106
  try {
103
107
  _headers = readFileSync(join(directory, "_headers"), "utf-8");
@@ -116,7 +120,10 @@ export async function publish({
116
120
  } catch {}
117
121
 
118
122
  try {
119
- _workerJS = readFileSync(workerScriptPath, "utf-8");
123
+ _workerJSIsDirectory = lstatSync(_workerPath).isDirectory();
124
+ if (!_workerJSIsDirectory) {
125
+ _workerJS = readFileSync(_workerPath, "utf-8");
126
+ }
120
127
  } catch {}
121
128
 
122
129
  // Grab the bindings from the API, we need these for shims and other such hacky inserts
@@ -240,16 +247,23 @@ export async function publish({
240
247
  * Advanced Mode
241
248
  * https://developers.cloudflare.com/pages/platform/functions/#advanced-mode
242
249
  *
243
- * When using a _worker.js file, the entire /functions directory is ignored
250
+ * When using a _worker.js file or _worker.js/ directory, the entire /functions directory is ignored
244
251
  * – this includes its routing and middleware characteristics.
245
252
  */
246
- if (_workerJS) {
253
+ if (_workerJSIsDirectory) {
254
+ workerBundle = await traverseAndBuildWorkerJSDirectory({
255
+ workerJSDirectory: _workerPath,
256
+ buildOutputDirectory: directory,
257
+ d1Databases,
258
+ nodejsCompat,
259
+ });
260
+ } else if (_workerJS) {
247
261
  if (bundle) {
248
262
  const outfile = join(tmpdir(), `./bundledWorker-${Math.random()}.mjs`);
249
263
  workerBundle = await buildRawWorker({
250
- workerScriptPath,
264
+ workerScriptPath: _workerPath,
251
265
  outfile,
252
- directory: directory ?? ".",
266
+ directory,
253
267
  local: false,
254
268
  sourcemap: true,
255
269
  watch: false,
@@ -258,17 +272,19 @@ export async function publish({
258
272
  nodejsCompat,
259
273
  });
260
274
  } else {
261
- await checkRawWorker(workerScriptPath, () => {});
262
- // TODO: Replace this with the cool new no-bundle stuff when that lands: https://github.com/cloudflare/workers-sdk/pull/2769
275
+ await checkRawWorker(_workerPath, () => {});
276
+ // TODO: Let users configure this in the future.
263
277
  workerBundle = {
264
278
  modules: [],
265
279
  dependencies: {},
266
280
  stop: undefined,
267
- resolvedEntryPointPath: workerScriptPath,
281
+ resolvedEntryPointPath: _workerPath,
268
282
  bundleType: "esm",
269
283
  };
270
284
  }
285
+ }
271
286
 
287
+ if (_workerJS || _workerJSIsDirectory) {
272
288
  const workerBundleContents = await createUploadWorkerBundleContents(
273
289
  workerBundle as BundleResult
274
290
  );
@@ -302,7 +318,7 @@ export async function publish({
302
318
  * Pages Functions
303
319
  * https://developers.cloudflare.com/pages/platform/functions/
304
320
  */
305
- if (builtFunctions && !_workerJS) {
321
+ if (builtFunctions && !_workerJS && !_workerJSIsDirectory) {
306
322
  const workerBundleContents = await createUploadWorkerBundleContents(
307
323
  workerBundle as BundleResult
308
324
  );
package/src/bundle.ts CHANGED
@@ -12,6 +12,7 @@ import type { Config } from "./config";
12
12
  import type { DurableObjectBindings } from "./config/environment";
13
13
  import type { WorkerRegistry } from "./dev-registry";
14
14
  import type { Entry } from "./entry";
15
+ import type { SourceMapMetadata } from "./inspect";
15
16
  import type { CfModule } from "./worker";
16
17
 
17
18
  export const COMMON_ESBUILD_OPTIONS = {
@@ -27,6 +28,7 @@ export type BundleResult = {
27
28
  bundleType: "esm" | "commonjs";
28
29
  stop: (() => void) | undefined;
29
30
  sourceMapPath?: string | undefined;
31
+ sourceMapMetadata?: SourceMapMetadata | undefined;
30
32
  };
31
33
 
32
34
  type StaticAssetsConfig =
@@ -77,15 +79,25 @@ export function isBuildFailure(err: unknown): err is esbuild.BuildFailure {
77
79
  * Rewrites esbuild BuildFailures for failing to resolve Node built-in modules
78
80
  * to suggest enabling Node compat as opposed to `platform: "node"`.
79
81
  */
80
- export function rewriteNodeCompatBuildFailure(err: esbuild.BuildFailure) {
82
+ export function rewriteNodeCompatBuildFailure(
83
+ err: esbuild.BuildFailure,
84
+ forPages = false
85
+ ) {
81
86
  for (const error of err.errors) {
82
87
  const match = nodeBuiltinResolveErrorText.exec(error.text);
83
88
  if (match !== null) {
89
+ const issue = `The package "${match[1]}" wasn't found on the file system but is built into node.`;
90
+
91
+ const instructionForUser = `${
92
+ forPages
93
+ ? 'Add the "nodejs_compat" compatibility flag to your Pages project'
94
+ : 'Add "node_compat = true" to your wrangler.toml file'
95
+ } to enable Node.js compatibility.`;
96
+
84
97
  error.notes = [
85
98
  {
86
99
  location: null,
87
- text: `The package "${match[1]}" wasn't found on the file system but is built into node.
88
- Add "node_compat = true" to your wrangler.toml file to enable Node compatibility.`,
100
+ text: `${issue}\n${instructionForUser}`,
89
101
  },
90
102
  ];
91
103
  }
@@ -117,6 +129,8 @@ export async function bundleWorker(
117
129
  entry: Entry,
118
130
  destination: string,
119
131
  options: {
132
+ // When `bundle` is set to false, we apply shims to the Worker, but won't pull in any imports
133
+ bundle?: boolean;
120
134
  serveAssetsFromWorker: boolean;
121
135
  assets?: StaticAssetsConfig;
122
136
  betaD1Shims?: string[];
@@ -146,9 +160,11 @@ export async function bundleWorker(
146
160
  // TODO: Rip these out https://github.com/cloudflare/workers-sdk/issues/2153
147
161
  disableModuleCollection?: boolean;
148
162
  isOutfile?: boolean;
163
+ forPages?: boolean;
149
164
  }
150
165
  ): Promise<BundleResult> {
151
166
  const {
167
+ bundle = true,
152
168
  serveAssetsFromWorker,
153
169
  betaD1Shims,
154
170
  doBindings,
@@ -176,6 +192,7 @@ export async function bundleWorker(
176
192
  plugins,
177
193
  disableModuleCollection,
178
194
  isOutfile,
195
+ forPages,
179
196
  } = options;
180
197
 
181
198
  // We create a temporary directory for any oneoff files we
@@ -350,7 +367,7 @@ export async function bundleWorker(
350
367
 
351
368
  const buildOptions: esbuild.BuildOptions & { metafile: true } = {
352
369
  entryPoints: [inputEntry.file],
353
- bundle: true,
370
+ bundle,
354
371
  absWorkingDir: entry.directory,
355
372
  outdir: destination,
356
373
  entryNames: entryName || path.parse(entry.file).name,
@@ -362,10 +379,10 @@ export async function bundleWorker(
362
379
  }
363
380
  : {}),
364
381
  inject,
365
- external: ["__STATIC_CONTENT_MANIFEST"],
382
+ external: bundle ? ["__STATIC_CONTENT_MANIFEST"] : undefined,
366
383
  format: entry.format === "modules" ? "esm" : "iife",
367
384
  target: COMMON_ESBUILD_OPTIONS.target,
368
- sourcemap: sourcemap ?? true, // this needs to use ?? to accept false
385
+ sourcemap: sourcemap ?? true,
369
386
  // Include a reference to the output folder in the sourcemap.
370
387
  // This is omitted by default, but we need it to properly resolve source paths in error output.
371
388
  sourceRoot: destination,
@@ -409,7 +426,7 @@ export async function bundleWorker(
409
426
  result = await esbuild.build(buildOptions);
410
427
  } catch (e) {
411
428
  if (!legacyNodeCompat && isBuildFailure(e))
412
- rewriteNodeCompatBuildFailure(e);
429
+ rewriteNodeCompatBuildFailure(e, forPages);
413
430
  throw e;
414
431
  }
415
432
 
@@ -455,6 +472,10 @@ export async function bundleWorker(
455
472
  bundleType,
456
473
  stop: result.stop,
457
474
  sourceMapPath,
475
+ sourceMapMetadata: {
476
+ tmpDir: tmpDir.path,
477
+ entryDirectory: entry.directory,
478
+ },
458
479
  };
459
480
  }
460
481
 
@@ -265,6 +265,13 @@ interface EnvironmentInheritable {
265
265
  * @inheritable
266
266
  */
267
267
  logpush: boolean | undefined;
268
+
269
+ /**
270
+ * Specify how the worker should be located to minimize round-trip time.
271
+ *
272
+ * More details: https://developers.cloudflare.com/workers/platform/smart-placement/
273
+ */
274
+ placement: { mode: "off" | "smart" } | undefined;
268
275
  }
269
276
 
270
277
  export type DurableObjectBindings = {
@@ -873,6 +873,32 @@ function validateRoutes(
873
873
  );
874
874
  }
875
875
 
876
+ function normalizeAndValidatePlacement(
877
+ diagnostics: Diagnostics,
878
+ topLevelEnv: Environment | undefined,
879
+ rawEnv: RawEnvironment
880
+ ): Config["placement"] {
881
+ if (rawEnv.placement) {
882
+ validateRequiredProperty(
883
+ diagnostics,
884
+ "placement",
885
+ "mode",
886
+ rawEnv.placement.mode,
887
+ "string",
888
+ ["off", "smart"]
889
+ );
890
+ }
891
+
892
+ return inheritable(
893
+ diagnostics,
894
+ topLevelEnv,
895
+ rawEnv,
896
+ "placement",
897
+ () => true,
898
+ undefined
899
+ );
900
+ }
901
+
876
902
  /**
877
903
  * Validate top-level environment configuration and return the normalized values.
878
904
  */
@@ -1060,6 +1086,7 @@ function normalizeAndValidateEnvironment(
1060
1086
  isOneOf("bundled", "unbound"),
1061
1087
  undefined
1062
1088
  ),
1089
+ placement: normalizeAndValidatePlacement(diagnostics, topLevelEnv, rawEnv),
1063
1090
  build,
1064
1091
  workers_dev,
1065
1092
  // Not inherited fields
@@ -0,0 +1,51 @@
1
+ import { fetchResult } from "../cfetch";
2
+ import { withConfig } from "../config";
3
+ import { logger } from "../logger";
4
+ import { requireAuth } from "../user";
5
+ import { takeName } from "./options";
6
+ import { constellationBetaWarning } from "./utils";
7
+ import type {
8
+ CommonYargsArgv,
9
+ StrictYargsOptionsToInterface,
10
+ } from "../yargs-types";
11
+ import type { Project } from "./types";
12
+
13
+ export function options(yargs: CommonYargsArgv) {
14
+ return takeName(yargs)
15
+ .positional("runtime", {
16
+ describe: "The name of the runtime to use",
17
+ type: "string",
18
+ demandOption: true,
19
+ })
20
+ .epilogue(constellationBetaWarning);
21
+ }
22
+
23
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof options>;
24
+ export const handler = withConfig<HandlerOptions>(
25
+ async ({ name, runtime, config }): Promise<void> => {
26
+ const accountId = await requireAuth(config);
27
+
28
+ logger.log(constellationBetaWarning);
29
+
30
+ let proj: Project;
31
+ try {
32
+ proj = await fetchResult(`/accounts/${accountId}/constellation/project`, {
33
+ method: "POST",
34
+ headers: {
35
+ "Content-Type": "application/json",
36
+ },
37
+ body: JSON.stringify({
38
+ name,
39
+ runtime,
40
+ }),
41
+ });
42
+ } catch (e) {
43
+ if ((e as { code: number }).code === 7409) {
44
+ throw new Error("A project with that name already exists");
45
+ }
46
+ throw e;
47
+ }
48
+
49
+ logger.log(`✅ Successfully created Project "${proj.name}"!`);
50
+ }
51
+ );
@@ -0,0 +1,51 @@
1
+ import { fetchResult } from "../cfetch";
2
+ import { withConfig } from "../config";
3
+ import { confirm } from "../dialogs";
4
+ import { logger } from "../logger";
5
+ import { requireAuth } from "../user";
6
+ import { takeName } from "./options";
7
+ import { constellationBetaWarning, getProjectByName } from "./utils";
8
+ import type {
9
+ CommonYargsArgv,
10
+ StrictYargsOptionsToInterface,
11
+ } from "../yargs-types";
12
+
13
+ export function options(yargs: CommonYargsArgv) {
14
+ return takeName(yargs)
15
+ .option("force", {
16
+ describe: "Skip confirmation",
17
+ type: "boolean",
18
+ alias: "f",
19
+ default: false,
20
+ })
21
+ .epilogue(constellationBetaWarning);
22
+ }
23
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof options>;
24
+ export const handler = withConfig<HandlerOptions>(
25
+ async ({ name, force, config }): Promise<void> => {
26
+ const accountId = await requireAuth(config);
27
+ logger.log(constellationBetaWarning);
28
+
29
+ const proj = await getProjectByName(config, accountId, name);
30
+
31
+ logger.log(`About to delete Project '${name}' (${proj.id}).`);
32
+ if (!force) {
33
+ const response = await confirm(`Ok to proceed?`);
34
+ if (!response) {
35
+ logger.log(`Not deleting.`);
36
+ return;
37
+ }
38
+
39
+ logger.log("Deleting...");
40
+ }
41
+
42
+ await fetchResult(
43
+ `/accounts/${accountId}/constellation/project/${proj.id}`,
44
+ {
45
+ method: "DELETE",
46
+ }
47
+ );
48
+
49
+ logger.log(`Deleted '${name}' successfully.`);
50
+ }
51
+ );
@@ -0,0 +1,68 @@
1
+ import { fetchResult } from "../cfetch";
2
+ import { withConfig } from "../config";
3
+ import { confirm } from "../dialogs";
4
+ import { logger } from "../logger";
5
+ import { requireAuth } from "../user";
6
+ import { takeName } from "./options";
7
+ import {
8
+ constellationBetaWarning,
9
+ getProjectByName,
10
+ getProjectModelByName,
11
+ } from "./utils";
12
+ import type {
13
+ CommonYargsArgv,
14
+ StrictYargsOptionsToInterface,
15
+ } from "../yargs-types";
16
+ import type { Project, Model } from "./types";
17
+
18
+ export function options(yargs: CommonYargsArgv) {
19
+ return takeName(yargs)
20
+ .positional("modelName", {
21
+ describe: "The name of the uploaded model",
22
+ type: "string",
23
+ demandOption: true,
24
+ })
25
+ .option("force", {
26
+ describe: "Skip confirmation",
27
+ type: "boolean",
28
+ alias: "f",
29
+ default: false,
30
+ })
31
+ .epilogue(constellationBetaWarning);
32
+ }
33
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof options>;
34
+ export const handler = withConfig<HandlerOptions>(
35
+ async ({ name, modelName, force, config }): Promise<void> => {
36
+ const accountId = await requireAuth(config);
37
+ logger.log(constellationBetaWarning);
38
+
39
+ const proj: Project = await getProjectByName(config, accountId, name);
40
+
41
+ const model: Model = await getProjectModelByName(
42
+ config,
43
+ accountId,
44
+ proj,
45
+ modelName
46
+ );
47
+
48
+ logger.log(`About to delete Model '${modelName}' (${model.id}).`);
49
+ if (!force) {
50
+ const response = await confirm(`Ok to proceed?`);
51
+ if (!response) {
52
+ logger.log(`Not deleting.`);
53
+ return;
54
+ }
55
+
56
+ logger.log("Deleting...");
57
+ }
58
+
59
+ await fetchResult(
60
+ `/accounts/${accountId}/constellation/project/${proj.id}/model/${model.id}`,
61
+ {
62
+ method: "DELETE",
63
+ }
64
+ );
65
+
66
+ logger.log(`Deleted '${modelName}' successfully.`);
67
+ }
68
+ );
@@ -0,0 +1,75 @@
1
+ import * as CreateProject from "./createProject";
2
+ import * as DeleteProject from "./deleteProject";
3
+ import * as DeleteProjectModel from "./deleteProjectModel";
4
+ import * as ListCatalog from "./listCatalog";
5
+ import * as ListModel from "./listModel";
6
+ import * as ListProject from "./listProject";
7
+ import * as ListRuntime from "./listRuntime";
8
+ import * as UploadModel from "./uploadModel";
9
+ import type { CommonYargsArgv } from "../yargs-types";
10
+
11
+ export function constellation(yargs: CommonYargsArgv) {
12
+ return yargs
13
+ .command("project", "Manage your projects", (constProjYargs) => {
14
+ return constProjYargs
15
+ .command(
16
+ "list",
17
+ "List your projects",
18
+ ListProject.options,
19
+ ListProject.handler
20
+ )
21
+ .command(
22
+ "create <name> <runtime>",
23
+ "Create project",
24
+ CreateProject.options,
25
+ CreateProject.handler
26
+ )
27
+ .command(
28
+ "delete <name>",
29
+ "Delete project",
30
+ DeleteProject.options,
31
+ DeleteProject.handler
32
+ );
33
+ })
34
+ .command("model", "Manage your models", (constModelYargs) => {
35
+ return constModelYargs
36
+ .command(
37
+ "upload <name> <modelName> <modelFile>",
38
+ "Upload a model for an existing project",
39
+ UploadModel.options,
40
+ UploadModel.handler
41
+ )
42
+ .command(
43
+ "list <name>",
44
+ "List models of a project",
45
+ ListModel.options,
46
+ ListModel.handler
47
+ )
48
+ .command(
49
+ "delete <name> <modelName>",
50
+ "Delete a model of a project",
51
+ DeleteProjectModel.options,
52
+ DeleteProjectModel.handler
53
+ );
54
+ })
55
+ .command(
56
+ "catalog",
57
+ "Check the curated model catalog",
58
+ (constCatalogYargs) => {
59
+ return constCatalogYargs.command(
60
+ "list",
61
+ "List catalog models",
62
+ ListCatalog.options,
63
+ ListCatalog.handler
64
+ );
65
+ }
66
+ )
67
+ .command("runtime", "Check the suported runtimes", (constRuntimeYargs) => {
68
+ return constRuntimeYargs.command(
69
+ "list",
70
+ "List suported runtimes",
71
+ ListRuntime.options,
72
+ ListRuntime.handler
73
+ );
74
+ });
75
+ }
@@ -0,0 +1,35 @@
1
+ import { withConfig } from "../config";
2
+ import { logger } from "../logger";
3
+ import { requireAuth } from "../user";
4
+ import { asJson } from "./options";
5
+ import { constellationBetaWarning, listCatalogEntries } from "./utils";
6
+ import type {
7
+ CommonYargsArgv,
8
+ StrictYargsOptionsToInterface,
9
+ } from "../yargs-types";
10
+
11
+ export function options(yargs: CommonYargsArgv) {
12
+ return asJson(yargs).epilogue(constellationBetaWarning);
13
+ }
14
+
15
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof options>;
16
+ export const handler = withConfig<HandlerOptions>(
17
+ async ({ json, config }): Promise<void> => {
18
+ const accountId = await requireAuth(config);
19
+ const entries = await listCatalogEntries(accountId);
20
+
21
+ if (json) {
22
+ logger.log(JSON.stringify(entries, null, 2));
23
+ } else {
24
+ logger.log(constellationBetaWarning);
25
+ logger.table(
26
+ entries.map((entry) => ({
27
+ project_id: entry.project.id,
28
+ project_name: entry.project.name,
29
+ project_runtime: entry.project.runtime,
30
+ models: entry.models.map((model) => model.name).join(","),
31
+ }))
32
+ );
33
+ }
34
+ }
35
+ );
@@ -0,0 +1,41 @@
1
+ import { withConfig } from "../config";
2
+ import { logger } from "../logger";
3
+ import { requireAuth } from "../user";
4
+ import { takeName } from "./options";
5
+ import {
6
+ constellationBetaWarning,
7
+ getProjectByName,
8
+ listModels,
9
+ } from "./utils";
10
+ import type {
11
+ CommonYargsArgv,
12
+ StrictYargsOptionsToInterface,
13
+ } from "../yargs-types";
14
+ import type { Project } from "./types";
15
+
16
+ export function options(yargs: CommonYargsArgv) {
17
+ return takeName(yargs)
18
+ .option("json", {
19
+ describe: "return output as clean JSON",
20
+ type: "boolean",
21
+ default: false,
22
+ })
23
+ .epilogue(constellationBetaWarning);
24
+ }
25
+
26
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof options>;
27
+ export const handler = withConfig<HandlerOptions>(
28
+ async ({ name, json, config }): Promise<void> => {
29
+ const accountId = await requireAuth(config);
30
+ const proj: Project = await getProjectByName(config, accountId, name);
31
+
32
+ const models = await listModels(accountId, proj);
33
+
34
+ if (json) {
35
+ logger.log(JSON.stringify(models, null, 2));
36
+ } else {
37
+ logger.log(constellationBetaWarning);
38
+ logger.table(models);
39
+ }
40
+ }
41
+ );
@@ -0,0 +1,28 @@
1
+ import { withConfig } from "../config";
2
+ import { logger } from "../logger";
3
+ import { requireAuth } from "../user";
4
+ import { asJson } from "./options";
5
+ import { constellationBetaWarning, listProjects } from "./utils";
6
+ import type {
7
+ CommonYargsArgv,
8
+ StrictYargsOptionsToInterface,
9
+ } from "../yargs-types";
10
+
11
+ export function options(yargs: CommonYargsArgv) {
12
+ return asJson(yargs).epilogue(constellationBetaWarning);
13
+ }
14
+
15
+ type HandlerOptions = StrictYargsOptionsToInterface<typeof options>;
16
+ export const handler = withConfig<HandlerOptions>(
17
+ async ({ json, config }): Promise<void> => {
18
+ const accountId = await requireAuth(config);
19
+ const projs = await listProjects(accountId);
20
+
21
+ if (json) {
22
+ logger.log(JSON.stringify(projs, null, 2));
23
+ } else {
24
+ logger.log(constellationBetaWarning);
25
+ logger.table(projs);
26
+ }
27
+ }
28
+ );