@wraps.dev/cli 2.17.1 → 2.17.3

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.
package/dist/cli.js CHANGED
@@ -5691,10 +5691,10 @@ __export(lambda_exports, {
5691
5691
  getLambdaCode: () => getLambdaCode
5692
5692
  });
5693
5693
  import { randomBytes as randomBytes2 } from "crypto";
5694
- import { existsSync as existsSync6, mkdirSync } from "fs";
5694
+ import { existsSync as existsSync7, mkdirSync } from "fs";
5695
5695
  import { builtinModules } from "module";
5696
5696
  import { tmpdir } from "os";
5697
- import { dirname as dirname3, join as join7 } from "path";
5697
+ import { dirname as dirname3, join as join8 } from "path";
5698
5698
  import { fileURLToPath as fileURLToPath3 } from "url";
5699
5699
  import * as aws8 from "@pulumi/aws";
5700
5700
  import * as pulumi11 from "@pulumi/pulumi";
@@ -5703,7 +5703,7 @@ function getPackageRoot() {
5703
5703
  const currentFile = fileURLToPath3(import.meta.url);
5704
5704
  let dir = dirname3(currentFile);
5705
5705
  while (dir !== dirname3(dir)) {
5706
- if (existsSync6(join7(dir, "package.json"))) {
5706
+ if (existsSync7(join8(dir, "package.json"))) {
5707
5707
  return dir;
5708
5708
  }
5709
5709
  dir = dirname3(dir);
@@ -5730,18 +5730,18 @@ async function findEventSourceMapping(functionName, queueArn) {
5730
5730
  }
5731
5731
  async function getLambdaCode(functionName) {
5732
5732
  const packageRoot = getPackageRoot();
5733
- const distLambdaPath = join7(packageRoot, "dist", "lambda", functionName);
5734
- const distBundleMarker = join7(distLambdaPath, ".bundled");
5735
- if (existsSync6(distBundleMarker)) {
5733
+ const distLambdaPath = join8(packageRoot, "dist", "lambda", functionName);
5734
+ const distBundleMarker = join8(distLambdaPath, ".bundled");
5735
+ if (existsSync7(distBundleMarker)) {
5736
5736
  return distLambdaPath;
5737
5737
  }
5738
- const lambdaPath = join7(packageRoot, "lambda", functionName);
5739
- const lambdaBundleMarker = join7(lambdaPath, ".bundled");
5740
- if (existsSync6(lambdaBundleMarker)) {
5738
+ const lambdaPath = join8(packageRoot, "lambda", functionName);
5739
+ const lambdaBundleMarker = join8(lambdaPath, ".bundled");
5740
+ if (existsSync7(lambdaBundleMarker)) {
5741
5741
  return lambdaPath;
5742
5742
  }
5743
- const sourcePath = join7(lambdaPath, "index.ts");
5744
- if (!existsSync6(sourcePath)) {
5743
+ const sourcePath = join8(lambdaPath, "index.ts");
5744
+ if (!existsSync7(sourcePath)) {
5745
5745
  throw new Error(
5746
5746
  `Lambda source not found: ${sourcePath}
5747
5747
  This usually means the build process didn't complete successfully.
@@ -5749,8 +5749,8 @@ Try running: pnpm build`
5749
5749
  );
5750
5750
  }
5751
5751
  const buildId = randomBytes2(8).toString("hex");
5752
- const outdir = join7(tmpdir(), `wraps-lambda-${buildId}`);
5753
- if (!existsSync6(outdir)) {
5752
+ const outdir = join8(tmpdir(), `wraps-lambda-${buildId}`);
5753
+ if (!existsSync7(outdir)) {
5754
5754
  mkdirSync(outdir, { recursive: true });
5755
5755
  }
5756
5756
  await build({
@@ -5759,7 +5759,7 @@ Try running: pnpm build`
5759
5759
  platform: "node",
5760
5760
  target: "node24",
5761
5761
  format: "cjs",
5762
- outfile: join7(outdir, "index.js"),
5762
+ outfile: join8(outdir, "index.js"),
5763
5763
  external: ["@aws-sdk/*", ...nodeBuiltins],
5764
5764
  minify: true,
5765
5765
  sourcemap: false
@@ -8901,7 +8901,7 @@ var init_dynamodb_metrics = __esm({
8901
8901
  // src/cli.ts
8902
8902
  init_esm_shims();
8903
8903
  import { readFileSync as readFileSync3 } from "fs";
8904
- import { dirname as dirname4, join as join19 } from "path";
8904
+ import { dirname as dirname4, join as join20 } from "path";
8905
8905
  import { fileURLToPath as fileURLToPath5 } from "url";
8906
8906
  import * as clack50 from "@clack/prompts";
8907
8907
  import args from "args";
@@ -10100,15 +10100,32 @@ import pc10 from "picocolors";
10100
10100
  init_esm_shims();
10101
10101
  init_errors();
10102
10102
  import { exec } from "child_process";
10103
- import { dirname as dirname2 } from "path";
10103
+ import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
10104
+ import { homedir as homedir3 } from "os";
10105
+ import { dirname as dirname2, join as join7 } from "path";
10104
10106
  import { promisify } from "util";
10105
10107
  import { PulumiCommand } from "@pulumi/pulumi/automation/index.js";
10106
10108
  var execAsync = promisify(exec);
10109
+ function findSdkInstalledPulumi() {
10110
+ const versionsDir = join7(homedir3(), ".pulumi", "versions");
10111
+ if (!existsSync6(versionsDir)) return;
10112
+ const versions = readdirSync2(versionsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort().reverse();
10113
+ for (const version of versions) {
10114
+ const binPath = join7(versionsDir, version, "bin", "pulumi");
10115
+ if (existsSync6(binPath)) return dirname2(binPath);
10116
+ }
10117
+ return;
10118
+ }
10107
10119
  async function checkPulumiInstalled() {
10108
10120
  try {
10109
10121
  await execAsync("pulumi version");
10110
10122
  return true;
10111
- } catch (_error) {
10123
+ } catch {
10124
+ const binDir = findSdkInstalledPulumi();
10125
+ if (binDir) {
10126
+ process.env.PATH = `${binDir}:${process.env.PATH}`;
10127
+ return true;
10128
+ }
10112
10129
  return false;
10113
10130
  }
10114
10131
  }
@@ -21653,17 +21670,17 @@ init_config();
21653
21670
  init_errors();
21654
21671
  init_json_output();
21655
21672
  init_output();
21656
- import { existsSync as existsSync8 } from "fs";
21673
+ import { existsSync as existsSync9 } from "fs";
21657
21674
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
21658
- import { join as join9 } from "path";
21675
+ import { join as join10 } from "path";
21659
21676
  import * as clack26 from "@clack/prompts";
21660
21677
  import pc27 from "picocolors";
21661
21678
 
21662
21679
  // src/utils/shared/scaffold-claude.ts
21663
21680
  init_esm_shims();
21664
- import { existsSync as existsSync7 } from "fs";
21681
+ import { existsSync as existsSync8 } from "fs";
21665
21682
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
21666
- import { join as join8 } from "path";
21683
+ import { join as join9 } from "path";
21667
21684
  var CLAUDE_MD_HEADER = `# Wraps
21668
21685
 
21669
21686
  This project uses [Wraps](https://wraps.dev) for email infrastructure.
@@ -21673,15 +21690,15 @@ async function scaffoldClaudeMdSection({
21673
21690
  sectionId,
21674
21691
  sectionContent
21675
21692
  }) {
21676
- const claudeDir = join8(projectDir, ".claude");
21677
- const claudeMdPath = join8(claudeDir, "CLAUDE.md");
21693
+ const claudeDir = join9(projectDir, ".claude");
21694
+ const claudeMdPath = join9(claudeDir, "CLAUDE.md");
21678
21695
  await mkdir2(claudeDir, { recursive: true });
21679
21696
  const startMarker = `<!-- wraps:${sectionId}-start -->`;
21680
21697
  const endMarker = `<!-- wraps:${sectionId}-end -->`;
21681
21698
  const wrappedContent = `${startMarker}
21682
21699
  ${sectionContent.trim()}
21683
21700
  ${endMarker}`;
21684
- if (!existsSync7(claudeMdPath)) {
21701
+ if (!existsSync8(claudeMdPath)) {
21685
21702
  await writeFile4(
21686
21703
  claudeMdPath,
21687
21704
  `${CLAUDE_MD_HEADER}
@@ -21715,8 +21732,8 @@ async function scaffoldClaudeSkill({
21715
21732
  skillName,
21716
21733
  skillContent
21717
21734
  }) {
21718
- const skillDir = join8(projectDir, ".claude", "skills", skillName);
21719
- const skillPath = join8(skillDir, "SKILL.md");
21735
+ const skillDir = join9(projectDir, ".claude", "skills", skillName);
21736
+ const skillPath = join9(skillDir, "SKILL.md");
21720
21737
  await mkdir2(skillDir, { recursive: true });
21721
21738
  await writeFile4(skillPath, `${skillContent.trim()}
21722
21739
  `, "utf-8");
@@ -22101,12 +22118,12 @@ wraps email templates preview # Preview in browser
22101
22118
  async function templatesInit(options) {
22102
22119
  const startTime = Date.now();
22103
22120
  const cwd = process.cwd();
22104
- const wrapsDir = join9(cwd, "wraps");
22121
+ const wrapsDir = join10(cwd, "wraps");
22105
22122
  if (!isJsonMode()) {
22106
22123
  clack26.intro(pc27.bold("Templates as Code"));
22107
22124
  }
22108
22125
  const progress = new DeploymentProgress();
22109
- if (existsSync8(wrapsDir) && !options.force) {
22126
+ if (existsSync9(wrapsDir) && !options.force) {
22110
22127
  throw new WrapsError(
22111
22128
  "wraps/ directory already exists",
22112
22129
  "TEMPLATES_DIR_EXISTS",
@@ -22141,8 +22158,8 @@ async function templatesInit(options) {
22141
22158
  let detectedDomain;
22142
22159
  let detectedRegion;
22143
22160
  try {
22144
- const pkgPath = join9(cwd, "package.json");
22145
- if (existsSync8(pkgPath)) {
22161
+ const pkgPath = join10(cwd, "package.json");
22162
+ if (existsSync9(pkgPath)) {
22146
22163
  const pkg = JSON.parse(await readFile4(pkgPath, "utf-8"));
22147
22164
  if (pkg.homepage) {
22148
22165
  try {
@@ -22155,9 +22172,9 @@ async function templatesInit(options) {
22155
22172
  } catch {
22156
22173
  }
22157
22174
  try {
22158
- const { homedir: homedir3 } = await import("os");
22159
- const connectionsDir = join9(homedir3(), ".wraps", "connections");
22160
- if (existsSync8(connectionsDir)) {
22175
+ const { homedir: homedir4 } = await import("os");
22176
+ const connectionsDir = join10(homedir4(), ".wraps", "connections");
22177
+ if (existsSync9(connectionsDir)) {
22161
22178
  const { readdir: readdir5 } = await import("fs/promises");
22162
22179
  const files = await readdir5(connectionsDir);
22163
22180
  if (files.length > 0) {
@@ -22172,34 +22189,34 @@ async function templatesInit(options) {
22172
22189
  }
22173
22190
  progress.start("Creating wraps/ directory structure");
22174
22191
  await mkdir3(wrapsDir, { recursive: true });
22175
- await mkdir3(join9(wrapsDir, "templates"), { recursive: true });
22176
- await mkdir3(join9(wrapsDir, "templates", "_components"), { recursive: true });
22177
- await mkdir3(join9(wrapsDir, "workflows"), { recursive: true });
22178
- await mkdir3(join9(wrapsDir, ".wraps"), { recursive: true });
22192
+ await mkdir3(join10(wrapsDir, "templates"), { recursive: true });
22193
+ await mkdir3(join10(wrapsDir, "templates", "_components"), { recursive: true });
22194
+ await mkdir3(join10(wrapsDir, "workflows"), { recursive: true });
22195
+ await mkdir3(join10(wrapsDir, ".wraps"), { recursive: true });
22179
22196
  const configContent = generateConfigFile(
22180
22197
  orgSlug,
22181
22198
  detectedDomain,
22182
22199
  detectedRegion
22183
22200
  );
22184
- await writeFile5(join9(wrapsDir, "wraps.config.ts"), configContent, "utf-8");
22201
+ await writeFile5(join10(wrapsDir, "wraps.config.ts"), configContent, "utf-8");
22185
22202
  const brandContent = generateBrandFile();
22186
- await writeFile5(join9(wrapsDir, "brand.ts"), brandContent, "utf-8");
22203
+ await writeFile5(join10(wrapsDir, "brand.ts"), brandContent, "utf-8");
22187
22204
  if (!options.noExample) {
22188
22205
  await writeFile5(
22189
- join9(wrapsDir, "templates", "welcome.tsx"),
22206
+ join10(wrapsDir, "templates", "welcome.tsx"),
22190
22207
  generateWelcomeTemplate(),
22191
22208
  "utf-8"
22192
22209
  );
22193
22210
  await writeFile5(
22194
- join9(wrapsDir, "templates", "_components", "footer.tsx"),
22211
+ join10(wrapsDir, "templates", "_components", "footer.tsx"),
22195
22212
  generateFooterComponent(),
22196
22213
  "utf-8"
22197
22214
  );
22198
22215
  }
22199
- const gitignorePath = join9(wrapsDir, ".gitignore");
22216
+ const gitignorePath = join10(wrapsDir, ".gitignore");
22200
22217
  await writeFile5(gitignorePath, ".wraps/\n", "utf-8");
22201
- const rootGitignorePath = join9(cwd, ".gitignore");
22202
- if (existsSync8(rootGitignorePath)) {
22218
+ const rootGitignorePath = join10(cwd, ".gitignore");
22219
+ if (existsSync9(rootGitignorePath)) {
22203
22220
  const gitignoreContent = await readFile4(rootGitignorePath, "utf-8");
22204
22221
  if (!gitignoreContent.includes("wraps/.wraps")) {
22205
22222
  await writeFile5(
@@ -22470,23 +22487,23 @@ const unsubscribeLink = {
22470
22487
  // src/commands/email/templates/preview.ts
22471
22488
  init_esm_shims();
22472
22489
  init_events();
22473
- import { existsSync as existsSync10, watch } from "fs";
22474
- import { join as join11 } from "path";
22490
+ import { existsSync as existsSync11, watch } from "fs";
22491
+ import { join as join12 } from "path";
22475
22492
  import * as clack27 from "@clack/prompts";
22476
22493
  import pc28 from "picocolors";
22477
22494
 
22478
22495
  // src/utils/email/template-compiler.ts
22479
22496
  init_esm_shims();
22480
- import { existsSync as existsSync9 } from "fs";
22497
+ import { existsSync as existsSync10 } from "fs";
22481
22498
  import { mkdir as mkdir4, readdir as readdir3, writeFile as writeFile6 } from "fs/promises";
22482
- import { join as join10 } from "path";
22499
+ import { join as join11 } from "path";
22483
22500
  async function loadWrapsConfig(wrapsDir) {
22484
- const configPath = join10(wrapsDir, "wraps.config.ts");
22501
+ const configPath = join11(wrapsDir, "wraps.config.ts");
22485
22502
  const { build: build2 } = await import("esbuild");
22486
- const shimDir = join10(wrapsDir, ".wraps", "_shims");
22503
+ const shimDir = join11(wrapsDir, ".wraps", "_shims");
22487
22504
  await mkdir4(shimDir, { recursive: true });
22488
22505
  await writeFile6(
22489
- join10(shimDir, "wraps-client-shim.mjs"),
22506
+ join11(shimDir, "wraps-client-shim.mjs"),
22490
22507
  "export const defineConfig = (c) => c;\nexport const defineBrand = (b) => b;\n",
22491
22508
  "utf-8"
22492
22509
  );
@@ -22498,11 +22515,11 @@ async function loadWrapsConfig(wrapsDir) {
22498
22515
  platform: "node",
22499
22516
  target: "node20",
22500
22517
  alias: {
22501
- "@wraps.dev/client": join10(shimDir, "wraps-client-shim.mjs")
22518
+ "@wraps.dev/client": join11(shimDir, "wraps-client-shim.mjs")
22502
22519
  }
22503
22520
  });
22504
22521
  const code = result.outputFiles[0].text;
22505
- const tmpPath = join10(wrapsDir, ".wraps", "_config.mjs");
22522
+ const tmpPath = join11(wrapsDir, ".wraps", "_config.mjs");
22506
22523
  await writeFile6(tmpPath, code, "utf-8");
22507
22524
  const mod = await import(tmpPath);
22508
22525
  const config2 = mod.default;
@@ -22537,8 +22554,8 @@ async function findCliNodeModules() {
22537
22554
  try {
22538
22555
  const req = createRequire(base);
22539
22556
  const reactPkg = req.resolve("react/package.json");
22540
- const reactNodeModules = join10(dirname5(reactPkg), "..");
22541
- if (existsSync9(join10(reactNodeModules, "react"))) {
22557
+ const reactNodeModules = join11(dirname5(reactPkg), "..");
22558
+ if (existsSync10(join11(reactNodeModules, "react"))) {
22542
22559
  paths.push(reactNodeModules);
22543
22560
  break;
22544
22561
  }
@@ -22566,10 +22583,10 @@ async function compileForPreview(filePath, slug, wrapsDir) {
22566
22583
  }
22567
22584
  });
22568
22585
  const bundledCode = result.outputFiles[0].text;
22569
- const projectRoot = join10(wrapsDir, "..");
22570
- const tmpDir = join10(projectRoot, "node_modules", ".wraps-compiled");
22586
+ const projectRoot = join11(wrapsDir, "..");
22587
+ const tmpDir = join11(projectRoot, "node_modules", ".wraps-compiled");
22571
22588
  await mkdir4(tmpDir, { recursive: true });
22572
- const tmpPath = join10(tmpDir, `${slug}.preview.mjs`);
22589
+ const tmpPath = join11(tmpDir, `${slug}.preview.mjs`);
22573
22590
  await writeFile6(tmpPath, bundledCode, "utf-8");
22574
22591
  const mod = await import(`${tmpPath}?t=${Date.now()}`);
22575
22592
  const Component = mod.default;
@@ -22592,15 +22609,15 @@ async function compileForPreview(filePath, slug, wrapsDir) {
22592
22609
  init_errors();
22593
22610
  async function templatesPreview(options) {
22594
22611
  const cwd = process.cwd();
22595
- const wrapsDir = join11(cwd, "wraps");
22596
- const configPath = join11(wrapsDir, "wraps.config.ts");
22597
- if (!existsSync10(configPath)) {
22612
+ const wrapsDir = join12(cwd, "wraps");
22613
+ const configPath = join12(wrapsDir, "wraps.config.ts");
22614
+ if (!existsSync11(configPath)) {
22598
22615
  throw errors.wrapsConfigNotFound();
22599
22616
  }
22600
22617
  clack27.intro(pc28.bold("Preview Templates"));
22601
22618
  const config2 = await loadWrapsConfig(wrapsDir);
22602
- const templatesDir = join11(wrapsDir, config2.templatesDir || "./templates");
22603
- if (!existsSync10(templatesDir)) {
22619
+ const templatesDir = join12(wrapsDir, config2.templatesDir || "./templates");
22620
+ if (!existsSync11(templatesDir)) {
22604
22621
  throw errors.wrapsConfigNotFound();
22605
22622
  }
22606
22623
  const templateFiles = await discoverTemplates(templatesDir, options.template);
@@ -22619,7 +22636,7 @@ async function templatesPreview(options) {
22619
22636
  throw new Error(`Template not found: ${slug}`);
22620
22637
  }
22621
22638
  const result = await compileForPreview(
22622
- join11(templatesDir, file),
22639
+ join12(templatesDir, file),
22623
22640
  slug,
22624
22641
  wrapsDir
22625
22642
  );
@@ -22921,9 +22938,9 @@ function renderErrorPage(err) {
22921
22938
  init_esm_shims();
22922
22939
  init_events();
22923
22940
  import { createHash } from "crypto";
22924
- import { existsSync as existsSync12 } from "fs";
22941
+ import { existsSync as existsSync13 } from "fs";
22925
22942
  import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile8 } from "fs/promises";
22926
- import { join as join13 } from "path";
22943
+ import { join as join14 } from "path";
22927
22944
  import * as clack28 from "@clack/prompts";
22928
22945
  import pc29 from "picocolors";
22929
22946
  init_config();
@@ -22932,15 +22949,15 @@ init_json_output();
22932
22949
 
22933
22950
  // src/utils/shared/lockfile.ts
22934
22951
  init_esm_shims();
22935
- import { existsSync as existsSync11 } from "fs";
22952
+ import { existsSync as existsSync12 } from "fs";
22936
22953
  import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile7 } from "fs/promises";
22937
- import { join as join12 } from "path";
22954
+ import { join as join13 } from "path";
22938
22955
  function getLockfilePath(wrapsDir) {
22939
- return join12(wrapsDir, ".wraps", "lockfile.json");
22956
+ return join13(wrapsDir, ".wraps", "lockfile.json");
22940
22957
  }
22941
22958
  async function loadLockfile(wrapsDir) {
22942
22959
  const path3 = getLockfilePath(wrapsDir);
22943
- if (!existsSync11(path3)) {
22960
+ if (!existsSync12(path3)) {
22944
22961
  return { version: "1.0.0", lastSync: "", templates: {}, workflows: {} };
22945
22962
  }
22946
22963
  try {
@@ -22959,7 +22976,7 @@ async function loadLockfile(wrapsDir) {
22959
22976
  }
22960
22977
  async function saveLockfile(wrapsDir, lockfile) {
22961
22978
  const path3 = getLockfilePath(wrapsDir);
22962
- const dir = join12(path3, "..");
22979
+ const dir = join13(path3, "..");
22963
22980
  await mkdir5(dir, { recursive: true });
22964
22981
  await writeFile7(path3, JSON.stringify(lockfile, null, 2), "utf-8");
22965
22982
  }
@@ -22969,9 +22986,9 @@ init_output();
22969
22986
  async function templatesPush(options) {
22970
22987
  const startTime = Date.now();
22971
22988
  const cwd = process.cwd();
22972
- const wrapsDir = join13(cwd, "wraps");
22973
- const configPath = join13(wrapsDir, "wraps.config.ts");
22974
- if (!existsSync12(configPath)) {
22989
+ const wrapsDir = join14(cwd, "wraps");
22990
+ const configPath = join14(wrapsDir, "wraps.config.ts");
22991
+ if (!existsSync13(configPath)) {
22975
22992
  throw errors.wrapsConfigNotFound();
22976
22993
  }
22977
22994
  if (!isJsonMode()) {
@@ -22981,8 +22998,8 @@ async function templatesPush(options) {
22981
22998
  progress.start("Loading configuration");
22982
22999
  const config2 = await loadWrapsConfig(wrapsDir);
22983
23000
  progress.succeed("Configuration loaded");
22984
- const templatesDir = join13(wrapsDir, config2.templatesDir || "./templates");
22985
- if (!existsSync12(templatesDir)) {
23001
+ const templatesDir = join14(wrapsDir, config2.templatesDir || "./templates");
23002
+ if (!existsSync13(templatesDir)) {
22986
23003
  throw errors.wrapsConfigNotFound();
22987
23004
  }
22988
23005
  const templateFiles = await discoverTemplates(templatesDir, options.template);
@@ -23000,7 +23017,7 @@ async function templatesPush(options) {
23000
23017
  const compileErrors = [];
23001
23018
  for (const file of templateFiles) {
23002
23019
  const slug = file.replace(/\.tsx?$/, "");
23003
- const filePath = join13(templatesDir, file);
23020
+ const filePath = join14(templatesDir, file);
23004
23021
  const source = await readFile6(filePath, "utf-8");
23005
23022
  const sourceHash = sha256(source);
23006
23023
  const localHashMatches = lockfile.templates[slug]?.localHash === sourceHash;
@@ -23142,10 +23159,10 @@ async function compileTemplate(filePath, slug, source, sourceHash, wrapsDir) {
23142
23159
  }
23143
23160
  });
23144
23161
  const bundledCode = result.outputFiles[0].text;
23145
- const projectRoot = join13(wrapsDir, "..");
23146
- const tmpDir = join13(projectRoot, "node_modules", ".wraps-compiled");
23162
+ const projectRoot = join14(wrapsDir, "..");
23163
+ const tmpDir = join14(projectRoot, "node_modules", ".wraps-compiled");
23147
23164
  await mkdir6(tmpDir, { recursive: true });
23148
- const tmpPath = join13(tmpDir, `${slug}.mjs`);
23165
+ const tmpPath = join14(tmpDir, `${slug}.mjs`);
23149
23166
  await writeFile8(tmpPath, bundledCode, "utf-8");
23150
23167
  const mod = await import(tmpPath);
23151
23168
  const Component = mod.default;
@@ -23652,6 +23669,11 @@ ${pc30.bold("Current Configuration:")}
23652
23669
  value: "smtp-credentials",
23653
23670
  label: metadata.services.email?.smtpCredentials?.enabled ? "Manage SMTP credentials" : "Enable SMTP credentials",
23654
23671
  hint: metadata.services.email?.smtpCredentials?.enabled ? "Rotate or disable credentials" : "Generate credentials for PHP, WordPress, etc."
23672
+ },
23673
+ {
23674
+ value: "hosting-provider",
23675
+ label: "Change hosting provider",
23676
+ hint: metadata.provider === "vercel" ? `Currently: Vercel (${metadata.vercel?.teamSlug || "configured"})` : `Currently: ${metadata.provider} \u2192 Switch to Vercel OIDC, etc.`
23655
23677
  }
23656
23678
  );
23657
23679
  upgradeAction = await clack29.select({
@@ -24731,6 +24753,48 @@ ${pc30.bold("SMTP Credentials for Legacy Systems")}
24731
24753
  newPreset = void 0;
24732
24754
  break;
24733
24755
  }
24756
+ case "hosting-provider": {
24757
+ const newProvider = await clack29.select({
24758
+ message: "Where is your app hosted?",
24759
+ options: [
24760
+ {
24761
+ value: "aws",
24762
+ label: "AWS (Lambda/ECS/EC2)",
24763
+ hint: "Uses IAM roles automatically"
24764
+ },
24765
+ {
24766
+ value: "vercel",
24767
+ label: "Vercel",
24768
+ hint: "Uses OIDC (no AWS credentials needed)"
24769
+ },
24770
+ {
24771
+ value: "railway",
24772
+ label: "Railway",
24773
+ hint: "Requires AWS credentials"
24774
+ },
24775
+ {
24776
+ value: "other",
24777
+ label: "Other",
24778
+ hint: "Will use AWS access keys"
24779
+ }
24780
+ ]
24781
+ });
24782
+ if (clack29.isCancel(newProvider)) {
24783
+ clack29.cancel("Upgrade cancelled.");
24784
+ process.exit(0);
24785
+ }
24786
+ if (newProvider === metadata.provider) {
24787
+ clack29.log.info("Provider unchanged \u2014 no changes needed.");
24788
+ process.exit(0);
24789
+ }
24790
+ metadata.provider = newProvider;
24791
+ if (newProvider === "vercel") {
24792
+ metadata.vercel = await promptVercelConfig();
24793
+ } else {
24794
+ metadata.vercel = void 0;
24795
+ }
24796
+ break;
24797
+ }
24734
24798
  }
24735
24799
  const newCostData = calculateCosts(updatedConfig, 5e4);
24736
24800
  const costDiff = newCostData.total.monthly - currentCostData.total.monthly;
@@ -25390,9 +25454,9 @@ init_esm_shims();
25390
25454
  init_events();
25391
25455
  init_json_output();
25392
25456
  init_output();
25393
- import { existsSync as existsSync13 } from "fs";
25457
+ import { existsSync as existsSync14 } from "fs";
25394
25458
  import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile9 } from "fs/promises";
25395
- import { join as join14 } from "path";
25459
+ import { join as join15 } from "path";
25396
25460
  import * as clack30 from "@clack/prompts";
25397
25461
  import pc31 from "picocolors";
25398
25462
 
@@ -25783,12 +25847,12 @@ export default defineWorkflow({
25783
25847
  async function workflowsInit(options) {
25784
25848
  const startTime = Date.now();
25785
25849
  const cwd = process.cwd();
25786
- const workflowsDir = join14(cwd, "wraps", "workflows");
25850
+ const workflowsDir = join15(cwd, "wraps", "workflows");
25787
25851
  if (!isJsonMode()) {
25788
25852
  clack30.intro(pc31.bold("Workflows as Code"));
25789
25853
  }
25790
25854
  const progress = new DeploymentProgress();
25791
- if (existsSync13(workflowsDir) && !options.force) {
25855
+ if (existsSync14(workflowsDir) && !options.force) {
25792
25856
  const { readdir: readdir5 } = await import("fs/promises");
25793
25857
  const files = await readdir5(workflowsDir);
25794
25858
  const tsFiles = files.filter(
@@ -25802,8 +25866,8 @@ async function workflowsInit(options) {
25802
25866
  }
25803
25867
  progress.start("Creating wraps/workflows/ directory");
25804
25868
  await mkdir7(workflowsDir, { recursive: true });
25805
- const configPath = join14(cwd, "wraps", "wraps.config.ts");
25806
- if (existsSync13(configPath)) {
25869
+ const configPath = join15(cwd, "wraps", "wraps.config.ts");
25870
+ if (existsSync14(configPath)) {
25807
25871
  const configContent = await readFile7(configPath, "utf-8");
25808
25872
  if (!configContent.includes("workflowsDir")) {
25809
25873
  const updated = configContent.replace(
@@ -25820,8 +25884,8 @@ async function workflowsInit(options) {
25820
25884
  }
25821
25885
  const filesCreated = [];
25822
25886
  if (!options.noExample) {
25823
- const examplePath = join14(workflowsDir, "welcome.ts");
25824
- if (!existsSync13(examplePath) || options.force) {
25887
+ const examplePath = join15(workflowsDir, "welcome.ts");
25888
+ if (!existsSync14(examplePath) || options.force) {
25825
25889
  await writeFile9(examplePath, EXAMPLE_WORKFLOW, "utf-8");
25826
25890
  filesCreated.push("wraps/workflows/welcome.ts");
25827
25891
  }
@@ -25903,8 +25967,8 @@ export default defineConfig({
25903
25967
  // src/commands/email/workflows/push.ts
25904
25968
  init_esm_shims();
25905
25969
  init_events();
25906
- import { existsSync as existsSync15 } from "fs";
25907
- import { join as join16 } from "path";
25970
+ import { existsSync as existsSync16 } from "fs";
25971
+ import { join as join17 } from "path";
25908
25972
  import * as clack31 from "@clack/prompts";
25909
25973
  import pc32 from "picocolors";
25910
25974
 
@@ -26123,11 +26187,11 @@ function assignPositions(steps, transitions) {
26123
26187
  // src/utils/email/workflow-ts.ts
26124
26188
  init_esm_shims();
26125
26189
  import { createHash as createHash2 } from "crypto";
26126
- import { existsSync as existsSync14 } from "fs";
26190
+ import { existsSync as existsSync15 } from "fs";
26127
26191
  import { mkdir as mkdir8, readdir as readdir4, readFile as readFile8, writeFile as writeFile10 } from "fs/promises";
26128
- import { basename, join as join15 } from "path";
26192
+ import { basename, join as join16 } from "path";
26129
26193
  async function discoverWorkflows(dir, filter) {
26130
- if (!existsSync14(dir)) {
26194
+ if (!existsSync15(dir)) {
26131
26195
  return [];
26132
26196
  }
26133
26197
  const entries = await readdir4(dir);
@@ -26150,7 +26214,7 @@ async function parseWorkflowTs(filePath, wrapsDir) {
26150
26214
  const source = await readFile8(filePath, "utf-8");
26151
26215
  const sourceHash = createHash2("sha256").update(source).digest("hex");
26152
26216
  const slug = basename(filePath, ".ts");
26153
- const shimDir = join15(wrapsDir, ".wraps", "_shims");
26217
+ const shimDir = join16(wrapsDir, ".wraps", "_shims");
26154
26218
  await mkdir8(shimDir, { recursive: true });
26155
26219
  const clientShimContent = `
26156
26220
  // Identity functions for workflow definitions
@@ -26379,7 +26443,7 @@ function durationToSeconds(duration) {
26379
26443
  }
26380
26444
  `;
26381
26445
  await writeFile10(
26382
- join15(shimDir, "wraps-client-shim.mjs"),
26446
+ join16(shimDir, "wraps-client-shim.mjs"),
26383
26447
  clientShimContent,
26384
26448
  "utf-8"
26385
26449
  );
@@ -26391,13 +26455,13 @@ function durationToSeconds(duration) {
26391
26455
  platform: "node",
26392
26456
  target: "node20",
26393
26457
  alias: {
26394
- "@wraps.dev/client": join15(shimDir, "wraps-client-shim.mjs")
26458
+ "@wraps.dev/client": join16(shimDir, "wraps-client-shim.mjs")
26395
26459
  }
26396
26460
  });
26397
26461
  const bundledCode = result.outputFiles[0].text;
26398
- const tmpDir = join15(wrapsDir, ".wraps", "_workflows");
26462
+ const tmpDir = join16(wrapsDir, ".wraps", "_workflows");
26399
26463
  await mkdir8(tmpDir, { recursive: true });
26400
- const tmpPath = join15(tmpDir, `${slug}.mjs`);
26464
+ const tmpPath = join16(tmpDir, `${slug}.mjs`);
26401
26465
  await writeFile10(tmpPath, bundledCode, "utf-8");
26402
26466
  const mod = await import(`${tmpPath}?t=${Date.now()}`);
26403
26467
  const definition = mod.default;
@@ -26750,9 +26814,9 @@ init_output();
26750
26814
  async function workflowsPush(options) {
26751
26815
  const startTime = Date.now();
26752
26816
  const cwd = process.cwd();
26753
- const wrapsDir = join16(cwd, "wraps");
26754
- const configPath = join16(wrapsDir, "wraps.config.ts");
26755
- if (!existsSync15(configPath)) {
26817
+ const wrapsDir = join17(cwd, "wraps");
26818
+ const configPath = join17(wrapsDir, "wraps.config.ts");
26819
+ if (!existsSync16(configPath)) {
26756
26820
  throw errors.wrapsConfigNotFound();
26757
26821
  }
26758
26822
  if (!isJsonMode()) {
@@ -26762,8 +26826,8 @@ async function workflowsPush(options) {
26762
26826
  progress.start("Loading configuration");
26763
26827
  const config2 = await loadWrapsConfig(wrapsDir);
26764
26828
  progress.succeed("Configuration loaded");
26765
- const workflowsDir = join16(wrapsDir, config2.workflowsDir || "./workflows");
26766
- if (!existsSync15(workflowsDir)) {
26829
+ const workflowsDir = join17(wrapsDir, config2.workflowsDir || "./workflows");
26830
+ if (!existsSync16(workflowsDir)) {
26767
26831
  if (isJsonMode()) {
26768
26832
  jsonSuccess("email.workflows.push", {
26769
26833
  pushed: [],
@@ -26789,9 +26853,9 @@ async function workflowsPush(options) {
26789
26853
  return;
26790
26854
  }
26791
26855
  const lockfile = await loadLockfile(wrapsDir);
26792
- const templatesDir = join16(wrapsDir, config2.templatesDir || "./templates");
26856
+ const templatesDir = join17(wrapsDir, config2.templatesDir || "./templates");
26793
26857
  let localTemplateSlugs;
26794
- if (existsSync15(templatesDir)) {
26858
+ if (existsSync16(templatesDir)) {
26795
26859
  const templateFiles = await discoverTemplates(templatesDir);
26796
26860
  localTemplateSlugs = new Set(
26797
26861
  templateFiles.map((f) => f.replace(/\.tsx?$/, ""))
@@ -26803,7 +26867,7 @@ async function workflowsPush(options) {
26803
26867
  const validationErrors = [];
26804
26868
  for (const file of workflowFiles) {
26805
26869
  const slug = file.replace(/\.ts$/, "");
26806
- const filePath = join16(workflowsDir, file);
26870
+ const filePath = join17(workflowsDir, file);
26807
26871
  progress.start(`Processing ${pc32.cyan(slug)}`);
26808
26872
  try {
26809
26873
  const parsed = await parseWorkflowTs(filePath, wrapsDir);
@@ -27121,8 +27185,8 @@ async function pushToAPI2(workflows, token, progress, options) {
27121
27185
  // src/commands/email/workflows/validate.ts
27122
27186
  init_esm_shims();
27123
27187
  init_events();
27124
- import { existsSync as existsSync16 } from "fs";
27125
- import { join as join17 } from "path";
27188
+ import { existsSync as existsSync17 } from "fs";
27189
+ import { join as join18 } from "path";
27126
27190
  import * as clack32 from "@clack/prompts";
27127
27191
  import pc33 from "picocolors";
27128
27192
  init_errors();
@@ -27131,9 +27195,9 @@ init_output();
27131
27195
  async function workflowsValidate(options) {
27132
27196
  const startTime = Date.now();
27133
27197
  const cwd = process.cwd();
27134
- const wrapsDir = join17(cwd, "wraps");
27135
- const configPath = join17(wrapsDir, "wraps.config.ts");
27136
- if (!existsSync16(configPath)) {
27198
+ const wrapsDir = join18(cwd, "wraps");
27199
+ const configPath = join18(wrapsDir, "wraps.config.ts");
27200
+ if (!existsSync17(configPath)) {
27137
27201
  throw errors.wrapsConfigNotFound();
27138
27202
  }
27139
27203
  if (!isJsonMode()) {
@@ -27143,8 +27207,8 @@ async function workflowsValidate(options) {
27143
27207
  progress.start("Loading configuration");
27144
27208
  const config2 = await loadWrapsConfig(wrapsDir);
27145
27209
  progress.succeed("Configuration loaded");
27146
- const workflowsDir = join17(wrapsDir, config2.workflowsDir || "./workflows");
27147
- if (!existsSync16(workflowsDir)) {
27210
+ const workflowsDir = join18(wrapsDir, config2.workflowsDir || "./workflows");
27211
+ if (!existsSync17(workflowsDir)) {
27148
27212
  if (isJsonMode()) {
27149
27213
  jsonSuccess("email.workflows.validate", { workflows: [], errors: [] });
27150
27214
  } else {
@@ -27161,9 +27225,9 @@ async function workflowsValidate(options) {
27161
27225
  }
27162
27226
  return;
27163
27227
  }
27164
- const templatesDir = join17(wrapsDir, config2.templatesDir || "./templates");
27228
+ const templatesDir = join18(wrapsDir, config2.templatesDir || "./templates");
27165
27229
  let localTemplateSlugs;
27166
- if (existsSync16(templatesDir)) {
27230
+ if (existsSync17(templatesDir)) {
27167
27231
  const templateFiles = await discoverTemplates(templatesDir);
27168
27232
  localTemplateSlugs = new Set(
27169
27233
  templateFiles.map((f) => f.replace(/\.tsx?$/, ""))
@@ -27173,7 +27237,7 @@ async function workflowsValidate(options) {
27173
27237
  const parseErrors = [];
27174
27238
  for (const file of workflowFiles) {
27175
27239
  const slug = file.replace(/\.ts$/, "");
27176
- const filePath = join17(workflowsDir, file);
27240
+ const filePath = join18(workflowsDir, file);
27177
27241
  progress.start(`Validating ${pc33.cyan(slug)}`);
27178
27242
  try {
27179
27243
  const parsed = await parseWorkflowTs(filePath, wrapsDir);
@@ -36177,8 +36241,8 @@ async function telemetryStatus() {
36177
36241
 
36178
36242
  // src/commands/workflow/init.ts
36179
36243
  init_esm_shims();
36180
- import { existsSync as existsSync17, mkdirSync as mkdirSync2, writeFileSync } from "fs";
36181
- import { join as join18 } from "path";
36244
+ import { existsSync as existsSync18, mkdirSync as mkdirSync2, writeFileSync } from "fs";
36245
+ import { join as join19 } from "path";
36182
36246
  import * as clack49 from "@clack/prompts";
36183
36247
  import pc52 from "picocolors";
36184
36248
  var EXAMPLE_CASCADE_WORKFLOW = `import {
@@ -36276,14 +36340,14 @@ export default defineConfig({
36276
36340
  `;
36277
36341
  async function workflowInit(options = {}) {
36278
36342
  clack49.intro(pc52.bgCyan(pc52.black(" wraps workflow init ")));
36279
- const wrapsDir = join18(process.cwd(), "wraps");
36280
- const workflowsDir = join18(wrapsDir, "workflows");
36281
- const configPath = join18(wrapsDir, "wraps.config.ts");
36282
- if (existsSync17(workflowsDir)) {
36343
+ const wrapsDir = join19(process.cwd(), "wraps");
36344
+ const workflowsDir = join19(wrapsDir, "workflows");
36345
+ const configPath = join19(wrapsDir, "wraps.config.ts");
36346
+ if (existsSync18(workflowsDir)) {
36283
36347
  clack49.log.info(
36284
36348
  `Workflows directory already exists at ${pc52.cyan("wraps/workflows/")}`
36285
36349
  );
36286
- const files = existsSync17(join18(workflowsDir, "cart-recovery.ts")) || existsSync17(join18(workflowsDir, "welcome-sequence.ts"));
36350
+ const files = existsSync18(join19(workflowsDir, "cart-recovery.ts")) || existsSync18(join19(workflowsDir, "welcome-sequence.ts"));
36287
36351
  if (files && !options.yes) {
36288
36352
  const shouldContinue = await clack49.confirm({
36289
36353
  message: "Example files may already exist. Overwrite them?",
@@ -36304,17 +36368,17 @@ async function workflowInit(options = {}) {
36304
36368
  s.stop("Created wraps/workflows/");
36305
36369
  s.start("Scaffolding example workflows...");
36306
36370
  writeFileSync(
36307
- join18(workflowsDir, "cart-recovery.ts"),
36371
+ join19(workflowsDir, "cart-recovery.ts"),
36308
36372
  EXAMPLE_CASCADE_WORKFLOW,
36309
36373
  "utf-8"
36310
36374
  );
36311
36375
  writeFileSync(
36312
- join18(workflowsDir, "welcome-sequence.ts"),
36376
+ join19(workflowsDir, "welcome-sequence.ts"),
36313
36377
  EXAMPLE_WELCOME_WORKFLOW,
36314
36378
  "utf-8"
36315
36379
  );
36316
36380
  s.stop("Created 2 example workflows");
36317
- if (!existsSync17(configPath)) {
36381
+ if (!existsSync18(configPath)) {
36318
36382
  writeFileSync(configPath, EXAMPLE_CONFIG, "utf-8");
36319
36383
  clack49.log.info(`Created ${pc52.cyan("wraps/wraps.config.ts")}`);
36320
36384
  }
@@ -36417,7 +36481,7 @@ if (nodeMajorVersion < 20) {
36417
36481
  var __filename2 = fileURLToPath5(import.meta.url);
36418
36482
  var __dirname3 = dirname4(__filename2);
36419
36483
  var packageJson = JSON.parse(
36420
- readFileSync3(join19(__dirname3, "../package.json"), "utf-8")
36484
+ readFileSync3(join20(__dirname3, "../package.json"), "utf-8")
36421
36485
  );
36422
36486
  var VERSION = packageJson.version;
36423
36487
  setupTabCompletion();