🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@01.software/init

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@01.software/init - npm Package Compare versions

Comparing version
0.5.1
to
0.6.1
+61
dist/chunk-VOEXMD2S.js
#!/usr/bin/env node
// src/file-ops.ts
var envLineRegexCache = /* @__PURE__ */ new Map();
function envLineRegex(name) {
let re = envLineRegexCache.get(name);
if (!re) {
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
re = new RegExp(`^${escaped}=(.*)$`, "m");
envLineRegexCache.set(name, re);
}
return re;
}
function readEnvValue(content, name) {
const m = content.match(envLineRegex(name));
return m ? m[1] : null;
}
function setEnvValue(content, name, value) {
const re = envLineRegex(name);
if (re.test(content)) return content.replace(re, `${name}=${value}`);
const sep = content.length === 0 || content.endsWith("\n") ? "" : "\n";
return content + sep + `${name}=${value}
`;
}
var TOML_SECTION_PREFIX = "[mcp_servers.01software";
function extractTomlApiKey(content) {
const headerIdx = content.indexOf(`${TOML_SECTION_PREFIX}.headers]`);
if (headerIdx < 0) return null;
const slice = content.slice(headerIdx);
const m = slice.match(/^x-api-key\s*=\s*"((?:[^"\\]|\\.)*)"/m);
if (!m) return null;
return m[1].replace(/\\"/g, '"').replace(/\\\\/g, "\\");
}
function replaceTomlMcpSection(content, newSection) {
const lines = content.split("\n");
const kept = [];
let inOurSection = false;
for (const line of lines) {
const trimmed = line.trim();
if (trimmed.startsWith(TOML_SECTION_PREFIX)) {
inOurSection = true;
continue;
}
if (inOurSection && /^\[[^\[]/.test(trimmed)) {
inOurSection = false;
}
if (!inOurSection) kept.push(line);
}
let result = kept.join("\n").replace(/\n+$/, "");
if (result.length > 0) result += "\n";
result += newSection.startsWith("\n") ? newSection : "\n" + newSection;
return result;
}
export {
readEnvValue,
setEnvValue,
extractTomlApiKey,
replaceTomlMcpSection
};
//# sourceMappingURL=chunk-VOEXMD2S.js.map
{"version":3,"sources":["../src/file-ops.ts"],"sourcesContent":["// Pure helpers for in-place file content manipulation. Kept side-effect-free\n// so they can be unit-tested without touching the filesystem or prompts.\n\n// ── .env merge ───────────────────────────────────────────────────────\n\nconst envLineRegexCache = new Map<string, RegExp>()\n\nfunction envLineRegex(name: string): RegExp {\n let re = envLineRegexCache.get(name)\n if (!re) {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n re = new RegExp(`^${escaped}=(.*)$`, 'm')\n envLineRegexCache.set(name, re)\n }\n return re\n}\n\nexport function readEnvValue(content: string, name: string): string | null {\n const m = content.match(envLineRegex(name))\n return m ? m[1] : null\n}\n\nexport function setEnvValue(content: string, name: string, value: string): string {\n const re = envLineRegex(name)\n if (re.test(content)) return content.replace(re, `${name}=${value}`)\n const sep = content.length === 0 || content.endsWith('\\n') ? '' : '\\n'\n return content + sep + `${name}=${value}\\n`\n}\n\n// ── Codex TOML manipulation ──────────────────────────────────────────\n\nconst TOML_SECTION_PREFIX = '[mcp_servers.01software'\n\n/** Pulls the current `x-api-key` value from `[mcp_servers.01software.headers]`.\n * Returns null if the section or key is absent. */\nexport function extractTomlApiKey(content: string): string | null {\n const headerIdx = content.indexOf(`${TOML_SECTION_PREFIX}.headers]`)\n if (headerIdx < 0) return null\n const slice = content.slice(headerIdx)\n const m = slice.match(/^x-api-key\\s*=\\s*\"((?:[^\"\\\\]|\\\\.)*)\"/m)\n if (!m) return null\n // Reverse the same escaping used when writing (escape backslash + quote)\n return m[1].replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, '\\\\')\n}\n\n/** Removes the existing `[mcp_servers.01software]` block (and its `.headers`\n * sub-block) from a TOML document, then appends the provided section. */\nexport function replaceTomlMcpSection(content: string, newSection: string): string {\n const lines = content.split('\\n')\n const kept: string[] = []\n let inOurSection = false\n for (const line of lines) {\n const trimmed = line.trim()\n if (trimmed.startsWith(TOML_SECTION_PREFIX)) {\n inOurSection = true\n continue\n }\n // Any other top-level header ends our section\n if (inOurSection && /^\\[[^\\[]/.test(trimmed)) {\n inOurSection = false\n }\n if (!inOurSection) kept.push(line)\n }\n let result = kept.join('\\n').replace(/\\n+$/, '')\n if (result.length > 0) result += '\\n'\n // newSection already starts with a blank line; keep it that way\n result += newSection.startsWith('\\n') ? newSection : '\\n' + newSection\n return result\n}\n"],"mappings":";;;AAKA,IAAM,oBAAoB,oBAAI,IAAoB;AAElD,SAAS,aAAa,MAAsB;AAC1C,MAAI,KAAK,kBAAkB,IAAI,IAAI;AACnC,MAAI,CAAC,IAAI;AACP,UAAM,UAAU,KAAK,QAAQ,uBAAuB,MAAM;AAC1D,SAAK,IAAI,OAAO,IAAI,OAAO,UAAU,GAAG;AACxC,sBAAkB,IAAI,MAAM,EAAE;AAAA,EAChC;AACA,SAAO;AACT;AAEO,SAAS,aAAa,SAAiB,MAA6B;AACzE,QAAM,IAAI,QAAQ,MAAM,aAAa,IAAI,CAAC;AAC1C,SAAO,IAAI,EAAE,CAAC,IAAI;AACpB;AAEO,SAAS,YAAY,SAAiB,MAAc,OAAuB;AAChF,QAAM,KAAK,aAAa,IAAI;AAC5B,MAAI,GAAG,KAAK,OAAO,EAAG,QAAO,QAAQ,QAAQ,IAAI,GAAG,IAAI,IAAI,KAAK,EAAE;AACnE,QAAM,MAAM,QAAQ,WAAW,KAAK,QAAQ,SAAS,IAAI,IAAI,KAAK;AAClE,SAAO,UAAU,MAAM,GAAG,IAAI,IAAI,KAAK;AAAA;AACzC;AAIA,IAAM,sBAAsB;AAIrB,SAAS,kBAAkB,SAAgC;AAChE,QAAM,YAAY,QAAQ,QAAQ,GAAG,mBAAmB,WAAW;AACnE,MAAI,YAAY,EAAG,QAAO;AAC1B,QAAM,QAAQ,QAAQ,MAAM,SAAS;AACrC,QAAM,IAAI,MAAM,MAAM,uCAAuC;AAC7D,MAAI,CAAC,EAAG,QAAO;AAEf,SAAO,EAAE,CAAC,EAAE,QAAQ,QAAQ,GAAG,EAAE,QAAQ,SAAS,IAAI;AACxD;AAIO,SAAS,sBAAsB,SAAiB,YAA4B;AACjF,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,OAAiB,CAAC;AACxB,MAAI,eAAe;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAQ,WAAW,mBAAmB,GAAG;AAC3C,qBAAe;AACf;AAAA,IACF;AAEA,QAAI,gBAAgB,WAAW,KAAK,OAAO,GAAG;AAC5C,qBAAe;AAAA,IACjB;AACA,QAAI,CAAC,aAAc,MAAK,KAAK,IAAI;AAAA,EACnC;AACA,MAAI,SAAS,KAAK,KAAK,IAAI,EAAE,QAAQ,QAAQ,EAAE;AAC/C,MAAI,OAAO,SAAS,EAAG,WAAU;AAEjC,YAAU,WAAW,WAAW,IAAI,IAAI,aAAa,OAAO;AAC5D,SAAO;AACT;","names":[]}
#!/usr/bin/env node
import {
extractTomlApiKey,
readEnvValue,
replaceTomlMcpSection,
setEnvValue
} from "./chunk-VOEXMD2S.js";
export {
extractTomlApiKey,
readEnvValue,
replaceTomlMcpSection,
setEnvValue
};
//# sourceMappingURL=file-ops.js.map
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
+302
-98

@@ -8,2 +8,8 @@ #!/usr/bin/env node

import {
extractTomlApiKey,
readEnvValue,
replaceTomlMcpSection,
setEnvValue
} from "./chunk-VOEXMD2S.js";
import {
CODEX_MCP_SECTION_MARKER,

@@ -30,2 +36,3 @@ getClientTemplate,

let hasSdk = false;
let hasReactQuery = false;
let parseError = false;

@@ -37,3 +44,11 @@ if (hasPackageJson) {

} catch {
return { hasPackageJson: true, parseError: true, env: "node", packageManager: null, hasSdk: false, srcDir: false };
return {
hasPackageJson: true,
parseError: true,
env: "node",
packageManager: null,
hasSdk: false,
hasReactQuery: false,
srcDir: false
};
}

@@ -45,2 +60,3 @@ const deps = {

hasSdk = "@01.software/sdk" in deps;
hasReactQuery = "@tanstack/react-query" in deps;
if ("next" in deps) {

@@ -75,3 +91,3 @@ env = "nextjs";

const srcDir = env === "nextjs" ? fs.existsSync(path.join(cwd, "src", "app")) : fs.existsSync(path.join(cwd, "src"));
return { hasPackageJson, parseError, env, packageManager, hasSdk, srcDir };
return { hasPackageJson, parseError, env, packageManager, hasSdk, hasReactQuery, srcDir };
}

@@ -267,2 +283,3 @@ function needsClient(env) {

import pc2 from "picocolors";
import prompts2 from "prompts";

@@ -448,2 +465,3 @@ // src/browser-auth.ts

var SECRET_KEY_ENV_VAR = "SOFTWARE_SECRET_KEY";
var API_KEY_PLACEHOLDER = "YOUR_API_KEY";
async function init(cwd, info, answers) {

@@ -457,52 +475,47 @@ const { packageManager, srcDir } = info;

const wantsReactQuery = needsReactQuery(env);
const deps = ["@01.software/sdk"];
if (wantsReactQuery) deps.push("@tanstack/react-query");
const addCmd = buildAddCmd(packageManager, hasPnpmWorkspace(cwd), deps);
let installFailed = false;
console.log(pc2.dim(` Installing ${deps.join(" and ")}...`));
const wsPatched = packageManager === "pnpm" && patchPnpmWorkspace(cwd);
try {
execSync(addCmd, { cwd, stdio: "pipe" });
console.log(pc2.green(" Installed"), deps.join(", "));
} catch (error) {
installFailed = true;
const err = error;
const msg = String(err.stderr || "").trim() || String(err.stdout || "").trim() || String(error);
console.log(pc2.yellow(" Install failed \u2014 continuing with scaffolding"));
const firstLines = msg.split("\n").slice(0, 3).map((l) => ` ${l}`).join("\n");
if (firstLines) console.log(pc2.dim(firstLines));
console.log(pc2.dim(` Run manually: ${addCmd}`));
} finally {
if (wsPatched) restorePnpmWorkspace(cwd);
const plan = await planConflictsAndEnv(cwd, baseDir, env, answers);
const installResult = installDeps(
cwd,
packageManager,
info.hasSdk,
info.hasReactQuery,
wantsReactQuery
);
if (wantsClient || wantsReactQuery || wantsServer) {
fs2.mkdirSync(path2.join(baseDir, "lib", "software"), { recursive: true });
}
const libDir = path2.join(baseDir, "lib", "software");
fs2.mkdirSync(libDir, { recursive: true });
if (wantsClient) {
writeFileIfAbsent(
await writeFileWithPolicy(
cwd,
path2.join(libDir, "client.ts"),
getClientTemplate(env, publishableKeyEnvVar)
getClientTemplate(env, publishableKeyEnvVar),
plan.policy
);
}
if (wantsReactQuery) {
writeFileIfAbsent(
await writeFileWithPolicy(
cwd,
path2.join(libDir, "query-provider.tsx"),
getQueryProviderTemplate(env)
getQueryProviderTemplate(env),
plan.policy
);
}
if (wantsServer) {
writeFileIfAbsent(
await writeFileWithPolicy(
cwd,
path2.join(libDir, "server.ts"),
getServerTemplate(env, publishableKeyEnvVar, SECRET_KEY_ENV_VAR)
getServerTemplate(env, publishableKeyEnvVar, SECRET_KEY_ENV_VAR),
plan.policy
);
}
if (env !== "vanilla" && env !== "edge" && answers.authMethod !== "browser") {
writeEnv(
if (plan.envFile && answers.authMethod !== "browser") {
await writeEnv(
cwd,
plan.envFile,
answers.publishableKey || "",
answers.secretKey || "",
publishableKeyEnvVar,
wantsServer ? SECRET_KEY_ENV_VAR : null
wantsServer ? SECRET_KEY_ENV_VAR : null,
plan.policy
);

@@ -520,5 +533,6 @@ }

tenantName = creds.tenantName;
if (env !== "vanilla" && env !== "edge" && publishableKey) {
writeEnv(
if (plan.envFile && publishableKey) {
await writeEnv(
cwd,
plan.envFile,
publishableKey,

@@ -528,2 +542,3 @@ secretKey,

wantsServer ? SECRET_KEY_ENV_VAR : null,
"overwrite",
true

@@ -540,13 +555,45 @@ );

if (answers.aiTools.length > 0) {
const apiKey = secretKey || "YOUR_API_KEY";
const apiKey = secretKey || API_KEY_PLACEHOLDER;
for (const tool of answers.aiTools) {
writeMcpConfig(tool, cwd, apiKey);
await writeMcpConfig(tool, cwd, apiKey, plan.policy);
}
addToGitignore(cwd, answers.aiTools);
if (answers.aiTools.includes("claude")) {
await writeClaudeDocs(cwd, publishableKey, secretKey, tenantName);
await writeClaudeDocs(cwd, publishableKey, secretKey, tenantName, plan.policy);
}
}
return { installFailed, installCmd: addCmd };
return installResult;
}
function installDeps(cwd, pm, hasSdk, hasReactQuery, wantsReactQuery) {
const allDeps = [
{ name: "@01.software/sdk", installed: hasSdk, needed: true },
{ name: "@tanstack/react-query", installed: hasReactQuery, needed: wantsReactQuery }
];
const fullList = allDeps.filter((d) => d.needed).map((d) => d.name);
const toInstall = allDeps.filter((d) => d.needed && !d.installed).map((d) => d.name);
const fullCmd = buildAddCmd(pm, hasPnpmWorkspace(cwd), fullList);
if (toInstall.length === 0) {
console.log(pc2.dim(` Dependencies already installed: ${fullList.join(", ")}`));
return { installFailed: false, installSkipped: true, installCmd: fullCmd };
}
const addCmd = buildAddCmd(pm, hasPnpmWorkspace(cwd), toInstall);
console.log(pc2.dim(` Installing ${toInstall.join(" and ")}...`));
const wsPatched = pm === "pnpm" && patchPnpmWorkspace(cwd);
let installFailed = false;
try {
execSync(addCmd, { cwd, stdio: "pipe" });
console.log(pc2.green(" Installed"), toInstall.join(", "));
} catch (error) {
installFailed = true;
const err = error;
const msg = String(err.stderr || "").trim() || String(err.stdout || "").trim() || String(error);
console.log(pc2.yellow(" Install failed \u2014 continuing with scaffolding"));
const firstLines = msg.split("\n").slice(0, 3).map((l) => ` ${l}`).join("\n");
if (firstLines) console.log(pc2.dim(firstLines));
console.log(pc2.dim(` Run manually: ${addCmd}`));
} finally {
if (wsPatched) restorePnpmWorkspace(cwd);
}
return { installFailed, installSkipped: false, installCmd: addCmd };
}
function buildAddCmd(pm, hasPnpmWs, deps) {

@@ -565,30 +612,151 @@ const pkgs = deps.join(" ");

}
function writeFileIfAbsent(cwd, filePath, content) {
if (fs2.existsSync(filePath)) {
console.log(pc2.yellow(" Skipped"), relativePath(cwd, filePath), pc2.dim("(already exists)"));
async function planConflictsAndEnv(cwd, baseDir, env, answers) {
const candidates = [];
const libDir = path2.join(baseDir, "lib", "software");
if (needsClient(env)) candidates.push(path2.join(libDir, "client.ts"));
if (needsReactQuery(env)) candidates.push(path2.join(libDir, "query-provider.tsx"));
if (needsServer(env)) candidates.push(path2.join(libDir, "server.ts"));
if (answers.aiTools.includes("claude")) {
for (const { dirName } of getSkillFiles()) {
candidates.push(path2.join(cwd, ".claude", "skills", dirName, "SKILL.md"));
}
}
const conflicts = candidates.filter((p) => fs2.existsSync(p));
let policy = "skip";
if (conflicts.length > 0) {
console.log(pc2.yellow(` ${conflicts.length} file(s) already exist:`));
for (const c of conflicts) console.log(pc2.dim(` ${path2.relative(cwd, c)}`));
const { selected } = await prompts2({
type: "select",
name: "selected",
message: "How should I handle existing files?",
choices: [
{ title: "Keep existing (skip)", value: "skip" },
{ title: "Overwrite all", value: "overwrite" },
{ title: "Ask for each", value: "ask" }
],
initial: 0
});
policy = selected ?? "skip";
}
const envFile = env === "vanilla" || env === "edge" ? "" : await pickEnvFile(cwd, env);
return { policy, envFile };
}
async function pickEnvFile(cwd, env) {
const candidates = [".env.local", ".env", ".env.development"];
const existing = candidates.filter((f) => fs2.existsSync(path2.join(cwd, f)));
const preferred = env === "nextjs" ? ".env.local" : ".env";
if (existing.length === 0) return preferred;
if (existing.length === 1 && existing[0] === preferred) return existing[0];
const options = Array.from(/* @__PURE__ */ new Set([...existing, preferred]));
const choices = options.map((f) => ({
title: f,
description: existing.includes(f) ? "exists" : "create",
value: f
}));
const initial = Math.max(
0,
choices.findIndex((c) => c.value === preferred)
);
const { file } = await prompts2({
type: "select",
name: "file",
message: "Which env file should I write API keys to?",
choices,
initial
});
return file ?? preferred;
}
async function writeFileWithPolicy(cwd, filePath, content, policy) {
const rel = path2.relative(cwd, filePath);
if (!fs2.existsSync(filePath)) {
fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
fs2.writeFileSync(filePath, content);
console.log(pc2.green(" Created"), rel);
return;
}
fs2.writeFileSync(filePath, content);
console.log(pc2.green(" Created"), relativePath(cwd, filePath));
const existing = fs2.readFileSync(filePath, "utf-8");
if (existing === content) {
console.log(pc2.dim(" Unchanged"), rel);
return;
}
let shouldWrite = false;
if (policy === "overwrite") {
shouldWrite = true;
} else if (policy === "ask") {
const { confirm } = await prompts2({
type: "confirm",
name: "confirm",
message: `Overwrite ${rel}?`,
initial: false
});
shouldWrite = !!confirm;
}
if (shouldWrite) {
fs2.writeFileSync(filePath, content);
console.log(pc2.green(" Overwrote"), rel);
} else {
console.log(pc2.yellow(" Skipped"), rel, pc2.dim("(already exists)"));
}
}
function writeEnv(cwd, publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar, afterBrowserAuth = false) {
const envPath = path2.join(cwd, ".env");
const envContent = getEnvContent(publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar);
if (fs2.existsSync(envPath)) {
const existing = fs2.readFileSync(envPath, "utf-8");
if (existing.includes(publishableKeyEnvVar)) {
if (!afterBrowserAuth) {
console.log(pc2.yellow(" Skipped"), ".env", pc2.dim("(keys already present)"));
async function writeEnv(cwd, envFile, publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar, policy, fromBrowserAuth = false) {
const envPath = path2.join(cwd, envFile);
const targets = [
{ name: publishableKeyEnvVar, value: publishableKey }
];
if (secretKeyEnvVar) {
targets.push({ name: secretKeyEnvVar, value: secretKey });
}
if (!fs2.existsSync(envPath)) {
const initial = getEnvContent(publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar);
fs2.writeFileSync(envPath, initial.trimStart());
console.log(pc2.green(" Created"), envFile);
return;
}
let content = fs2.readFileSync(envPath, "utf-8");
let modified = false;
let appendedHeader = false;
const headerAlreadyPresent = targets.some(
(t) => readEnvValue(content, t.name) !== null
);
for (const { name, value } of targets) {
const existing = readEnvValue(content, name);
if (existing === null) {
if (!headerAlreadyPresent && !appendedHeader) {
if (content.length > 0 && !content.endsWith("\n")) content += "\n";
content += "\n# 01.software\n";
appendedHeader = true;
}
return;
content = setEnvValue(content, name, value);
modified = true;
continue;
}
fs2.appendFileSync(envPath, envContent);
if (existing === value) continue;
if (!value) continue;
let shouldOverwrite = false;
if (policy === "overwrite") {
shouldOverwrite = true;
} else if (policy === "ask") {
const { confirm } = await prompts2({
type: "confirm",
name: "confirm",
message: `${name} already set in ${envFile}. Overwrite?`,
initial: fromBrowserAuth
});
shouldOverwrite = !!confirm;
}
if (shouldOverwrite) {
content = setEnvValue(content, name, value);
modified = true;
}
}
if (modified) {
fs2.writeFileSync(envPath, content);
console.log(
pc2.green(" Updated"),
".env",
afterBrowserAuth ? pc2.dim("(added API keys)") : ""
envFile,
fromBrowserAuth ? pc2.dim("(API keys)") : ""
);
} else {
fs2.writeFileSync(envPath, envContent.trimStart());
console.log(pc2.green(" Created"), ".env");
console.log(pc2.dim(" Unchanged"), envFile);
}

@@ -637,3 +805,3 @@ }

}
function writeMcpConfig(tool, cwd, apiKey) {
async function writeMcpConfig(tool, cwd, apiKey, policy) {
const loc = resolveMcpLocation(tool, cwd);

@@ -646,43 +814,83 @@ if (!loc) {

if (loc.kind === "json") {
writeJsonMcp(loc, apiKey);
await writeJsonMcp(loc, apiKey, policy);
} else {
writeTomlMcp(loc, apiKey);
await writeTomlMcp(loc, apiKey, policy);
}
}
function writeJsonMcp(loc, apiKey) {
if (fs2.existsSync(loc.absolutePath)) {
try {
const existing = JSON.parse(fs2.readFileSync(loc.absolutePath, "utf-8"));
if (existing.mcpServers?.["01software"]) {
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(01software already configured)"));
return;
}
existing.mcpServers = existing.mcpServers || {};
existing.mcpServers["01software"] = getMcpServerEntry(apiKey);
fs2.writeFileSync(loc.absolutePath, JSON.stringify(existing, null, 2) + "\n");
console.log(pc2.green(" Updated"), loc.displayPath);
} catch {
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(could not parse existing file)"));
}
} else {
async function writeJsonMcp(loc, apiKey, policy) {
if (!fs2.existsSync(loc.absolutePath)) {
fs2.writeFileSync(loc.absolutePath, getMcpConfigTemplate(apiKey));
console.log(pc2.green(" Created"), loc.displayPath);
return;
}
let existing;
try {
existing = JSON.parse(fs2.readFileSync(loc.absolutePath, "utf-8"));
} catch {
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(could not parse existing file)"));
return;
}
const existingApiKey = existing.mcpServers?.["01software"]?.headers?.["x-api-key"];
if (existingApiKey === apiKey) {
console.log(pc2.dim(" Unchanged"), loc.displayPath);
return;
}
if (apiKey === API_KEY_PLACEHOLDER && existingApiKey && existingApiKey !== API_KEY_PLACEHOLDER) {
console.log(pc2.dim(" Kept existing API key in"), loc.displayPath);
return;
}
if (existingApiKey) {
const shouldUpdate = await confirmKeyUpdate(loc.displayPath, policy);
if (!shouldUpdate) {
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(kept existing API key)"));
return;
}
}
existing.mcpServers = existing.mcpServers || {};
existing.mcpServers["01software"] = getMcpServerEntry(apiKey);
fs2.writeFileSync(loc.absolutePath, JSON.stringify(existing, null, 2) + "\n");
console.log(pc2.green(" Updated"), loc.displayPath);
}
function writeTomlMcp(loc, apiKey) {
async function writeTomlMcp(loc, apiKey, policy) {
const section = getCodexMcpTomlSection(apiKey);
if (fs2.existsSync(loc.absolutePath)) {
const existing = fs2.readFileSync(loc.absolutePath, "utf-8");
if (existing.includes(CODEX_MCP_SECTION_MARKER)) {
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(01software already configured)"));
return;
}
if (!fs2.existsSync(loc.absolutePath)) {
fs2.writeFileSync(loc.absolutePath, section.trimStart());
console.log(pc2.green(" Created"), loc.displayPath);
return;
}
const existing = fs2.readFileSync(loc.absolutePath, "utf-8");
if (!existing.includes(CODEX_MCP_SECTION_MARKER)) {
const sep = existing.endsWith("\n") ? "" : "\n";
fs2.appendFileSync(loc.absolutePath, sep + section);
console.log(pc2.green(" Updated"), loc.displayPath);
} else {
fs2.writeFileSync(loc.absolutePath, section.trimStart());
console.log(pc2.green(" Created"), loc.displayPath);
return;
}
const existingApiKey = extractTomlApiKey(existing);
if (existingApiKey === apiKey) {
console.log(pc2.dim(" Unchanged"), loc.displayPath);
return;
}
if (apiKey === API_KEY_PLACEHOLDER && existingApiKey && existingApiKey !== API_KEY_PLACEHOLDER) {
console.log(pc2.dim(" Kept existing API key in"), loc.displayPath);
return;
}
const shouldUpdate = await confirmKeyUpdate(loc.displayPath, policy);
if (!shouldUpdate) {
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(kept existing API key)"));
return;
}
const replaced = replaceTomlMcpSection(existing, section);
fs2.writeFileSync(loc.absolutePath, replaced);
console.log(pc2.green(" Updated"), loc.displayPath);
}
async function confirmKeyUpdate(displayPath, policy) {
if (policy === "overwrite") return true;
const { confirm } = await prompts2({
type: "confirm",
name: "confirm",
message: `${displayPath} has a different 01software API key. Update?`,
initial: true
});
return !!confirm;
}
function addToGitignore(cwd, tools) {

@@ -707,3 +915,3 @@ const entries = [];

}
async function writeClaudeDocs(cwd, publishableKey, secretKey, tenantName) {
async function writeClaudeDocs(cwd, publishableKey, secretKey, tenantName, policy) {
let ctx = {

@@ -745,3 +953,3 @@ tenantName: tenantName || "Your Tenant",

} else {
console.log(pc2.yellow(" Skipped"), ".claude/CLAUDE.md", pc2.dim("(@import already present)"));
console.log(pc2.dim(" Unchanged"), ".claude/CLAUDE.md");
}

@@ -752,14 +960,6 @@ }

const skillPath = path2.join(skillDir, "SKILL.md");
if (!fs2.existsSync(skillPath)) {
fs2.mkdirSync(skillDir, { recursive: true });
fs2.writeFileSync(skillPath, content);
console.log(pc2.green(" Created"), `.claude/skills/${dirName}/SKILL.md`);
} else {
console.log(pc2.yellow(" Skipped"), `.claude/skills/${dirName}/SKILL.md`, pc2.dim("(already exists)"));
}
fs2.mkdirSync(skillDir, { recursive: true });
await writeFileWithPolicy(cwd, skillPath, content, policy);
}
}
function relativePath(cwd, filePath) {
return path2.relative(cwd, filePath);
}
var WS_FILE = "pnpm-workspace.yaml";

@@ -906,3 +1106,7 @@ var WS_BACKUP = "pnpm-workspace.yaml.bak";

if (answers.aiTools.length > 0 && (!answers.publishableKey || !answers.secretKey)) {
console.log(pc3.dim(" Update MCP config x-api-key with your sk01_... token"));
console.log(
pc3.dim(
" Update MCP config x-api-key with your sk01_... or pat01_... bearer token"
)
);
console.log();

@@ -909,0 +1113,0 @@ }

{
"name": "@01.software/init",
"version": "0.5.1",
"version": "0.6.1",
"description": "Initialize 01.software SDK in your project (Next.js, React, Vanilla JS, Node.js, Edge)",

@@ -5,0 +5,0 @@ "type": "module",

Sorry, the diff of this file is too big to display