🚀 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
23
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.1.6
to
0.2.0
+502
-90
dist/index.js
#!/usr/bin/env node
// src/index.ts
import pc2 from "picocolors";
import pc3 from "picocolors";

@@ -66,5 +66,2 @@ // src/detect.ts

}
function supportsMcp(env) {
return env === "nextjs" || env === "node" || env === "edge";
}
function getClientKeyEnvVar(env) {

@@ -152,3 +149,3 @@ switch (env) {

if (env === "other") {
return { env, clientKey: "", secretKey: "", setupMcp: false, packageManager: void 0 };
return { env, clientKey: "", secretKey: "", aiTools: [], authMethod: "skip", packageManager: void 0 };
}

@@ -191,21 +188,51 @@ let packageManager;

}
const keys = keyPrompts.length > 0 ? await prompts(keyPrompts, { onCancel }) : {};
let setupMcp = false;
if (supportsMcp(env)) {
const result = await prompts(
const { selectedTools } = await prompts(
{
type: "multiselect",
name: "selectedTools",
message: "Connect AI tools:",
choices: [
{ title: "Claude Code", description: ".mcp.json + .claude/ docs", value: "claude" },
{ title: "Cursor", description: ".cursor/mcp.json", value: "cursor" },
{ title: "VS Code", description: ".vscode/mcp.json", value: "vscode" },
{ title: "Windsurf", description: "~/.codeium/windsurf/mcp_config.json", value: "windsurf" },
{ title: "Skip", value: "skip" }
],
hint: "space to select"
},
{ onCancel }
);
const aiTools = Array.isArray(selectedTools) ? selectedTools.filter((t) => t !== "skip") : [];
let authMethod = "skip";
let keys = {};
if (aiTools.length > 0 && env !== "vanilla") {
const { method } = await prompts(
{
type: "confirm",
name: "setupMcp",
message: "Set up MCP integration? (.mcp.json)",
initial: true
type: "select",
name: "method",
message: "API keys:",
choices: [
{ title: "Browser login (recommended)", value: "browser" },
{ title: "Enter manually", value: "manual" },
{ title: "Skip for now", value: "skip" }
]
},
{ onCancel }
);
setupMcp = result.setupMcp;
authMethod = method ?? "skip";
if (authMethod === "manual") {
keys = await prompts(keyPrompts, { onCancel });
}
} else if (env !== "vanilla") {
if (keyPrompts.length > 0) {
keys = await prompts(keyPrompts, { onCancel });
}
authMethod = "skip";
}
return {
env,
clientKey: keys.clientKey ?? "",
secretKey: keys.secretKey ?? "",
setupMcp,
clientKey: authMethod === "browser" ? "" : keys.clientKey ?? "",
secretKey: authMethod === "browser" ? "" : keys.secretKey ?? "",
aiTools,
authMethod,
packageManager

@@ -219,3 +246,3 @@ };

import { execSync } from "child_process";
import pc from "picocolors";
import pc2 from "picocolors";

@@ -316,2 +343,273 @@ // src/templates.ts

// src/browser-auth.ts
import { randomBytes } from "crypto";
import { createServer } from "http";
import { execFile, exec } from "child_process";
import { platform } from "os";
import { URL } from "url";
import pc from "picocolors";
var DEFAULT_WEB_URL = process.env.SOFTWARE_WEB_URL || "https://01.software";
var TIMEOUT_MS = 5 * 60 * 1e3;
function escapeHtml(s) {
return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}
function openBrowser(url) {
const os = platform();
const onError = () => {
console.log(
pc.yellow(
`Could not open browser automatically. Open this URL manually:
${url}`
)
);
};
if (os === "win32") {
exec(`start "" "${url}"`, (err) => {
if (err) onError();
});
} else {
const cmd = os === "darwin" ? "open" : "xdg-open";
execFile(cmd, [url], (err) => {
if (err) onError();
});
}
}
var PAGE_STYLE = `*{margin:0;box-sizing:border-box}
body{font-family:system-ui,-apple-system,sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;background:#fff;color:#252525}
@media(prefers-color-scheme:dark){body{background:#252525;color:#f5f5f5}}
.card{text-align:center;padding:2rem 2.5rem;border-radius:10px;max-width:380px;width:100%}
.icon{width:40px;height:40px;margin:0 auto 1rem;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.25rem}
.icon.ok{background:rgba(0,0,0,.05);color:#252525}
.icon.err{background:rgba(220,38,38,.08);color:#dc2626}
@media(prefers-color-scheme:dark){.icon.ok{background:rgba(255,255,255,.08);color:#f5f5f5}}
h1{font-size:.875rem;font-weight:600;margin-bottom:.375rem}
p{font-size:.75rem;color:#737373;line-height:1.5}`;
var SUCCESS_HTML = `<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Login</title>
<style>${PAGE_STYLE}</style>
</head><body><div class="card"><div class="icon ok">\u2713</div><h1>Authenticated</h1><p>You can close this tab and return to the terminal.</p></div></body></html>`;
var ERROR_HTML = (msg) => `<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Login Error</title>
<style>${PAGE_STYLE}</style>
</head><body><div class="card"><div class="icon err">!</div><h1>Authentication failed</h1><p>${escapeHtml(msg)}</p></div></body></html>`;
async function startBrowserAuth(options) {
const state = randomBytes(32).toString("hex");
const webUrl = options?.webUrl ?? DEFAULT_WEB_URL;
return new Promise((resolve, reject) => {
const server = createServer((req, res) => {
if (!req.url) {
res.writeHead(400).end();
return;
}
const url = new URL(req.url, `http://localhost`);
if (url.pathname !== "/callback") {
res.writeHead(404).end();
return;
}
const receivedState = url.searchParams.get("state");
const clientKey = url.searchParams.get("clientKey");
const secretKey = url.searchParams.get("secretKey");
const tenant = url.searchParams.get("tenant");
const tenantIdParam = url.searchParams.get("tenantId");
const error = url.searchParams.get("error");
if (error) {
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(ERROR_HTML(error));
console.error(pc.red(`Login failed: ${error}`));
cleanup(new Error(`Login failed: ${error}`));
return;
}
if (receivedState !== state) {
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(ERROR_HTML("State mismatch \u2014 possible CSRF attack."));
console.error(pc.red("Login failed: state mismatch."));
cleanup(new Error("Login failed: state mismatch."));
return;
}
if (!clientKey || !secretKey || !tenant) {
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(ERROR_HTML("Missing credentials in callback."));
console.error(pc.red("Login failed: missing credentials."));
cleanup(new Error("Login failed: missing credentials."));
return;
}
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(SUCCESS_HTML);
console.log(pc.green(`
Logged in successfully!`));
console.log(pc.dim(`Tenant: ${tenant}`));
const result = {
clientKey,
secretKey,
tenantName: tenant,
...tenantIdParam ? { tenantId: tenantIdParam } : {}
};
cleanup(null, result);
});
let timeout;
let completed = false;
function cleanup(err, result) {
if (completed) return;
completed = true;
clearTimeout(timeout);
server.close(() => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
}
server.listen(0, "127.0.0.1", () => {
const addr = server.address();
if (!addr || typeof addr === "string") {
reject(new Error("Failed to start local server."));
return;
}
const port = addr.port;
timeout = setTimeout(() => {
console.error(pc.red("\nLogin timed out (5 minutes). Please try again."));
cleanup(new Error("Login timed out"));
}, TIMEOUT_MS);
const params = new URLSearchParams({ port: String(port), state });
if (options?.tenantId) {
params.set("tenantId", options.tenantId);
}
const loginUrl = `${webUrl}/cli-auth?${params.toString()}`;
console.log(pc.dim("Opening browser for login..."));
console.log(pc.dim(`If the browser does not open, visit:
${loginUrl}`));
openBrowser(loginUrl);
});
server.on("error", (err) => {
reject(err);
});
});
}
// src/ai-docs.ts
function generateClaudeMd(ctx) {
const featuresSection = ctx.features && ctx.features.length > 0 ? ctx.features.map((f) => `- ${f}`).join("\n") : "- See console";
const collectionsSection = ctx.collections && ctx.collections.length > 0 ? ctx.collections.join(", ") : "Run `01 schema list`";
return `# 01.software SDK \u2014 ${ctx.tenantName}
## Connection
- Client Key: \`NEXT_PUBLIC_SOFTWARE_CLIENT_KEY\` (env)
- Server Key: \`SOFTWARE_SECRET_KEY\` (env)
- MCP: \`.mcp.json\`
## Active Features
${featuresSection}
## Collections
${collectionsSection}
## MCP Quick Reference
| Tool | Use |
|------|-----|
| \`query-collection\` | List/filter documents |
| \`create-collection\` | Create documents |
| \`update-field-config\` | Hide unused fields |
| \`get-tenant-context\` | Show active features & collections |
## CLI
- \`01 query <collection>\` \u2014 query data
- \`01 schema show <collection>\` \u2014 inspect fields
- \`01 schema list\` \u2014 list all collections
## Initial Setup
Run \`/field-config\` in Claude Code to configure field visibility for your use case.
`;
}
function getSkillFiles() {
return [
{
filename: "field-config.md",
content: `Configure field visibility for this tenant using MCP tools.
Steps:
1. Use \`list-configurable-fields\` to see current visibility settings
2. Identify fields/collections not needed for your use case
3. Use \`update-field-config\` to hide them
Common setups:
- Blog only: hide \`ecommerce\`, \`customers\`, \`videos\` collections
- Store: hide \`posts\`, \`documents\`, \`galleries\`, \`flows\` collections
- Minimal: hide all except the collections you actively use
Ask me: "Show current field config" or "Hide ecommerce fields"
`
},
{
filename: "query.md",
content: `Query collections using the MCP \`query-collection\` tool or CLI.
MCP examples:
- List products: \`query-collection\` with collection="products", limit=10
- Filter by status: add where={"status":{"equals":"published"}}
- Sort by date: sort="-createdAt"
- Paginate: page=2, limit=20
CLI examples:
- \`01 query products --limit 10\`
- \`01 query orders --where '{"status":{"equals":"paid"}}'\`
- \`01 schema show products\` \u2014 inspect available fields
SDK (server):
\`\`\`typescript
const { docs } = await serverClient.collection('products').find({
where: { status: { equals: 'published' } },
sort: '-createdAt',
limit: 10,
})
\`\`\`
`
},
{
filename: "order-flow.md",
content: `Complete order flow from creation to fulfillment.
States: pending \u2192 paid \u2192 preparing \u2192 shipped \u2192 delivered \u2192 confirmed
1. Create order: \`create-order\` with orderNumber, customerSnapshot, orderProducts, totalAmount
2. Mark paid: \`update-order\` with status="paid" (after payment gateway confirms)
3. Fulfill: \`create-fulfillment\` with items and carrier/trackingNumber
4. Returns: \`create-return\` or \`return-with-refund\` (atomic)
Free orders: omit paymentId, totalAmount=0 \u2192 auto-transitions to paid
CLI: \`01 order create --help\` for full options
`
},
{
filename: "schema.md",
content: `Inspect collection schemas to understand available fields.
MCP: use \`get-collection-fields\` with collectionSlug
CLI:
- \`01 schema list\` \u2014 all available collections
- \`01 schema show <collection>\` \u2014 field names, types, required status
Common collections: products, orders, customers, posts, documents, images
Use \`get-tenant-context\` to see which collections are active for this tenant.
`
}
];
}
async function fetchTenantContext(clientKey, secretKey) {
try {
const apiUrl = process.env.SOFTWARE_API_URL || "https://api.01.software";
const base64 = Buffer.from(`${clientKey}:${secretKey}`).toString("base64");
const res = await fetch(`${apiUrl}/api/tenants/context`, {
headers: { "x-api-key": base64 }
});
if (!res.ok) return null;
const data = await res.json();
return {
tenantName: data.tenant?.name || "",
features: data.features || [],
collections: data.collections || []
};
} catch {
return null;
}
}
// src/init.ts

@@ -329,3 +627,3 @@ var SECRET_KEY_ENV_VAR = "SOFTWARE_SECRET_KEY";

if (wantsReactQuery) deps.push("@tanstack/react-query");
console.log(pc.dim(` Installing ${deps.join(" and ")}...`));
console.log(pc2.dim(` Installing ${deps.join(" and ")}...`));
const wsPatched = packageManager === "pnpm" && patchPnpmWorkspace(cwd);

@@ -340,4 +638,4 @@ const pkgs = deps.join(" ");

const msg = String(err.stderr || "").trim() || String(err.stdout || "").trim() || String(error);
console.log(pc.red(" Failed to install dependencies:"));
console.log(pc.dim(` ${msg}`));
console.log(pc2.red(" Failed to install dependencies:"));
console.log(pc2.dim(` ${msg}`));
throw error;

@@ -352,6 +650,6 @@ } finally {

if (fs2.existsSync(clientPath)) {
console.log(pc.yellow(" Skipped"), relativePath(cwd, clientPath), pc.dim("(already exists)"));
console.log(pc2.yellow(" Skipped"), relativePath(cwd, clientPath), pc2.dim("(already exists)"));
} else {
fs2.writeFileSync(clientPath, getClientTemplate(env, clientKeyEnvVar));
console.log(pc.green(" Created"), relativePath(cwd, clientPath));
console.log(pc2.green(" Created"), relativePath(cwd, clientPath));
}

@@ -362,6 +660,6 @@ }

if (fs2.existsSync(queryProviderPath)) {
console.log(pc.yellow(" Skipped"), relativePath(cwd, queryProviderPath), pc.dim("(already exists)"));
console.log(pc2.yellow(" Skipped"), relativePath(cwd, queryProviderPath), pc2.dim("(already exists)"));
} else {
fs2.writeFileSync(queryProviderPath, getQueryProviderTemplate(env));
console.log(pc.green(" Created"), relativePath(cwd, queryProviderPath));
console.log(pc2.green(" Created"), relativePath(cwd, queryProviderPath));
}

@@ -372,9 +670,9 @@ }

if (fs2.existsSync(serverPath)) {
console.log(pc.yellow(" Skipped"), relativePath(cwd, serverPath), pc.dim("(already exists)"));
console.log(pc2.yellow(" Skipped"), relativePath(cwd, serverPath), pc2.dim("(already exists)"));
} else {
fs2.writeFileSync(serverPath, getServerTemplate(env, clientKeyEnvVar, SECRET_KEY_ENV_VAR));
console.log(pc.green(" Created"), relativePath(cwd, serverPath));
console.log(pc2.green(" Created"), relativePath(cwd, serverPath));
}
}
if (env !== "vanilla" && env !== "edge") {
if (env !== "vanilla" && env !== "edge" && answers.authMethod !== "browser") {
const envPath = path2.join(cwd, ".env");

@@ -390,48 +688,162 @@ const envContent = getEnvContent(

if (existing.includes(clientKeyEnvVar)) {
console.log(pc.yellow(" Skipped"), ".env", pc.dim("(keys already present)"));
console.log(pc2.yellow(" Skipped"), ".env", pc2.dim("(keys already present)"));
} else {
fs2.appendFileSync(envPath, envContent);
console.log(pc.green(" Updated"), ".env");
console.log(pc2.green(" Updated"), ".env");
}
} else {
fs2.writeFileSync(envPath, envContent.trimStart());
console.log(pc.green(" Created"), ".env");
console.log(pc2.green(" Created"), ".env");
}
}
if (answers.setupMcp) {
const clientKey = answers.clientKey || "";
const secretKey = answers.secretKey || "";
const apiKey = clientKey && secretKey ? Buffer.from(`${clientKey}:${secretKey}`).toString("base64") : "YOUR_API_KEY";
const mcpPath = path2.join(cwd, ".mcp.json");
if (fs2.existsSync(mcpPath)) {
try {
const existing = JSON.parse(fs2.readFileSync(mcpPath, "utf-8"));
if (existing.mcpServers?.["01software"]) {
console.log(pc.yellow(" Skipped"), ".mcp.json", pc.dim("(01software already configured)"));
let clientKey = answers.clientKey;
let secretKey = answers.secretKey;
let tenantName = "";
if (answers.authMethod === "browser" && answers.aiTools.length > 0) {
try {
console.log();
const creds = await startBrowserAuth();
clientKey = creds.clientKey;
secretKey = creds.secretKey;
tenantName = creds.tenantName;
if (env !== "vanilla" && env !== "edge" && clientKey) {
const envPath = path2.join(cwd, ".env");
const envContent = getEnvContent(
clientKey,
secretKey,
clientKeyEnvVar,
wantsServer ? SECRET_KEY_ENV_VAR : null
);
if (fs2.existsSync(envPath)) {
const existing = fs2.readFileSync(envPath, "utf-8");
if (!existing.includes(clientKeyEnvVar)) {
fs2.appendFileSync(envPath, envContent);
console.log(pc2.green(" Updated"), ".env", pc2.dim("(added API keys)"));
}
} else {
existing.mcpServers = existing.mcpServers || {};
existing.mcpServers["01software"] = getMcpServerEntry(apiKey);
fs2.writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + "\n");
console.log(pc.green(" Updated"), ".mcp.json");
fs2.writeFileSync(envPath, envContent.trimStart());
console.log(pc2.green(" Created"), ".env");
}
} catch {
console.log(pc.yellow(" Skipped"), ".mcp.json", pc.dim("(could not parse existing file)"));
}
} else {
fs2.writeFileSync(mcpPath, getMcpConfigTemplate(apiKey));
console.log(pc.green(" Created"), ".mcp.json");
} catch (err) {
console.log(
pc2.yellow(" Browser auth skipped:"),
err instanceof Error ? err.message : String(err)
);
}
const gitignorePath = path2.join(cwd, ".gitignore");
if (fs2.existsSync(gitignorePath)) {
const gitignore = fs2.readFileSync(gitignorePath, "utf-8");
if (!gitignore.includes(".mcp.json")) {
fs2.appendFileSync(gitignorePath, "\n# MCP config (contains API key)\n.mcp.json\n");
console.log(pc.green(" Updated"), ".gitignore", pc.dim("(added .mcp.json)"));
}
if (answers.aiTools.length > 0) {
const apiKey = clientKey && secretKey ? Buffer.from(`${clientKey}:${secretKey}`).toString("base64") : "YOUR_API_KEY";
for (const tool of answers.aiTools) {
writeMcpConfig(tool, cwd, apiKey);
}
addToGitignore(cwd, answers.aiTools);
if (answers.aiTools.includes("claude")) {
await writeClaudeDocs(cwd, clientKey, secretKey, tenantName);
}
}
}
function writeMcpConfig(tool, cwd, apiKey) {
let configPath;
let displayPath;
switch (tool) {
case "claude":
configPath = path2.join(cwd, ".mcp.json");
displayPath = ".mcp.json";
break;
case "cursor":
configPath = path2.join(cwd, ".cursor", "mcp.json");
displayPath = ".cursor/mcp.json";
fs2.mkdirSync(path2.dirname(configPath), { recursive: true });
break;
case "vscode":
configPath = path2.join(cwd, ".vscode", "mcp.json");
displayPath = ".vscode/mcp.json";
fs2.mkdirSync(path2.dirname(configPath), { recursive: true });
break;
case "windsurf": {
const home = process.env.HOME || process.env.USERPROFILE || "";
if (!home) {
console.log(pc2.yellow(" Skipped windsurf"), pc2.dim("(HOME not set)"));
return;
}
} else {
fs2.writeFileSync(gitignorePath, "# MCP config (contains API key)\n.mcp.json\n");
console.log(pc.green(" Created"), ".gitignore", pc.dim("(added .mcp.json)"));
configPath = path2.join(home, ".codeium", "windsurf", "mcp_config.json");
displayPath = configPath;
fs2.mkdirSync(path2.dirname(configPath), { recursive: true });
break;
}
default:
return;
}
if (fs2.existsSync(configPath)) {
try {
const existing = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
if (existing.mcpServers?.["01software"]) {
console.log(pc2.yellow(" Skipped"), displayPath, pc2.dim("(01software already configured)"));
return;
}
existing.mcpServers = existing.mcpServers || {};
existing.mcpServers["01software"] = getMcpServerEntry(apiKey);
fs2.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
console.log(pc2.green(" Updated"), displayPath);
} catch {
console.log(pc2.yellow(" Skipped"), displayPath, pc2.dim("(could not parse existing file)"));
}
} else {
fs2.writeFileSync(configPath, getMcpConfigTemplate(apiKey));
console.log(pc2.green(" Created"), displayPath);
}
}
function addToGitignore(cwd, tools) {
const entries = [];
if (tools.includes("claude")) entries.push(".mcp.json");
if (tools.includes("cursor")) entries.push(".cursor/mcp.json");
if (tools.includes("vscode")) entries.push(".vscode/mcp.json");
if (entries.length === 0) return;
const gitignorePath = path2.join(cwd, ".gitignore");
const existing = fs2.existsSync(gitignorePath) ? fs2.readFileSync(gitignorePath, "utf-8") : "";
const toAdd = entries.filter((e) => !existing.includes(e));
if (toAdd.length === 0) return;
const content = "\n# MCP configs (contain API key)\n" + toAdd.join("\n") + "\n";
if (fs2.existsSync(gitignorePath)) {
fs2.appendFileSync(gitignorePath, content);
} else {
fs2.writeFileSync(gitignorePath, content.trimStart());
}
console.log(pc2.green(" Updated"), ".gitignore", pc2.dim(`(added ${toAdd.join(", ")})`));
}
async function writeClaudeDocs(cwd, clientKey, secretKey, tenantName) {
let ctx = {
tenantName: tenantName || "Your Tenant",
features: void 0,
collections: void 0
};
if (clientKey && secretKey) {
const fetched = await fetchTenantContext(clientKey, secretKey);
if (fetched) {
ctx = {
tenantName: fetched.tenantName || ctx.tenantName,
features: fetched.features,
collections: fetched.collections
};
}
}
const claudeDir = path2.join(cwd, ".claude");
const commandsDir = path2.join(claudeDir, "commands");
fs2.mkdirSync(commandsDir, { recursive: true });
const claudeMdPath = path2.join(claudeDir, "CLAUDE.md");
if (!fs2.existsSync(claudeMdPath)) {
fs2.writeFileSync(claudeMdPath, generateClaudeMd(ctx));
console.log(pc2.green(" Created"), ".claude/CLAUDE.md");
} else {
console.log(pc2.yellow(" Skipped"), ".claude/CLAUDE.md", pc2.dim("(already exists)"));
}
for (const { filename, content } of getSkillFiles()) {
const skillPath = path2.join(commandsDir, filename);
if (!fs2.existsSync(skillPath)) {
fs2.writeFileSync(skillPath, content);
console.log(pc2.green(" Created"), `.claude/commands/${filename}`);
}
}
}
function relativePath(cwd, filePath) {

@@ -494,4 +906,4 @@ return path2.relative(cwd, filePath);

console.log();
console.log(pc2.bold(" @01.software/init"));
console.log(pc2.dim(" Initialize 01.software SDK in your project"));
console.log(pc3.bold(" @01.software/init"));
console.log(pc3.dim(" Initialize 01.software SDK in your project"));
console.log();

@@ -501,7 +913,7 @@ const info = detectProject(cwd);

if (info.parseError) {
console.log(pc2.red(" Could not parse package.json (invalid JSON)."));
console.log(pc2.dim(" Fix the syntax error and try again."));
console.log(pc3.red(" Could not parse package.json (invalid JSON)."));
console.log(pc3.dim(" Fix the syntax error and try again."));
} else {
console.log(pc2.red(" No package.json found in the current directory."));
console.log(pc2.dim(" Run this command inside an existing project."));
console.log(pc3.red(" No package.json found in the current directory."));
console.log(pc3.dim(" Run this command inside an existing project."));
}

@@ -515,3 +927,3 @@ console.log();

if (info.env !== "node") {
console.log(pc2.dim(` Detected: ${detectedParts.join(" / ")}`));
console.log(pc3.dim(` Detected: ${detectedParts.join(" / ")}`));
console.log();

@@ -522,7 +934,7 @@ }

if (!answers) {
console.log(pc2.yellow(" Cancelled."));
console.log(pc3.yellow(" Cancelled."));
process.exit(0);
}
if (answers.env === "other") {
console.log(pc2.yellow(" Manual setup required for your framework:"));
console.log(pc3.yellow(" Manual setup required for your framework:"));
console.log(OTHER_FRAMEWORK_GUIDE);

@@ -538,3 +950,3 @@ process.exit(0);

console.log();
console.log(pc2.green(" Done!"));
console.log(pc3.green(" Done!"));
console.log();

@@ -544,30 +956,30 @@ console.log(" Next steps:");

if (env === "nextjs") {
console.log(pc2.dim(" Add QueryProvider to your root layout:"));
console.log(pc3.dim(" Add QueryProvider to your root layout:"));
console.log();
console.log(pc2.cyan(" import { QueryProvider } from '@/lib/software/query-provider'"));
console.log(pc2.cyan(" <QueryProvider>{children}</QueryProvider>"));
console.log(pc3.cyan(" import { QueryProvider } from '@/lib/software/query-provider'"));
console.log(pc3.cyan(" <QueryProvider>{children}</QueryProvider>"));
console.log();
} else if (env === "react-vite" || env === "react-cra") {
console.log(pc2.dim(" Wrap your app entry with QueryProvider:"));
console.log(pc3.dim(" Wrap your app entry with QueryProvider:"));
console.log();
console.log(pc2.cyan(" import { QueryProvider } from './lib/software/query-provider'"));
console.log(pc2.cyan(" <QueryProvider><App /></QueryProvider>"));
console.log(pc3.cyan(" import { QueryProvider } from './lib/software/query-provider'"));
console.log(pc3.cyan(" <QueryProvider><App /></QueryProvider>"));
console.log();
} else if (env === "vanilla") {
console.log(pc2.dim(" Replace YOUR_CLIENT_KEY in lib/software/client.ts"));
console.log(pc3.dim(" Replace YOUR_CLIENT_KEY in lib/software/client.ts"));
console.log();
console.log(pc2.cyan(" import { client } from './lib/software/client'"));
console.log(pc2.cyan(" const posts = await client.from('posts').find()"));
console.log(pc3.cyan(" import { client } from './lib/software/client'"));
console.log(pc3.cyan(" const posts = await client.from('posts').find()"));
console.log();
} else if (env === "node") {
console.log(pc2.dim(" Use the server client:"));
console.log(pc3.dim(" Use the server client:"));
console.log();
console.log(pc2.cyan(" import { serverClient } from './lib/software/server'"));
console.log(pc2.cyan(" const posts = await serverClient.from('posts').find()"));
console.log(pc3.cyan(" import { serverClient } from './lib/software/server'"));
console.log(pc3.cyan(" const posts = await serverClient.from('posts').find()"));
console.log();
} else if (env === "edge") {
console.log(pc2.dim(" Pass your env bindings to createEdgeClient():"));
console.log(pc3.dim(" Pass your env bindings to createEdgeClient():"));
console.log();
console.log(pc2.cyan(" import { createEdgeClient } from './lib/software/server'"));
console.log(pc2.cyan(" const serverClient = createEdgeClient(env.CLIENT_KEY, env.SECRET_KEY)"));
console.log(pc3.cyan(" import { createEdgeClient } from './lib/software/server'"));
console.log(pc3.cyan(" const serverClient = createEdgeClient(env.CLIENT_KEY, env.SECRET_KEY)"));
console.log();

@@ -578,11 +990,11 @@ }

if (missingClientKey || missingSecretKey) {
console.log(pc2.dim(" Update .env with your API keys"));
console.log(pc3.dim(" Update .env with your API keys"));
console.log();
}
if (answers.setupMcp && (!answers.clientKey || !answers.secretKey)) {
console.log(pc2.dim(" Update .mcp.json x-api-key with Base64(clientKey:secretKey)"));
if (answers.aiTools.length > 0 && (!answers.clientKey || !answers.secretKey)) {
console.log(pc3.dim(" Update .mcp.json x-api-key with Base64(clientKey:secretKey)"));
console.log();
}
if (env !== "vanilla") {
console.log(pc2.cyan(` ${run} dev`));
console.log(pc3.cyan(` ${run} dev`));
console.log();

@@ -592,6 +1004,6 @@ }

if (error instanceof Error && error.message === "cancelled") {
console.log(pc2.yellow(" Cancelled."));
console.log(pc3.yellow(" Cancelled."));
process.exit(0);
}
console.error(pc2.red(" Error:"), error);
console.error(pc3.red(" Error:"), error);
process.exit(1);

@@ -598,0 +1010,0 @@ }

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/detect.ts","../src/prompts.ts","../src/init.ts","../src/templates.ts"],"sourcesContent":["import pc from 'picocolors'\nimport { detectProject } from './detect'\nimport type { ProjectEnv } from './detect'\nimport { promptUser } from './prompts'\nimport { init } from './init'\n\nconst ENV_LABELS: Record<ProjectEnv, string> = {\n nextjs: 'Next.js',\n 'react-vite': 'React + Vite',\n 'react-cra': 'React + Webpack/CRA',\n vanilla: 'Vanilla JS',\n node: 'Node.js',\n edge: 'Edge runtime',\n other: 'Other framework',\n}\n\n// Manual setup guide for unsupported frameworks\nconst OTHER_FRAMEWORK_GUIDE = `\n Astro, Remix, SvelteKit, and other meta-frameworks have their own\n environment conventions. Manual setup:\n\n 1. Install the SDK:\n npm install @01.software/sdk\n\n 2. Browser client (client islands / RSC):\n import { createClient } from '@01.software/sdk'\n export const client = createClient({ clientKey: 'YOUR_CLIENT_KEY' })\n\n 3. Server client (SSR / loaders / endpoints):\n import { createServerClient } from '@01.software/sdk'\n export const serverClient = createServerClient({\n clientKey: process.env.PUBLIC_SOFTWARE_CLIENT_KEY!, // prefix varies by framework\n secretKey: process.env.SOFTWARE_SECRET_KEY!,\n })\n\n 4. Docs: https://01.software/docs/guide/quickstart\n`\n\nasync function main() {\n const cwd = process.cwd()\n\n console.log()\n console.log(pc.bold(' @01.software/init'))\n console.log(pc.dim(' Initialize 01.software SDK in your project'))\n console.log()\n\n // 1. Detect project\n const info = detectProject(cwd)\n\n if (!info.hasPackageJson) {\n if (info.parseError) {\n console.log(pc.red(' Could not parse package.json (invalid JSON).'))\n console.log(pc.dim(' Fix the syntax error and try again.'))\n } else {\n console.log(pc.red(' No package.json found in the current directory.'))\n console.log(pc.dim(' Run this command inside an existing project.'))\n }\n console.log()\n process.exit(1)\n }\n\n // Show detected environment\n const detectedParts: string[] = [ENV_LABELS[info.env]]\n if (info.packageManager) detectedParts.push(info.packageManager)\n if (info.srcDir) detectedParts.push('src/')\n\n if (info.env !== 'node') {\n // Only show detected label when it's unambiguous\n console.log(pc.dim(` Detected: ${detectedParts.join(' / ')}`))\n console.log()\n }\n\n try {\n // 2. Prompt\n const answers = await promptUser(info.hasSdk, info.env, info.packageManager)\n if (!answers) {\n console.log(pc.yellow(' Cancelled.'))\n process.exit(0)\n }\n\n // \"Other\" framework — print guide and exit\n if (answers.env === 'other') {\n console.log(pc.yellow(' Manual setup required for your framework:'))\n console.log(OTHER_FRAMEWORK_GUIDE)\n process.exit(0)\n }\n\n // Resolve package manager from detection or user selection\n const resolvedPm = info.packageManager ?? answers.packageManager ?? 'npm'\n const resolvedInfo = { ...info, packageManager: resolvedPm }\n\n // 3. Init\n console.log()\n await init(cwd, resolvedInfo, answers)\n\n // 4. Next steps\n const env = answers.env\n const run = resolvedPm === 'npm' ? 'npm run' : resolvedPm\n\n console.log()\n console.log(pc.green(' Done!'))\n console.log()\n console.log(' Next steps:')\n console.log()\n\n if (env === 'nextjs') {\n console.log(pc.dim(' Add QueryProvider to your root layout:'))\n console.log()\n console.log(pc.cyan(\" import { QueryProvider } from '@/lib/software/query-provider'\"))\n console.log(pc.cyan(' <QueryProvider>{children}</QueryProvider>'))\n console.log()\n } else if (env === 'react-vite' || env === 'react-cra') {\n console.log(pc.dim(' Wrap your app entry with QueryProvider:'))\n console.log()\n console.log(pc.cyan(\" import { QueryProvider } from './lib/software/query-provider'\"))\n console.log(pc.cyan(' <QueryProvider><App /></QueryProvider>'))\n console.log()\n } else if (env === 'vanilla') {\n console.log(pc.dim(' Replace YOUR_CLIENT_KEY in lib/software/client.ts'))\n console.log()\n console.log(pc.cyan(\" import { client } from './lib/software/client'\"))\n console.log(pc.cyan(\" const posts = await client.from('posts').find()\"))\n console.log()\n } else if (env === 'node') {\n console.log(pc.dim(' Use the server client:'))\n console.log()\n console.log(pc.cyan(\" import { serverClient } from './lib/software/server'\"))\n console.log(pc.cyan(\" const posts = await serverClient.from('posts').find()\"))\n console.log()\n } else if (env === 'edge') {\n console.log(pc.dim(' Pass your env bindings to createEdgeClient():'))\n console.log()\n console.log(pc.cyan(\" import { createEdgeClient } from './lib/software/server'\"))\n console.log(pc.cyan(' const serverClient = createEdgeClient(env.CLIENT_KEY, env.SECRET_KEY)'))\n console.log()\n }\n\n const missingClientKey = env !== 'vanilla' && !answers.clientKey\n const missingSecretKey = (env === 'nextjs' || env === 'node') && !answers.secretKey\n if (missingClientKey || missingSecretKey) {\n console.log(pc.dim(' Update .env with your API keys'))\n console.log()\n }\n if (answers.setupMcp && (!answers.clientKey || !answers.secretKey)) {\n console.log(pc.dim(' Update .mcp.json x-api-key with Base64(clientKey:secretKey)'))\n console.log()\n }\n if (env !== 'vanilla') {\n console.log(pc.cyan(` ${run} dev`))\n console.log()\n }\n } catch (error) {\n if (error instanceof Error && error.message === 'cancelled') {\n console.log(pc.yellow(' Cancelled.'))\n process.exit(0)\n }\n console.error(pc.red(' Error:'), error)\n process.exit(1)\n }\n}\n\nmain()\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\nexport type ProjectEnv =\n | 'nextjs'\n | 'react-vite'\n | 'react-cra'\n | 'vanilla'\n | 'node'\n | 'edge'\n | 'other' // Astro, Remix, SvelteKit, etc. — print guidance only\n\nexport interface ProjectInfo {\n hasPackageJson: boolean\n parseError?: boolean\n env: ProjectEnv\n packageManager: PackageManager | null\n hasSdk: boolean\n srcDir: boolean\n}\n\nexport function detectProject(cwd: string): ProjectInfo {\n const pkgPath = path.join(cwd, 'package.json')\n const hasPackageJson = fs.existsSync(pkgPath)\n\n let env: ProjectEnv = 'node'\n let hasSdk = false\n\n if (hasPackageJson) {\n let pkg: Record<string, unknown>\n try {\n pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n } catch {\n return { hasPackageJson: false, parseError: true, env: 'node', packageManager: null, hasSdk: false, srcDir: false }\n }\n\n const deps = {\n ...((pkg.dependencies as Record<string, string>) || {}),\n ...((pkg.devDependencies as Record<string, string>) || {}),\n }\n hasSdk = '@01.software/sdk' in deps\n\n if ('next' in deps) {\n env = 'nextjs'\n } else if ('astro' in deps || '@astrojs/node' in deps) {\n env = 'other'\n } else if ('@remix-run/node' in deps || '@remix-run/react' in deps) {\n env = 'other'\n } else if ('@sveltejs/kit' in deps) {\n env = 'other'\n } else if ('react' in deps) {\n if ('vite' in deps) {\n env = 'react-vite'\n } else if ('react-scripts' in deps) {\n env = 'react-cra'\n } else {\n // React + unknown bundler (Webpack, Parcel, etc.) — leave as 'node'\n // so the prompt selector is shown\n env = 'node'\n }\n }\n // else: no react/next → 'node' (covers real Node.js, Deno, Bun, etc.)\n }\n\n // Detect package manager from lockfile\n let packageManager: PackageManager | null = null\n if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) {\n packageManager = 'pnpm'\n } else if (fs.existsSync(path.join(cwd, 'yarn.lock'))) {\n packageManager = 'yarn'\n } else if (\n fs.existsSync(path.join(cwd, 'bun.lockb')) ||\n fs.existsSync(path.join(cwd, 'bun.lock'))\n ) {\n packageManager = 'bun'\n } else if (fs.existsSync(path.join(cwd, 'package-lock.json'))) {\n packageManager = 'npm'\n }\n\n // Detect src directory structure\n const srcDir =\n env === 'nextjs'\n ? fs.existsSync(path.join(cwd, 'src', 'app'))\n : fs.existsSync(path.join(cwd, 'src'))\n\n return { hasPackageJson, env, packageManager, hasSdk, srcDir }\n}\n\n/** Environments that generate a browser client file */\nexport function needsClient(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'react-vite' || env === 'react-cra' || env === 'vanilla'\n}\n\n/** Environments that generate a server client file */\nexport function needsServer(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'node' || env === 'edge'\n}\n\n/** Environments that generate a query-provider file */\nexport function needsReactQuery(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'react-vite' || env === 'react-cra'\n}\n\n/** Environments that support MCP setup (need both client + secret key) */\nexport function supportsMcp(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'node' || env === 'edge'\n}\n\n/** Get the env var name for the public client key */\nexport function getClientKeyEnvVar(env: ProjectEnv): string {\n switch (env) {\n case 'nextjs':\n return 'NEXT_PUBLIC_SOFTWARE_CLIENT_KEY'\n case 'react-vite':\n return 'VITE_SOFTWARE_CLIENT_KEY'\n case 'react-cra':\n return 'REACT_APP_SOFTWARE_CLIENT_KEY'\n default:\n return 'SOFTWARE_CLIENT_KEY'\n }\n}\n","import prompts from 'prompts'\nimport type { PackageManager, ProjectEnv } from './detect'\nimport { supportsMcp } from './detect'\n\nexport interface InitAnswers {\n env: ProjectEnv\n clientKey: string\n secretKey: string\n setupMcp: boolean\n packageManager?: PackageManager\n}\n\n// Envs that need the user to disambiguate (couldn't be auto-detected)\nconst AMBIGUOUS_ENVS: ProjectEnv[] = ['node']\n\nexport async function promptUser(\n hasSdk: boolean,\n detectedEnv: ProjectEnv,\n detectedPm: PackageManager | null,\n): Promise<InitAnswers | null> {\n const onCancel = () => {\n throw new Error('cancelled')\n }\n\n // Confirm re-init if SDK already installed\n if (hasSdk) {\n const { proceed } = await prompts(\n {\n type: 'confirm',\n name: 'proceed',\n message: '@01.software/sdk is already installed. Re-initialize?',\n initial: false,\n },\n { onCancel },\n )\n if (!proceed) return null\n }\n\n // Ask for environment when auto-detection is ambiguous\n let env = detectedEnv\n if (AMBIGUOUS_ENVS.includes(detectedEnv)) {\n const { selectedEnv } = await prompts(\n {\n type: 'select',\n name: 'selectedEnv',\n message: 'Which environment are you using?',\n choices: [\n {\n title: 'Next.js',\n description: 'Full-stack React (client + server)',\n value: 'nextjs',\n },\n {\n title: 'React + Vite',\n description: 'Client-only SPA with Vite',\n value: 'react-vite',\n },\n {\n title: 'React + Webpack / other',\n description: 'Client-only SPA, CRA or custom bundler',\n value: 'react-cra',\n },\n {\n title: 'Vanilla JS',\n description: 'Browser app without a framework',\n value: 'vanilla',\n },\n {\n title: 'Node.js / Bun / Deno',\n description: 'Server-only, no browser client',\n value: 'node',\n },\n {\n title: 'Edge runtime',\n description: 'Cloudflare Workers, Vercel Edge Functions',\n value: 'edge',\n },\n {\n title: 'Other (Astro / Remix / SvelteKit…)',\n description: 'Print manual setup guide for your framework',\n value: 'other',\n },\n ],\n },\n { onCancel },\n )\n env = selectedEnv as ProjectEnv\n }\n\n // \"Other\" frameworks — we can't scaffold correctly; exit with guidance\n if (env === 'other') {\n return { env, clientKey: '', secretKey: '', setupMcp: false, packageManager: undefined }\n }\n\n // Ask for package manager if no lockfile detected\n let packageManager: PackageManager | undefined\n if (!detectedPm) {\n const { pm } = await prompts(\n {\n type: 'select',\n name: 'pm',\n message: 'Which package manager do you use?',\n choices: [\n { title: 'npm', value: 'npm' },\n { title: 'pnpm', value: 'pnpm' },\n { title: 'yarn', value: 'yarn' },\n { title: 'bun', value: 'bun' },\n ],\n },\n { onCancel },\n )\n packageManager = pm\n }\n\n const needsSecretKey = env === 'nextjs' || env === 'node' || env === 'edge'\n\n const keyPrompts: prompts.PromptObject[] = []\n\n // Vanilla JS doesn't use env vars — no prompts for keys\n if (env !== 'vanilla') {\n keyPrompts.push({\n type: 'text',\n name: 'clientKey',\n message: 'Client Key (optional, saved to .env)',\n initial: '',\n })\n }\n\n if (needsSecretKey) {\n keyPrompts.push({\n type: 'text',\n name: 'secretKey',\n message: 'Secret Key (optional, saved to .env)',\n initial: '',\n })\n }\n\n const keys = keyPrompts.length > 0 ? await prompts(keyPrompts, { onCancel }) : {}\n\n // MCP requires both client + secret key\n let setupMcp = false\n if (supportsMcp(env)) {\n const result = await prompts(\n {\n type: 'confirm',\n name: 'setupMcp',\n message: 'Set up MCP integration? (.mcp.json)',\n initial: true,\n },\n { onCancel },\n )\n setupMcp = result.setupMcp\n }\n\n return {\n env,\n clientKey: (keys as Record<string, string>).clientKey ?? '',\n secretKey: (keys as Record<string, string>).secretKey ?? '',\n setupMcp,\n packageManager,\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execSync } from 'node:child_process'\nimport pc from 'picocolors'\nimport type { PackageManager, ProjectInfo } from './detect'\nimport {\n needsClient,\n needsServer,\n needsReactQuery,\n getClientKeyEnvVar,\n} from './detect'\nimport type { InitAnswers } from './prompts'\nimport {\n getClientTemplate,\n getQueryProviderTemplate,\n getServerTemplate,\n getEnvContent,\n getMcpConfigTemplate,\n getMcpServerEntry,\n} from './templates'\n\ntype ResolvedProjectInfo = Omit<ProjectInfo, 'packageManager'> & {\n packageManager: PackageManager\n}\n\nconst SECRET_KEY_ENV_VAR = 'SOFTWARE_SECRET_KEY'\n\nexport async function init(\n cwd: string,\n info: ResolvedProjectInfo,\n answers: InitAnswers,\n): Promise<void> {\n const { packageManager, srcDir } = info\n const env = answers.env\n const baseDir = srcDir ? path.join(cwd, 'src') : cwd\n\n const clientKeyEnvVar = getClientKeyEnvVar(env)\n const wantsClient = needsClient(env)\n const wantsServer = needsServer(env)\n const wantsReactQuery = needsReactQuery(env)\n\n // 1. Install dependencies\n const deps = ['@01.software/sdk']\n if (wantsReactQuery) deps.push('@tanstack/react-query')\n\n console.log(pc.dim(` Installing ${deps.join(' and ')}...`))\n\n // pnpm-workspace.yaml without packages: breaks pnpm add — patch temporarily\n const wsPatched = packageManager === 'pnpm' && patchPnpmWorkspace(cwd)\n\n const pkgs = deps.join(' ')\n const pnpmFlag = hasPnpmWorkspace(cwd) ? ' -w' : ''\n const addCmd =\n packageManager === 'pnpm'\n ? `pnpm add${pnpmFlag} ${pkgs}`\n : packageManager === 'yarn'\n ? `yarn add ${pkgs}`\n : packageManager === 'bun'\n ? `bun add ${pkgs}`\n : `npm install ${pkgs}`\n\n try {\n execSync(addCmd, { cwd, stdio: 'pipe' })\n } catch (error) {\n const err = error as { stdout?: Buffer; stderr?: Buffer }\n const msg =\n String(err.stderr || '').trim() ||\n String(err.stdout || '').trim() ||\n String(error)\n console.log(pc.red(' Failed to install dependencies:'))\n console.log(pc.dim(` ${msg}`))\n throw error\n } finally {\n if (wsPatched) restorePnpmWorkspace(cwd)\n }\n\n // 2. Write lib/software/ files\n const libDir = path.join(baseDir, 'lib', 'software')\n fs.mkdirSync(libDir, { recursive: true })\n\n // Client (browser)\n if (wantsClient) {\n const clientPath = path.join(libDir, 'client.ts')\n if (fs.existsSync(clientPath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, clientPath), pc.dim('(already exists)'))\n } else {\n fs.writeFileSync(clientPath, getClientTemplate(env, clientKeyEnvVar))\n console.log(pc.green(' Created'), relativePath(cwd, clientPath))\n }\n }\n\n // Query Provider (React)\n if (wantsReactQuery) {\n const queryProviderPath = path.join(libDir, 'query-provider.tsx')\n if (fs.existsSync(queryProviderPath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, queryProviderPath), pc.dim('(already exists)'))\n } else {\n fs.writeFileSync(queryProviderPath, getQueryProviderTemplate(env))\n console.log(pc.green(' Created'), relativePath(cwd, queryProviderPath))\n }\n }\n\n // Server\n if (wantsServer) {\n const serverPath = path.join(libDir, 'server.ts')\n if (fs.existsSync(serverPath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, serverPath), pc.dim('(already exists)'))\n } else {\n fs.writeFileSync(serverPath, getServerTemplate(env, clientKeyEnvVar, SECRET_KEY_ENV_VAR))\n console.log(pc.green(' Created'), relativePath(cwd, serverPath))\n }\n }\n\n // 3. Append to .env (vanilla uses inline key, no env file needed)\n if (env !== 'vanilla' && env !== 'edge') {\n const envPath = path.join(cwd, '.env')\n const envContent = getEnvContent(\n answers.clientKey || '',\n answers.secretKey || '',\n clientKeyEnvVar,\n wantsServer ? SECRET_KEY_ENV_VAR : null,\n )\n\n if (fs.existsSync(envPath)) {\n const existing = fs.readFileSync(envPath, 'utf-8')\n if (existing.includes(clientKeyEnvVar)) {\n console.log(pc.yellow(' Skipped'), '.env', pc.dim('(keys already present)'))\n } else {\n fs.appendFileSync(envPath, envContent)\n console.log(pc.green(' Updated'), '.env')\n }\n } else {\n fs.writeFileSync(envPath, envContent.trimStart())\n console.log(pc.green(' Created'), '.env')\n }\n }\n\n // 4. Write .mcp.json (MCP integration)\n if (answers.setupMcp) {\n const clientKey = answers.clientKey || ''\n const secretKey = answers.secretKey || ''\n const apiKey =\n clientKey && secretKey\n ? Buffer.from(`${clientKey}:${secretKey}`).toString('base64')\n : 'YOUR_API_KEY'\n\n const mcpPath = path.join(cwd, '.mcp.json')\n if (fs.existsSync(mcpPath)) {\n try {\n const existing = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'))\n if (existing.mcpServers?.['01software']) {\n console.log(pc.yellow(' Skipped'), '.mcp.json', pc.dim('(01software already configured)'))\n } else {\n existing.mcpServers = existing.mcpServers || {}\n existing.mcpServers['01software'] = getMcpServerEntry(apiKey)\n fs.writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + '\\n')\n console.log(pc.green(' Updated'), '.mcp.json')\n }\n } catch {\n console.log(pc.yellow(' Skipped'), '.mcp.json', pc.dim('(could not parse existing file)'))\n }\n } else {\n fs.writeFileSync(mcpPath, getMcpConfigTemplate(apiKey))\n console.log(pc.green(' Created'), '.mcp.json')\n }\n\n // 5. Add .mcp.json to .gitignore (contains API key)\n const gitignorePath = path.join(cwd, '.gitignore')\n if (fs.existsSync(gitignorePath)) {\n const gitignore = fs.readFileSync(gitignorePath, 'utf-8')\n if (!gitignore.includes('.mcp.json')) {\n fs.appendFileSync(gitignorePath, '\\n# MCP config (contains API key)\\n.mcp.json\\n')\n console.log(pc.green(' Updated'), '.gitignore', pc.dim('(added .mcp.json)'))\n }\n } else {\n fs.writeFileSync(gitignorePath, '# MCP config (contains API key)\\n.mcp.json\\n')\n console.log(pc.green(' Created'), '.gitignore', pc.dim('(added .mcp.json)'))\n }\n }\n}\n\nfunction relativePath(cwd: string, filePath: string): string {\n return path.relative(cwd, filePath)\n}\n\nconst WS_FILE = 'pnpm-workspace.yaml'\nconst WS_BACKUP = 'pnpm-workspace.yaml.bak'\n\nfunction hasPnpmWorkspace(cwd: string): boolean {\n return fs.existsSync(path.join(cwd, WS_FILE))\n}\n\nfunction patchPnpmWorkspace(cwd: string): boolean {\n const wsPath = path.join(cwd, WS_FILE)\n if (!fs.existsSync(wsPath)) return false\n const content = fs.readFileSync(wsPath, 'utf-8')\n if (content.includes('packages:')) return false\n fs.copyFileSync(wsPath, path.join(cwd, WS_BACKUP))\n fs.writeFileSync(wsPath, content.trimEnd() + '\\npackages: []\\n')\n return true\n}\n\nfunction restorePnpmWorkspace(cwd: string): void {\n const backupPath = path.join(cwd, WS_BACKUP)\n if (!fs.existsSync(backupPath)) return\n fs.copyFileSync(backupPath, path.join(cwd, WS_FILE))\n fs.unlinkSync(backupPath)\n}\n","import type { ProjectEnv } from './detect'\n\n// ── Client template (browser) ────────────────────────────────────────\n\nexport function getClientTemplate(env: ProjectEnv, clientKeyEnvVar: string): string {\n if (env === 'nextjs') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n clientKey: process.env.${clientKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'react-cra') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n clientKey: process.env.${clientKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'vanilla') {\n return `import { createClient } from '@01.software/sdk'\n\n// Replace 'YOUR_CLIENT_KEY' with your actual client key from the 01.software console\nexport const client = createClient({\n clientKey: 'YOUR_CLIENT_KEY',\n})\n`\n }\n\n // react-vite (import.meta.env)\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n clientKey: import.meta.env.${clientKeyEnvVar},\n})\n`\n}\n\n// ── Query Provider template ──────────────────────────────────────────\n\nexport function getQueryProviderTemplate(env: ProjectEnv): string {\n const useClientDirective = env === 'nextjs' ? \"'use client'\\n\\n\" : ''\n\n return `${useClientDirective}import { QueryClientProvider } from '@tanstack/react-query'\nimport { client } from './client'\n\nexport function QueryProvider({ children }: { children: React.ReactNode }) {\n return (\n <QueryClientProvider client={client.queryClient}>\n {children}\n </QueryClientProvider>\n )\n}\n`\n}\n\n// ── Server template ──────────────────────────────────────────────────\n\nexport function getServerTemplate(\n env: ProjectEnv,\n clientKeyEnvVar: string,\n secretKeyEnvVar: string,\n): string {\n if (env === 'edge') {\n return `import { createServerClient } from '@01.software/sdk'\n\n// Edge runtime: pass your env bindings here\n// e.g. Cloudflare Workers: use env.SOFTWARE_CLIENT_KEY from the handler context\n// e.g. Vercel Edge: use process.env.${clientKeyEnvVar}\nexport function createEdgeClient(clientKey: string, secretKey: string) {\n return createServerClient({ clientKey, secretKey })\n}\n`\n }\n\n return `import { createServerClient } from '@01.software/sdk'\n\nexport const serverClient = createServerClient({\n clientKey: process.env.${clientKeyEnvVar}!,\n secretKey: process.env.${secretKeyEnvVar}!,\n})\n`\n}\n\n// ── Env file content ─────────────────────────────────────────────────\n\nexport function getEnvContent(\n clientKey: string,\n secretKey: string,\n clientKeyEnvVar: string,\n secretKeyEnvVar: string | null,\n): string {\n let content = `\\n# 01.software\\n${clientKeyEnvVar}=${clientKey}\\n`\n if (secretKeyEnvVar) {\n content += `${secretKeyEnvVar}=${secretKey}\\n`\n }\n return content\n}\n\n// ── MCP config ───────────────────────────────────────────────────────\n\nexport function getMcpServerEntry(apiKey: string) {\n return {\n type: 'http' as const,\n url: 'https://mcp.01.software/mcp',\n headers: { 'x-api-key': apiKey },\n }\n}\n\nexport function getMcpConfigTemplate(apiKey: string): string {\n return (\n JSON.stringify(\n { mcpServers: { '01software': getMcpServerEntry(apiKey) } },\n null,\n 2,\n ) + '\\n'\n )\n}\n"],"mappings":"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","names":["pc","fs","path","path","fs","pc"]}
{"version":3,"sources":["../src/index.ts","../src/detect.ts","../src/prompts.ts","../src/init.ts","../src/templates.ts","../src/browser-auth.ts","../src/ai-docs.ts"],"sourcesContent":["import pc from 'picocolors'\nimport { detectProject } from './detect'\nimport type { ProjectEnv } from './detect'\nimport { promptUser } from './prompts'\nimport { init } from './init'\n\nconst ENV_LABELS: Record<ProjectEnv, string> = {\n nextjs: 'Next.js',\n 'react-vite': 'React + Vite',\n 'react-cra': 'React + Webpack/CRA',\n vanilla: 'Vanilla JS',\n node: 'Node.js',\n edge: 'Edge runtime',\n other: 'Other framework',\n}\n\n// Manual setup guide for unsupported frameworks\nconst OTHER_FRAMEWORK_GUIDE = `\n Astro, Remix, SvelteKit, and other meta-frameworks have their own\n environment conventions. Manual setup:\n\n 1. Install the SDK:\n npm install @01.software/sdk\n\n 2. Browser client (client islands / RSC):\n import { createClient } from '@01.software/sdk'\n export const client = createClient({ clientKey: 'YOUR_CLIENT_KEY' })\n\n 3. Server client (SSR / loaders / endpoints):\n import { createServerClient } from '@01.software/sdk'\n export const serverClient = createServerClient({\n clientKey: process.env.PUBLIC_SOFTWARE_CLIENT_KEY!, // prefix varies by framework\n secretKey: process.env.SOFTWARE_SECRET_KEY!,\n })\n\n 4. Docs: https://01.software/docs/guide/quickstart\n`\n\nasync function main() {\n const cwd = process.cwd()\n\n console.log()\n console.log(pc.bold(' @01.software/init'))\n console.log(pc.dim(' Initialize 01.software SDK in your project'))\n console.log()\n\n // 1. Detect project\n const info = detectProject(cwd)\n\n if (!info.hasPackageJson) {\n if (info.parseError) {\n console.log(pc.red(' Could not parse package.json (invalid JSON).'))\n console.log(pc.dim(' Fix the syntax error and try again.'))\n } else {\n console.log(pc.red(' No package.json found in the current directory.'))\n console.log(pc.dim(' Run this command inside an existing project.'))\n }\n console.log()\n process.exit(1)\n }\n\n // Show detected environment\n const detectedParts: string[] = [ENV_LABELS[info.env]]\n if (info.packageManager) detectedParts.push(info.packageManager)\n if (info.srcDir) detectedParts.push('src/')\n\n if (info.env !== 'node') {\n // Only show detected label when it's unambiguous\n console.log(pc.dim(` Detected: ${detectedParts.join(' / ')}`))\n console.log()\n }\n\n try {\n // 2. Prompt\n const answers = await promptUser(info.hasSdk, info.env, info.packageManager)\n if (!answers) {\n console.log(pc.yellow(' Cancelled.'))\n process.exit(0)\n }\n\n // \"Other\" framework — print guide and exit\n if (answers.env === 'other') {\n console.log(pc.yellow(' Manual setup required for your framework:'))\n console.log(OTHER_FRAMEWORK_GUIDE)\n process.exit(0)\n }\n\n // Resolve package manager from detection or user selection\n const resolvedPm = info.packageManager ?? answers.packageManager ?? 'npm'\n const resolvedInfo = { ...info, packageManager: resolvedPm }\n\n // 3. Init\n console.log()\n await init(cwd, resolvedInfo, answers)\n\n // 4. Next steps\n const env = answers.env\n const run = resolvedPm === 'npm' ? 'npm run' : resolvedPm\n\n console.log()\n console.log(pc.green(' Done!'))\n console.log()\n console.log(' Next steps:')\n console.log()\n\n if (env === 'nextjs') {\n console.log(pc.dim(' Add QueryProvider to your root layout:'))\n console.log()\n console.log(pc.cyan(\" import { QueryProvider } from '@/lib/software/query-provider'\"))\n console.log(pc.cyan(' <QueryProvider>{children}</QueryProvider>'))\n console.log()\n } else if (env === 'react-vite' || env === 'react-cra') {\n console.log(pc.dim(' Wrap your app entry with QueryProvider:'))\n console.log()\n console.log(pc.cyan(\" import { QueryProvider } from './lib/software/query-provider'\"))\n console.log(pc.cyan(' <QueryProvider><App /></QueryProvider>'))\n console.log()\n } else if (env === 'vanilla') {\n console.log(pc.dim(' Replace YOUR_CLIENT_KEY in lib/software/client.ts'))\n console.log()\n console.log(pc.cyan(\" import { client } from './lib/software/client'\"))\n console.log(pc.cyan(\" const posts = await client.from('posts').find()\"))\n console.log()\n } else if (env === 'node') {\n console.log(pc.dim(' Use the server client:'))\n console.log()\n console.log(pc.cyan(\" import { serverClient } from './lib/software/server'\"))\n console.log(pc.cyan(\" const posts = await serverClient.from('posts').find()\"))\n console.log()\n } else if (env === 'edge') {\n console.log(pc.dim(' Pass your env bindings to createEdgeClient():'))\n console.log()\n console.log(pc.cyan(\" import { createEdgeClient } from './lib/software/server'\"))\n console.log(pc.cyan(' const serverClient = createEdgeClient(env.CLIENT_KEY, env.SECRET_KEY)'))\n console.log()\n }\n\n const missingClientKey = env !== 'vanilla' && !answers.clientKey\n const missingSecretKey = (env === 'nextjs' || env === 'node') && !answers.secretKey\n if (missingClientKey || missingSecretKey) {\n console.log(pc.dim(' Update .env with your API keys'))\n console.log()\n }\n if (answers.aiTools.length > 0 && (!answers.clientKey || !answers.secretKey)) {\n console.log(pc.dim(' Update .mcp.json x-api-key with Base64(clientKey:secretKey)'))\n console.log()\n }\n if (env !== 'vanilla') {\n console.log(pc.cyan(` ${run} dev`))\n console.log()\n }\n } catch (error) {\n if (error instanceof Error && error.message === 'cancelled') {\n console.log(pc.yellow(' Cancelled.'))\n process.exit(0)\n }\n console.error(pc.red(' Error:'), error)\n process.exit(1)\n }\n}\n\nmain()\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\nexport type ProjectEnv =\n | 'nextjs'\n | 'react-vite'\n | 'react-cra'\n | 'vanilla'\n | 'node'\n | 'edge'\n | 'other' // Astro, Remix, SvelteKit, etc. — print guidance only\n\nexport interface ProjectInfo {\n hasPackageJson: boolean\n parseError?: boolean\n env: ProjectEnv\n packageManager: PackageManager | null\n hasSdk: boolean\n srcDir: boolean\n}\n\nexport function detectProject(cwd: string): ProjectInfo {\n const pkgPath = path.join(cwd, 'package.json')\n const hasPackageJson = fs.existsSync(pkgPath)\n\n let env: ProjectEnv = 'node'\n let hasSdk = false\n\n if (hasPackageJson) {\n let pkg: Record<string, unknown>\n try {\n pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n } catch {\n return { hasPackageJson: false, parseError: true, env: 'node', packageManager: null, hasSdk: false, srcDir: false }\n }\n\n const deps = {\n ...((pkg.dependencies as Record<string, string>) || {}),\n ...((pkg.devDependencies as Record<string, string>) || {}),\n }\n hasSdk = '@01.software/sdk' in deps\n\n if ('next' in deps) {\n env = 'nextjs'\n } else if ('astro' in deps || '@astrojs/node' in deps) {\n env = 'other'\n } else if ('@remix-run/node' in deps || '@remix-run/react' in deps) {\n env = 'other'\n } else if ('@sveltejs/kit' in deps) {\n env = 'other'\n } else if ('react' in deps) {\n if ('vite' in deps) {\n env = 'react-vite'\n } else if ('react-scripts' in deps) {\n env = 'react-cra'\n } else {\n // React + unknown bundler (Webpack, Parcel, etc.) — leave as 'node'\n // so the prompt selector is shown\n env = 'node'\n }\n }\n // else: no react/next → 'node' (covers real Node.js, Deno, Bun, etc.)\n }\n\n // Detect package manager from lockfile\n let packageManager: PackageManager | null = null\n if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) {\n packageManager = 'pnpm'\n } else if (fs.existsSync(path.join(cwd, 'yarn.lock'))) {\n packageManager = 'yarn'\n } else if (\n fs.existsSync(path.join(cwd, 'bun.lockb')) ||\n fs.existsSync(path.join(cwd, 'bun.lock'))\n ) {\n packageManager = 'bun'\n } else if (fs.existsSync(path.join(cwd, 'package-lock.json'))) {\n packageManager = 'npm'\n }\n\n // Detect src directory structure\n const srcDir =\n env === 'nextjs'\n ? fs.existsSync(path.join(cwd, 'src', 'app'))\n : fs.existsSync(path.join(cwd, 'src'))\n\n return { hasPackageJson, env, packageManager, hasSdk, srcDir }\n}\n\n/** Environments that generate a browser client file */\nexport function needsClient(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'react-vite' || env === 'react-cra' || env === 'vanilla'\n}\n\n/** Environments that generate a server client file */\nexport function needsServer(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'node' || env === 'edge'\n}\n\n/** Environments that generate a query-provider file */\nexport function needsReactQuery(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'react-vite' || env === 'react-cra'\n}\n\n/** Environments that support MCP setup (need both client + secret key) */\nexport function supportsMcp(env: ProjectEnv): boolean {\n return env === 'nextjs' || env === 'node' || env === 'edge'\n}\n\n/** Get the env var name for the public client key */\nexport function getClientKeyEnvVar(env: ProjectEnv): string {\n switch (env) {\n case 'nextjs':\n return 'NEXT_PUBLIC_SOFTWARE_CLIENT_KEY'\n case 'react-vite':\n return 'VITE_SOFTWARE_CLIENT_KEY'\n case 'react-cra':\n return 'REACT_APP_SOFTWARE_CLIENT_KEY'\n default:\n return 'SOFTWARE_CLIENT_KEY'\n }\n}\n","import prompts from 'prompts'\nimport type { PackageManager, ProjectEnv } from './detect'\n\nexport type AiTool = 'claude' | 'cursor' | 'vscode' | 'windsurf'\nexport type AuthMethod = 'browser' | 'manual' | 'skip'\n\nexport interface InitAnswers {\n env: ProjectEnv\n clientKey: string\n secretKey: string\n aiTools: AiTool[]\n authMethod: AuthMethod\n packageManager?: PackageManager\n}\n\n// Envs that need the user to disambiguate (couldn't be auto-detected)\nconst AMBIGUOUS_ENVS: ProjectEnv[] = ['node']\n\nexport async function promptUser(\n hasSdk: boolean,\n detectedEnv: ProjectEnv,\n detectedPm: PackageManager | null,\n): Promise<InitAnswers | null> {\n const onCancel = () => {\n throw new Error('cancelled')\n }\n\n // Confirm re-init if SDK already installed\n if (hasSdk) {\n const { proceed } = await prompts(\n {\n type: 'confirm',\n name: 'proceed',\n message: '@01.software/sdk is already installed. Re-initialize?',\n initial: false,\n },\n { onCancel },\n )\n if (!proceed) return null\n }\n\n // Ask for environment when auto-detection is ambiguous\n let env = detectedEnv\n if (AMBIGUOUS_ENVS.includes(detectedEnv)) {\n const { selectedEnv } = await prompts(\n {\n type: 'select',\n name: 'selectedEnv',\n message: 'Which environment are you using?',\n choices: [\n {\n title: 'Next.js',\n description: 'Full-stack React (client + server)',\n value: 'nextjs',\n },\n {\n title: 'React + Vite',\n description: 'Client-only SPA with Vite',\n value: 'react-vite',\n },\n {\n title: 'React + Webpack / other',\n description: 'Client-only SPA, CRA or custom bundler',\n value: 'react-cra',\n },\n {\n title: 'Vanilla JS',\n description: 'Browser app without a framework',\n value: 'vanilla',\n },\n {\n title: 'Node.js / Bun / Deno',\n description: 'Server-only, no browser client',\n value: 'node',\n },\n {\n title: 'Edge runtime',\n description: 'Cloudflare Workers, Vercel Edge Functions',\n value: 'edge',\n },\n {\n title: 'Other (Astro / Remix / SvelteKit…)',\n description: 'Print manual setup guide for your framework',\n value: 'other',\n },\n ],\n },\n { onCancel },\n )\n env = selectedEnv as ProjectEnv\n }\n\n // \"Other\" frameworks — we can't scaffold correctly; exit with guidance\n if (env === 'other') {\n return { env, clientKey: '', secretKey: '', aiTools: [], authMethod: 'skip', packageManager: undefined }\n }\n\n // Ask for package manager if no lockfile detected\n let packageManager: PackageManager | undefined\n if (!detectedPm) {\n const { pm } = await prompts(\n {\n type: 'select',\n name: 'pm',\n message: 'Which package manager do you use?',\n choices: [\n { title: 'npm', value: 'npm' },\n { title: 'pnpm', value: 'pnpm' },\n { title: 'yarn', value: 'yarn' },\n { title: 'bun', value: 'bun' },\n ],\n },\n { onCancel },\n )\n packageManager = pm\n }\n\n const needsSecretKey = env === 'nextjs' || env === 'node' || env === 'edge'\n\n const keyPrompts: prompts.PromptObject[] = []\n\n // Vanilla JS doesn't use env vars — no prompts for keys\n if (env !== 'vanilla') {\n keyPrompts.push({\n type: 'text',\n name: 'clientKey',\n message: 'Client Key (optional, saved to .env)',\n initial: '',\n })\n }\n\n if (needsSecretKey) {\n keyPrompts.push({\n type: 'text',\n name: 'secretKey',\n message: 'Secret Key (optional, saved to .env)',\n initial: '',\n })\n }\n\n // AI tool multi-select\n const { selectedTools } = await prompts(\n {\n type: 'multiselect',\n name: 'selectedTools',\n message: 'Connect AI tools:',\n choices: [\n { title: 'Claude Code', description: '.mcp.json + .claude/ docs', value: 'claude' },\n { title: 'Cursor', description: '.cursor/mcp.json', value: 'cursor' },\n { title: 'VS Code', description: '.vscode/mcp.json', value: 'vscode' },\n { title: 'Windsurf', description: '~/.codeium/windsurf/mcp_config.json', value: 'windsurf' },\n { title: 'Skip', value: 'skip' },\n ],\n hint: 'space to select',\n },\n { onCancel },\n )\n\n const aiTools: AiTool[] = Array.isArray(selectedTools)\n ? (selectedTools as string[]).filter((t): t is AiTool => t !== 'skip')\n : []\n\n // Auth method — only if tools selected and env supports secrets\n let authMethod: AuthMethod = 'skip'\n let keys: Record<string, string> = {}\n\n if (aiTools.length > 0 && env !== 'vanilla') {\n const { method } = await prompts(\n {\n type: 'select',\n name: 'method',\n message: 'API keys:',\n choices: [\n { title: 'Browser login (recommended)', value: 'browser' },\n { title: 'Enter manually', value: 'manual' },\n { title: 'Skip for now', value: 'skip' },\n ],\n },\n { onCancel },\n )\n authMethod = (method as AuthMethod) ?? 'skip'\n\n if (authMethod === 'manual') {\n keys = await prompts(keyPrompts, { onCancel })\n }\n } else if (env !== 'vanilla') {\n // No AI tools selected — still collect keys from the key prompts if any were defined\n if (keyPrompts.length > 0) {\n keys = await prompts(keyPrompts, { onCancel })\n }\n authMethod = 'skip'\n }\n\n return {\n env,\n clientKey: authMethod === 'browser' ? '' : (keys.clientKey ?? ''),\n secretKey: authMethod === 'browser' ? '' : (keys.secretKey ?? ''),\n aiTools,\n authMethod,\n packageManager,\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execSync } from 'node:child_process'\nimport pc from 'picocolors'\nimport type { PackageManager, ProjectInfo } from './detect'\nimport {\n needsClient,\n needsServer,\n needsReactQuery,\n getClientKeyEnvVar,\n} from './detect'\nimport type { InitAnswers } from './prompts'\nimport {\n getClientTemplate,\n getQueryProviderTemplate,\n getServerTemplate,\n getEnvContent,\n getMcpConfigTemplate,\n getMcpServerEntry,\n} from './templates'\nimport { startBrowserAuth } from './browser-auth'\nimport {\n generateClaudeMd,\n getSkillFiles,\n fetchTenantContext,\n} from './ai-docs'\n\ntype ResolvedProjectInfo = Omit<ProjectInfo, 'packageManager'> & {\n packageManager: PackageManager\n}\n\nconst SECRET_KEY_ENV_VAR = 'SOFTWARE_SECRET_KEY'\n\nexport async function init(\n cwd: string,\n info: ResolvedProjectInfo,\n answers: InitAnswers,\n): Promise<void> {\n const { packageManager, srcDir } = info\n const env = answers.env\n const baseDir = srcDir ? path.join(cwd, 'src') : cwd\n\n const clientKeyEnvVar = getClientKeyEnvVar(env)\n const wantsClient = needsClient(env)\n const wantsServer = needsServer(env)\n const wantsReactQuery = needsReactQuery(env)\n\n // 1. Install dependencies\n const deps = ['@01.software/sdk']\n if (wantsReactQuery) deps.push('@tanstack/react-query')\n\n console.log(pc.dim(` Installing ${deps.join(' and ')}...`))\n\n // pnpm-workspace.yaml without packages: breaks pnpm add — patch temporarily\n const wsPatched = packageManager === 'pnpm' && patchPnpmWorkspace(cwd)\n\n const pkgs = deps.join(' ')\n const pnpmFlag = hasPnpmWorkspace(cwd) ? ' -w' : ''\n const addCmd =\n packageManager === 'pnpm'\n ? `pnpm add${pnpmFlag} ${pkgs}`\n : packageManager === 'yarn'\n ? `yarn add ${pkgs}`\n : packageManager === 'bun'\n ? `bun add ${pkgs}`\n : `npm install ${pkgs}`\n\n try {\n execSync(addCmd, { cwd, stdio: 'pipe' })\n } catch (error) {\n const err = error as { stdout?: Buffer; stderr?: Buffer }\n const msg =\n String(err.stderr || '').trim() ||\n String(err.stdout || '').trim() ||\n String(error)\n console.log(pc.red(' Failed to install dependencies:'))\n console.log(pc.dim(` ${msg}`))\n throw error\n } finally {\n if (wsPatched) restorePnpmWorkspace(cwd)\n }\n\n // 2. Write lib/software/ files\n const libDir = path.join(baseDir, 'lib', 'software')\n fs.mkdirSync(libDir, { recursive: true })\n\n // Client (browser)\n if (wantsClient) {\n const clientPath = path.join(libDir, 'client.ts')\n if (fs.existsSync(clientPath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, clientPath), pc.dim('(already exists)'))\n } else {\n fs.writeFileSync(clientPath, getClientTemplate(env, clientKeyEnvVar))\n console.log(pc.green(' Created'), relativePath(cwd, clientPath))\n }\n }\n\n // Query Provider (React)\n if (wantsReactQuery) {\n const queryProviderPath = path.join(libDir, 'query-provider.tsx')\n if (fs.existsSync(queryProviderPath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, queryProviderPath), pc.dim('(already exists)'))\n } else {\n fs.writeFileSync(queryProviderPath, getQueryProviderTemplate(env))\n console.log(pc.green(' Created'), relativePath(cwd, queryProviderPath))\n }\n }\n\n // Server\n if (wantsServer) {\n const serverPath = path.join(libDir, 'server.ts')\n if (fs.existsSync(serverPath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, serverPath), pc.dim('(already exists)'))\n } else {\n fs.writeFileSync(serverPath, getServerTemplate(env, clientKeyEnvVar, SECRET_KEY_ENV_VAR))\n console.log(pc.green(' Created'), relativePath(cwd, serverPath))\n }\n }\n\n // 3. Append to .env (vanilla uses inline key; browser auth writes keys later in step 4)\n if (env !== 'vanilla' && env !== 'edge' && answers.authMethod !== 'browser') {\n const envPath = path.join(cwd, '.env')\n const envContent = getEnvContent(\n answers.clientKey || '',\n answers.secretKey || '',\n clientKeyEnvVar,\n wantsServer ? SECRET_KEY_ENV_VAR : null,\n )\n\n if (fs.existsSync(envPath)) {\n const existing = fs.readFileSync(envPath, 'utf-8')\n if (existing.includes(clientKeyEnvVar)) {\n console.log(pc.yellow(' Skipped'), '.env', pc.dim('(keys already present)'))\n } else {\n fs.appendFileSync(envPath, envContent)\n console.log(pc.green(' Updated'), '.env')\n }\n } else {\n fs.writeFileSync(envPath, envContent.trimStart())\n console.log(pc.green(' Created'), '.env')\n }\n }\n\n // 4. Browser auth — get real credentials if user chose browser login\n let clientKey = answers.clientKey\n let secretKey = answers.secretKey\n let tenantName = ''\n\n if (answers.authMethod === 'browser' && answers.aiTools.length > 0) {\n try {\n console.log()\n const creds = await startBrowserAuth()\n clientKey = creds.clientKey\n secretKey = creds.secretKey\n tenantName = creds.tenantName\n\n // Write .env with the real keys obtained from browser\n if (env !== 'vanilla' && env !== 'edge' && clientKey) {\n const envPath = path.join(cwd, '.env')\n const envContent = getEnvContent(\n clientKey,\n secretKey,\n clientKeyEnvVar,\n wantsServer ? SECRET_KEY_ENV_VAR : null,\n )\n if (fs.existsSync(envPath)) {\n const existing = fs.readFileSync(envPath, 'utf-8')\n if (!existing.includes(clientKeyEnvVar)) {\n fs.appendFileSync(envPath, envContent)\n console.log(pc.green(' Updated'), '.env', pc.dim('(added API keys)'))\n }\n } else {\n fs.writeFileSync(envPath, envContent.trimStart())\n console.log(pc.green(' Created'), '.env')\n }\n }\n } catch (err) {\n console.log(\n pc.yellow(' Browser auth skipped:'),\n err instanceof Error ? err.message : String(err),\n )\n }\n }\n\n // 5. Write AI tool configs (MCP + Claude docs)\n if (answers.aiTools.length > 0) {\n const apiKey =\n clientKey && secretKey\n ? Buffer.from(`${clientKey}:${secretKey}`).toString('base64')\n : 'YOUR_API_KEY'\n\n for (const tool of answers.aiTools) {\n writeMcpConfig(tool, cwd, apiKey)\n }\n\n addToGitignore(cwd, answers.aiTools)\n\n if (answers.aiTools.includes('claude')) {\n await writeClaudeDocs(cwd, clientKey, secretKey, tenantName)\n }\n }\n}\n\nfunction writeMcpConfig(tool: string, cwd: string, apiKey: string): void {\n let configPath: string\n let displayPath: string\n\n switch (tool) {\n case 'claude':\n configPath = path.join(cwd, '.mcp.json')\n displayPath = '.mcp.json'\n break\n case 'cursor':\n configPath = path.join(cwd, '.cursor', 'mcp.json')\n displayPath = '.cursor/mcp.json'\n fs.mkdirSync(path.dirname(configPath), { recursive: true })\n break\n case 'vscode':\n configPath = path.join(cwd, '.vscode', 'mcp.json')\n displayPath = '.vscode/mcp.json'\n fs.mkdirSync(path.dirname(configPath), { recursive: true })\n break\n case 'windsurf': {\n const home = process.env.HOME || process.env.USERPROFILE || ''\n if (!home) {\n console.log(pc.yellow(' Skipped windsurf'), pc.dim('(HOME not set)'))\n return\n }\n configPath = path.join(home, '.codeium', 'windsurf', 'mcp_config.json')\n displayPath = configPath // global path, show absolute\n fs.mkdirSync(path.dirname(configPath), { recursive: true })\n break\n }\n default:\n return\n }\n\n if (fs.existsSync(configPath)) {\n try {\n const existing = JSON.parse(fs.readFileSync(configPath, 'utf-8'))\n if (existing.mcpServers?.['01software']) {\n console.log(pc.yellow(' Skipped'), displayPath, pc.dim('(01software already configured)'))\n return\n }\n existing.mcpServers = existing.mcpServers || {}\n existing.mcpServers['01software'] = getMcpServerEntry(apiKey)\n fs.writeFileSync(configPath, JSON.stringify(existing, null, 2) + '\\n')\n console.log(pc.green(' Updated'), displayPath)\n } catch {\n console.log(pc.yellow(' Skipped'), displayPath, pc.dim('(could not parse existing file)'))\n }\n } else {\n fs.writeFileSync(configPath, getMcpConfigTemplate(apiKey))\n console.log(pc.green(' Created'), displayPath)\n }\n}\n\nfunction addToGitignore(cwd: string, tools: string[]): void {\n const entries: string[] = []\n if (tools.includes('claude')) entries.push('.mcp.json')\n if (tools.includes('cursor')) entries.push('.cursor/mcp.json')\n if (tools.includes('vscode')) entries.push('.vscode/mcp.json')\n // windsurf is global (~/.codeium/...) — no project-level gitignore needed\n\n if (entries.length === 0) return\n\n const gitignorePath = path.join(cwd, '.gitignore')\n const existing = fs.existsSync(gitignorePath)\n ? fs.readFileSync(gitignorePath, 'utf-8')\n : ''\n const toAdd = entries.filter((e) => !existing.includes(e))\n if (toAdd.length === 0) return\n\n const content = '\\n# MCP configs (contain API key)\\n' + toAdd.join('\\n') + '\\n'\n if (fs.existsSync(gitignorePath)) {\n fs.appendFileSync(gitignorePath, content)\n } else {\n fs.writeFileSync(gitignorePath, content.trimStart())\n }\n console.log(pc.green(' Updated'), '.gitignore', pc.dim(`(added ${toAdd.join(', ')})`))\n}\n\nasync function writeClaudeDocs(\n cwd: string,\n clientKey: string,\n secretKey: string,\n tenantName: string,\n): Promise<void> {\n let ctx = {\n tenantName: tenantName || 'Your Tenant',\n features: undefined as string[] | undefined,\n collections: undefined as string[] | undefined,\n }\n\n if (clientKey && secretKey) {\n const fetched = await fetchTenantContext(clientKey, secretKey)\n if (fetched) {\n ctx = {\n tenantName: fetched.tenantName || ctx.tenantName,\n features: fetched.features,\n collections: fetched.collections,\n }\n }\n }\n\n const claudeDir = path.join(cwd, '.claude')\n const commandsDir = path.join(claudeDir, 'commands')\n fs.mkdirSync(commandsDir, { recursive: true })\n\n // CLAUDE.md\n const claudeMdPath = path.join(claudeDir, 'CLAUDE.md')\n if (!fs.existsSync(claudeMdPath)) {\n fs.writeFileSync(claudeMdPath, generateClaudeMd(ctx))\n console.log(pc.green(' Created'), '.claude/CLAUDE.md')\n } else {\n console.log(pc.yellow(' Skipped'), '.claude/CLAUDE.md', pc.dim('(already exists)'))\n }\n\n // Skill files\n for (const { filename, content } of getSkillFiles()) {\n const skillPath = path.join(commandsDir, filename)\n if (!fs.existsSync(skillPath)) {\n fs.writeFileSync(skillPath, content)\n console.log(pc.green(' Created'), `.claude/commands/${filename}`)\n }\n }\n}\n\nfunction relativePath(cwd: string, filePath: string): string {\n return path.relative(cwd, filePath)\n}\n\nconst WS_FILE = 'pnpm-workspace.yaml'\nconst WS_BACKUP = 'pnpm-workspace.yaml.bak'\n\nfunction hasPnpmWorkspace(cwd: string): boolean {\n return fs.existsSync(path.join(cwd, WS_FILE))\n}\n\nfunction patchPnpmWorkspace(cwd: string): boolean {\n const wsPath = path.join(cwd, WS_FILE)\n if (!fs.existsSync(wsPath)) return false\n const content = fs.readFileSync(wsPath, 'utf-8')\n if (content.includes('packages:')) return false\n fs.copyFileSync(wsPath, path.join(cwd, WS_BACKUP))\n fs.writeFileSync(wsPath, content.trimEnd() + '\\npackages: []\\n')\n return true\n}\n\nfunction restorePnpmWorkspace(cwd: string): void {\n const backupPath = path.join(cwd, WS_BACKUP)\n if (!fs.existsSync(backupPath)) return\n fs.copyFileSync(backupPath, path.join(cwd, WS_FILE))\n fs.unlinkSync(backupPath)\n}\n","import type { ProjectEnv } from './detect'\n\n// ── Client template (browser) ────────────────────────────────────────\n\nexport function getClientTemplate(env: ProjectEnv, clientKeyEnvVar: string): string {\n if (env === 'nextjs') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n clientKey: process.env.${clientKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'react-cra') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n clientKey: process.env.${clientKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'vanilla') {\n return `import { createClient } from '@01.software/sdk'\n\n// Replace 'YOUR_CLIENT_KEY' with your actual client key from the 01.software console\nexport const client = createClient({\n clientKey: 'YOUR_CLIENT_KEY',\n})\n`\n }\n\n // react-vite (import.meta.env)\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n clientKey: import.meta.env.${clientKeyEnvVar},\n})\n`\n}\n\n// ── Query Provider template ──────────────────────────────────────────\n\nexport function getQueryProviderTemplate(env: ProjectEnv): string {\n const useClientDirective = env === 'nextjs' ? \"'use client'\\n\\n\" : ''\n\n return `${useClientDirective}import { QueryClientProvider } from '@tanstack/react-query'\nimport { client } from './client'\n\nexport function QueryProvider({ children }: { children: React.ReactNode }) {\n return (\n <QueryClientProvider client={client.queryClient}>\n {children}\n </QueryClientProvider>\n )\n}\n`\n}\n\n// ── Server template ──────────────────────────────────────────────────\n\nexport function getServerTemplate(\n env: ProjectEnv,\n clientKeyEnvVar: string,\n secretKeyEnvVar: string,\n): string {\n if (env === 'edge') {\n return `import { createServerClient } from '@01.software/sdk'\n\n// Edge runtime: pass your env bindings here\n// e.g. Cloudflare Workers: use env.SOFTWARE_CLIENT_KEY from the handler context\n// e.g. Vercel Edge: use process.env.${clientKeyEnvVar}\nexport function createEdgeClient(clientKey: string, secretKey: string) {\n return createServerClient({ clientKey, secretKey })\n}\n`\n }\n\n return `import { createServerClient } from '@01.software/sdk'\n\nexport const serverClient = createServerClient({\n clientKey: process.env.${clientKeyEnvVar}!,\n secretKey: process.env.${secretKeyEnvVar}!,\n})\n`\n}\n\n// ── Env file content ─────────────────────────────────────────────────\n\nexport function getEnvContent(\n clientKey: string,\n secretKey: string,\n clientKeyEnvVar: string,\n secretKeyEnvVar: string | null,\n): string {\n let content = `\\n# 01.software\\n${clientKeyEnvVar}=${clientKey}\\n`\n if (secretKeyEnvVar) {\n content += `${secretKeyEnvVar}=${secretKey}\\n`\n }\n return content\n}\n\n// ── MCP config ───────────────────────────────────────────────────────\n\nexport function getMcpServerEntry(apiKey: string) {\n return {\n type: 'http' as const,\n url: 'https://mcp.01.software/mcp',\n headers: { 'x-api-key': apiKey },\n }\n}\n\nexport function getMcpConfigTemplate(apiKey: string): string {\n return (\n JSON.stringify(\n { mcpServers: { '01software': getMcpServerEntry(apiKey) } },\n null,\n 2,\n ) + '\\n'\n )\n}\n","import { randomBytes } from 'node:crypto'\nimport { createServer } from 'node:http'\nimport { execFile, exec } from 'node:child_process'\nimport { platform } from 'node:os'\nimport { URL } from 'node:url'\nimport pc from 'picocolors'\n\nconst DEFAULT_WEB_URL = process.env.SOFTWARE_WEB_URL || 'https://01.software'\nconst TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction openBrowser(url: string): void {\n const os = platform()\n\n const onError = () => {\n console.log(\n pc.yellow(\n `Could not open browser automatically. Open this URL manually:\\n${url}`,\n ),\n )\n }\n\n if (os === 'win32') {\n exec(`start \"\" \"${url}\"`, (err) => {\n if (err) onError()\n })\n } else {\n const cmd = os === 'darwin' ? 'open' : 'xdg-open'\n execFile(cmd, [url], (err) => {\n if (err) onError()\n })\n }\n}\n\nconst PAGE_STYLE = `*{margin:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;background:#fff;color:#252525}\n@media(prefers-color-scheme:dark){body{background:#252525;color:#f5f5f5}}\n.card{text-align:center;padding:2rem 2.5rem;border-radius:10px;max-width:380px;width:100%}\n.icon{width:40px;height:40px;margin:0 auto 1rem;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.25rem}\n.icon.ok{background:rgba(0,0,0,.05);color:#252525}\n.icon.err{background:rgba(220,38,38,.08);color:#dc2626}\n@media(prefers-color-scheme:dark){.icon.ok{background:rgba(255,255,255,.08);color:#f5f5f5}}\nh1{font-size:.875rem;font-weight:600;margin-bottom:.375rem}\np{font-size:.75rem;color:#737373;line-height:1.5}`\n\nconst SUCCESS_HTML = `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><title>Login</title>\n<style>${PAGE_STYLE}</style>\n</head><body><div class=\"card\"><div class=\"icon ok\">\\u2713</div><h1>Authenticated</h1><p>You can close this tab and return to the terminal.</p></div></body></html>`\n\nconst ERROR_HTML = (msg: string) => `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><title>Login Error</title>\n<style>${PAGE_STYLE}</style>\n</head><body><div class=\"card\"><div class=\"icon err\">!</div><h1>Authentication failed</h1><p>${escapeHtml(msg)}</p></div></body></html>`\n\nexport async function startBrowserAuth(options?: {\n webUrl?: string\n tenantId?: string\n}): Promise<{ clientKey: string; secretKey: string; tenantName: string; tenantId?: string }> {\n const state = randomBytes(32).toString('hex')\n const webUrl = options?.webUrl ?? DEFAULT_WEB_URL\n\n return new Promise((resolve, reject) => {\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400).end()\n return\n }\n\n const url = new URL(req.url, `http://localhost`)\n\n if (url.pathname !== '/callback') {\n res.writeHead(404).end()\n return\n }\n\n const receivedState = url.searchParams.get('state')\n const clientKey = url.searchParams.get('clientKey')\n const secretKey = url.searchParams.get('secretKey')\n const tenant = url.searchParams.get('tenant')\n const tenantIdParam = url.searchParams.get('tenantId')\n const error = url.searchParams.get('error')\n\n if (error) {\n res\n .writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n .end(ERROR_HTML(error))\n console.error(pc.red(`Login failed: ${error}`))\n cleanup(new Error(`Login failed: ${error}`))\n return\n }\n\n if (receivedState !== state) {\n res\n .writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n .end(ERROR_HTML('State mismatch — possible CSRF attack.'))\n console.error(pc.red('Login failed: state mismatch.'))\n cleanup(new Error('Login failed: state mismatch.'))\n return\n }\n\n if (!clientKey || !secretKey || !tenant) {\n res\n .writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n .end(ERROR_HTML('Missing credentials in callback.'))\n console.error(pc.red('Login failed: missing credentials.'))\n cleanup(new Error('Login failed: missing credentials.'))\n return\n }\n\n res\n .writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n .end(SUCCESS_HTML)\n\n console.log(pc.green(`\\nLogged in successfully!`))\n console.log(pc.dim(`Tenant: ${tenant}`))\n\n const result: { clientKey: string; secretKey: string; tenantName: string; tenantId?: string } = {\n clientKey,\n secretKey,\n tenantName: tenant,\n ...(tenantIdParam ? { tenantId: tenantIdParam } : {}),\n }\n\n cleanup(null, result)\n })\n\n let timeout: ReturnType<typeof setTimeout>\n let completed = false\n\n function cleanup(\n err: Error | null,\n result?: { clientKey: string; secretKey: string; tenantName: string; tenantId?: string },\n ) {\n if (completed) return\n completed = true\n clearTimeout(timeout)\n server.close(() => {\n if (err) {\n reject(err)\n } else {\n resolve(result!)\n }\n })\n }\n\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address()\n if (!addr || typeof addr === 'string') {\n reject(new Error('Failed to start local server.'))\n return\n }\n\n const port = addr.port\n\n timeout = setTimeout(() => {\n console.error(pc.red('\\nLogin timed out (5 minutes). Please try again.'))\n cleanup(new Error('Login timed out'))\n }, TIMEOUT_MS)\n\n const params = new URLSearchParams({ port: String(port), state })\n if (options?.tenantId) {\n params.set('tenantId', options.tenantId)\n }\n const loginUrl = `${webUrl}/cli-auth?${params.toString()}`\n\n console.log(pc.dim('Opening browser for login...'))\n console.log(pc.dim(`If the browser does not open, visit:\\n${loginUrl}`))\n openBrowser(loginUrl)\n })\n\n server.on('error', (err) => {\n reject(err)\n })\n })\n}\n","export interface TenantContext {\n tenantName: string\n features?: string[]\n collections?: string[]\n}\n\n// ── CLAUDE.md ────────────────────────────────────────────────────────\n\nexport function generateClaudeMd(ctx: TenantContext): string {\n const featuresSection =\n ctx.features && ctx.features.length > 0\n ? ctx.features.map((f) => `- ${f}`).join('\\n')\n : '- See console'\n\n const collectionsSection =\n ctx.collections && ctx.collections.length > 0\n ? ctx.collections.join(', ')\n : 'Run `01 schema list`'\n\n return `# 01.software SDK — ${ctx.tenantName}\n\n## Connection\n- Client Key: \\`NEXT_PUBLIC_SOFTWARE_CLIENT_KEY\\` (env)\n- Server Key: \\`SOFTWARE_SECRET_KEY\\` (env)\n- MCP: \\`.mcp.json\\`\n\n## Active Features\n${featuresSection}\n\n## Collections\n${collectionsSection}\n\n## MCP Quick Reference\n| Tool | Use |\n|------|-----|\n| \\`query-collection\\` | List/filter documents |\n| \\`create-collection\\` | Create documents |\n| \\`update-field-config\\` | Hide unused fields |\n| \\`get-tenant-context\\` | Show active features & collections |\n\n## CLI\n- \\`01 query <collection>\\` — query data\n- \\`01 schema show <collection>\\` — inspect fields\n- \\`01 schema list\\` — list all collections\n\n## Initial Setup\nRun \\`/field-config\\` in Claude Code to configure field visibility for your use case.\n`\n}\n\n// ── Skill files ──────────────────────────────────────────────────────\n\nexport function getSkillFiles(): Array<{ filename: string; content: string }> {\n return [\n {\n filename: 'field-config.md',\n content: `Configure field visibility for this tenant using MCP tools.\n\nSteps:\n1. Use \\`list-configurable-fields\\` to see current visibility settings\n2. Identify fields/collections not needed for your use case\n3. Use \\`update-field-config\\` to hide them\n\nCommon setups:\n- Blog only: hide \\`ecommerce\\`, \\`customers\\`, \\`videos\\` collections\n- Store: hide \\`posts\\`, \\`documents\\`, \\`galleries\\`, \\`flows\\` collections\n- Minimal: hide all except the collections you actively use\n\nAsk me: \"Show current field config\" or \"Hide ecommerce fields\"\n`,\n },\n {\n filename: 'query.md',\n content: `Query collections using the MCP \\`query-collection\\` tool or CLI.\n\nMCP examples:\n- List products: \\`query-collection\\` with collection=\"products\", limit=10\n- Filter by status: add where={\"status\":{\"equals\":\"published\"}}\n- Sort by date: sort=\"-createdAt\"\n- Paginate: page=2, limit=20\n\nCLI examples:\n- \\`01 query products --limit 10\\`\n- \\`01 query orders --where '{\"status\":{\"equals\":\"paid\"}}'\\`\n- \\`01 schema show products\\` — inspect available fields\n\nSDK (server):\n\\`\\`\\`typescript\nconst { docs } = await serverClient.collection('products').find({\n where: { status: { equals: 'published' } },\n sort: '-createdAt',\n limit: 10,\n})\n\\`\\`\\`\n`,\n },\n {\n filename: 'order-flow.md',\n content: `Complete order flow from creation to fulfillment.\n\nStates: pending → paid → preparing → shipped → delivered → confirmed\n\n1. Create order: \\`create-order\\` with orderNumber, customerSnapshot, orderProducts, totalAmount\n2. Mark paid: \\`update-order\\` with status=\"paid\" (after payment gateway confirms)\n3. Fulfill: \\`create-fulfillment\\` with items and carrier/trackingNumber\n4. Returns: \\`create-return\\` or \\`return-with-refund\\` (atomic)\n\nFree orders: omit paymentId, totalAmount=0 → auto-transitions to paid\n\nCLI: \\`01 order create --help\\` for full options\n`,\n },\n {\n filename: 'schema.md',\n content: `Inspect collection schemas to understand available fields.\n\nMCP: use \\`get-collection-fields\\` with collectionSlug\n\nCLI:\n- \\`01 schema list\\` — all available collections\n- \\`01 schema show <collection>\\` — field names, types, required status\n\nCommon collections: products, orders, customers, posts, documents, images\nUse \\`get-tenant-context\\` to see which collections are active for this tenant.\n`,\n },\n ]\n}\n\n// ── Tenant context fetch ─────────────────────────────────────────────\n\nexport async function fetchTenantContext(\n clientKey: string,\n secretKey: string,\n): Promise<TenantContext | null> {\n try {\n const apiUrl = process.env.SOFTWARE_API_URL || 'https://api.01.software'\n const base64 = Buffer.from(`${clientKey}:${secretKey}`).toString('base64')\n const res = await fetch(`${apiUrl}/api/tenants/context`, {\n headers: { 'x-api-key': base64 },\n })\n if (!res.ok) return null\n const data = (await res.json()) as {\n tenant?: { name?: string }\n features?: string[]\n collections?: string[]\n }\n return {\n tenantName: data.tenant?.name || '',\n features: data.features || [],\n collections: data.collections || [],\n }\n } catch {\n return null\n }\n}\n"],"mappings":"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","names":["pc","fs","path","pc","path","pc","fs","pc"]}
{
"name": "@01.software/init",
"version": "0.1.6",
"version": "0.2.0",
"description": "Initialize 01.software SDK in your project (Next.js, React, Vanilla JS, Node.js, Edge)",

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