@suronai/cli 0.1.43 → 0.1.45

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/package.json +1 -1
  2. package/src/commands.js +26 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suronai/cli",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "description": "Suron CLI — secrets delivery",
5
5
  "type": "module",
6
6
  "bin": {
package/src/commands.js CHANGED
@@ -104,7 +104,18 @@ function installSdk(cwd) {
104
104
 
105
105
  // ── Entry-point patching ──────────────────────────────────────────────────────
106
106
 
107
- async function patchEntryPoint(cwd, isEsm) {
107
+ /**
108
+ * Detect whether a file should be treated as ESM by inspecting its content,
109
+ * regardless of what package.json says. A file is ESM if it contains top-level
110
+ * import/export statements or top-level await outside of an async function.
111
+ */
112
+ function detectFileIsEsm(src) {
113
+ if (/^(import|export)\s/m.test(src)) return true;
114
+ if (/^\s*await\s/m.test(src)) return true;
115
+ return false;
116
+ }
117
+
118
+ async function patchEntryPoint(cwd, isEsmFromPkg) {
108
119
  // Check package.json "main" first, then fall back to common names
109
120
  let mainFromPkg = null;
110
121
  try {
@@ -112,9 +123,7 @@ async function patchEntryPoint(cwd, isEsm) {
112
123
  if (pkg.main) mainFromPkg = pkg.main;
113
124
  } catch {}
114
125
 
115
- const candidates = isEsm
116
- ? ["index.js", "index.mjs", "src/index.js", "src/index.mjs"]
117
- : ["index.js", "index.cjs", "src/index.js", "src/index.cjs"];
126
+ const candidates = ["index.js", "index.mjs", "index.cjs", "src/index.js", "src/index.mjs", "src/index.cjs"];
118
127
 
119
128
  if (mainFromPkg && !candidates.includes(mainFromPkg)) {
120
129
  candidates.unshift(mainFromPkg);
@@ -126,11 +135,15 @@ async function patchEntryPoint(cwd, isEsm) {
126
135
  if (existsSync(abs)) { entryPath = abs; break; }
127
136
  }
128
137
 
129
- if (!entryPath) { printSnippet(isEsm); return; }
138
+ if (!entryPath) { printSnippet(isEsmFromPkg); return; }
130
139
 
131
140
  let src;
132
141
  try { src = readFileSync(entryPath, "utf-8"); } catch { return; }
133
142
 
143
+ // Prefer content-based detection — a file with ESM syntax IS ESM regardless
144
+ // of what package.json declares, and must be patched accordingly.
145
+ const isEsm = detectFileIsEsm(src) || isEsmFromPkg;
146
+
134
147
  const lines = src.split("\n");
135
148
  const toReplace = [];
136
149
  const seenIndices = new Set();
@@ -142,30 +155,24 @@ async function patchEntryPoint(cwd, isEsm) {
142
155
  if (lines[i].includes("dotenv")) {
143
156
  seenIndices.add(i);
144
157
  let replacement = null;
158
+
145
159
  if (isEsm) {
160
+ // ESM: replace any dotenv import with @suronai/sdk import + await config()
146
161
  if (trimmed.startsWith("import")) {
147
- replacement = indent + trimmed.replace(/(from\s+)['"]dotenv(?:\/config)?['"]/, '$1"@suronai/sdk"');
162
+ replacement = indent + `import { config } from "@suronai/sdk";\n` + indent + `await config();`;
148
163
  }
149
164
  } else {
165
+ // CJS: replace dotenv require — wrap in IIFE so top-level await is never emitted
150
166
  if (trimmed.includes("require")) {
151
- // Handle: require("dotenv").config() → require("@suronai/sdk").config()
152
- // Handle: require("dotenv/config") → require("@suronai/sdk").config()
153
- // Handle: const x = require("dotenv") → const { config } = require("@suronai/sdk")\nawait config()
154
- if (/require\(['"]dotenv['"]\)\.config/.test(trimmed)) {
155
- replacement = indent + trimmed.replace(/require\(['"]dotenv['"]\)/, 'require("@suronai/sdk")');
156
- // wrap the whole statement to be async-aware
157
- replacement = indent + `await require("@suronai/sdk").config();`;
158
- } else if (/require\(['"]dotenv\/config['"]\)/.test(trimmed)) {
159
- replacement = indent + `await require("@suronai/sdk").config();`;
160
- } else {
161
- replacement = indent + `const { config: suronConfig } = require("@suronai/sdk");\n` + indent + `await suronConfig();`;
162
- }
167
+ replacement = indent + `const { config: _suronConfig } = require("@suronai/sdk");\n`
168
+ + indent + `await (async () => { await _suronConfig(); })();`;
163
169
  }
164
170
  }
165
171
  toReplace.push({ index: i, content: lines[i], replacement });
166
172
  }
167
173
  }
168
174
 
175
+ // ESM only: if there's a standalone `config()` call left over after an import swap
169
176
  if (isEsm) {
170
177
  for (let i = 0; i < lines.length; i++) {
171
178
  if (seenIndices.has(i)) continue;
@@ -213,6 +220,7 @@ async function patchEntryPoint(cwd, isEsm) {
213
220
  return (r && r.replacement !== null) ? r.replacement : line;
214
221
  });
215
222
 
223
+ // For ESM: ensure the `await config()` call sits right after the last import
216
224
  if (isEsm) {
217
225
  const callLineIndex = outLines.findIndex(l => /^\s*await config\s*\(/.test(l));
218
226
  const lastImportIndex = outLines.reduce((last, l, i) => l.trimStart().startsWith("import ") ? i : last, -1);