@impulselab/cli 0.2.0 → 0.2.1

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 +81 -64
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15,9 +15,6 @@ function configPath(cwd = process.cwd()) {
15
15
  return path.join(cwd, CONFIG_FILE);
16
16
  }
17
17
 
18
- // src/config/read-config.ts
19
- import fsExtra from "fs-extra";
20
-
21
18
  // src/schemas/impulse-config.ts
22
19
  import { z } from "zod";
23
20
  var ImpulseConfigSchema = z.object({
@@ -36,20 +33,44 @@ var ImpulseConfigSchema = z.object({
36
33
  ).default([])
37
34
  });
38
35
 
39
- // src/config/read-config.ts
40
- var { readJson, pathExists } = fsExtra;
41
- async function readConfig(cwd = process.cwd()) {
42
- const file = configPath(cwd);
43
- if (!await pathExists(file)) return null;
44
- const raw = await readJson(file);
45
- const parsed = ImpulseConfigSchema.safeParse(raw);
36
+ // src/shared/json-file.ts
37
+ import fsExtra from "fs-extra";
38
+ import { chmod } from "fs/promises";
39
+ var { readJson, pathExists, outputJson } = fsExtra;
40
+ async function readJsonFile(filePath, schema, opts) {
41
+ if (!await pathExists(filePath)) return null;
42
+ let raw;
43
+ try {
44
+ raw = await readJson(filePath);
45
+ } catch {
46
+ if (opts?.throwOnInvalid !== void 0) {
47
+ throw new Error(`${opts.throwOnInvalid}: failed to read file`);
48
+ }
49
+ return null;
50
+ }
51
+ const parsed = schema.safeParse(raw);
46
52
  if (!parsed.success) {
47
- throw new Error(
48
- `Invalid .impulse.json: ${parsed.error.message}`
49
- );
53
+ if (opts?.throwOnInvalid !== void 0) {
54
+ throw new Error(`${opts.throwOnInvalid}: ${parsed.error.message}`);
55
+ }
56
+ return null;
50
57
  }
51
58
  return parsed.data;
52
59
  }
60
+ async function writeJsonFile(filePath, data, opts) {
61
+ const { spaces = 2, mode } = opts ?? {};
62
+ await outputJson(filePath, data, { spaces, ...mode !== void 0 ? { mode } : {} });
63
+ if (mode !== void 0) {
64
+ await chmod(filePath, mode);
65
+ }
66
+ }
67
+
68
+ // src/config/read-config.ts
69
+ async function readConfig(cwd = process.cwd()) {
70
+ return readJsonFile(configPath(cwd), ImpulseConfigSchema, {
71
+ throwOnInvalid: "Invalid .impulse.json"
72
+ });
73
+ }
53
74
 
54
75
  // src/config/write-config.ts
55
76
  import fsExtra2 from "fs-extra";
@@ -331,7 +352,7 @@ function moduleRegistryPath(moduleId) {
331
352
  }
332
353
 
333
354
  // src/registry/fetch-module-manifest.ts
334
- var { readJson: readJson3, pathExists: pathExists4 } = fsExtra5;
355
+ var { pathExists: pathExists4 } = fsExtra5;
335
356
  async function fetchModuleManifest(moduleId, localPath) {
336
357
  const registryPath = moduleRegistryPath(moduleId);
337
358
  if (localPath) {
@@ -339,12 +360,10 @@ async function fetchModuleManifest(moduleId, localPath) {
339
360
  if (!await pathExists4(file)) {
340
361
  throw new Error(`Local module not found: ${file}`);
341
362
  }
342
- const raw2 = await readJson3(file);
343
- const parsed2 = ModuleManifestSchema.safeParse(raw2);
344
- if (!parsed2.success) {
345
- throw new Error(`Invalid module.json for ${moduleId}: ${parsed2.error.message}`);
346
- }
347
- return parsed2.data;
363
+ const manifest = await readJsonFile(file, ModuleManifestSchema, {
364
+ throwOnInvalid: `Invalid module.json for ${moduleId}`
365
+ });
366
+ return manifest;
348
367
  }
349
368
  const url = githubUrls.rawFile(registryPath, registryConstants.manifestFileName);
350
369
  const res = await fetch(url, { headers: getGitHubHeaders() });
@@ -365,7 +384,7 @@ async function fetchModuleManifest(moduleId, localPath) {
365
384
  // src/registry/list-available-modules.ts
366
385
  import fsExtra6 from "fs-extra";
367
386
  import path4 from "path";
368
- var { readJson: readJson4, pathExists: pathExists5 } = fsExtra6;
387
+ var { readJson: readJson3, pathExists: pathExists5 } = fsExtra6;
369
388
  var _cachedModuleList = null;
370
389
  async function listAvailableModules(localPath) {
371
390
  if (localPath) {
@@ -381,7 +400,7 @@ async function listAvailableModules(localPath) {
381
400
  );
382
401
  if (!await pathExists5(manifestFile)) continue;
383
402
  try {
384
- const raw = await readJson4(manifestFile);
403
+ const raw = await readJson3(manifestFile);
385
404
  const parsed = ModuleManifestSchema.safeParse(raw);
386
405
  if (!parsed.success) continue;
387
406
  let subModules;
@@ -542,15 +561,32 @@ ${value}
542
561
  // src/transforms/register-route.ts
543
562
  import fsExtra9 from "fs-extra";
544
563
  import path7 from "path";
564
+
565
+ // src/transforms/base-router-content.ts
566
+ var BASE_ROUTER_CONTENT = [
567
+ 'import type { RouterInput } from "@orpc/server";',
568
+ 'import { createRouter } from "@orpc/server";',
569
+ "",
570
+ "export const appRouter = createRouter({",
571
+ "} satisfies RouterInput);",
572
+ "",
573
+ "export type AppRouter = typeof appRouter;",
574
+ ""
575
+ ].join("\n");
576
+
577
+ // src/transforms/register-route.ts
545
578
  var { readFile: readFile3, outputFile: outputFile3, pathExists: pathExists8 } = fsExtra9;
546
579
  async function registerRoute(target, value, cwd, dryRun) {
547
580
  const file = path7.join(cwd, target);
581
+ let content;
548
582
  if (!await pathExists8(file)) {
549
- throw new Error(
550
- `register-route: target file not found: ${target}. Please ensure your router file exists.`
551
- );
583
+ content = BASE_ROUTER_CONTENT;
584
+ if (!dryRun) {
585
+ await outputFile3(file, content, "utf-8");
586
+ }
587
+ } else {
588
+ content = await readFile3(file, "utf-8");
552
589
  }
553
- const content = await readFile3(file, "utf-8");
554
590
  if (content.includes(value)) return;
555
591
  const routerPattern = /^([ \t]*\})[ \t]*(?:satisfies|as)\s/m;
556
592
  const match = routerPattern.exec(content);
@@ -697,9 +733,6 @@ async function runTransform(transform, cwd, dryRun) {
697
733
  // src/auth/require-auth.ts
698
734
  import * as p4 from "@clack/prompts";
699
735
 
700
- // src/auth/read-auth.ts
701
- import fsExtra13 from "fs-extra";
702
-
703
736
  // src/auth/auth-path.ts
704
737
  import path11 from "path";
705
738
  import os from "os";
@@ -716,19 +749,8 @@ var AuthCredentialsSchema = z6.object({
716
749
  });
717
750
 
718
751
  // src/auth/read-auth.ts
719
- var { readJson: readJson5, pathExists: pathExists12 } = fsExtra13;
720
752
  async function readAuth() {
721
- const file = authPath();
722
- if (!await pathExists12(file)) return null;
723
- let raw;
724
- try {
725
- raw = await readJson5(file);
726
- } catch {
727
- return null;
728
- }
729
- const parsed = AuthCredentialsSchema.safeParse(raw);
730
- if (!parsed.success) return null;
731
- return parsed.data;
753
+ return readJsonFile(authPath(), AuthCredentialsSchema);
732
754
  }
733
755
 
734
756
  // src/auth/require-auth.ts
@@ -1409,13 +1431,8 @@ function mapDeviceTokenResponse(raw) {
1409
1431
  }
1410
1432
 
1411
1433
  // src/auth/write-auth.ts
1412
- import fsExtra14 from "fs-extra";
1413
- import { chmod } from "fs/promises";
1414
- var { outputJson } = fsExtra14;
1415
1434
  async function writeAuth(credentials) {
1416
- const file = authPath();
1417
- await outputJson(file, credentials, { spaces: 2, mode: 384 });
1418
- await chmod(file, 384);
1435
+ await writeJsonFile(authPath(), credentials, { mode: 384 });
1419
1436
  }
1420
1437
 
1421
1438
  // src/commands/login.ts
@@ -1515,11 +1532,11 @@ function sleep(ms) {
1515
1532
  import * as p8 from "@clack/prompts";
1516
1533
 
1517
1534
  // src/auth/clear-auth.ts
1518
- import fsExtra15 from "fs-extra";
1519
- var { remove, pathExists: pathExists13 } = fsExtra15;
1535
+ import fsExtra13 from "fs-extra";
1536
+ var { remove, pathExists: pathExists12 } = fsExtra13;
1520
1537
  async function clearAuth() {
1521
1538
  const file = authPath();
1522
- if (!await pathExists13(file)) return false;
1539
+ if (!await pathExists12(file)) return false;
1523
1540
  await remove(file);
1524
1541
  return true;
1525
1542
  }
@@ -1571,10 +1588,10 @@ import { execFileSync as execFileSync3 } from "child_process";
1571
1588
  import { existsSync as existsSync2 } from "fs";
1572
1589
  import path15 from "path";
1573
1590
  import * as p10 from "@clack/prompts";
1574
- import fsExtra18 from "fs-extra";
1591
+ import fsExtra16 from "fs-extra";
1575
1592
 
1576
1593
  // src/registry/fetch-template.ts
1577
- import fsExtra16 from "fs-extra";
1594
+ import fsExtra14 from "fs-extra";
1578
1595
  import path13 from "path";
1579
1596
 
1580
1597
  // src/schemas/template-manifest.ts
@@ -1595,7 +1612,7 @@ var TemplateManifestSchema = z7.object({
1595
1612
  });
1596
1613
 
1597
1614
  // src/registry/fetch-template.ts
1598
- var { readJson: readJson6, pathExists: pathExists14, readFile: readFile8 } = fsExtra16;
1615
+ var { readJson: readJson4, pathExists: pathExists13, readFile: readFile8 } = fsExtra14;
1599
1616
  var TEMPLATES_DIR = "templates";
1600
1617
  var TEMPLATE_MANIFEST_FILE = "template.json";
1601
1618
  function templateRawUrl(templateId, file) {
@@ -1604,10 +1621,10 @@ function templateRawUrl(templateId, file) {
1604
1621
  async function fetchTemplateManifest(templateId, localPath) {
1605
1622
  if (localPath) {
1606
1623
  const file = path13.join(localPath, TEMPLATES_DIR, templateId, TEMPLATE_MANIFEST_FILE);
1607
- if (!await pathExists14(file)) {
1624
+ if (!await pathExists13(file)) {
1608
1625
  throw new Error(`Local template not found: ${file}`);
1609
1626
  }
1610
- const raw2 = await readJson6(file);
1627
+ const raw2 = await readJson4(file);
1611
1628
  const parsed2 = TemplateManifestSchema.safeParse(raw2);
1612
1629
  if (!parsed2.success) {
1613
1630
  throw new Error(`Invalid template.json for "${templateId}": ${parsed2.error.message}`);
@@ -1643,7 +1660,7 @@ async function fetchTemplateFile(templateId, src, localPath) {
1643
1660
  }
1644
1661
 
1645
1662
  // src/registry/fetch-preset.ts
1646
- import fsExtra17 from "fs-extra";
1663
+ import fsExtra15 from "fs-extra";
1647
1664
  import path14 from "path";
1648
1665
 
1649
1666
  // src/schemas/preset-manifest.ts
@@ -1660,7 +1677,7 @@ var PresetManifestSchema = z8.object({
1660
1677
  });
1661
1678
 
1662
1679
  // src/registry/fetch-preset.ts
1663
- var { readJson: readJson7, pathExists: pathExists15 } = fsExtra17;
1680
+ var { readJson: readJson5, pathExists: pathExists14 } = fsExtra15;
1664
1681
  var PRESETS_DIR = registryConstants.presetsDir;
1665
1682
  var PRESET_MANIFEST_FILE = "preset.json";
1666
1683
  function presetRawUrl(presetId, file) {
@@ -1669,10 +1686,10 @@ function presetRawUrl(presetId, file) {
1669
1686
  async function fetchPresetManifest(presetId, localPath) {
1670
1687
  if (localPath) {
1671
1688
  const file = path14.join(localPath, PRESETS_DIR, presetId, PRESET_MANIFEST_FILE);
1672
- if (!await pathExists15(file)) {
1689
+ if (!await pathExists14(file)) {
1673
1690
  throw new Error(`Local preset not found: ${file}`);
1674
1691
  }
1675
- const raw2 = await readJson7(file);
1692
+ const raw2 = await readJson5(file);
1676
1693
  const parsed2 = PresetManifestSchema.safeParse(raw2);
1677
1694
  if (!parsed2.success) {
1678
1695
  throw new Error(`Invalid preset.json for "${presetId}": ${parsed2.error.message}`);
@@ -1697,7 +1714,7 @@ async function fetchPresetManifest(presetId, localPath) {
1697
1714
  async function listAvailablePresets(localPath) {
1698
1715
  if (localPath) {
1699
1716
  const presetsDir = path14.join(localPath, PRESETS_DIR);
1700
- if (!await pathExists15(presetsDir)) return [];
1717
+ if (!await pathExists14(presetsDir)) return [];
1701
1718
  const { readdir } = await import("fs/promises");
1702
1719
  const entries2 = await readdir(presetsDir, { withFileTypes: true });
1703
1720
  return entries2.filter((e) => e.isDirectory()).map((e) => e.name);
@@ -1711,7 +1728,7 @@ async function listAvailablePresets(localPath) {
1711
1728
  }
1712
1729
 
1713
1730
  // src/commands/create.ts
1714
- var { outputFile: outputFile7, pathExists: pathExists16 } = fsExtra18;
1731
+ var { outputFile: outputFile7, pathExists: pathExists15 } = fsExtra16;
1715
1732
  function slugify(name) {
1716
1733
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
1717
1734
  }
@@ -1896,8 +1913,8 @@ Stack: ${manifest.stack.join(", ")}`);
1896
1913
  }
1897
1914
  const pkgPath = path15.join(targetDir, "package.json");
1898
1915
  if (existsSync2(pkgPath)) {
1899
- const { readJson: readJson8, writeJson: writeJson2 } = fsExtra18;
1900
- const pkg = await readJson8(pkgPath);
1916
+ const { readJson: readJson6, writeJson: writeJson2 } = fsExtra16;
1917
+ const pkg = await readJson6(pkgPath);
1901
1918
  if (pkg && typeof pkg === "object") {
1902
1919
  pkg["name"] = projectName;
1903
1920
  await writeJson2(pkgPath, pkg, { spaces: 2 });
@@ -1923,7 +1940,7 @@ Stack: ${manifest.stack.join(", ")}`);
1923
1940
  skipAuth: true
1924
1941
  });
1925
1942
  }
1926
- const hasPnpmLock = await pathExists16(path15.join(targetDir, "pnpm-lock.yaml"));
1943
+ const hasPnpmLock = await pathExists15(path15.join(targetDir, "pnpm-lock.yaml"));
1927
1944
  const pm = hasPnpmLock ? "pnpm" : existsSync2(path15.join(targetDir, "yarn.lock")) ? "yarn" : "pnpm";
1928
1945
  const s5 = p10.spinner();
1929
1946
  s5.start(`Running ${pm} install...`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulselab/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "ImpulseLab CLI — install and manage modules for your projects",
5
5
  "private": false,
6
6
  "type": "module",