@karmaniverous/smoz 0.2.14 → 0.2.15

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.
@@ -1,20 +1,17 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
2
+ import { createCli } from '@karmaniverous/get-dotenv/cli';
3
+ import { awsPlugin, cmdPlugin, batchPlugin } from '@karmaniverous/get-dotenv/plugins';
4
+ import { definePlugin } from '@karmaniverous/get-dotenv/cliHost';
5
+ import { packageDirectorySync } from 'package-directory';
6
+ import fs, { existsSync, promises, readFileSync } from 'node:fs';
7
+ import path, { join, posix, sep, dirname, relative, resolve } from 'node:path';
8
+ import chokidar from 'chokidar';
9
+ import { spawn, spawnSync } from 'node:child_process';
10
+ import { buildSpawnEnv } from '@karmaniverous/get-dotenv';
11
+ import { pathToFileURL, fileURLToPath } from 'node:url';
12
+ import { stdout, stdin } from 'node:process';
13
+ import { createInterface } from 'node:readline/promises';
3
14
 
4
- var cli = require('@karmaniverous/get-dotenv/cli');
5
- var plugins = require('@karmaniverous/get-dotenv/plugins');
6
- var cliHost = require('@karmaniverous/get-dotenv/cliHost');
7
- var packageDirectory = require('package-directory');
8
- var fs = require('node:fs');
9
- var path = require('node:path');
10
- var chokidar = require('chokidar');
11
- var node_child_process = require('node:child_process');
12
- var getDotenv = require('@karmaniverous/get-dotenv');
13
- var node_url = require('node:url');
14
- var node_process = require('node:process');
15
- var promises = require('node:readline/promises');
16
-
17
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
18
15
  /**
19
16
  * SMOZ CLI: add
20
17
  *
@@ -39,7 +36,7 @@ const HTTP_METHODS = new Set([
39
36
  'options',
40
37
  'trace',
41
38
  ]);
42
- const toPosix$2 = (p) => p.split(path.sep).join('/');
39
+ const toPosix$2 = (p) => p.split(sep).join('/');
43
40
  const formatMaybe$1 = async (root, filePath, source) => {
44
41
  try {
45
42
  const prettier = (await import('prettier'));
@@ -51,10 +48,10 @@ const formatMaybe$1 = async (root, filePath, source) => {
51
48
  }
52
49
  };
53
50
  const writeIfAbsent$1 = async (outFile, content) => {
54
- if (fs.existsSync(outFile))
51
+ if (existsSync(outFile))
55
52
  return { created: false };
56
- await fs.promises.mkdir(path.dirname(outFile), { recursive: true });
57
- await fs.promises.writeFile(outFile, content, 'utf8');
53
+ await promises.mkdir(dirname(outFile), { recursive: true });
54
+ await promises.writeFile(outFile, content, 'utf8');
58
55
  return { created: true };
59
56
  };
60
57
  /** True if a segment encodes a path param (:id | {id} | [id]). */
