@freecodecamp/universe-cli 0.12.0 → 0.13.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.cjs +162 -59
  2. package/package.json +30 -27
package/dist/index.cjs CHANGED
@@ -9609,7 +9609,7 @@ var require_public_api = /* @__PURE__ */ __commonJSMin(((exports) => {
9609
9609
  exports.stringify = stringify;
9610
9610
  }));
9611
9611
  //#endregion
9612
- //#region src/commands/create/layer-composition/build-compose-dev-yaml.ts
9612
+ //#region src/commands/create/layer-composition/build-compose-yaml.ts
9613
9613
  var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
9614
9614
  var composer = require_composer();
9615
9615
  var Document = require_Document();
@@ -9656,7 +9656,7 @@ var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
9656
9656
  exports.visit = visit.visit;
9657
9657
  exports.visitAsync = visit.visitAsync;
9658
9658
  })))();
9659
- const buildComposeDevYaml = (framework, packageManager) => {
9659
+ const buildComposeYaml = (framework, packageManager) => {
9660
9660
  const { port } = framework;
9661
9661
  const portMapping = `${port}:${port}`;
9662
9662
  const syncEntries = framework.watchSync.map((entry) => ({
@@ -9677,6 +9677,28 @@ const buildComposeDevYaml = (framework, packageManager) => {
9677
9677
  ports: [portMapping]
9678
9678
  } } });
9679
9679
  };
9680
+ const buildDevcontainerComposeYaml = () => `services:
9681
+ devcontainer:
9682
+ build:
9683
+ context: ..
9684
+ target: dev
9685
+ command: ["sleep", "infinity"]
9686
+ volumes:
9687
+ # First mount the source
9688
+ - type: bind
9689
+ source: ..
9690
+ target: /app
9691
+ consistency: cached
9692
+ # Then mount an anonymous volume to hold node_modules. Otherwise the bind mount causes the host node_modules to be used.
9693
+ - type: volume
9694
+ target: /app/node_modules
9695
+ `;
9696
+ const buildDevcontainerJson = () => `{
9697
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
9698
+ "dockerComposeFile": ["./docker-compose.yml"],
9699
+ "service": "devcontainer",
9700
+ "workspaceFolder": "/app"
9701
+ }`;
9680
9702
  //#endregion
9681
9703
  //#region src/output/exit-codes.ts
9682
9704
  /**
@@ -9804,7 +9826,7 @@ const composeLayerFiles = (layers, pmPreinstall) => {
9804
9826
  //#region src/commands/create/layer-composition/layer-template-renderer.ts
9805
9827
  var LayerTemplateRenderer = class {
9806
9828
  render(template, context) {
9807
- return template.replaceAll("{{name}}", context.name).replaceAll("{{port}}", String(context.port)).replaceAll("{{runtime}}", context.runtime).replaceAll("{{framework}}", context.framework);
9829
+ return template.replaceAll("{{name}}", context.name).replaceAll("{{port}}", String(context.port)).replaceAll("{{runtime}}", context.runtime).replaceAll("{{framework}}", context.framework).replaceAll("{{pmVersion}}", context.pmVersion);
9808
9830
  }
9809
9831
  };
9810
9832
  //#endregion
@@ -9864,23 +9886,24 @@ const buildDockerfileData = (runtime, framework, packageManager) => {
9864
9886
  const renderDockerfile = (data) => `FROM ${data.baseImage} AS base\nWORKDIR /app\n\nFROM base AS package-manager\n${data.pmInstall} \n\nFROM package-manager AS dev\n${data.devInstall}\n${data.devCopySource}\nCMD ${JSON.stringify(data.devCmd)}\n`;
9865
9887
  const resolveWithLayers = (input, layers, labels) => {
9866
9888
  const resolvedLayers = resolveOrderedLayers(input, layers);
9867
- const composedFiles = composeLayerFiles(resolvedLayers, input.packageManager === void 0 ? void 0 : layers["package-managers"][input.packageManager]?.preinstall);
9889
+ const pmData = input.packageManager !== void 0 ? layers["package-managers"][input.packageManager] : void 0;
9890
+ const composedFiles = composeLayerFiles(resolvedLayers, pmData?.preinstall);
9868
9891
  const renderer = new LayerTemplateRenderer();
9869
9892
  const frameworkData = layers.frameworks?.[input.framework];
9870
9893
  const context = {
9871
9894
  framework: getLabel(labels, "framework", input.framework),
9872
9895
  name: input.name,
9896
+ pmVersion: pmData?.pmVersion ?? "",
9873
9897
  port: frameworkData?.port ?? 0,
9874
9898
  runtime: getLabel(labels, "runtime", input.runtime)
9875
9899
  };
9876
9900
  const renderedFiles = Object.fromEntries(Object.entries(composedFiles).map(([filePath, content]) => [filePath, renderer.render(content, context)]));
9877
9901
  const runtimeData = layers.runtime?.[input.runtime];
9878
- if (runtimeData !== void 0 && frameworkData !== void 0 && input.packageManager !== void 0) {
9879
- const pmData = layers["package-managers"][input.packageManager];
9880
- if (pmData !== void 0) {
9881
- renderedFiles["Dockerfile"] = renderDockerfile(buildDockerfileData(runtimeData, frameworkData, pmData));
9882
- renderedFiles["docker-compose.dev.yml"] = buildComposeDevYaml(frameworkData, pmData);
9883
- }
9902
+ if (runtimeData !== void 0 && frameworkData !== void 0 && pmData !== void 0) {
9903
+ renderedFiles["Dockerfile"] = renderer.render(renderDockerfile(buildDockerfileData(runtimeData, frameworkData, pmData)), context);
9904
+ renderedFiles["compose.yaml"] = renderer.render(buildComposeYaml(frameworkData, pmData), context);
9905
+ renderedFiles[".devcontainer/docker-compose.yml"] = buildDevcontainerComposeYaml();
9906
+ renderedFiles[".devcontainer/devcontainer.json"] = buildDevcontainerJson();
9884
9907
  }
9885
9908
  return {
9886
9909
  files: renderedFiles,
@@ -9905,10 +9928,10 @@ var PackageManagerService = class {
9905
9928
  this.adapters = adapters;
9906
9929
  }
9907
9930
  async specifyDeps(options) {
9908
- const { manager, projectDirectory } = options;
9931
+ const { manager, pmVersion, projectDirectory } = options;
9909
9932
  const adapter = this.adapters[manager];
9910
9933
  if (!adapter) throw new Error(`Unknown package manager: ${manager}`);
9911
- await adapter.specifyDeps(projectDirectory);
9934
+ await adapter.specifyDeps(projectDirectory, pmVersion);
9912
9935
  }
9913
9936
  };
9914
9937
  //#endregion
@@ -9933,7 +9956,7 @@ Please check that the output format of list() has not changed, and that extractV
9933
9956
  if (devDependencies !== void 0) pinned.devDependencies = pin(devDependencies);
9934
9957
  return pinned;
9935
9958
  };
9936
- const createPackageSpecifier = (config) => ({ async specifyDeps(projectDirectory) {
9959
+ const createPackageSpecifier = (config) => ({ async run(projectDirectory) {
9937
9960
  const { lockfileName, runner, deleteBeforeFirstInstall } = config;
9938
9961
  const lockfilePath = (0, node_path.join)(projectDirectory, lockfileName);
9939
9962
  if (deleteBeforeFirstInstall) try {
@@ -9965,11 +9988,11 @@ const createPackageSpecifier = (config) => ({ async specifyDeps(projectDirectory
9965
9988
  } });
9966
9989
  //#endregion
9967
9990
  //#region src/commands/create/package-manager/docker-runner.ts
9968
- const execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
9991
+ const execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
9969
9992
  const IMAGE_TAG = "universe-runner:pm";
9970
9993
  const ensureImageBuilt = async (cwd) => {
9971
9994
  const dockerfile = (0, node_path.resolve)(cwd, "Dockerfile");
9972
- await execFileAsync$2("docker", [
9995
+ await execFileAsync$3("docker", [
9973
9996
  "build",
9974
9997
  "--file",
9975
9998
  dockerfile,
@@ -9982,7 +10005,7 @@ const ensureImageBuilt = async (cwd) => {
9982
10005
  };
9983
10006
  const runCmdForFiles = async (cwd, cmd, inputs, outputs) => {
9984
10007
  await ensureImageBuilt(cwd);
9985
- const { stdout: idRaw } = await execFileAsync$2("docker", [
10008
+ const { stdout: idRaw } = await execFileAsync$3("docker", [
9986
10009
  "create",
9987
10010
  "-w",
9988
10011
  "/app",
@@ -9991,28 +10014,28 @@ const runCmdForFiles = async (cwd, cmd, inputs, outputs) => {
9991
10014
  ], { encoding: "utf8" });
9992
10015
  const id = idRaw.trim();
9993
10016
  try {
9994
- await Promise.all(inputs.map((file) => execFileAsync$2("docker", [
10017
+ await Promise.all(inputs.map((file) => execFileAsync$3("docker", [
9995
10018
  "cp",
9996
10019
  `${cwd}/${file}`,
9997
10020
  `${id}:/app/${file}`
9998
10021
  ], { encoding: "utf8" })));
9999
- await execFileAsync$2("docker", [
10022
+ await execFileAsync$3("docker", [
10000
10023
  "start",
10001
10024
  "-a",
10002
10025
  id
10003
10026
  ], { encoding: "utf8" });
10004
- await Promise.all(outputs.map((file) => execFileAsync$2("docker", [
10027
+ await Promise.all(outputs.map((file) => execFileAsync$3("docker", [
10005
10028
  "cp",
10006
10029
  `${id}:/app/${file}`,
10007
10030
  `${cwd}/${file}`
10008
10031
  ], { encoding: "utf8" })));
10009
10032
  } finally {
10010
- await execFileAsync$2("docker", ["rm", id], { encoding: "utf8" });
10033
+ await execFileAsync$3("docker", ["rm", id], { encoding: "utf8" });
10011
10034
  }
10012
10035
  };
10013
10036
  const runCmdForStdout = async (cwd, cmd, inputs) => {
10014
10037
  await ensureImageBuilt(cwd);
10015
- const { stdout: idRaw } = await execFileAsync$2("docker", [
10038
+ const { stdout: idRaw } = await execFileAsync$3("docker", [
10016
10039
  "create",
10017
10040
  "-w",
10018
10041
  "/app",
@@ -10021,19 +10044,19 @@ const runCmdForStdout = async (cwd, cmd, inputs) => {
10021
10044
  ], { encoding: "utf8" });
10022
10045
  const id = idRaw.trim();
10023
10046
  try {
10024
- await Promise.all(inputs.map((file) => execFileAsync$2("docker", [
10047
+ await Promise.all(inputs.map((file) => execFileAsync$3("docker", [
10025
10048
  "cp",
10026
10049
  `${cwd}/${file}`,
10027
10050
  `${id}:/app/${file}`
10028
10051
  ], { encoding: "utf8" })));
10029
- const { stdout } = await execFileAsync$2("docker", [
10052
+ const { stdout } = await execFileAsync$3("docker", [
10030
10053
  "start",
10031
10054
  "-a",
10032
10055
  id
10033
10056
  ], { encoding: "utf8" });
10034
10057
  return stdout;
10035
10058
  } finally {
10036
- await execFileAsync$2("docker", ["rm", id], { encoding: "utf8" });
10059
+ await execFileAsync$3("docker", ["rm", id], { encoding: "utf8" });
10037
10060
  }
10038
10061
  };
10039
10062
  //#endregion
@@ -10067,17 +10090,17 @@ const extractVersions$1 = (listOutput) => {
10067
10090
  return versions;
10068
10091
  };
10069
10092
  var BunPackageManager = class {
10070
- impl;
10093
+ runner;
10071
10094
  constructor(runner = bunRunner) {
10072
- this.impl = createPackageSpecifier({
10095
+ this.runner = runner;
10096
+ }
10097
+ specifyDeps(projectDirectory, _pmVersion) {
10098
+ return createPackageSpecifier({
10073
10099
  deleteBeforeFirstInstall: true,
10074
10100
  extractVersions: extractVersions$1,
10075
10101
  lockfileName: LOCKFILE$1,
10076
- runner
10077
- });
10078
- }
10079
- specifyDeps(projectDirectory) {
10080
- return this.impl.specifyDeps(projectDirectory);
10102
+ runner: this.runner
10103
+ }).run(projectDirectory);
10081
10104
  }
10082
10105
  };
10083
10106
  //#endregion
@@ -10088,13 +10111,13 @@ var BunPackageManager = class {
10088
10111
  */
10089
10112
  const LOCKFILE = "pnpm-lock.yaml";
10090
10113
  const MANIFESTS = ["package.json", "pnpm-workspace.yaml"];
10091
- const defaultPnpmRunner = {
10114
+ const defaultRunnerFactory = (pmVersion) => ({
10092
10115
  async installLockfileOnly(cwd) {
10093
10116
  await runCmdForFiles(cwd, [
10094
- "pnpm",
10095
- "install",
10096
- "--lockfile-only"
10097
- ], MANIFESTS, [LOCKFILE]);
10117
+ "sh",
10118
+ "-c",
10119
+ `corepack use pnpm@${pmVersion} && pnpm install --lockfile-only`
10120
+ ], MANIFESTS, [LOCKFILE, "package.json"]);
10098
10121
  },
10099
10122
  list(cwd) {
10100
10123
  return runCmdForStdout(cwd, [
@@ -10105,7 +10128,7 @@ const defaultPnpmRunner = {
10105
10128
  "--lockfile-only"
10106
10129
  ], [...MANIFESTS, LOCKFILE]);
10107
10130
  }
10108
- };
10131
+ });
10109
10132
  const extractVersions = (listOutput) => {
10110
10133
  const root = JSON.parse(listOutput)[0] ?? {};
10111
10134
  const versions = {};
@@ -10114,17 +10137,17 @@ const extractVersions = (listOutput) => {
10114
10137
  return versions;
10115
10138
  };
10116
10139
  var PnpmPackageManager = class {
10117
- impl;
10118
- constructor(runner = defaultPnpmRunner) {
10119
- this.impl = createPackageSpecifier({
10140
+ createRunner;
10141
+ constructor(createRunner = defaultRunnerFactory) {
10142
+ this.createRunner = createRunner;
10143
+ }
10144
+ async specifyDeps(projectDirectory, pmVersion) {
10145
+ await createPackageSpecifier({
10120
10146
  deleteBeforeFirstInstall: false,
10121
10147
  extractVersions,
10122
10148
  lockfileName: LOCKFILE,
10123
- runner
10124
- });
10125
- }
10126
- specifyDeps(projectDirectory) {
10127
- return this.impl.specifyDeps(projectDirectory);
10149
+ runner: this.createRunner(pmVersion)
10150
+ }).run(projectDirectory);
10128
10151
  }
10129
10152
  };
10130
10153
  //#endregion
@@ -11372,13 +11395,13 @@ var ClackPrompt = class {
11372
11395
  };
11373
11396
  //#endregion
11374
11397
  //#region src/commands/create/io/git-repo-initialiser.ts
11375
- const execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
11376
- const defaultRun = async (command, args, cwd) => {
11377
- await execFileAsync$1(command, args, { cwd });
11398
+ const execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
11399
+ const defaultRun$1 = async (command, args, cwd) => {
11400
+ await execFileAsync$2(command, args, { cwd });
11378
11401
  };
11379
11402
  var GitRepoInitialiser = class {
11380
11403
  run;
11381
- constructor(run = defaultRun) {
11404
+ constructor(run = defaultRun$1) {
11382
11405
  this.run = run;
11383
11406
  }
11384
11407
  async initialise(projectDirectory) {
@@ -11396,6 +11419,41 @@ var GitRepoInitialiser = class {
11396
11419
  }
11397
11420
  };
11398
11421
  //#endregion
11422
+ //#region src/commands/create/io/npx-skill-installer.ts
11423
+ const execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
11424
+ const defaultRun = async (command, args, cwd) => {
11425
+ await execFileAsync$1(command, args, { cwd });
11426
+ };
11427
+ var NpxSkillInstaller = class {
11428
+ run;
11429
+ constructor(run = defaultRun) {
11430
+ this.run = run;
11431
+ }
11432
+ async installSkills(skills, projectDirectory) {
11433
+ const skillsByRepo = /* @__PURE__ */ new Map();
11434
+ for (const { repo, skill } of skills) {
11435
+ const existing = skillsByRepo.get(repo);
11436
+ if (existing === void 0) skillsByRepo.set(repo, [skill]);
11437
+ else existing.push(skill);
11438
+ }
11439
+ try {
11440
+ for (const [repo, repoSkills] of skillsByRepo) {
11441
+ const args = [
11442
+ "--yes",
11443
+ "skills",
11444
+ "add",
11445
+ "--yes",
11446
+ repo,
11447
+ ...repoSkills.flatMap((skill) => ["--skill", skill])
11448
+ ];
11449
+ await this.run("npx", args, projectDirectory);
11450
+ }
11451
+ } catch (error) {
11452
+ throw new ConfigError(error.message);
11453
+ }
11454
+ }
11455
+ };
11456
+ //#endregion
11399
11457
  //#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
11400
11458
  var _a$1;
11401
11459
  function $constructor(name, initializer, params) {
@@ -15712,6 +15770,15 @@ const silentLogger = {
15712
15770
  warn: () => {}
15713
15771
  };
15714
15772
  //#endregion
15773
+ //#region src/output/spinner.ts
15774
+ const clackSpinner = () => vt();
15775
+ const silentSpinner = () => ({
15776
+ error: () => {},
15777
+ start: () => {},
15778
+ message: () => {},
15779
+ stop: () => {}
15780
+ });
15781
+ //#endregion
15715
15782
  //#region src/output/envelope.ts
15716
15783
  function buildEnvelope(command, success, data) {
15717
15784
  return {
@@ -15866,6 +15933,7 @@ const PackageManagerSchema = record(literal(["bun", "pnpm"]), strictObject({
15866
15933
  lockfile: string(),
15867
15934
  manifests: array(string()),
15868
15935
  pmInstall: string(),
15936
+ pmVersion: string().regex(/^\d+\.\d+\.\d+$/, "pmVersion must be a semver version (major.minor.patch), e.g. 1.2.3"),
15869
15937
  preinstall: string().optional()
15870
15938
  }));
15871
15939
  const ServiceSchema = record(literal([
@@ -15877,6 +15945,10 @@ const FrameworkSchema = record(string(), strictObject({
15877
15945
  devCopySource: string(),
15878
15946
  files: record(string(), string()),
15879
15947
  port: number(),
15948
+ skills: array(strictObject({
15949
+ repo: string(),
15950
+ skill: string()
15951
+ })).optional(),
15880
15952
  watchSync: array(strictObject({
15881
15953
  path: string(),
15882
15954
  target: string()
@@ -15893,7 +15965,7 @@ const LabelsSchema = record(union([
15893
15965
  ]), record(string(), string()));
15894
15966
  //#endregion
15895
15967
  //#region src/commands/create/layer-composition/assets.json
15896
- var templateVersion = "0.2.0";
15968
+ var templateVersion = "0.4.1";
15897
15969
  var templateUrl = "https://github.com/freeCodeCamp-Universe/templates/releases/download/app-templates-v{{version}}/app-templates-{{version}}.tar.gz";
15898
15970
  //#endregion
15899
15971
  //#region src/commands/create/layer-composition/assets.ts
@@ -16225,6 +16297,9 @@ const create$1 = async (options, deps = {}) => {
16225
16297
  });
16226
16298
  const platformManifestGenerator = deps.platformManifestGenerator ?? new PlatformManifestService();
16227
16299
  const repoInitialiser = deps.repoInitialiser ?? new GitRepoInitialiser();
16300
+ const skillInstaller = deps.skillInstaller ?? new NpxSkillInstaller();
16301
+ const isTTY = process.stdin.isTTY;
16302
+ const spinner = deps.spinner ?? (options.json || !isTTY ? silentSpinner() : clackSpinner());
16228
16303
  try {
16229
16304
  const templatesDir = process.env["UNIVERSE_TEMPLATES_DIR"];
16230
16305
  if (!(templatesDir && templatesDir.length > 0)) {
@@ -16267,20 +16342,38 @@ const create$1 = async (options, deps = {}) => {
16267
16342
  ...pm !== void 0 ? { packageManager: pm } : {}
16268
16343
  };
16269
16344
  }
16345
+ spinner.start("Preparing your project");
16270
16346
  const validatedInput = validator.validateCreateInput(selections);
16347
+ spinner.message("Composing project layers");
16271
16348
  const resolvedLayers = await layerResolver.resolveLayers(validatedInput);
16272
16349
  const targetDirectory = `${cwd}/${validatedInput.name}`;
16273
16350
  const projectFiles = {
16274
16351
  ...resolvedLayers.files,
16275
16352
  "platform.yaml": platformManifestGenerator.generatePlatformManifest(validatedInput)
16276
16353
  };
16354
+ spinner.message("Writing project files");
16277
16355
  await filesystemWriter.writeProject(targetDirectory, projectFiles);
16278
16356
  const manager = validatedInput.packageManager;
16279
- if (manager !== void 0) await packageManager.specifyDeps({
16280
- manager,
16281
- projectDirectory: targetDirectory
16282
- });
16357
+ if (manager !== void 0) {
16358
+ spinner.message(`Pinning dependencies with ${manager}`);
16359
+ await packageManager.specifyDeps({
16360
+ manager,
16361
+ pmVersion: registry["package-managers"][manager]?.pmVersion ?? "",
16362
+ projectDirectory: targetDirectory
16363
+ });
16364
+ }
16365
+ const skills = registry.frameworks[validatedInput.framework]?.skills;
16366
+ if (skills && skills.length > 0) {
16367
+ spinner.message("Installing skills");
16368
+ try {
16369
+ await skillInstaller.installSkills(skills, targetDirectory);
16370
+ } catch (err) {
16371
+ logger.error(err instanceof Error ? err.message : String(err));
16372
+ }
16373
+ }
16374
+ spinner.message("Initialising git repository");
16283
16375
  await repoInitialiser.initialise(targetDirectory);
16376
+ spinner.stop("Project scaffolded");
16284
16377
  if (options.json) {
16285
16378
  emitJson(buildEnvelope("create", true, {
16286
16379
  path: targetDirectory,
@@ -16293,9 +16386,11 @@ const create$1 = async (options, deps = {}) => {
16293
16386
  }));
16294
16387
  return;
16295
16388
  }
16296
- if (interactive) logger.success(`Scaffolded project at ${targetDirectory}`);
16297
- else logger.info(`Scaffolded project '${validatedInput.name}' at ${targetDirectory}`);
16389
+ const startInstruction = `Project scaffolded. cd into ${validatedInput.name} and run \`docker compose up --watch\` to start the project`;
16390
+ if (interactive) logger.success(startInstruction);
16391
+ else logger.info(startInstruction);
16298
16392
  } catch (err) {
16393
+ spinner.error("Create failed");
16299
16394
  const code = err instanceof CliError ? err.exitCode : 10;
16300
16395
  const message = err instanceof Error ? err.message : String(err);
16301
16396
  outputError({
@@ -16735,6 +16830,10 @@ const auditRowArraySchema = array(object({
16735
16830
  requestId: string().optional(),
16736
16831
  detail: record(string(), unknown()).optional()
16737
16832
  }));
16833
+ const deploySummaryArraySchema = array(object({
16834
+ deployId: string(),
16835
+ actor: string().optional()
16836
+ }));
16738
16837
  const repoName = string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,99}$/, "must start with a letter or digit, then letters, digits, '.', '_' or '-' (max 100 chars)");
16739
16838
  const visibilitySchema = _enum(["public", "private"]);
16740
16839
  const repoStatusSchema = _enum([
@@ -17013,7 +17112,7 @@ function createProxyClient(cfg) {
17013
17112
  Authorization: await userBearer(),
17014
17113
  Accept: "application/json"
17015
17114
  }
17016
- });
17115
+ }, (raw) => deploySummaryArraySchema.parse(raw));
17017
17116
  },
17018
17117
  async getAlias(req) {
17019
17118
  const url = `${base}/api/site/${encodeURIComponent(req.site)}/alias/${encodeURIComponent(req.mode)}`;
@@ -19133,7 +19232,7 @@ function formatTable(rows) {
19133
19232
  r.occurredAt,
19134
19233
  r.actor,
19135
19234
  r.action,
19136
- r.site || r.deployId || targetFromDetail(r),
19235
+ targetOf(r),
19137
19236
  r.outcome
19138
19237
  ]);
19139
19238
  const widths = headers.map((h, i) => Math.max(h.length, ...cells.map((row) => row[i]?.length ?? 0)));
@@ -19144,6 +19243,10 @@ function targetFromDetail(r) {
19144
19243
  const name = r.detail?.["name"];
19145
19244
  return typeof name === "string" ? name : "";
19146
19245
  }
19246
+ function targetOf(r) {
19247
+ if (r.site && r.deployId) return `${r.site}/${r.deployId}`;
19248
+ return r.site || r.deployId || targetFromDetail(r);
19249
+ }
19147
19250
  async function ls(options, deps = {}) {
19148
19251
  const command = "audit ls";
19149
19252
  const message = deps.logMessage ?? ((s) => R.message(s));
@@ -19316,7 +19419,7 @@ function installExitNotice(current) {
19316
19419
  }
19317
19420
  //#endregion
19318
19421
  //#region src/cli.ts
19319
- const version = "0.12.0";
19422
+ const version = "0.13.0";
19320
19423
  function handleActionError(command, json, err) {
19321
19424
  const ctx = {
19322
19425
  json,
package/package.json CHANGED
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "name": "@freecodecamp/universe-cli",
3
- "version": "0.12.0",
4
- "main": "dist/index.cjs",
5
- "scripts": {
6
- "test": "vitest run",
7
- "test:smoke": "UNIVERSE_E2E_REAL=1 vitest run tests/e2e/smoke-real-artemis.test.ts",
8
- "build": "tsdown",
9
- "lint": "oxlint src tests",
10
- "typecheck": "tsc --noEmit",
11
- "prepare": "husky",
12
- "dev": "tsx src/index.ts"
3
+ "version": "0.13.0",
4
+ "description": "Static site deployment CLI for the freeCodeCamp Universe platform",
5
+ "keywords": [
6
+ "cli",
7
+ "deployment",
8
+ "freecodecamp",
9
+ "static-site"
10
+ ],
11
+ "homepage": "https://github.com/freeCodeCamp-Universe/universe-cli#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/freeCodeCamp-Universe/universe-cli/issues"
13
14
  },
14
- "author": "Mrugesh Mohapatra <noreply@mrugesh.dev> (https://mrugesh.dev/)",
15
15
  "license": "BSD-3-Clause",
16
+ "author": "Mrugesh Mohapatra <noreply@mrugesh.dev> (https://mrugesh.dev/)",
16
17
  "repository": {
17
18
  "type": "git",
18
19
  "url": "git+https://github.com/freeCodeCamp-Universe/universe-cli.git"
19
20
  },
20
- "publishConfig": {
21
- "access": "public"
21
+ "bin": {
22
+ "universe": "dist/index.cjs"
22
23
  },
23
24
  "files": [
24
25
  "dist/",
@@ -26,8 +27,20 @@
26
27
  "LICENSE"
27
28
  ],
28
29
  "type": "module",
29
- "bin": {
30
- "universe": "dist/index.cjs"
30
+ "main": "dist/index.cjs",
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "scripts": {
35
+ "test": "vitest run",
36
+ "test:smoke": "UNIVERSE_E2E_REAL=1 vitest run tests/e2e/smoke-real-artemis.test.ts",
37
+ "build": "tsdown",
38
+ "lint": "oxlint src tests",
39
+ "typecheck": "tsc --noEmit",
40
+ "prepare": "husky",
41
+ "dev": "tsx src/index.ts",
42
+ "fmt": "oxfmt",
43
+ "fmt:check": "oxfmt --check"
31
44
  },
32
45
  "dependencies": {
33
46
  "@clack/prompts": "^1.5.0",
@@ -38,6 +51,7 @@
38
51
  "devDependencies": {
39
52
  "@types/node": "^24.12.2",
40
53
  "husky": "^9.1.7",
54
+ "oxfmt": "^0.59.0",
41
55
  "oxlint": "^1.68.0",
42
56
  "postject": "1.0.0-alpha.6",
43
57
  "tsdown": "0.22.1",
@@ -45,19 +59,8 @@
45
59
  "typescript": "^5.9.3",
46
60
  "vitest": "^3.2.4"
47
61
  },
48
- "packageManager": "pnpm@10.33.0",
49
62
  "engines": {
50
63
  "node": ">=24.0.0"
51
64
  },
52
- "description": "Static site deployment CLI for the freeCodeCamp Universe platform",
53
- "homepage": "https://github.com/freeCodeCamp-Universe/universe-cli#readme",
54
- "bugs": {
55
- "url": "https://github.com/freeCodeCamp-Universe/universe-cli/issues"
56
- },
57
- "keywords": [
58
- "cli",
59
- "static-site",
60
- "deployment",
61
- "freecodecamp"
62
- ]
65
+ "packageManager": "pnpm@10.33.0"
63
66
  }