@biffo/cli 0.103.1 → 0.103.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.
Files changed (2) hide show
  1. package/dist/index.js +205 -85
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2029,9 +2029,7 @@ function pluginModuleSource(cwd, name) {
2029
2029
  return isFirstPartyPlugin(cwd, name) ? FIRST_PARTY_TERRAFORM(name) : THIRD_PARTY_TERRAFORM(name);
2030
2030
  }
2031
2031
  function listWireablePlugins(cwd) {
2032
- const copied = listPluginModules(cwd);
2033
- const firstParty = firstPartyPluginNames(cwd);
2034
- return [.../* @__PURE__ */ new Set([...copied, ...firstParty])].sort();
2032
+ return listPluginModules(cwd).filter((name) => !isFirstPartyPlugin(cwd, name)).sort();
2035
2033
  }
2036
2034
  function firstPartyPluginNames(cwd) {
2037
2035
  const dir = join10(cwd, "services", "_plugins");
@@ -2217,8 +2215,7 @@ function syncPluginTerraform(cwd) {
2217
2215
  const skippedEnvironments = listUnwirableEnvironments(cwd);
2218
2216
  const changedPaths = [];
2219
2217
  const rendered = plugins.map((name) => {
2220
- const firstParty = isFirstPartyPlugin(cwd, name);
2221
- const moduleDir = firstParty ? join10(cwd, "services", "_plugins", name, "terraform") : join10(cwd, "modules", "plugins", name);
2218
+ const moduleDir = join10(cwd, "modules", "plugins", name);
2222
2219
  return {
2223
2220
  name,
2224
2221
  declaredVariables: declaredVariables(moduleDir),
@@ -6627,8 +6624,8 @@ function printEntry(entry) {
6627
6624
  }
6628
6625
 
6629
6626
  // src/commands/plugin-install.ts
6630
- import { cpSync as cpSync3, existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync18, statSync as statSync6 } from "fs";
6631
- import { basename, join as join25, relative as relative3, resolve as resolve12 } from "path";
6627
+ import { cpSync as cpSync3, existsSync as existsSync25, mkdirSync as mkdirSync9, readFileSync as readFileSync19, statSync as statSync6 } from "fs";
6628
+ import { basename, join as join26, relative as relative3, resolve as resolve12 } from "path";
6632
6629
  import chalk15 from "chalk";
6633
6630
  import { Command as Command15 } from "commander";
6634
6631
 
@@ -6674,6 +6671,120 @@ var PluginMigrationsAdapter = class {
6674
6671
  }
6675
6672
  };
6676
6673
 
6674
+ // src/lib/plugin-workspace-sources.ts
6675
+ import { existsSync as existsSync24, readdirSync as readdirSync12, readFileSync as readFileSync18, writeFileSync as writeFileSync9 } from "fs";
6676
+ import { join as join25 } from "path";
6677
+ function readTomlStringArray(text, key) {
6678
+ const open = new RegExp(`^${key}\\s*=\\s*\\[`, "m").exec(text);
6679
+ if (!open) return [];
6680
+ const start = open.index + open[0].length;
6681
+ let depth = 1;
6682
+ let inString = false;
6683
+ let quote = "";
6684
+ let end = -1;
6685
+ for (let i = start; i < text.length; i++) {
6686
+ const c = text[i];
6687
+ if (inString) {
6688
+ if (c === quote) inString = false;
6689
+ } else if (c === '"' || c === "'") {
6690
+ inString = true;
6691
+ quote = c;
6692
+ } else if (c === "[") {
6693
+ depth++;
6694
+ } else if (c === "]") {
6695
+ depth--;
6696
+ if (depth === 0) {
6697
+ end = i;
6698
+ break;
6699
+ }
6700
+ }
6701
+ }
6702
+ if (end === -1) return [];
6703
+ const body = text.slice(start, end);
6704
+ return [...body.matchAll(/["']([^"']+)["']/g)].map((m) => m[1]);
6705
+ }
6706
+ function readProjectName(text) {
6707
+ let inProject = false;
6708
+ for (const line of text.split("\n")) {
6709
+ const trimmed = line.trim();
6710
+ if (trimmed.startsWith("[")) {
6711
+ inProject = trimmed === "[project]";
6712
+ continue;
6713
+ }
6714
+ if (inProject) {
6715
+ const m = /^name\s*=\s*["']([^"']+)["']/.exec(trimmed);
6716
+ if (m) return m[1];
6717
+ }
6718
+ }
6719
+ return null;
6720
+ }
6721
+ function readDependencyNames(text) {
6722
+ return readTomlStringArray(text, "dependencies").map((dep) => /^\s*([A-Za-z0-9._-]+)/.exec(dep)?.[1] ?? "").filter(Boolean);
6723
+ }
6724
+ function workspaceMemberNames(instanceRoot) {
6725
+ const rootPyproject = join25(instanceRoot, "pyproject.toml");
6726
+ if (!existsSync24(rootPyproject)) return /* @__PURE__ */ new Set();
6727
+ const text = readFileSync18(rootPyproject, "utf8");
6728
+ const members = readTomlStringArray(text, "members");
6729
+ const excluded = new Set(readTomlStringArray(text, "exclude"));
6730
+ const dirs = [];
6731
+ for (const member of members) {
6732
+ if (member.endsWith("/*")) {
6733
+ const base = member.slice(0, -2);
6734
+ let entries;
6735
+ try {
6736
+ entries = readdirSync12(join25(instanceRoot, base), { withFileTypes: true });
6737
+ } catch {
6738
+ continue;
6739
+ }
6740
+ for (const entry of entries) {
6741
+ const rel = `${base}/${entry.name}`;
6742
+ if (entry.isDirectory() && !entry.name.startsWith(".") && !excluded.has(rel)) dirs.push(rel);
6743
+ }
6744
+ } else if (!excluded.has(member)) {
6745
+ dirs.push(member);
6746
+ }
6747
+ }
6748
+ const names = /* @__PURE__ */ new Set();
6749
+ for (const dir of dirs) {
6750
+ const pp = join25(instanceRoot, dir, "pyproject.toml");
6751
+ if (!existsSync24(pp)) continue;
6752
+ const name = readProjectName(readFileSync18(pp, "utf8"));
6753
+ if (name) names.add(name);
6754
+ }
6755
+ return names;
6756
+ }
6757
+ function existingWorkspaceSources(text) {
6758
+ return new Set(
6759
+ [...text.matchAll(/^\s*([A-Za-z0-9._-]+)\s*=\s*\{[^}]*\bworkspace\b/gm)].map((m) => m[1])
6760
+ );
6761
+ }
6762
+ function ensureWorkspaceSources(pluginPyprojectPath, memberNames) {
6763
+ if (!existsSync24(pluginPyprojectPath) || memberNames.size === 0) return [];
6764
+ const text = readFileSync18(pluginPyprojectPath, "utf8");
6765
+ const already = existingWorkspaceSources(text);
6766
+ const toAdd = readDependencyNames(text).filter((n) => memberNames.has(n) && !already.has(n));
6767
+ if (toAdd.length === 0) return [];
6768
+ const lines = toAdd.map((n) => `${n} = { workspace = true }`);
6769
+ const header = /^\[tool\.uv\.sources\]\s*$/m.exec(text);
6770
+ let updated;
6771
+ if (header) {
6772
+ const insertAt = header.index + header[0].length;
6773
+ updated = `${text.slice(0, insertAt)}
6774
+ ${lines.join("\n")}${text.slice(insertAt)}`;
6775
+ } else {
6776
+ const sep4 = text.endsWith("\n") ? "" : "\n";
6777
+ updated = `${text}${sep4}
6778
+ # Vendored into this instance by \`biffo plugin install\`: resolve dependencies the
6779
+ # instance's uv workspace provides as members from the workspace, not PyPI.
6780
+ [tool.uv.sources]
6781
+ ${lines.join("\n")}
6782
+ `;
6783
+ }
6784
+ writeFileSync9(pluginPyprojectPath, updated);
6785
+ return toAdd;
6786
+ }
6787
+
6677
6788
  // src/commands/plugin-install.ts
6678
6789
  var TARGET_PATTERN = /^([a-z][a-z0-9-]*)@(\d+\.\d+)$/;
6679
6790
  var pluginInstallCommand = new Command15("install").description(
@@ -6716,14 +6827,14 @@ var LOCAL_COPY_EXCLUDES = /* @__PURE__ */ new Set([
6716
6827
  ".terraform"
6717
6828
  ]);
6718
6829
  function resolveLocalPlugin(localPath) {
6719
- if (!existsSync24(localPath)) {
6830
+ if (!existsSync25(localPath)) {
6720
6831
  throw new Error(`--local path does not exist: ${localPath}`);
6721
6832
  }
6722
6833
  if (!statSync6(localPath).isDirectory()) {
6723
6834
  throw new Error(`--local path is not a directory: ${localPath}`);
6724
6835
  }
6725
- const manifestPath = join25(localPath, "biffo.plugin.json");
6726
- if (!existsSync24(manifestPath)) {
6836
+ const manifestPath = join26(localPath, "biffo.plugin.json");
6837
+ if (!existsSync25(manifestPath)) {
6727
6838
  throw new Error(
6728
6839
  `${localPath} does not contain a biffo.plugin.json manifest at its root \u2014 is it a plugin directory? (Scaffold one with \`biffo plugin create <name>\`.)`
6729
6840
  );
@@ -6749,8 +6860,8 @@ function parsePluginTarget(target) {
6749
6860
  async function cloneAndValidatePlugin(entry, git) {
6750
6861
  const tmpDir = await git.cloneToTemp(entry.repo, `biffo-plugin-${entry.name}`);
6751
6862
  try {
6752
- const manifestPath = join25(tmpDir, "biffo.plugin.json");
6753
- if (!existsSync24(manifestPath)) {
6863
+ const manifestPath = join26(tmpDir, "biffo.plugin.json");
6864
+ if (!existsSync25(manifestPath)) {
6754
6865
  throw new Error(
6755
6866
  `Plugin repo ${entry.repo} does not contain a biffo.plugin.json manifest at its root.`
6756
6867
  );
@@ -6778,8 +6889,8 @@ async function runPluginInstall(target, options, deps) {
6778
6889
  `Nothing to install. Pass a registry target (e.g. \`biffo plugin install acme-crm@1.0\`) or a local plugin directory (\`biffo plugin install --local services/acme-crm\`).`
6779
6890
  );
6780
6891
  }
6781
- const servicesDir = join25(options.cwd, "services");
6782
- if (!existsSync24(servicesDir)) {
6892
+ const servicesDir = join26(options.cwd, "services");
6893
+ if (!existsSync25(servicesDir)) {
6783
6894
  throw new Error(
6784
6895
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
6785
6896
  );
@@ -6797,10 +6908,10 @@ async function runPluginInstall(target, options, deps) {
6797
6908
  }
6798
6909
  const pluginName = entry ? entry.name : source.name;
6799
6910
  const relTargetDir = pluginDir(pluginName, "third-party");
6800
- const targetDir = join25(options.cwd, relTargetDir);
6801
- const modulesDir = join25(options.cwd, "modules", "plugins", pluginName);
6911
+ const targetDir = join26(options.cwd, relTargetDir);
6912
+ const modulesDir = join26(options.cwd, "modules", "plugins", pluginName);
6802
6913
  const inTreeSource = options.local !== void 0 && resolve12(options.local) === resolve12(targetDir);
6803
- if (existsSync24(targetDir) && !inTreeSource) {
6914
+ if (existsSync25(targetDir) && !inTreeSource) {
6804
6915
  throw new Error(
6805
6916
  `Plugin '${pluginName}' is already installed at ${relTargetDir}/. Remove it first, or wait for a future 'biffo plugin upgrade' command.`
6806
6917
  );
@@ -6842,9 +6953,18 @@ async function runPluginInstall(target, options, deps) {
6842
6953
  });
6843
6954
  log.success(`Installed plugin source at ${relTargetDir}/`);
6844
6955
  }
6956
+ const pluginPyproject = join26(targetDir, "pyproject.toml");
6957
+ if (existsSync25(pluginPyproject)) {
6958
+ const sourced = ensureWorkspaceSources(pluginPyproject, workspaceMemberNames(options.cwd));
6959
+ if (sourced.length > 0) {
6960
+ log.info(
6961
+ `Sourced ${sourced.join(", ")} from the workspace in ${relTargetDir}/pyproject.toml (the instance provides it as a workspace member).`
6962
+ );
6963
+ }
6964
+ }
6845
6965
  const stagePaths = [relTargetDir];
6846
- const tfSourceDir = join25(targetDir, "terraform");
6847
- if (existsSync24(tfSourceDir)) {
6966
+ const tfSourceDir = join26(targetDir, "terraform");
6967
+ if (existsSync25(tfSourceDir)) {
6848
6968
  mkdirSync9(modulesDir, { recursive: true });
6849
6969
  cpSync3(tfSourceDir, modulesDir, { recursive: true });
6850
6970
  stagePaths.push(`modules/plugins/${pluginName}`);
@@ -6923,7 +7043,7 @@ async function runPluginInstall(target, options, deps) {
6923
7043
  }
6924
7044
  function parseManifestFile(path) {
6925
7045
  try {
6926
- return JSON.parse(readFileSync18(path, "utf8"));
7046
+ return JSON.parse(readFileSync19(path, "utf8"));
6927
7047
  } catch (err) {
6928
7048
  throw new Error(`Could not parse ${path} as JSON: ${err.message}`);
6929
7049
  }
@@ -6960,8 +7080,8 @@ function printDryRun4(entry, source, relTargetDir, inTreeSource) {
6960
7080
  }
6961
7081
 
6962
7082
  // src/commands/plugin-list.ts
6963
- import { existsSync as existsSync25, readFileSync as readFileSync19 } from "fs";
6964
- import { join as join26, resolve as resolve13 } from "path";
7083
+ import { existsSync as existsSync26, readFileSync as readFileSync20 } from "fs";
7084
+ import { join as join27, resolve as resolve13 } from "path";
6965
7085
  import chalk16 from "chalk";
6966
7086
  import { Command as Command16 } from "commander";
6967
7087
  var pluginListCommand = new Command16("list").description("List plugins installed in this project checkout").option("--cwd <path>", "Project root to scan (defaults to the current directory)").action(async (options) => {
@@ -6974,8 +7094,8 @@ var pluginListCommand = new Command16("list").description("List plugins installe
6974
7094
  }
6975
7095
  });
6976
7096
  async function runPluginList(options) {
6977
- const servicesDir = join26(options.cwd, "services");
6978
- if (!existsSync25(servicesDir)) {
7097
+ const servicesDir = join27(options.cwd, "services");
7098
+ if (!existsSync26(servicesDir)) {
6979
7099
  throw new Error(
6980
7100
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
6981
7101
  );
@@ -6983,7 +7103,7 @@ async function runPluginList(options) {
6983
7103
  const plugins = [];
6984
7104
  for (const location of findInstalledPlugins(options.cwd)) {
6985
7105
  try {
6986
- const manifest = validateManifest(JSON.parse(readFileSync19(location.manifestPath, "utf8")));
7106
+ const manifest = validateManifest(JSON.parse(readFileSync20(location.manifestPath, "utf8")));
6987
7107
  plugins.push({
6988
7108
  name: manifest.name,
6989
7109
  version: manifest.version,
@@ -7020,8 +7140,8 @@ async function runPluginList(options) {
7020
7140
  }
7021
7141
 
7022
7142
  // src/commands/plugin-sync-migrations.ts
7023
- import { existsSync as existsSync26 } from "fs";
7024
- import { join as join27, relative as relative4, resolve as resolve14 } from "path";
7143
+ import { existsSync as existsSync27 } from "fs";
7144
+ import { join as join28, relative as relative4, resolve as resolve14 } from "path";
7025
7145
  import chalk17 from "chalk";
7026
7146
  import { Command as Command17 } from "commander";
7027
7147
  var pluginSyncMigrationsCommand = new Command17("sync-migrations").description(
@@ -7042,11 +7162,11 @@ var pluginSyncMigrationsCommand = new Command17("sync-migrations").description(
7042
7162
  }
7043
7163
  );
7044
7164
  async function runPluginSyncMigrations(name, options, deps) {
7045
- const servicesDir = join27(options.cwd, "services");
7046
- if (!existsSync26(servicesDir)) {
7165
+ const servicesDir = join28(options.cwd, "services");
7166
+ if (!existsSync27(servicesDir)) {
7047
7167
  throw new Error(`${servicesDir} does not exist \u2014 is ${options.cwd} a Biffo project checkout?`);
7048
7168
  }
7049
- if (name && !existsSync26(join27(servicesDir, name, "biffo.plugin.json"))) {
7169
+ if (name && !existsSync27(join28(servicesDir, name, "biffo.plugin.json"))) {
7050
7170
  throw new Error(`Plugin '${name}' is not installed at services/${name}/.`);
7051
7171
  }
7052
7172
  if (options.dryRun) {
@@ -7082,8 +7202,8 @@ async function runPluginSyncMigrations(name, options, deps) {
7082
7202
  }
7083
7203
 
7084
7204
  // src/commands/plugin-uninstall.ts
7085
- import { existsSync as existsSync27, readFileSync as readFileSync20, rmSync as rmSync8 } from "fs";
7086
- import { join as join28, resolve as resolve15 } from "path";
7205
+ import { existsSync as existsSync28, readFileSync as readFileSync21, rmSync as rmSync8 } from "fs";
7206
+ import { join as join29, resolve as resolve15 } from "path";
7087
7207
  import chalk18 from "chalk";
7088
7208
  import { Command as Command18 } from "commander";
7089
7209
  import inquirer6 from "inquirer";
@@ -7115,16 +7235,16 @@ async function runPluginUninstall(name, options, deps) {
7115
7235
  if (!NAME_PATTERN2.test(name)) {
7116
7236
  throw new Error(`Invalid plugin name '${name}'. Expected a lowercase kebab-case slug.`);
7117
7237
  }
7118
- const servicesDir = join28(options.cwd, "services");
7119
- if (!existsSync27(servicesDir)) {
7238
+ const servicesDir = join29(options.cwd, "services");
7239
+ if (!existsSync28(servicesDir)) {
7120
7240
  throw new Error(
7121
7241
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
7122
7242
  );
7123
7243
  }
7124
- const targetDir = join28(servicesDir, name);
7125
- if (!existsSync27(targetDir)) {
7126
- const firstParty = join28(servicesDir, FIRST_PARTY_PLUGINS_DIR, name);
7127
- if (existsSync27(firstParty)) {
7244
+ const targetDir = join29(servicesDir, name);
7245
+ if (!existsSync28(targetDir)) {
7246
+ const firstParty = join29(servicesDir, FIRST_PARTY_PLUGINS_DIR, name);
7247
+ if (existsSync28(firstParty)) {
7128
7248
  throw new Error(
7129
7249
  `Plugin '${name}' is a first-party plugin at ${pluginDir(name, "first-party")}/, which is template-owned \u2014 \`biffo core upgrade\` would restore it on the next upgrade. Disable it instead by removing '${name}' from \`enabled_plugins\` in infra/environments/<env>/main.tf and re-applying.`
7130
7250
  );
@@ -7132,9 +7252,9 @@ async function runPluginUninstall(name, options, deps) {
7132
7252
  throw new Error(`Plugin '${name}' is not installed at services/${name}/.`);
7133
7253
  }
7134
7254
  const version = readInstalledVersion(targetDir);
7135
- const modulesDir = join28(options.cwd, "modules", "plugins", name);
7255
+ const modulesDir = join29(options.cwd, "modules", "plugins", name);
7136
7256
  const stagePaths = [`services/${name}`];
7137
- if (existsSync27(modulesDir)) {
7257
+ if (existsSync28(modulesDir)) {
7138
7258
  stagePaths.push(`modules/plugins/${name}`);
7139
7259
  }
7140
7260
  if (options.dryRun) {
@@ -7156,7 +7276,7 @@ async function runPluginUninstall(name, options, deps) {
7156
7276
  }
7157
7277
  rmSync8(targetDir, { recursive: true, force: true });
7158
7278
  log.success(`Removed services/${name}/`);
7159
- if (existsSync27(modulesDir)) {
7279
+ if (existsSync28(modulesDir)) {
7160
7280
  rmSync8(modulesDir, { recursive: true, force: true });
7161
7281
  log.success(`Removed modules/plugins/${name}/`);
7162
7282
  const wiring = syncPluginTerraform(options.cwd);
@@ -7193,10 +7313,10 @@ async function runPluginUninstall(name, options, deps) {
7193
7313
  }
7194
7314
  }
7195
7315
  function readInstalledVersion(targetDir) {
7196
- const manifestPath = join28(targetDir, "biffo.plugin.json");
7197
- if (!existsSync27(manifestPath)) return void 0;
7316
+ const manifestPath = join29(targetDir, "biffo.plugin.json");
7317
+ if (!existsSync28(manifestPath)) return void 0;
7198
7318
  try {
7199
- return validateManifest(JSON.parse(readFileSync20(manifestPath, "utf8"))).version;
7319
+ return validateManifest(JSON.parse(readFileSync21(manifestPath, "utf8"))).version;
7200
7320
  } catch {
7201
7321
  return void 0;
7202
7322
  }
@@ -7229,8 +7349,8 @@ function printDryRun5(name, version, stagePaths, keepData) {
7229
7349
  }
7230
7350
 
7231
7351
  // src/commands/plugin-upgrade.ts
7232
- import { cpSync as cpSync4, existsSync as existsSync28, mkdirSync as mkdirSync10, readFileSync as readFileSync21, rmSync as rmSync9 } from "fs";
7233
- import { join as join29, relative as relative5, resolve as resolve16 } from "path";
7352
+ import { cpSync as cpSync4, existsSync as existsSync29, mkdirSync as mkdirSync10, readFileSync as readFileSync22, rmSync as rmSync9 } from "fs";
7353
+ import { join as join30, relative as relative5, resolve as resolve16 } from "path";
7234
7354
  import chalk19 from "chalk";
7235
7355
  import { Command as Command19 } from "commander";
7236
7356
  import inquirer7 from "inquirer";
@@ -7255,14 +7375,14 @@ var pluginUpgradeCommand = new Command19("upgrade").description(
7255
7375
  });
7256
7376
  async function runPluginUpgrade(target, options, deps) {
7257
7377
  const { name, minor } = parsePluginTarget(target);
7258
- const servicesDir = join29(options.cwd, "services");
7259
- if (!existsSync28(servicesDir)) {
7378
+ const servicesDir = join30(options.cwd, "services");
7379
+ if (!existsSync29(servicesDir)) {
7260
7380
  throw new Error(
7261
7381
  `${servicesDir} does not exist \u2014 is ${options.cwd} the root of a Biffo project checkout?`
7262
7382
  );
7263
7383
  }
7264
- const targetDir = join29(servicesDir, name);
7265
- if (!existsSync28(targetDir)) {
7384
+ const targetDir = join30(servicesDir, name);
7385
+ if (!existsSync29(targetDir)) {
7266
7386
  throw new Error(
7267
7387
  `Plugin '${name}' is not installed at services/${name}/. Use 'biffo plugin install ${name}@${minor}' instead.`
7268
7388
  );
@@ -7276,7 +7396,7 @@ async function runPluginUpgrade(target, options, deps) {
7276
7396
  `Plugin declares required_core_version '${entry.required_core_version}'. The CLI cannot verify this against your deployment \u2014 the Core API exposes no version endpoint and services/api/pyproject.toml's version is a static placeholder, not a real release marker. Confirm compatibility yourself before deploying.`
7277
7397
  );
7278
7398
  }
7279
- const modulesDir = join29(options.cwd, "modules", "plugins", entry.name);
7399
+ const modulesDir = join30(options.cwd, "modules", "plugins", entry.name);
7280
7400
  if (options.dryRun) {
7281
7401
  printDryRun6(entry, currentVersion);
7282
7402
  return;
@@ -7309,11 +7429,11 @@ async function runPluginUpgrade(target, options, deps) {
7309
7429
  cpSync4(tmpDir, targetDir, { recursive: true });
7310
7430
  log.success(`Upgraded plugin source at services/${entry.name}/`);
7311
7431
  const stagePaths = [`services/${entry.name}`];
7312
- if (existsSync28(modulesDir)) {
7432
+ if (existsSync29(modulesDir)) {
7313
7433
  rmSync9(modulesDir, { recursive: true, force: true });
7314
7434
  }
7315
- const tfSourceDir = join29(targetDir, "terraform");
7316
- if (existsSync28(tfSourceDir)) {
7435
+ const tfSourceDir = join30(targetDir, "terraform");
7436
+ if (existsSync29(tfSourceDir)) {
7317
7437
  mkdirSync10(modulesDir, { recursive: true });
7318
7438
  cpSync4(tfSourceDir, modulesDir, { recursive: true });
7319
7439
  stagePaths.push(`modules/plugins/${entry.name}`);
@@ -7347,10 +7467,10 @@ async function runPluginUpgrade(target, options, deps) {
7347
7467
  }
7348
7468
  }
7349
7469
  function readInstalledVersion2(targetDir) {
7350
- const manifestPath = join29(targetDir, "biffo.plugin.json");
7351
- if (!existsSync28(manifestPath)) return void 0;
7470
+ const manifestPath = join30(targetDir, "biffo.plugin.json");
7471
+ if (!existsSync29(manifestPath)) return void 0;
7352
7472
  try {
7353
- return validateManifest(JSON.parse(readFileSync21(manifestPath, "utf8"))).version;
7473
+ return validateManifest(JSON.parse(readFileSync22(manifestPath, "utf8"))).version;
7354
7474
  } catch {
7355
7475
  return void 0;
7356
7476
  }
@@ -7379,14 +7499,14 @@ function printDryRun6(entry, currentVersion) {
7379
7499
  }
7380
7500
 
7381
7501
  // src/commands/plugin-wire.ts
7382
- import { existsSync as existsSync30, readFileSync as readFileSync23 } from "fs";
7502
+ import { existsSync as existsSync31, readFileSync as readFileSync24 } from "fs";
7383
7503
  import { resolve as resolve17 } from "path";
7384
7504
  import chalk20 from "chalk";
7385
7505
  import { Command as Command20 } from "commander";
7386
7506
 
7387
7507
  // src/lib/plugin-origin.ts
7388
- import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync9 } from "fs";
7389
- import { join as join30 } from "path";
7508
+ import { existsSync as existsSync30, readFileSync as readFileSync23, writeFileSync as writeFileSync10 } from "fs";
7509
+ import { join as join31 } from "path";
7390
7510
  var PLUGIN_API_TFVARS = "plugin-apis.auto.tfvars.json";
7391
7511
  var SIBLINGS_TFVARS = "siblings.auto.tfvars.json";
7392
7512
  function upsertPluginApiOrigin(existing, entry) {
@@ -7396,9 +7516,9 @@ function serializePluginApiRegistry(origins) {
7396
7516
  return JSON.stringify({ plugin_api_origins: origins }, null, 2) + "\n";
7397
7517
  }
7398
7518
  function readArray(path, key) {
7399
- if (!existsSync29(path)) return [];
7519
+ if (!existsSync30(path)) return [];
7400
7520
  try {
7401
- const parsed = JSON.parse(readFileSync22(path, "utf8"));
7521
+ const parsed = JSON.parse(readFileSync23(path, "utf8"));
7402
7522
  const arr = parsed[key];
7403
7523
  return Array.isArray(arr) ? arr : [];
7404
7524
  } catch {
@@ -7406,19 +7526,19 @@ function readArray(path, key) {
7406
7526
  }
7407
7527
  }
7408
7528
  function registerUserFacingPlugin(cwd, environment, reg) {
7409
- const envDir = join30(cwd, "infra", "environments", environment);
7410
- const apiPath = join30(envDir, PLUGIN_API_TFVARS);
7411
- const siblingPath = join30(envDir, SIBLINGS_TFVARS);
7529
+ const envDir = join31(cwd, "infra", "environments", environment);
7530
+ const apiPath = join31(envDir, PLUGIN_API_TFVARS);
7531
+ const siblingPath = join31(envDir, SIBLINGS_TFVARS);
7412
7532
  const apis = upsertPluginApiOrigin(readArray(apiPath, "plugin_api_origins"), {
7413
7533
  name: reg.name,
7414
7534
  function_url_domain: reg.functionUrlDomain
7415
7535
  });
7416
- writeFileSync9(apiPath, serializePluginApiRegistry(apis));
7536
+ writeFileSync10(apiPath, serializePluginApiRegistry(apis));
7417
7537
  const siblings = upsertSiblingOrigin(readArray(siblingPath, "sibling_origins"), {
7418
7538
  name: reg.name,
7419
7539
  bucket_regional_domain: reg.bucketRegionalDomain
7420
7540
  });
7421
- writeFileSync9(siblingPath, serializeRegistry(siblings));
7541
+ writeFileSync10(siblingPath, serializeRegistry(siblings));
7422
7542
  return [
7423
7543
  `infra/environments/${environment}/${PLUGIN_API_TFVARS}`,
7424
7544
  `infra/environments/${environment}/${SIBLINGS_TFVARS}`
@@ -7499,7 +7619,7 @@ var pluginWireCommand = new Command20("wire").description(
7499
7619
  );
7500
7620
  async function resolveConfig4(options) {
7501
7621
  if (options.config) {
7502
- const raw = JSON.parse(readFileSync23(resolve17(options.config), "utf8"));
7622
+ const raw = JSON.parse(readFileSync24(resolve17(options.config), "utf8"));
7503
7623
  const result = BiffoConfigSchema.safeParse(raw);
7504
7624
  if (!result.success) {
7505
7625
  log.error(`Invalid config at ${options.config}:`);
@@ -7519,8 +7639,8 @@ async function resolveConfig4(options) {
7519
7639
  return cfg;
7520
7640
  }
7521
7641
  const localConfigPath = resolve17(process.cwd(), "biffo.config.json");
7522
- if (existsSync30(localConfigPath)) {
7523
- const raw = JSON.parse(readFileSync23(localConfigPath, "utf8"));
7642
+ if (existsSync31(localConfigPath)) {
7643
+ const raw = JSON.parse(readFileSync24(localConfigPath, "utf8"));
7524
7644
  const result = BiffoConfigSchema.safeParse(raw);
7525
7645
  if (result.success) return result.data;
7526
7646
  if (isTemplatePlaceholderConfig(raw)) {
@@ -7555,7 +7675,7 @@ pluginCommand.addCommand(pluginInfoCommand);
7555
7675
  import { Command as Command23 } from "commander";
7556
7676
 
7557
7677
  // src/commands/sibling-check-identity.ts
7558
- import { existsSync as existsSync31, readFileSync as readFileSync24 } from "fs";
7678
+ import { existsSync as existsSync32, readFileSync as readFileSync25 } from "fs";
7559
7679
  import { resolve as resolve18 } from "path";
7560
7680
  import chalk21 from "chalk";
7561
7681
  import { Command as Command22 } from "commander";
@@ -7749,7 +7869,7 @@ async function fetchPublishedIdentity(portalUrl) {
7749
7869
  }
7750
7870
  async function resolveConfig5(options) {
7751
7871
  if (options.config) {
7752
- const raw = JSON.parse(readFileSync24(resolve18(options.config), "utf8"));
7872
+ const raw = JSON.parse(readFileSync25(resolve18(options.config), "utf8"));
7753
7873
  const result = BiffoConfigSchema.safeParse(raw);
7754
7874
  if (!result.success) {
7755
7875
  log.error(`Invalid config at ${options.config}:`);
@@ -7769,8 +7889,8 @@ async function resolveConfig5(options) {
7769
7889
  return cfg;
7770
7890
  }
7771
7891
  const localConfigPath = resolve18(process.cwd(), "biffo.config.json");
7772
- if (existsSync31(localConfigPath)) {
7773
- const raw = JSON.parse(readFileSync24(localConfigPath, "utf8"));
7892
+ if (existsSync32(localConfigPath)) {
7893
+ const raw = JSON.parse(readFileSync25(localConfigPath, "utf8"));
7774
7894
  const result = BiffoConfigSchema.safeParse(raw);
7775
7895
  if (result.success) return result.data;
7776
7896
  if (isTemplatePlaceholderConfig(raw)) {
@@ -7839,8 +7959,8 @@ async function runOwnershipCheck(argv) {
7839
7959
  const { stdout } = await execa5("git", ["diff", "--cached", "--name-status"], { cwd: root });
7840
7960
  ({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
7841
7961
  if (messageFile) {
7842
- const { readFileSync: readFileSync26, existsSync: existsSync33 } = await import("fs");
7843
- if (existsSync33(messageFile)) commitMessage = readFileSync26(messageFile, "utf8");
7962
+ const { readFileSync: readFileSync27, existsSync: existsSync34 } = await import("fs");
7963
+ if (existsSync34(messageFile)) commitMessage = readFileSync27(messageFile, "utf8");
7844
7964
  }
7845
7965
  } else {
7846
7966
  const base = process.env["GITHUB_BASE_REF"] ?? args[0];
@@ -7944,8 +8064,8 @@ ${BOLD}If the divergence is deliberate${OFF}
7944
8064
  import { execa as execa6 } from "execa";
7945
8065
 
7946
8066
  // src/lib/plugin-terraform-guard.ts
7947
- import { existsSync as existsSync32, readFileSync as readFileSync25, readdirSync as readdirSync12 } from "fs";
7948
- import { dirname as dirname9, join as join31, relative as relative6, sep as sep3 } from "path";
8067
+ import { existsSync as existsSync33, readFileSync as readFileSync26, readdirSync as readdirSync13 } from "fs";
8068
+ import { dirname as dirname9, join as join32, relative as relative6, sep as sep3 } from "path";
7949
8069
  var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
7950
8070
  var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
7951
8071
  function findPluginManifests(root) {
@@ -7953,16 +8073,16 @@ function findPluginManifests(root) {
7953
8073
  const walk = (dir) => {
7954
8074
  let entries;
7955
8075
  try {
7956
- entries = readdirSync12(dir, { withFileTypes: true });
8076
+ entries = readdirSync13(dir, { withFileTypes: true });
7957
8077
  } catch {
7958
8078
  return;
7959
8079
  }
7960
8080
  for (const entry of entries) {
7961
8081
  if (entry.isDirectory()) {
7962
8082
  if (SKIP_DIRS.has(entry.name)) continue;
7963
- walk(join31(dir, entry.name));
8083
+ walk(join32(dir, entry.name));
7964
8084
  } else if (entry.isFile() && entry.name === PLUGIN_MANIFEST_FILE2) {
7965
- found.push(relative6(root, join31(dir, entry.name)).split(sep3).join("/"));
8085
+ found.push(relative6(root, join32(dir, entry.name)).split(sep3).join("/"));
7966
8086
  }
7967
8087
  }
7968
8088
  };
@@ -7972,7 +8092,7 @@ function findPluginManifests(root) {
7972
8092
  function readSubscriptions(absManifestPath) {
7973
8093
  let parsed;
7974
8094
  try {
7975
- parsed = JSON.parse(readFileSync25(absManifestPath, "utf8"));
8095
+ parsed = JSON.parse(readFileSync26(absManifestPath, "utf8"));
7976
8096
  } catch {
7977
8097
  return null;
7978
8098
  }
@@ -7987,14 +8107,14 @@ function readSubscriptions(absManifestPath) {
7987
8107
  }
7988
8108
  function checkPluginTerraform(root) {
7989
8109
  const violations = [];
7990
- const coreManifest = existsSync32(join31(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
8110
+ const coreManifest = existsSync33(join32(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
7991
8111
  for (const manifest of findPluginManifests(root)) {
7992
8112
  if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
7993
- const absManifest = join31(root, manifest);
8113
+ const absManifest = join32(root, manifest);
7994
8114
  const subscriptions = readSubscriptions(absManifest);
7995
8115
  if (subscriptions === null) continue;
7996
8116
  const pluginDir2 = dirname9(absManifest);
7997
- if (existsSync32(join31(pluginDir2, "terraform"))) continue;
8117
+ if (existsSync33(join32(pluginDir2, "terraform"))) continue;
7998
8118
  const relPluginDir = relative6(root, pluginDir2).split(sep3).join("/");
7999
8119
  violations.push({
8000
8120
  manifest,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.103.1",
3
+ "version": "0.103.3",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",