@@ -202,10 +199,10 @@ const runAdd = async (root, spec) => {
202
199
  // Derive path template and param names for OpenAPI hints
203
200
  const paramNames = baseParts.filter(isParamSeg).map(getParamName);
204
201
  const pathTemplate = '/' + pathSegs.join('/');
205
- const dir = path.join(root, 'app', 'functions', token, ...dirSegs, ...(method ? [method] : []));
206
- const lambdaPath = path.join(dir, 'lambda.ts');
207
- const handlerPath = path.join(dir, 'handler.ts');
208
- const openapiPath = path.join(dir, 'openapi.ts');
202
+ const dir = join(root, 'app', 'functions', token, ...dirSegs, ...(method ? [method] : []));
203
+ const lambdaPath = join(dir, 'lambda.ts');
204
+ const handlerPath = join(dir, 'handler.ts');
205
+ const openapiPath = join(dir, 'openapi.ts');
209
206
  // Compute contents
210
207
  const files = [];
211
208
  if (isHttp) {
@@ -250,9 +247,9 @@ const runAdd = async (root, spec) => {
250
247
  const formatted = await formatMaybe$1(root, f.path, f.content);
251
248
  const { created: c } = await writeIfAbsent$1(f.path, formatted);
252
249
  if (c)
253
- created.push(path.posix.normalize(f.path));
250
+ created.push(posix.normalize(f.path));
254
251
  else
255
- skipped.push(path.posix.normalize(f.path));
252
+ skipped.push(posix.normalize(f.path));
256
253
  }
257
254
  return { created, skipped };
258
255
  };
@@ -307,7 +304,7 @@ const launchOffline = async (root, opts) => {
307
304
  const spawnOffline = async (root, cmd, verbose) => {
308
305
  // Normalize child environment via get-dotenv when available; safe fallback otherwise.
309
306
  const baseEnv = { ...process.env };
310
- const childEnv = getDotenv.buildSpawnEnv(baseEnv);
307
+ const childEnv = buildSpawnEnv(baseEnv);
311
308
  // Optional diagnostics to verify the child sees sane temp-related envs
312
309
  if (verbose) {
313
310
  const snap = {
@@ -320,7 +317,7 @@ const spawnOffline = async (root, cmd, verbose) => {
320
317
  };
321
318
  process.stdout.write(`[offline] env snapshot: ${JSON.stringify(snap)}\n`);
322
319
  }
323
- const child = node_child_process.spawn(cmd.cmd, cmd.args, {
320
+ const child = spawn(cmd.cmd, cmd.args, {
324
321
  cwd: root,
325
322
  shell: cmd.shell,
326
323
  stdio: ['ignore', 'pipe', 'pipe'],
@@ -364,7 +361,7 @@ const spawnOffline = async (root, cmd, verbose) => {
364
361
  const findTsxCli = (root) => {
365
362
  // Prefer invoking the JS entry to avoid shell .cmd quirks on Windows.
366
363
  const js = path.resolve(root, 'node_modules', 'tsx', 'dist', 'cli.js');
367
- if (fs.existsSync(js)) {
364
+ if (existsSync(js)) {
368
365
  return {
369
366
  cmd: process.execPath,
370
367
  args: [js, 'app/config/openapi.ts'],
@@ -377,7 +374,7 @@ const findTsxCli = (root) => {
377
374
  };
378
375
  const findPrettierCli = (root) => {
379
376
  const js = path.resolve(root, 'node_modules', 'prettier', 'bin', 'prettier.cjs');
380
- if (!fs.existsSync(js)) {
377
+ if (!existsSync(js)) {
381
378
  throw new Error(`prettier not found at ${js}. Install it as a devDependency.`);
382
379
  }
383
380
  return {
@@ -391,21 +388,21 @@ const runOpenapi = async (root, opts) => {
391
388
  const outFile = path.resolve(root, 'app', 'generated', 'openapi.json');
392
389
  let before;
393
390
  try {
394
- if (fs.existsSync(outFile))
395
- before = fs.readFileSync(outFile, 'utf8');
391
+ if (existsSync(outFile))
392
+ before = readFileSync(outFile, 'utf8');
396
393
  }
397
394
  catch {
398
395
  // ignore read errors; treat as absent
399
396
  before = undefined;
400
397
  }
401
398
  // Build a normalized child env via get-dotenv (static import).
402
- const env = getDotenv.buildSpawnEnv({});
399
+ const env = buildSpawnEnv({});
403
400
  // Step 1: generate the OpenAPI spec.
404
401
  const tsx = findTsxCli(root);
405
402
  if (opts?.verbose) {
406
403
  console.log(`[openapi] ${[tsx.cmd, ...tsx.args].join(' ')}`);
407
404
  }
408
- const genRes = node_child_process.spawnSync(tsx.cmd, tsx.args, {
405
+ const genRes = spawnSync(tsx.cmd, tsx.args, {
409
406
  cwd: root,
410
407
  stdio: 'inherit',
411
408
  shell: tsx.shell,
@@ -425,7 +422,7 @@ const runOpenapi = async (root, opts) => {
425
422
  if (opts?.verbose) {
426
423
  console.log(`[openapi] ${[prettier.cmd, ...prettier.args].join(' ')}`);
427
424
  }
428
- const fmtRes = node_child_process.spawnSync(prettier.cmd, prettier.args, {
425
+ const fmtRes = spawnSync(prettier.cmd, prettier.args, {
429
426
  cwd: root,
430
427
  stdio: 'inherit',
431
428
  shell: prettier.shell,
@@ -442,9 +439,9 @@ const runOpenapi = async (root, opts) => {
442
439
  }
443
440
  // Determine whether the file content changed
444
441
  try {
445
- if (!fs.existsSync(outFile))
442
+ if (!existsSync(outFile))
446
443
  return before !== undefined; // deleted vs existed
447
- const after = fs.readFileSync(outFile, 'utf8');
444
+ const after = readFileSync(outFile, 'utf8');
448
445
  return before === undefined ? true : after !== before;
449
446
  }
450
447
  catch {
@@ -464,7 +461,7 @@ const runOpenapi = async (root, opts) => {
464
461
  *
465
462
  * Idempotent and formatted (uses Prettier if available).
466
463
  */
467
- const toPosix$1 = (p) => p.split(path.sep).join('/');
464
+ const toPosix$1 = (p) => p.split(sep).join('/');
468
465
  const withoutTsExt = (p) => p.endsWith('.ts') ? p.slice(0, -3) : p;
469
466
  const HEADER = `/* AUTO-GENERATED by smoz register — DO NOT EDIT */
470
467
  `;
@@ -481,21 +478,21 @@ const formatMaybe = async (root, filePath, source) => {
481
478
  };
482
479
  const writeIfChanged = async (outFile, content) => {
483
480
  try {
484
- const prev = await fs.promises.readFile(outFile, 'utf8');
481
+ const prev = await promises.readFile(outFile, 'utf8');
485
482
  if (prev === content)
486
483
  return false;
487
484
  }
488
485
  catch {
489
486
  // file missing — proceed
490
487
  }
491
- await fs.promises.mkdir(path.dirname(outFile), { recursive: true });
492
- await fs.promises.writeFile(outFile, content, 'utf8');
488
+ await promises.mkdir(dirname(outFile), { recursive: true });
489
+ await promises.writeFile(outFile, content, 'utf8');
493
490
  return true;
494
491
  };
495
492
  const walk$1 = async (dir, out = []) => {
496
- const entries = await fs.promises.readdir(dir, { withFileTypes: true });
493
+ const entries = await promises.readdir(dir, { withFileTypes: true });
497
494
  for (const ent of entries) {
498
- const p = path.join(dir, ent.name);
495
+ const p = join(dir, ent.name);
499
496
  if (ent.isDirectory()) {
500
497
  await walk$1(p, out);
501
498
  }
@@ -506,13 +503,13 @@ const walk$1 = async (dir, out = []) => {
506
503
  return out;
507
504
  };
508
505
  const collect = async (root) => {
509
- const base = path.join(root, 'app', 'functions');
506
+ const base = join(root, 'app', 'functions');
510
507
  const buckets = { lambda: [], openapi: [], serverless: [] };
511
- if (!fs.existsSync(base))
508
+ if (!existsSync(base))
512
509
  return buckets;
513
510
  const files = await walk$1(base);
514
511
  for (const abs of files) {
515
- const name = abs.split(path.sep).pop() ?? '';
512
+ const name = abs.split(sep).pop() ?? '';
516
513
  if (name === 'lambda.ts')
517
514
  buckets.lambda.push(abs);
518
515
  if (name === 'openapi.ts')
@@ -532,7 +529,7 @@ const collect = async (root) => {
532
529
  * dynamic import in the inline server works reliably under tsx.
533
530
  */
534
531
  const makeImports = (root, outDir, files) => files.map((abs) => {
535
- const relFromOut = toPosix$1(path.relative(outDir, abs));
532
+ const relFromOut = toPosix$1(relative(outDir, abs));
536
533
  const noExt = withoutTsExt(relFromOut);
537
534
  const spec = noExt.startsWith('.') ? noExt : `./${noExt}`;
538
535
  return `import '${spec}';`;
@@ -544,23 +541,23 @@ const buildFile = (imports) => {
544
541
  };
545
542
  const runRegister = async (root) => {
546
543
  const buckets = await collect(root);
547
- const outDir = path.join(root, 'app', 'generated');
544
+ const outDir = join(root, 'app', 'generated');
548
545
  const lambdaImports = makeImports(root, outDir, buckets.lambda);
549
546
  const openapiImports = makeImports(root, outDir, buckets.openapi);
550
547
  const serverlessImports = makeImports(root, outDir, buckets.serverless);
551
- const fnsPath = path.join(outDir, 'register.functions.ts');
552
- const oaiPath = path.join(outDir, 'register.openapi.ts');
553
- const srvPath = path.join(outDir, 'register.serverless.ts');
548
+ const fnsPath = join(outDir, 'register.functions.ts');
549
+ const oaiPath = join(outDir, 'register.openapi.ts');
550
+ const srvPath = join(outDir, 'register.serverless.ts');
554
551
  const fns = await formatMaybe(root, fnsPath, buildFile(lambdaImports));
555
552
  const oai = await formatMaybe(root, oaiPath, buildFile(openapiImports));
556
553
  const srv = await formatMaybe(root, srvPath, buildFile(serverlessImports));
557
554
  const wrote = [];
558
555
  if (await writeIfChanged(fnsPath, fns))
559
- wrote.push(path.posix.normalize(fnsPath));
556
+ wrote.push(posix.normalize(fnsPath));
560
557
  if (await writeIfChanged(oaiPath, oai))
561
- wrote.push(path.posix.normalize(oaiPath));
558
+ wrote.push(posix.normalize(oaiPath));
562
559
  if (await writeIfChanged(srvPath, srv))
563
- wrote.push(path.posix.normalize(srvPath));
560
+ wrote.push(posix.normalize(srvPath));
564
561
  return { wrote };
565
562
  };
566
563
 
@@ -592,8 +589,8 @@ const resolveStage = async (root, cliStage, verbose) => {
592
589
  // getdotenv.config.json → plugins.smoz.stage
593
590
  try {
594
591
  const cfgPath = path.resolve(root, 'getdotenv.config.json');
595
- if (fs.existsSync(cfgPath)) {
596
- const raw = fs.readFileSync(cfgPath, 'utf8');
592
+ if (existsSync(cfgPath)) {
593
+ const raw = readFileSync(cfgPath, 'utf8');
597
594
  const parsed = JSON.parse(raw);
598
595
  const fromCfg = parsed.plugins?.smoz?.stage;
599
596
  if (typeof fromCfg === 'string' && fromCfg.trim().length > 0) {
@@ -618,7 +615,7 @@ const seedEnvForStage = async (root, stage, verbose) => {
618
615
  // Best effort: import the app config to read declared env keys and concrete values.
619
616
  // Preserve existing process.env values; only seed when unset.
620
617
  try {
621
- const appConfigUrl = node_url.pathToFileURL(path.resolve(root, 'app', 'config', 'app.config.ts')).href;
618
+ const appConfigUrl = pathToFileURL(path.resolve(root, 'app', 'config', 'app.config.ts')).href;
622
619
  // Dynamically import the TS module under tsx
623
620
  const mod = (await import(appConfigUrl));
624
621
  const app = mod.app;
@@ -692,7 +689,7 @@ const resolveTsxCommand = (root, tsEntry) => {
692
689
  shell: false,
693
690
  };
694
691
  }
695
- const probe = node_child_process.spawnSync(process.platform === 'win32' ? 'tsx.cmd' : 'tsx', ['--version'], { shell: true });
692
+ const probe = spawnSync(process.platform === 'win32' ? 'tsx.cmd' : 'tsx', ['--version'], { shell: true });
696
693
  if (typeof probe.status === 'number' && probe.status === 0) {
697
694
  return {
698
695
  cmd: process.platform === 'win32' ? 'tsx.cmd' : 'tsx',
@@ -714,13 +711,13 @@ const launchInline = async (root, opts) => {
714
711
  // Prefer __dirname when available (CJS), otherwise derive from import.meta.url (ESM).
715
712
  const here = typeof __dirname === 'string'
716
713
  ? __dirname
717
- : path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
718
- const pkgRoot = packageDirectory.packageDirectorySync({ cwd: here }) ?? process.cwd();
714
+ : path.dirname(fileURLToPath(import.meta.url));
715
+ const pkgRoot = packageDirectorySync({ cwd: here }) ?? process.cwd();
719
716
  const { entry } = resolveInlineEntry(pkgRoot);
720
717
  const makeTsx = () => {
721
718
  const { cmd, args, shell } = resolveTsxCommand(root, entry);
722
719
  return (async () => {
723
- const env = getDotenv.buildSpawnEnv({
720
+ const env = buildSpawnEnv({
724
721
  ...process.env,
725
722
  // Enable tsconfig paths for "@/..." during TS fallback.
726
723
  TSX_TSCONFIG_PATHS: '1',
@@ -728,7 +725,7 @@ const launchInline = async (root, opts) => {
728
725
  SMOZ_PORT: String(opts.port),
729
726
  SMOZ_VERBOSE: opts.verbose ? '1' : '',
730
727
  });
731
- return node_child_process.spawn(cmd, args, {
728
+ return spawn(cmd, args, {
732
729
  cwd: root,
733
730
  stdio: 'inherit',
734
731
  shell,
@@ -894,16 +891,16 @@ const runDev = async (root, opts) => {
894
891
  };
895
892
 
896
893
  const writeIfAbsent = async (outFile, content) => {
897
- if (fs.existsSync(outFile))
894
+ if (existsSync(outFile))
898
895
  return { created: false };
899
- await fs.promises.mkdir(path.dirname(outFile), { recursive: true });
900
- await fs.promises.writeFile(outFile, content, 'utf8');
896
+ await promises.mkdir(dirname(outFile), { recursive: true });
897
+ await promises.writeFile(outFile, content, 'utf8');
901
898
  return { created: true };
902
899
  };
903
900
  const walk = async (dir, out = []) => {
904
- const entries = await fs.promises.readdir(dir, { withFileTypes: true });
901
+ const entries = await promises.readdir(dir, { withFileTypes: true });
905
902
  for (const ent of entries) {
906
- const p = path.join(dir, ent.name);
903
+ const p = join(dir, ent.name);
907
904
  if (ent.isDirectory()) {
908
905
  await walk(p, out);
909
906
  }
@@ -915,7 +912,7 @@ const walk = async (dir, out = []) => {
915
912
  };
916
913
  const readJson = async (file) => {
917
914
  try {
918
- const data = await fs.promises.readFile(file, 'utf8');
915
+ const data = await promises.readFile(file, 'utf8');
919
916
  return JSON.parse(data);
920
917
  }
921
918
  catch {
@@ -923,8 +920,8 @@ const readJson = async (file) => {
923
920
  }
924
921
  };
925
922
  const writeJson = async (file, obj) => {
926
- await fs.promises.mkdir(path.dirname(file), { recursive: true });
927
- await fs.promises.writeFile(file, JSON.stringify(obj, null, 2), 'utf8');
923
+ await promises.mkdir(dirname(file), { recursive: true });
924
+ await promises.writeFile(file, JSON.stringify(obj, null, 2), 'utf8');
928
925
  };
929
926
 
930
927
  const askConflict = async (rl, filePath) => {
@@ -950,25 +947,25 @@ const copyDirWithConflicts = async (srcDir, dstRoot, created, skipped, examples,
950
947
  const files = await walk(srcDir);
951
948
  let sticky;
952
949
  for (const abs of files) {
953
- const rel = path.relative(srcDir, abs);
950
+ const rel = relative(srcDir, abs);
954
951
  if (opts.exclude && opts.exclude(rel)) {
955
952
  // Skip dev-only or excluded files silently.
956
953
  continue;
957
954
  }
958
- const dest = path.resolve(dstRoot, rel);
959
- const data = await fs.promises.readFile(abs, 'utf8');
960
- if (!fs.existsSync(dest)) {
955
+ const dest = resolve(dstRoot, rel);
956
+ const data = await promises.readFile(abs, 'utf8');
957
+ if (!existsSync(dest)) {
961
958
  const { created: c } = await writeIfAbsent(dest, data);
962
959
  if (c)
963
- created.push(path.posix.normalize(dest));
960
+ created.push(posix.normalize(dest));
964
961
  else
965
- skipped.push(path.posix.normalize(dest));
962
+ skipped.push(posix.normalize(dest));
966
963
  continue;
967
964
  }
968
965
  // Conflict flow
969
966
  let decision = opts.conflict === 'ask' ? 'example' : opts.conflict;
970
967
  if (opts.conflict === 'ask' && opts.rl && !sticky) {
971
- const ans = await askConflict(opts.rl, path.posix.normalize(dest));
968
+ const ans = await askConflict(opts.rl, posix.normalize(dest));
972
969
  if (ans === 'all-overwrite') {
973
970
  sticky = 'overwrite';
974
971
  }
@@ -985,32 +982,32 @@ const copyDirWithConflicts = async (srcDir, dstRoot, created, skipped, examples,
985
982
  if (sticky)
986
983
  decision = sticky;
987
984
  if (decision === 'overwrite') {
988
- await fs.promises.mkdir(path.dirname(dest), { recursive: true });
989
- await fs.promises.writeFile(dest, data, 'utf8');
990
- created.push(path.posix.normalize(dest));
985
+ await promises.mkdir(dirname(dest), { recursive: true });
986
+ await promises.writeFile(dest, data, 'utf8');
987
+ created.push(posix.normalize(dest));
991
988
  }
992
989
  else if (decision === 'example') {
993
990
  const ex = `${dest}.example`;
994
991
  const { created: c } = await writeIfAbsent(ex, data);
995
992
  if (c)
996
- examples.push(path.posix.normalize(ex));
993
+ examples.push(posix.normalize(ex));
997
994
  else
998
- skipped.push(path.posix.normalize(ex));
995
+ skipped.push(posix.normalize(ex));
999
996
  }
1000
997
  else {
1001
- skipped.push(path.posix.normalize(dest));
998
+ skipped.push(posix.normalize(dest));
1002
999
  }
1003
1000
  }
1004
1001
  };
1005
1002
 
1006
1003
  const detectPm = (root) => {
1007
- if (fs.existsSync(path.join(root, 'pnpm-lock.yaml')))
1004
+ if (existsSync(join(root, 'pnpm-lock.yaml')))
1008
1005
  return 'pnpm';
1009
- if (fs.existsSync(path.join(root, 'yarn.lock')))
1006
+ if (existsSync(join(root, 'yarn.lock')))
1010
1007
  return 'yarn';
1011
- if (fs.existsSync(path.join(root, 'package-lock.json')))
1008
+ if (existsSync(join(root, 'package-lock.json')))
1012
1009
  return 'npm';
1013
- if (fs.existsSync(path.join(root, 'bun.lockb')))
1010
+ if (existsSync(join(root, 'bun.lockb')))
1014
1011
  return 'bun';
1015
1012
  const ua = process.env.npm_config_user_agent ?? '';
1016
1013
  if (ua.includes('pnpm'))
@@ -1029,7 +1026,7 @@ const runInstall = (root, pm) => {
1029
1026
  const known = pm === 'pnpm' || pm === 'yarn' || pm === 'bun' || pm === 'npm';
1030
1027
  if (!known)
1031
1028
  return 'unknown-pm';
1032
- const res = node_child_process.spawnSync(pm, ['install'], {
1029
+ const res = spawnSync(pm, ['install'], {
1033
1030
  stdio: 'inherit',
1034
1031
  cwd: root,
1035
1032
  shell: true,
@@ -1094,8 +1091,8 @@ const mergeAdditive = (target, source) => {
1094
1091
  */
1095
1092
  const ensureToolkitDependency = async (targetPkg, templatesBase) => {
1096
1093
  try {
1097
- const toolkitRoot = path.dirname(templatesBase);
1098
- const toolkitPkg = await readJson(path.join(toolkitRoot, 'package.json'));
1094
+ const toolkitRoot = dirname(templatesBase);
1095
+ const toolkitPkg = await readJson(join(toolkitRoot, 'package.json'));
1099
1096
  const verRaw = toolkitPkg?.version?.trim();
1100
1097
  const depVersion = verRaw ? `^${verRaw}` : '^0.0.0';
1101
1098
  const deps = targetPkg.dependencies ?? {};
@@ -1118,27 +1115,27 @@ const ensureToolkitDependency = async (targetPkg, templatesBase) => {
1118
1115
  * a consuming app and from this repository.
1119
1116
  + */
1120
1117
  const resolveTemplatesBase = () => {
1121
- const here = path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
1122
- const pkgRoot = packageDirectory.packageDirectorySync({ cwd: here }) ?? process.cwd();
1123
- return path.resolve(pkgRoot, 'templates');
1118
+ const here = dirname(fileURLToPath(import.meta.url));
1119
+ const pkgRoot = packageDirectorySync({ cwd: here }) ?? process.cwd();
1120
+ return resolve(pkgRoot, 'templates');
1124
1121
  };
1125
1122
  const toPosix = (p) =>
1126
1123
  // local helper for path presentation (not used for FS operations)
1127
1124
  p.replace(/\\/g, '/');
1128
1125
 
1129
1126
  const seedRegisterPlaceholders = async (root) => {
1130
- const genDir = path.join(root, 'app', 'generated');
1127
+ const genDir = join(root, 'app', 'generated');
1131
1128
  const seeds = [
1132
1129
  {
1133
- path: path.join(genDir, 'register.functions.ts'),
1130
+ path: join(genDir, 'register.functions.ts'),
1134
1131
  content: '/* AUTO-GENERATED placeholder; will be rewritten by `smoz register` */\nexport {};\n',
1135
1132
  },
1136
1133
  {
1137
- path: path.join(genDir, 'register.openapi.ts'),
1134
+ path: join(genDir, 'register.openapi.ts'),
1138
1135
  content: '/* AUTO-GENERATED placeholder; will be rewritten by `smoz register` */\nexport {};\n',
1139
1136
  },
1140
1137
  {
1141
- path: path.join(genDir, 'register.serverless.ts'),
1138
+ path: join(genDir, 'register.serverless.ts'),
1142
1139
  content: '/* AUTO-GENERATED placeholder; will be rewritten by `smoz register` */\nexport {};\n',
1143
1140
  },
1144
1141
  ];
@@ -1146,12 +1143,12 @@ const seedRegisterPlaceholders = async (root) => {
1146
1143
  const skipped = [];
1147
1144
  for (const s of seeds) {
1148
1145
  const { created: c } = await writeIfAbsent(s.path, s.content);
1149
- (c ? created : skipped).push(path.posix.normalize(s.path));
1146
+ (c ? created : skipped).push(posix.normalize(s.path));
1150
1147
  }
1151
1148
  return { created, skipped };
1152
1149
  };
1153
1150
 
1154
- const toPosixSep = (p) => p.split(path.sep).join('/');
1151
+ const toPosixSep = (p) => p.split(sep).join('/');
1155
1152
  // Exclude dev-only type stubs (not meant for downstream apps).
1156
1153
  const excludeDev = (rel) => {
1157
1154
  const posixRel = rel.replace(/\\/g, '/');
@@ -1178,19 +1175,19 @@ const runInit = async (root, template = 'default', opts) => {
1178
1175
  const optAll = opts ?? {};
1179
1176
  const templatesBase = resolveTemplatesBase();
1180
1177
  // Resolve template source: named template or filesystem path
1181
- const templateIsPath = fs.existsSync(template) && (await fs.promises.stat(template)).isDirectory();
1178
+ const templateIsPath = existsSync(template) && (await promises.stat(template)).isDirectory();
1182
1179
  const srcBase = templateIsPath
1183
- ? path.resolve(template)
1184
- : path.resolve(templatesBase, template);
1185
- const projectBase = path.resolve(templatesBase, 'project');
1186
- if (!fs.existsSync(srcBase)) {
1180
+ ? resolve(template)
1181
+ : resolve(templatesBase, template);
1182
+ const projectBase = resolve(templatesBase, 'project');
1183
+ if (!existsSync(srcBase)) {
1187
1184
  throw new Error(`Template "${template}" not found (path or name). Tried: ${toPosix(srcBase)}.`);
1188
1185
  }
1189
1186
  // 1) Copy shared project boilerplate
1190
- if (fs.existsSync(projectBase)) {
1187
+ if (existsSync(projectBase)) {
1191
1188
  const rl = optAll.yes === true
1192
1189
  ? undefined
1193
- : promises.createInterface({ input: node_process.stdin, output: node_process.stdout, terminal: true });
1190
+ : createInterface({ input: stdin, output: stdout, terminal: true });
1194
1191
  let policy;
1195
1192
  const c = optAll.conflict;
1196
1193
  if (c === 'overwrite' || c === 'example' || c === 'skip' || c === 'ask')
@@ -1210,7 +1207,7 @@ const runInit = async (root, template = 'default', opts) => {
1210
1207
  {
1211
1208
  const rl = optAll.yes === true
1212
1209
  ? undefined
1213
- : promises.createInterface({ input: node_process.stdin, output: node_process.stdout, terminal: true });
1210
+ : createInterface({ input: stdin, output: stdout, terminal: true });
1214
1211
  let policy;
1215
1212
  const c = optAll.conflict;
1216
1213
  if (c === 'overwrite' || c === 'example' || c === 'skip' || c === 'ask')
@@ -1228,21 +1225,21 @@ const runInit = async (root, template = 'default', opts) => {
1228
1225
  }
1229
1226
  // 2.5) Convert template 'gitignore' into a real '.gitignore'
1230
1227
  try {
1231
- const giSrc = path.join(root, 'gitignore');
1232
- const giDot = path.join(root, '.gitignore');
1233
- if (fs.existsSync(giSrc)) {
1234
- if (!fs.existsSync(giDot)) {
1235
- await fs.promises.rename(giSrc, giDot);
1236
- created.push(path.posix.normalize(giDot));
1228
+ const giSrc = join(root, 'gitignore');
1229
+ const giDot = join(root, '.gitignore');
1230
+ if (existsSync(giSrc)) {
1231
+ if (!existsSync(giDot)) {
1232
+ await promises.rename(giSrc, giDot);
1233
+ created.push(posix.normalize(giDot));
1237
1234
  }
1238
1235
  else {
1239
- const example = path.join(root, 'gitignore.example');
1240
- if (!fs.existsSync(example)) {
1241
- const data = await fs.promises.readFile(giSrc, 'utf8');
1242
- await fs.promises.writeFile(example, data, 'utf8');
1243
- examples.push(path.posix.normalize(example));
1236
+ const example = join(root, 'gitignore.example');
1237
+ if (!existsSync(example)) {
1238
+ const data = await promises.readFile(giSrc, 'utf8');
1239
+ await promises.writeFile(example, data, 'utf8');
1240
+ examples.push(posix.normalize(example));
1244
1241
  }
1245
- await fs.promises.rm(giSrc, { force: true });
1242
+ await promises.rm(giSrc, { force: true });
1246
1243
  }
1247
1244
  }
1248
1245
  }
@@ -1251,22 +1248,22 @@ const runInit = async (root, template = 'default', opts) => {
1251
1248
  }
1252
1249
  // 2.6) Convert 'tsconfig.downstream.json' into 'tsconfig.json'
1253
1250
  try {
1254
- const ds = path.join(root, 'tsconfig.downstream.json');
1255
- const dst = path.join(root, 'tsconfig.json');
1256
- if (fs.existsSync(ds)) {
1257
- if (!fs.existsSync(dst)) {
1258
- await fs.promises.rename(ds, dst);
1259
- created.push(path.posix.normalize(dst));
1251
+ const ds = join(root, 'tsconfig.downstream.json');
1252
+ const dst = join(root, 'tsconfig.json');
1253
+ if (existsSync(ds)) {
1254
+ if (!existsSync(dst)) {
1255
+ await promises.rename(ds, dst);
1256
+ created.push(posix.normalize(dst));
1260
1257
  }
1261
1258
  else {
1262
1259
  // If a tsconfig already exists, write an example and remove the source
1263
- const example = path.join(root, 'tsconfig.json.example');
1264
- if (!fs.existsSync(example)) {
1265
- const data = await fs.promises.readFile(ds, 'utf8');
1266
- await fs.promises.writeFile(example, data, 'utf8');
1267
- examples.push(path.posix.normalize(example));
1260
+ const example = join(root, 'tsconfig.json.example');
1261
+ if (!existsSync(example)) {
1262
+ const data = await promises.readFile(ds, 'utf8');
1263
+ await promises.writeFile(example, data, 'utf8');
1264
+ examples.push(posix.normalize(example));
1268
1265
  }
1269
- await fs.promises.rm(ds, { force: true });
1266
+ await promises.rm(ds, { force: true });
1270
1267
  }
1271
1268
  }
1272
1269
  }
@@ -1280,7 +1277,7 @@ const runInit = async (root, template = 'default', opts) => {
1280
1277
  skipped.push(...res.skipped);
1281
1278
  }
1282
1279
  // 3) package.json presence (create when missing)
1283
- const pkgPath = path.join(root, 'package.json');
1280
+ const pkgPath = join(root, 'package.json');
1284
1281
  let pkg = await readJson(pkgPath);
1285
1282
  if (!pkg) {
1286
1283
  const name = toPosixSep(root).split('/').pop() ?? 'smoz-app';
@@ -1293,13 +1290,13 @@ const runInit = async (root, template = 'default', opts) => {
1293
1290
  };
1294
1291
  if (!optAll.dryRun)
1295
1292
  await writeJson(pkgPath, pkg);
1296
- created.push(path.posix.normalize(pkgPath));
1293
+ created.push(posix.normalize(pkgPath));
1297
1294
  }
1298
1295
  // 4) Merge manifest additively (prefer template's embedded package.json)
1299
- const templatePkgPath = path.resolve(srcBase, 'package.json');
1300
- const manifest = fs.existsSync(templatePkgPath)
1296
+ const templatePkgPath = resolve(srcBase, 'package.json');
1297
+ const manifest = existsSync(templatePkgPath)
1301
1298
  ? await readJson(templatePkgPath)
1302
- : await readJson(path.resolve(templatesBase, '.manifests', `package.${template}.json`));
1299
+ : await readJson(resolve(templatesBase, '.manifests', `package.${template}.json`));
1303
1300
  let pkgChanged = false;
1304
1301
  if (manifest) {
1305
1302
  const added = mergeAdditive(pkg, manifest);
@@ -1340,7 +1337,7 @@ const runInit = async (root, template = 'default', opts) => {
1340
1337
  * Registers init/add/register/openapi/dev on a GetDotenvCli instance and
1341
1338
  * delegates to existing implementations. No business logic here.
1342
1339
  */
1343
- const repoRoot = () => packageDirectory.packageDirectorySync() ?? process.cwd();
1340
+ const repoRoot = () => packageDirectorySync() ?? process.cwd();
1344
1341
  const setupSmozCommands = (cli) => {
1345
1342
  // init
1346
1343
  cli
@@ -1443,7 +1440,7 @@ const setupSmozCommands = (cli) => {
1443
1440
  });
1444
1441
  });
1445
1442
  };
1446
- const smozPlugin = () => cliHost.definePlugin({
1443
+ const smozPlugin = () => definePlugin({
1447
1444
  ns: 'smoz',
1448
1445
  setup: setupSmozCommands,
1449
1446
  });
@@ -1456,7 +1453,7 @@ const smozPlugin = () => cliHost.definePlugin({
1456
1453
  * - Install included plugins (cmd/batch/aws) and the SMOZ command plugin
1457
1454
  * (init/add/register/openapi/dev).
1458
1455
  */
1459
- const main = cli.createCli({
1456
+ const main = createCli({
1460
1457
  alias: 'smoz',
1461
1458
  compose: (cli) => {
1462
1459
  const setupResult = smozPlugin().setup(cli);
@@ -1464,12 +1461,12 @@ const main = cli.createCli({
1464
1461
  throw new Error('smozPlugin root setup must remain synchronous.');
1465
1462
  }
1466
1463
  return cli
1467
- .use(plugins.awsPlugin())
1468
- .use(plugins.cmdPlugin({
1464
+ .use(awsPlugin())
1465
+ .use(cmdPlugin({
1469
1466
  asDefault: true,
1470
1467
  optionAlias: '-c, --cmd <command...>',
1471
1468
  }))
1472
- .use(plugins.batchPlugin());
1469
+ .use(batchPlugin());
1473
1470
  },
1474
1471
  });
1475
1472
  void main();
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "hideCredit": true
8
8
  },
9
9
  "bin": {
10
- "smoz": "dist/cli/index.cjs"
10
+ "smoz": "dist/cli/index.mjs"
11
11
  },
12
12
  "bugs": {
13
13
  "url": "https://github.com/karmaniverous/smoz/issues"
@@ -183,7 +183,7 @@
183
183
  "templates:lint": "eslint --fix -c templates/default/eslint.config.ts \"templates/default/**/*.{ts,tsx,js,jsx}\" \"templates/default/eslint.config.ts\""
184
184
  },
185
185
  "type": "module",
186
- "version": "0.2.14",
186
+ "version": "0.2.15",
187
187
  "volta": {
188
188
  "node": "22.19.0"
189
189
  }