@01.software/init 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-OEAQV63E.js +120 -0
- package/dist/chunk-OEAQV63E.js.map +1 -0
- package/dist/index.js +180 -196
- package/dist/index.js.map +1 -1
- package/dist/templates.js +22 -0
- package/dist/templates.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/templates.ts
|
|
4
|
+
function getClientTemplate(env, publishableKeyEnvVar) {
|
|
5
|
+
if (env === "nextjs") {
|
|
6
|
+
return `import { createClient } from '@01.software/sdk'
|
|
7
|
+
|
|
8
|
+
export const client = createClient({
|
|
9
|
+
publishableKey: process.env.${publishableKeyEnvVar}!,
|
|
10
|
+
})
|
|
11
|
+
`;
|
|
12
|
+
}
|
|
13
|
+
if (env === "react-cra") {
|
|
14
|
+
return `import { createClient } from '@01.software/sdk'
|
|
15
|
+
|
|
16
|
+
export const client = createClient({
|
|
17
|
+
publishableKey: process.env.${publishableKeyEnvVar}!,
|
|
18
|
+
})
|
|
19
|
+
`;
|
|
20
|
+
}
|
|
21
|
+
if (env === "vanilla") {
|
|
22
|
+
return `import { createClient } from '@01.software/sdk'
|
|
23
|
+
|
|
24
|
+
// Replace 'YOUR_PUBLISHABLE_KEY' with your actual publishable key from the 01.software console
|
|
25
|
+
export const client = createClient({
|
|
26
|
+
publishableKey: 'YOUR_PUBLISHABLE_KEY',
|
|
27
|
+
})
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
return `import { createClient } from '@01.software/sdk'
|
|
31
|
+
|
|
32
|
+
export const client = createClient({
|
|
33
|
+
publishableKey: import.meta.env.${publishableKeyEnvVar},
|
|
34
|
+
})
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
37
|
+
function getQueryProviderTemplate(env) {
|
|
38
|
+
const useClientDirective = env === "nextjs" ? "'use client'\n\n" : "";
|
|
39
|
+
return `${useClientDirective}import { QueryClientProvider } from '@tanstack/react-query'
|
|
40
|
+
import { client } from './client'
|
|
41
|
+
|
|
42
|
+
export function QueryProvider({ children }: { children: React.ReactNode }) {
|
|
43
|
+
return (
|
|
44
|
+
<QueryClientProvider client={client.queryClient}>
|
|
45
|
+
{children}
|
|
46
|
+
</QueryClientProvider>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
function getServerTemplate(env, publishableKeyEnvVar, secretKeyEnvVar) {
|
|
52
|
+
if (env === "edge") {
|
|
53
|
+
return `import { createServerClient } from '@01.software/sdk'
|
|
54
|
+
|
|
55
|
+
// Edge runtime: pass your env bindings here
|
|
56
|
+
// e.g. Cloudflare Workers: use env.SOFTWARE_PUBLISHABLE_KEY from the handler context
|
|
57
|
+
// e.g. Vercel Edge: use process.env.${publishableKeyEnvVar}
|
|
58
|
+
export function createEdgeClient(publishableKey: string, secretKey: string) {
|
|
59
|
+
return createServerClient({ publishableKey, secretKey })
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
return `import { createServerClient } from '@01.software/sdk'
|
|
64
|
+
|
|
65
|
+
export const serverClient = createServerClient({
|
|
66
|
+
publishableKey: process.env.${publishableKeyEnvVar}!,
|
|
67
|
+
secretKey: process.env.${secretKeyEnvVar}!,
|
|
68
|
+
})
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
function getEnvContent(publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar) {
|
|
72
|
+
let content = `
|
|
73
|
+
# 01.software
|
|
74
|
+
${publishableKeyEnvVar}=${publishableKey}
|
|
75
|
+
`;
|
|
76
|
+
if (secretKeyEnvVar) {
|
|
77
|
+
content += `${secretKeyEnvVar}=${secretKey}
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
return content;
|
|
81
|
+
}
|
|
82
|
+
function getMcpServerEntry(apiKey) {
|
|
83
|
+
return {
|
|
84
|
+
type: "http",
|
|
85
|
+
url: "https://mcp.01.software/mcp",
|
|
86
|
+
headers: { "x-api-key": apiKey }
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function getMcpConfigTemplate(apiKey) {
|
|
90
|
+
return JSON.stringify(
|
|
91
|
+
{ mcpServers: { "01software": getMcpServerEntry(apiKey) } },
|
|
92
|
+
null,
|
|
93
|
+
2
|
|
94
|
+
) + "\n";
|
|
95
|
+
}
|
|
96
|
+
function escapeTomlString(s) {
|
|
97
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
98
|
+
}
|
|
99
|
+
function getCodexMcpTomlSection(apiKey) {
|
|
100
|
+
return `
|
|
101
|
+
[mcp_servers.01software]
|
|
102
|
+
url = "https://mcp.01.software/mcp"
|
|
103
|
+
|
|
104
|
+
[mcp_servers.01software.headers]
|
|
105
|
+
x-api-key = "${escapeTomlString(apiKey)}"
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
var CODEX_MCP_SECTION_MARKER = "[mcp_servers.01software]";
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
getClientTemplate,
|
|
112
|
+
getQueryProviderTemplate,
|
|
113
|
+
getServerTemplate,
|
|
114
|
+
getEnvContent,
|
|
115
|
+
getMcpServerEntry,
|
|
116
|
+
getMcpConfigTemplate,
|
|
117
|
+
getCodexMcpTomlSection,
|
|
118
|
+
CODEX_MCP_SECTION_MARKER
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=chunk-OEAQV63E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/templates.ts"],"sourcesContent":["import type { ProjectEnv } from './detect'\n\n// ── Client template (browser) ────────────────────────────────────────\n\nexport function getClientTemplate(env: ProjectEnv, publishableKeyEnvVar: string): string {\n if (env === 'nextjs') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n publishableKey: process.env.${publishableKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'react-cra') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n publishableKey: process.env.${publishableKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'vanilla') {\n return `import { createClient } from '@01.software/sdk'\n\n// Replace 'YOUR_PUBLISHABLE_KEY' with your actual publishable key from the 01.software console\nexport const client = createClient({\n publishableKey: 'YOUR_PUBLISHABLE_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 publishableKey: import.meta.env.${publishableKeyEnvVar},\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 publishableKeyEnvVar: 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_PUBLISHABLE_KEY from the handler context\n// e.g. Vercel Edge: use process.env.${publishableKeyEnvVar}\nexport function createEdgeClient(publishableKey: string, secretKey: string) {\n return createServerClient({ publishableKey, secretKey })\n}\n`\n }\n\n return `import { createServerClient } from '@01.software/sdk'\n\nexport const serverClient = createServerClient({\n publishableKey: process.env.${publishableKeyEnvVar}!,\n secretKey: process.env.${secretKeyEnvVar}!,\n})\n`\n}\n\n// ── Env file content ─────────────────────────────────────────────────\n\nexport function getEnvContent(\n publishableKey: string,\n secretKey: string,\n publishableKeyEnvVar: string,\n secretKeyEnvVar: string | null,\n): string {\n let content = `\\n# 01.software\\n${publishableKeyEnvVar}=${publishableKey}\\n`\n if (secretKeyEnvVar) {\n content += `${secretKeyEnvVar}=${secretKey}\\n`\n }\n return content\n}\n\n// ── MCP config (JSON) ────────────────────────────────────────────────\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\n// ── MCP config (TOML — Codex CLI) ────────────────────────────────────\n\nfunction escapeTomlString(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n/** Codex CLI `[mcp_servers.01software]` block. Idempotent marker: the header\n * line. Intended to be appended to `~/.codex/config.toml`. */\nexport function getCodexMcpTomlSection(apiKey: string): string {\n return `\n[mcp_servers.01software]\nurl = \"https://mcp.01.software/mcp\"\n\n[mcp_servers.01software.headers]\nx-api-key = \"${escapeTomlString(apiKey)}\"\n`\n}\n\nexport const CODEX_MCP_SECTION_MARKER = '[mcp_servers.01software]'\n"],"mappings":";;;AAIO,SAAS,kBAAkB,KAAiB,sBAAsC;AACvF,MAAI,QAAQ,UAAU;AACpB,WAAO;AAAA;AAAA;AAAA,gCAGqB,oBAAoB;AAAA;AAAA;AAAA,EAGlD;AAEA,MAAI,QAAQ,aAAa;AACvB,WAAO;AAAA;AAAA;AAAA,gCAGqB,oBAAoB;AAAA;AAAA;AAAA,EAGlD;AAEA,MAAI,QAAQ,WAAW;AACrB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT;AAGA,SAAO;AAAA;AAAA;AAAA,oCAG2B,oBAAoB;AAAA;AAAA;AAGxD;AAIO,SAAS,yBAAyB,KAAyB;AAChE,QAAM,qBAAqB,QAAQ,WAAW,qBAAqB;AAEnE,SAAO,GAAG,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAW9B;AAIO,SAAS,kBACd,KACA,sBACA,iBACQ;AACR,MAAI,QAAQ,QAAQ;AAClB,WAAO;AAAA;AAAA;AAAA;AAAA,8CAImC,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKhE;AAEA,SAAO;AAAA;AAAA;AAAA,gCAGuB,oBAAoB;AAAA,2BACzB,eAAe;AAAA;AAAA;AAG1C;AAIO,SAAS,cACd,gBACA,WACA,sBACA,iBACQ;AACR,MAAI,UAAU;AAAA;AAAA,EAAoB,oBAAoB,IAAI,cAAc;AAAA;AACxE,MAAI,iBAAiB;AACnB,eAAW,GAAG,eAAe,IAAI,SAAS;AAAA;AAAA,EAC5C;AACA,SAAO;AACT;AAIO,SAAS,kBAAkB,QAAgB;AAChD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,SAAS,EAAE,aAAa,OAAO;AAAA,EACjC;AACF;AAEO,SAAS,qBAAqB,QAAwB;AAC3D,SACE,KAAK;AAAA,IACH,EAAE,YAAY,EAAE,cAAc,kBAAkB,MAAM,EAAE,EAAE;AAAA,IAC1D;AAAA,IACA;AAAA,EACF,IAAI;AAER;AAIA,SAAS,iBAAiB,GAAmB;AAC3C,SAAO,EAAE,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK;AACrD;AAIO,SAAS,uBAAuB,QAAwB;AAC7D,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,eAKM,iBAAiB,MAAM,CAAC;AAAA;AAEvC;AAEO,IAAM,2BAA2B;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,16 @@ import {
|
|
|
4
4
|
generateClaudeMd,
|
|
5
5
|
getSkillFiles
|
|
6
6
|
} from "./chunk-SRLZ5OIV.js";
|
|
7
|
+
import {
|
|
8
|
+
CODEX_MCP_SECTION_MARKER,
|
|
9
|
+
getClientTemplate,
|
|
10
|
+
getCodexMcpTomlSection,
|
|
11
|
+
getEnvContent,
|
|
12
|
+
getMcpConfigTemplate,
|
|
13
|
+
getMcpServerEntry,
|
|
14
|
+
getQueryProviderTemplate,
|
|
15
|
+
getServerTemplate
|
|
16
|
+
} from "./chunk-OEAQV63E.js";
|
|
7
17
|
|
|
8
18
|
// src/index.ts
|
|
9
19
|
import pc3 from "picocolors";
|
|
@@ -16,12 +26,13 @@ function detectProject(cwd) {
|
|
|
16
26
|
const hasPackageJson = fs.existsSync(pkgPath);
|
|
17
27
|
let env = "node";
|
|
18
28
|
let hasSdk = false;
|
|
29
|
+
let parseError = false;
|
|
19
30
|
if (hasPackageJson) {
|
|
20
31
|
let pkg;
|
|
21
32
|
try {
|
|
22
33
|
pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
23
34
|
} catch {
|
|
24
|
-
return { hasPackageJson:
|
|
35
|
+
return { hasPackageJson: true, parseError: true, env: "node", packageManager: null, hasSdk: false, srcDir: false };
|
|
25
36
|
}
|
|
26
37
|
const deps = {
|
|
27
38
|
...pkg.dependencies || {},
|
|
@@ -57,7 +68,7 @@ function detectProject(cwd) {
|
|
|
57
68
|
packageManager = "npm";
|
|
58
69
|
}
|
|
59
70
|
const srcDir = env === "nextjs" ? fs.existsSync(path.join(cwd, "src", "app")) : fs.existsSync(path.join(cwd, "src"));
|
|
60
|
-
return { hasPackageJson, env, packageManager, hasSdk, srcDir };
|
|
71
|
+
return { hasPackageJson, parseError, env, packageManager, hasSdk, srcDir };
|
|
61
72
|
}
|
|
62
73
|
function needsClient(env) {
|
|
63
74
|
return env === "nextjs" || env === "react-vite" || env === "react-cra" || env === "vanilla";
|
|
@@ -192,19 +203,20 @@ async function promptUser(hasSdk, detectedEnv, detectedPm) {
|
|
|
192
203
|
{
|
|
193
204
|
type: "multiselect",
|
|
194
205
|
name: "selectedTools",
|
|
195
|
-
message: "Connect AI tools:",
|
|
206
|
+
message: "Connect AI tools (leave empty to skip):",
|
|
196
207
|
choices: [
|
|
197
208
|
{ title: "Claude Code", description: ".mcp.json + .claude/ docs", value: "claude" },
|
|
198
209
|
{ title: "Cursor", description: ".cursor/mcp.json", value: "cursor" },
|
|
199
210
|
{ title: "VS Code", description: ".vscode/mcp.json", value: "vscode" },
|
|
200
211
|
{ title: "Windsurf", description: "~/.codeium/windsurf/mcp_config.json", value: "windsurf" },
|
|
201
|
-
{ title: "
|
|
212
|
+
{ title: "Codex CLI", description: "~/.codex/config.toml", value: "codex" },
|
|
213
|
+
{ title: "Gemini CLI", description: "~/.gemini/settings.json", value: "gemini" }
|
|
202
214
|
],
|
|
203
|
-
hint: "space to select"
|
|
215
|
+
hint: "space to select, enter to confirm"
|
|
204
216
|
},
|
|
205
217
|
{ onCancel }
|
|
206
218
|
);
|
|
207
|
-
const aiTools = Array.isArray(selectedTools) ? selectedTools
|
|
219
|
+
const aiTools = Array.isArray(selectedTools) ? selectedTools : [];
|
|
208
220
|
let authMethod = "skip";
|
|
209
221
|
let keys = {};
|
|
210
222
|
if (aiTools.length > 0 && env !== "vanilla") {
|
|
@@ -244,103 +256,10 @@ async function promptUser(hasSdk, detectedEnv, detectedPm) {
|
|
|
244
256
|
// src/init.ts
|
|
245
257
|
import fs2 from "fs";
|
|
246
258
|
import path2 from "path";
|
|
259
|
+
import os from "os";
|
|
247
260
|
import { execSync } from "child_process";
|
|
248
261
|
import pc2 from "picocolors";
|
|
249
262
|
|
|
250
|
-
// src/templates.ts
|
|
251
|
-
function getClientTemplate(env, publishableKeyEnvVar) {
|
|
252
|
-
if (env === "nextjs") {
|
|
253
|
-
return `import { createClient } from '@01.software/sdk'
|
|
254
|
-
|
|
255
|
-
export const client = createClient({
|
|
256
|
-
publishableKey: process.env.${publishableKeyEnvVar}!,
|
|
257
|
-
})
|
|
258
|
-
`;
|
|
259
|
-
}
|
|
260
|
-
if (env === "react-cra") {
|
|
261
|
-
return `import { createClient } from '@01.software/sdk'
|
|
262
|
-
|
|
263
|
-
export const client = createClient({
|
|
264
|
-
publishableKey: process.env.${publishableKeyEnvVar}!,
|
|
265
|
-
})
|
|
266
|
-
`;
|
|
267
|
-
}
|
|
268
|
-
if (env === "vanilla") {
|
|
269
|
-
return `import { createClient } from '@01.software/sdk'
|
|
270
|
-
|
|
271
|
-
// Replace 'YOUR_PUBLISHABLE_KEY' with your actual publishable key from the 01.software console
|
|
272
|
-
export const client = createClient({
|
|
273
|
-
publishableKey: 'YOUR_PUBLISHABLE_KEY',
|
|
274
|
-
})
|
|
275
|
-
`;
|
|
276
|
-
}
|
|
277
|
-
return `import { createClient } from '@01.software/sdk'
|
|
278
|
-
|
|
279
|
-
export const client = createClient({
|
|
280
|
-
publishableKey: import.meta.env.${publishableKeyEnvVar},
|
|
281
|
-
})
|
|
282
|
-
`;
|
|
283
|
-
}
|
|
284
|
-
function getQueryProviderTemplate(env) {
|
|
285
|
-
const useClientDirective = env === "nextjs" ? "'use client'\n\n" : "";
|
|
286
|
-
return `${useClientDirective}import { QueryClientProvider } from '@tanstack/react-query'
|
|
287
|
-
import { client } from './client'
|
|
288
|
-
|
|
289
|
-
export function QueryProvider({ children }: { children: React.ReactNode }) {
|
|
290
|
-
return (
|
|
291
|
-
<QueryClientProvider client={client.queryClient}>
|
|
292
|
-
{children}
|
|
293
|
-
</QueryClientProvider>
|
|
294
|
-
)
|
|
295
|
-
}
|
|
296
|
-
`;
|
|
297
|
-
}
|
|
298
|
-
function getServerTemplate(env, publishableKeyEnvVar, secretKeyEnvVar) {
|
|
299
|
-
if (env === "edge") {
|
|
300
|
-
return `import { createServerClient } from '@01.software/sdk'
|
|
301
|
-
|
|
302
|
-
// Edge runtime: pass your env bindings here
|
|
303
|
-
// e.g. Cloudflare Workers: use env.SOFTWARE_PUBLISHABLE_KEY from the handler context
|
|
304
|
-
// e.g. Vercel Edge: use process.env.${publishableKeyEnvVar}
|
|
305
|
-
export function createEdgeClient(publishableKey: string, secretKey: string) {
|
|
306
|
-
return createServerClient({ publishableKey, secretKey })
|
|
307
|
-
}
|
|
308
|
-
`;
|
|
309
|
-
}
|
|
310
|
-
return `import { createServerClient } from '@01.software/sdk'
|
|
311
|
-
|
|
312
|
-
export const serverClient = createServerClient({
|
|
313
|
-
publishableKey: process.env.${publishableKeyEnvVar}!,
|
|
314
|
-
secretKey: process.env.${secretKeyEnvVar}!,
|
|
315
|
-
})
|
|
316
|
-
`;
|
|
317
|
-
}
|
|
318
|
-
function getEnvContent(publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar) {
|
|
319
|
-
let content = `
|
|
320
|
-
# 01.software
|
|
321
|
-
${publishableKeyEnvVar}=${publishableKey}
|
|
322
|
-
`;
|
|
323
|
-
if (secretKeyEnvVar) {
|
|
324
|
-
content += `${secretKeyEnvVar}=${secretKey}
|
|
325
|
-
`;
|
|
326
|
-
}
|
|
327
|
-
return content;
|
|
328
|
-
}
|
|
329
|
-
function getMcpServerEntry(apiKey) {
|
|
330
|
-
return {
|
|
331
|
-
type: "http",
|
|
332
|
-
url: "https://mcp.01.software/mcp",
|
|
333
|
-
headers: { "x-api-key": apiKey }
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
function getMcpConfigTemplate(apiKey) {
|
|
337
|
-
return JSON.stringify(
|
|
338
|
-
{ mcpServers: { "01software": getMcpServerEntry(apiKey) } },
|
|
339
|
-
null,
|
|
340
|
-
2
|
|
341
|
-
) + "\n";
|
|
342
|
-
}
|
|
343
|
-
|
|
344
263
|
// src/browser-auth.ts
|
|
345
264
|
import { randomBytes } from "crypto";
|
|
346
265
|
import { createServer } from "http";
|
|
@@ -354,7 +273,7 @@ function escapeHtml(s) {
|
|
|
354
273
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
355
274
|
}
|
|
356
275
|
function openBrowser(url) {
|
|
357
|
-
const
|
|
276
|
+
const os2 = platform();
|
|
358
277
|
const onError = () => {
|
|
359
278
|
console.log(
|
|
360
279
|
pc.yellow(
|
|
@@ -363,12 +282,12 @@ ${url}`
|
|
|
363
282
|
)
|
|
364
283
|
);
|
|
365
284
|
};
|
|
366
|
-
if (
|
|
285
|
+
if (os2 === "win32") {
|
|
367
286
|
exec(`start "" "${url}"`, (err) => {
|
|
368
287
|
if (err) onError();
|
|
369
288
|
});
|
|
370
289
|
} else {
|
|
371
|
-
const cmd =
|
|
290
|
+
const cmd = os2 === "darwin" ? "open" : "xdg-open";
|
|
372
291
|
execFile(cmd, [url], (err) => {
|
|
373
292
|
if (err) onError();
|
|
374
293
|
});
|
|
@@ -400,6 +319,7 @@ async function startBrowserAuth(options) {
|
|
|
400
319
|
"Access-Control-Allow-Origin": webUrl,
|
|
401
320
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
402
321
|
"Access-Control-Allow-Headers": "Content-Type",
|
|
322
|
+
"Access-Control-Allow-Private-Network": "true",
|
|
403
323
|
"Access-Control-Max-Age": "600",
|
|
404
324
|
Vary: "Origin"
|
|
405
325
|
};
|
|
@@ -535,71 +455,55 @@ async function init(cwd, info, answers) {
|
|
|
535
455
|
const wantsReactQuery = needsReactQuery(env);
|
|
536
456
|
const deps = ["@01.software/sdk"];
|
|
537
457
|
if (wantsReactQuery) deps.push("@tanstack/react-query");
|
|
458
|
+
const addCmd = buildAddCmd(packageManager, hasPnpmWorkspace(cwd), deps);
|
|
459
|
+
let installFailed = false;
|
|
538
460
|
console.log(pc2.dim(` Installing ${deps.join(" and ")}...`));
|
|
539
461
|
const wsPatched = packageManager === "pnpm" && patchPnpmWorkspace(cwd);
|
|
540
|
-
const pkgs = deps.join(" ");
|
|
541
|
-
const pnpmFlag = hasPnpmWorkspace(cwd) ? " -w" : "";
|
|
542
|
-
const addCmd = packageManager === "pnpm" ? `pnpm add${pnpmFlag} ${pkgs}` : packageManager === "yarn" ? `yarn add ${pkgs}` : packageManager === "bun" ? `bun add ${pkgs}` : `npm install ${pkgs}`;
|
|
543
462
|
try {
|
|
544
463
|
execSync(addCmd, { cwd, stdio: "pipe" });
|
|
464
|
+
console.log(pc2.green(" Installed"), deps.join(", "));
|
|
545
465
|
} catch (error) {
|
|
466
|
+
installFailed = true;
|
|
546
467
|
const err = error;
|
|
547
468
|
const msg = String(err.stderr || "").trim() || String(err.stdout || "").trim() || String(error);
|
|
548
|
-
console.log(pc2.
|
|
549
|
-
|
|
550
|
-
|
|
469
|
+
console.log(pc2.yellow(" Install failed \u2014 continuing with scaffolding"));
|
|
470
|
+
const firstLines = msg.split("\n").slice(0, 3).map((l) => ` ${l}`).join("\n");
|
|
471
|
+
if (firstLines) console.log(pc2.dim(firstLines));
|
|
472
|
+
console.log(pc2.dim(` Run manually: ${addCmd}`));
|
|
551
473
|
} finally {
|
|
552
474
|
if (wsPatched) restorePnpmWorkspace(cwd);
|
|
553
475
|
}
|
|
554
476
|
const libDir = path2.join(baseDir, "lib", "software");
|
|
555
477
|
fs2.mkdirSync(libDir, { recursive: true });
|
|
556
478
|
if (wantsClient) {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
console.log(pc2.green(" Created"), relativePath(cwd, clientPath));
|
|
563
|
-
}
|
|
479
|
+
writeFileIfAbsent(
|
|
480
|
+
cwd,
|
|
481
|
+
path2.join(libDir, "client.ts"),
|
|
482
|
+
getClientTemplate(env, publishableKeyEnvVar)
|
|
483
|
+
);
|
|
564
484
|
}
|
|
565
485
|
if (wantsReactQuery) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
console.log(pc2.green(" Created"), relativePath(cwd, queryProviderPath));
|
|
572
|
-
}
|
|
486
|
+
writeFileIfAbsent(
|
|
487
|
+
cwd,
|
|
488
|
+
path2.join(libDir, "query-provider.tsx"),
|
|
489
|
+
getQueryProviderTemplate(env)
|
|
490
|
+
);
|
|
573
491
|
}
|
|
574
492
|
if (wantsServer) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
console.log(pc2.green(" Created"), relativePath(cwd, serverPath));
|
|
581
|
-
}
|
|
493
|
+
writeFileIfAbsent(
|
|
494
|
+
cwd,
|
|
495
|
+
path2.join(libDir, "server.ts"),
|
|
496
|
+
getServerTemplate(env, publishableKeyEnvVar, SECRET_KEY_ENV_VAR)
|
|
497
|
+
);
|
|
582
498
|
}
|
|
583
499
|
if (env !== "vanilla" && env !== "edge" && answers.authMethod !== "browser") {
|
|
584
|
-
|
|
585
|
-
|
|
500
|
+
writeEnv(
|
|
501
|
+
cwd,
|
|
586
502
|
answers.publishableKey || "",
|
|
587
503
|
answers.secretKey || "",
|
|
588
504
|
publishableKeyEnvVar,
|
|
589
505
|
wantsServer ? SECRET_KEY_ENV_VAR : null
|
|
590
506
|
);
|
|
591
|
-
if (fs2.existsSync(envPath)) {
|
|
592
|
-
const existing = fs2.readFileSync(envPath, "utf-8");
|
|
593
|
-
if (existing.includes(publishableKeyEnvVar)) {
|
|
594
|
-
console.log(pc2.yellow(" Skipped"), ".env", pc2.dim("(keys already present)"));
|
|
595
|
-
} else {
|
|
596
|
-
fs2.appendFileSync(envPath, envContent);
|
|
597
|
-
console.log(pc2.green(" Updated"), ".env");
|
|
598
|
-
}
|
|
599
|
-
} else {
|
|
600
|
-
fs2.writeFileSync(envPath, envContent.trimStart());
|
|
601
|
-
console.log(pc2.green(" Created"), ".env");
|
|
602
|
-
}
|
|
603
507
|
}
|
|
604
508
|
let publishableKey = answers.publishableKey;
|
|
605
509
|
let secretKey = answers.secretKey;
|
|
@@ -612,23 +516,14 @@ async function init(cwd, info, answers) {
|
|
|
612
516
|
secretKey = creds.secretKey;
|
|
613
517
|
tenantName = creds.tenantName;
|
|
614
518
|
if (env !== "vanilla" && env !== "edge" && publishableKey) {
|
|
615
|
-
|
|
616
|
-
|
|
519
|
+
writeEnv(
|
|
520
|
+
cwd,
|
|
617
521
|
publishableKey,
|
|
618
522
|
secretKey,
|
|
619
523
|
publishableKeyEnvVar,
|
|
620
|
-
wantsServer ? SECRET_KEY_ENV_VAR : null
|
|
524
|
+
wantsServer ? SECRET_KEY_ENV_VAR : null,
|
|
525
|
+
true
|
|
621
526
|
);
|
|
622
|
-
if (fs2.existsSync(envPath)) {
|
|
623
|
-
const existing = fs2.readFileSync(envPath, "utf-8");
|
|
624
|
-
if (!existing.includes(publishableKeyEnvVar)) {
|
|
625
|
-
fs2.appendFileSync(envPath, envContent);
|
|
626
|
-
console.log(pc2.green(" Updated"), ".env", pc2.dim("(added API keys)"));
|
|
627
|
-
}
|
|
628
|
-
} else {
|
|
629
|
-
fs2.writeFileSync(envPath, envContent.trimStart());
|
|
630
|
-
console.log(pc2.green(" Created"), ".env");
|
|
631
|
-
}
|
|
632
527
|
}
|
|
633
528
|
} catch (err) {
|
|
634
529
|
console.log(
|
|
@@ -647,63 +542,147 @@ async function init(cwd, info, answers) {
|
|
|
647
542
|
await writeClaudeDocs(cwd, publishableKey, secretKey, tenantName);
|
|
648
543
|
}
|
|
649
544
|
}
|
|
545
|
+
return { installFailed, installCmd: addCmd };
|
|
650
546
|
}
|
|
651
|
-
function
|
|
652
|
-
|
|
653
|
-
|
|
547
|
+
function buildAddCmd(pm, hasPnpmWs, deps) {
|
|
548
|
+
const pkgs = deps.join(" ");
|
|
549
|
+
switch (pm) {
|
|
550
|
+
case "pnpm":
|
|
551
|
+
return hasPnpmWs ? `pnpm add -w ${pkgs}` : `pnpm add ${pkgs}`;
|
|
552
|
+
case "yarn":
|
|
553
|
+
return `yarn add ${pkgs}`;
|
|
554
|
+
case "bun":
|
|
555
|
+
return `bun add ${pkgs}`;
|
|
556
|
+
default:
|
|
557
|
+
return `npm install ${pkgs}`;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
function writeFileIfAbsent(cwd, filePath, content) {
|
|
561
|
+
if (fs2.existsSync(filePath)) {
|
|
562
|
+
console.log(pc2.yellow(" Skipped"), relativePath(cwd, filePath), pc2.dim("(already exists)"));
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
fs2.writeFileSync(filePath, content);
|
|
566
|
+
console.log(pc2.green(" Created"), relativePath(cwd, filePath));
|
|
567
|
+
}
|
|
568
|
+
function writeEnv(cwd, publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar, afterBrowserAuth = false) {
|
|
569
|
+
const envPath = path2.join(cwd, ".env");
|
|
570
|
+
const envContent = getEnvContent(publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar);
|
|
571
|
+
if (fs2.existsSync(envPath)) {
|
|
572
|
+
const existing = fs2.readFileSync(envPath, "utf-8");
|
|
573
|
+
if (existing.includes(publishableKeyEnvVar)) {
|
|
574
|
+
if (!afterBrowserAuth) {
|
|
575
|
+
console.log(pc2.yellow(" Skipped"), ".env", pc2.dim("(keys already present)"));
|
|
576
|
+
}
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
fs2.appendFileSync(envPath, envContent);
|
|
580
|
+
console.log(
|
|
581
|
+
pc2.green(" Updated"),
|
|
582
|
+
".env",
|
|
583
|
+
afterBrowserAuth ? pc2.dim("(added API keys)") : ""
|
|
584
|
+
);
|
|
585
|
+
} else {
|
|
586
|
+
fs2.writeFileSync(envPath, envContent.trimStart());
|
|
587
|
+
console.log(pc2.green(" Created"), ".env");
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function resolveMcpLocation(tool, cwd) {
|
|
591
|
+
const home = os.homedir();
|
|
654
592
|
switch (tool) {
|
|
655
593
|
case "claude":
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
594
|
+
return {
|
|
595
|
+
kind: "json",
|
|
596
|
+
absolutePath: path2.join(cwd, ".mcp.json"),
|
|
597
|
+
displayPath: ".mcp.json",
|
|
598
|
+
gitignoreEntry: ".mcp.json"
|
|
599
|
+
};
|
|
659
600
|
case "cursor":
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
601
|
+
return {
|
|
602
|
+
kind: "json",
|
|
603
|
+
absolutePath: path2.join(cwd, ".cursor", "mcp.json"),
|
|
604
|
+
displayPath: ".cursor/mcp.json",
|
|
605
|
+
gitignoreEntry: ".cursor/mcp.json"
|
|
606
|
+
};
|
|
664
607
|
case "vscode":
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
608
|
+
return {
|
|
609
|
+
kind: "json",
|
|
610
|
+
absolutePath: path2.join(cwd, ".vscode", "mcp.json"),
|
|
611
|
+
displayPath: ".vscode/mcp.json",
|
|
612
|
+
gitignoreEntry: ".vscode/mcp.json"
|
|
613
|
+
};
|
|
669
614
|
case "windsurf": {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
configPath = path2.join(home, ".codeium", "windsurf", "mcp_config.json");
|
|
676
|
-
displayPath = configPath;
|
|
677
|
-
fs2.mkdirSync(path2.dirname(configPath), { recursive: true });
|
|
678
|
-
break;
|
|
615
|
+
if (!home) return null;
|
|
616
|
+
const p = path2.join(home, ".codeium", "windsurf", "mcp_config.json");
|
|
617
|
+
return { kind: "json", absolutePath: p, displayPath: p, gitignoreEntry: null };
|
|
679
618
|
}
|
|
680
|
-
|
|
681
|
-
return;
|
|
619
|
+
case "codex": {
|
|
620
|
+
if (!home) return null;
|
|
621
|
+
const p = path2.join(home, ".codex", "config.toml");
|
|
622
|
+
return { kind: "toml", absolutePath: p, displayPath: p, gitignoreEntry: null };
|
|
623
|
+
}
|
|
624
|
+
case "gemini": {
|
|
625
|
+
if (!home) return null;
|
|
626
|
+
const p = path2.join(home, ".gemini", "settings.json");
|
|
627
|
+
return { kind: "json", absolutePath: p, displayPath: p, gitignoreEntry: null };
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function writeMcpConfig(tool, cwd, apiKey) {
|
|
632
|
+
const loc = resolveMcpLocation(tool, cwd);
|
|
633
|
+
if (!loc) {
|
|
634
|
+
console.log(pc2.yellow(` Skipped ${tool}`), pc2.dim("(HOME not set)"));
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
fs2.mkdirSync(path2.dirname(loc.absolutePath), { recursive: true });
|
|
638
|
+
if (loc.kind === "json") {
|
|
639
|
+
writeJsonMcp(loc, apiKey);
|
|
640
|
+
} else {
|
|
641
|
+
writeTomlMcp(loc, apiKey);
|
|
682
642
|
}
|
|
683
|
-
|
|
643
|
+
}
|
|
644
|
+
function writeJsonMcp(loc, apiKey) {
|
|
645
|
+
if (fs2.existsSync(loc.absolutePath)) {
|
|
684
646
|
try {
|
|
685
|
-
const existing = JSON.parse(fs2.readFileSync(
|
|
647
|
+
const existing = JSON.parse(fs2.readFileSync(loc.absolutePath, "utf-8"));
|
|
686
648
|
if (existing.mcpServers?.["01software"]) {
|
|
687
|
-
console.log(pc2.yellow(" Skipped"), displayPath, pc2.dim("(01software already configured)"));
|
|
649
|
+
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(01software already configured)"));
|
|
688
650
|
return;
|
|
689
651
|
}
|
|
690
652
|
existing.mcpServers = existing.mcpServers || {};
|
|
691
653
|
existing.mcpServers["01software"] = getMcpServerEntry(apiKey);
|
|
692
|
-
fs2.writeFileSync(
|
|
693
|
-
console.log(pc2.green(" Updated"), displayPath);
|
|
654
|
+
fs2.writeFileSync(loc.absolutePath, JSON.stringify(existing, null, 2) + "\n");
|
|
655
|
+
console.log(pc2.green(" Updated"), loc.displayPath);
|
|
694
656
|
} catch {
|
|
695
|
-
console.log(pc2.yellow(" Skipped"), displayPath, pc2.dim("(could not parse existing file)"));
|
|
657
|
+
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(could not parse existing file)"));
|
|
696
658
|
}
|
|
697
659
|
} else {
|
|
698
|
-
fs2.writeFileSync(
|
|
699
|
-
console.log(pc2.green(" Created"), displayPath);
|
|
660
|
+
fs2.writeFileSync(loc.absolutePath, getMcpConfigTemplate(apiKey));
|
|
661
|
+
console.log(pc2.green(" Created"), loc.displayPath);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
function writeTomlMcp(loc, apiKey) {
|
|
665
|
+
const section = getCodexMcpTomlSection(apiKey);
|
|
666
|
+
if (fs2.existsSync(loc.absolutePath)) {
|
|
667
|
+
const existing = fs2.readFileSync(loc.absolutePath, "utf-8");
|
|
668
|
+
if (existing.includes(CODEX_MCP_SECTION_MARKER)) {
|
|
669
|
+
console.log(pc2.yellow(" Skipped"), loc.displayPath, pc2.dim("(01software already configured)"));
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
const sep = existing.endsWith("\n") ? "" : "\n";
|
|
673
|
+
fs2.appendFileSync(loc.absolutePath, sep + section);
|
|
674
|
+
console.log(pc2.green(" Updated"), loc.displayPath);
|
|
675
|
+
} else {
|
|
676
|
+
fs2.writeFileSync(loc.absolutePath, section.trimStart());
|
|
677
|
+
console.log(pc2.green(" Created"), loc.displayPath);
|
|
700
678
|
}
|
|
701
679
|
}
|
|
702
680
|
function addToGitignore(cwd, tools) {
|
|
703
681
|
const entries = [];
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
682
|
+
for (const tool of tools) {
|
|
683
|
+
const loc = resolveMcpLocation(tool, cwd);
|
|
684
|
+
if (loc?.gitignoreEntry) entries.push(loc.gitignoreEntry);
|
|
685
|
+
}
|
|
707
686
|
if (entries.length === 0) return;
|
|
708
687
|
const gitignorePath = path2.join(cwd, ".gitignore");
|
|
709
688
|
const existing = fs2.existsSync(gitignorePath) ? fs2.readFileSync(gitignorePath, "utf-8") : "";
|
|
@@ -830,7 +809,7 @@ async function main() {
|
|
|
830
809
|
console.log(pc3.dim(" Initialize 01.software SDK in your project"));
|
|
831
810
|
console.log();
|
|
832
811
|
const info = detectProject(cwd);
|
|
833
|
-
if (!info.hasPackageJson) {
|
|
812
|
+
if (!info.hasPackageJson || info.parseError) {
|
|
834
813
|
if (info.parseError) {
|
|
835
814
|
console.log(pc3.red(" Could not parse package.json (invalid JSON)."));
|
|
836
815
|
console.log(pc3.dim(" Fix the syntax error and try again."));
|
|
@@ -862,7 +841,7 @@ async function main() {
|
|
|
862
841
|
const resolvedPm = info.packageManager ?? answers.packageManager ?? "npm";
|
|
863
842
|
const resolvedInfo = { ...info, packageManager: resolvedPm };
|
|
864
843
|
console.log();
|
|
865
|
-
await init(cwd, resolvedInfo, answers);
|
|
844
|
+
const result = await init(cwd, resolvedInfo, answers);
|
|
866
845
|
const env = answers.env;
|
|
867
846
|
const run = resolvedPm === "npm" ? "npm run" : resolvedPm;
|
|
868
847
|
console.log();
|
|
@@ -870,6 +849,11 @@ async function main() {
|
|
|
870
849
|
console.log();
|
|
871
850
|
console.log(" Next steps:");
|
|
872
851
|
console.log();
|
|
852
|
+
if (result.installFailed) {
|
|
853
|
+
console.log(pc3.yellow(" Install the SDK manually:"));
|
|
854
|
+
console.log(pc3.cyan(` ${result.installCmd}`));
|
|
855
|
+
console.log();
|
|
856
|
+
}
|
|
873
857
|
if (env === "nextjs") {
|
|
874
858
|
console.log(pc3.dim(" Add QueryProvider to your root layout:"));
|
|
875
859
|
console.log();
|
|
@@ -908,7 +892,7 @@ async function main() {
|
|
|
908
892
|
console.log();
|
|
909
893
|
}
|
|
910
894
|
if (answers.aiTools.length > 0 && (!answers.publishableKey || !answers.secretKey)) {
|
|
911
|
-
console.log(pc3.dim(" Update
|
|
895
|
+
console.log(pc3.dim(" Update MCP config x-api-key with your sk01_... token"));
|
|
912
896
|
console.log();
|
|
913
897
|
}
|
|
914
898
|
if (env !== "vanilla") {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/detect.ts","../src/prompts.ts","../src/init.ts","../src/templates.ts","../src/browser-auth.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({ publishableKey: 'YOUR_PUBLISHABLE_KEY' })\n\n 3. Server client (SSR / loaders / endpoints):\n import { createServerClient } from '@01.software/sdk'\n export const serverClient = createServerClient({\n publishableKey: process.env.PUBLIC_SOFTWARE_PUBLISHABLE_KEY!, // prefix varies by framework\n secretKey: process.env.SOFTWARE_SECRET_KEY!,\n })\n\n 4. Docs: https://01.software/docs/developers/sdk/client\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_PUBLISHABLE_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.PUBLISHABLE_KEY, env.SECRET_KEY)'))\n console.log()\n }\n\n const missingPublishableKey = env !== 'vanilla' && !answers.publishableKey\n const missingSecretKey = (env === 'nextjs' || env === 'node') && !answers.secretKey\n if (missingPublishableKey || missingSecretKey) {\n console.log(pc.dim(' Update .env with your API keys'))\n console.log()\n }\n if (answers.aiTools.length > 0 && (!answers.publishableKey || !answers.secretKey)) {\n console.log(pc.dim(' Update .mcp.json x-api-key with your sk01_... token'))\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 publishable key */\nexport function getPublishableKeyEnvVar(env: ProjectEnv): string {\n switch (env) {\n case 'nextjs':\n return 'NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY'\n case 'react-vite':\n return 'VITE_SOFTWARE_PUBLISHABLE_KEY'\n case 'react-cra':\n return 'REACT_APP_SOFTWARE_PUBLISHABLE_KEY'\n default:\n return 'SOFTWARE_PUBLISHABLE_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 publishableKey: 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, publishableKey: '', 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: 'publishableKey',\n message: 'Publishable 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 publishableKey: authMethod === 'browser' ? '' : (keys.publishableKey ?? ''),\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 getPublishableKeyEnvVar,\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 publishableKeyEnvVar = getPublishableKeyEnvVar(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, publishableKeyEnvVar))\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, publishableKeyEnvVar, 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.publishableKey || '',\n answers.secretKey || '',\n publishableKeyEnvVar,\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(publishableKeyEnvVar)) {\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 publishableKey = answers.publishableKey\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 publishableKey = creds.publishableKey\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' && publishableKey) {\n const envPath = path.join(cwd, '.env')\n const envContent = getEnvContent(\n publishableKey,\n secretKey,\n publishableKeyEnvVar,\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(publishableKeyEnvVar)) {\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 // secretKey is an opaque sk01_/pat01_ bearer token — pass it as x-api-key directly.\n const apiKey = secretKey || '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, publishableKey, 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 publishableKey: 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 (publishableKey && secretKey) {\n const fetched = await fetchTenantContext(publishableKey, 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 softwareDir = path.join(claudeDir, '01software')\n const skillsDir = path.join(claudeDir, 'skills')\n fs.mkdirSync(softwareDir, { recursive: true })\n fs.mkdirSync(skillsDir, { recursive: true })\n\n // context.md — always overwrite so re-running init refreshes tenant data\n const contextPath = path.join(softwareDir, 'context.md')\n const contextExists = fs.existsSync(contextPath)\n fs.writeFileSync(contextPath, generateClaudeMd(ctx))\n console.log(pc.green(contextExists ? ' Updated' : ' Created'), '.claude/01software/context.md')\n\n // CLAUDE.md — append @import line (idempotent, never overwrites user content)\n const claudeMdPath = path.join(claudeDir, 'CLAUDE.md')\n const importLine = '@.claude/01software/context.md'\n if (!fs.existsSync(claudeMdPath)) {\n fs.writeFileSync(claudeMdPath, importLine + '\\n')\n console.log(pc.green(' Created'), '.claude/CLAUDE.md')\n } else {\n const existing = fs.readFileSync(claudeMdPath, 'utf-8')\n if (!existing.includes(importLine)) {\n const prefix = existing.endsWith('\\n') ? '\\n' : '\\n\\n'\n fs.appendFileSync(claudeMdPath, prefix + importLine + '\\n')\n console.log(pc.green(' Updated'), '.claude/CLAUDE.md', pc.dim('(added @import)'))\n } else {\n console.log(pc.yellow(' Skipped'), '.claude/CLAUDE.md', pc.dim('(@import already present)'))\n }\n }\n\n // Skill files — skip-if-exists\n for (const { dirName, content } of getSkillFiles()) {\n const skillDir = path.join(skillsDir, dirName)\n const skillPath = path.join(skillDir, 'SKILL.md')\n if (!fs.existsSync(skillPath)) {\n fs.mkdirSync(skillDir, { recursive: true })\n fs.writeFileSync(skillPath, content)\n console.log(pc.green(' Created'), `.claude/skills/${dirName}/SKILL.md`)\n } else {\n console.log(pc.yellow(' Skipped'), `.claude/skills/${dirName}/SKILL.md`, pc.dim('(already exists)'))\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, publishableKeyEnvVar: string): string {\n if (env === 'nextjs') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n publishableKey: process.env.${publishableKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'react-cra') {\n return `import { createClient } from '@01.software/sdk'\n\nexport const client = createClient({\n publishableKey: process.env.${publishableKeyEnvVar}!,\n})\n`\n }\n\n if (env === 'vanilla') {\n return `import { createClient } from '@01.software/sdk'\n\n// Replace 'YOUR_PUBLISHABLE_KEY' with your actual publishable key from the 01.software console\nexport const client = createClient({\n publishableKey: 'YOUR_PUBLISHABLE_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 publishableKey: import.meta.env.${publishableKeyEnvVar},\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 publishableKeyEnvVar: 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_PUBLISHABLE_KEY from the handler context\n// e.g. Vercel Edge: use process.env.${publishableKeyEnvVar}\nexport function createEdgeClient(publishableKey: string, secretKey: string) {\n return createServerClient({ publishableKey, secretKey })\n}\n`\n }\n\n return `import { createServerClient } from '@01.software/sdk'\n\nexport const serverClient = createServerClient({\n publishableKey: process.env.${publishableKeyEnvVar}!,\n secretKey: process.env.${secretKeyEnvVar}!,\n})\n`\n}\n\n// ── Env file content ─────────────────────────────────────────────────\n\nexport function getEnvContent(\n publishableKey: string,\n secretKey: string,\n publishableKeyEnvVar: string,\n secretKeyEnvVar: string | null,\n): string {\n let content = `\\n# 01.software\\n${publishableKeyEnvVar}=${publishableKey}\\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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\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<{ publishableKey: 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 corsHeaders: Record<string, string> = {\n 'Access-Control-Allow-Origin': webUrl,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n 'Access-Control-Max-Age': '600',\n Vary: 'Origin',\n }\n\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400, corsHeaders).end()\n return\n }\n\n const url = new URL(req.url, `http://localhost`)\n\n if (url.pathname !== '/callback') {\n res.writeHead(404, corsHeaders).end()\n return\n }\n\n // CORS preflight\n if (req.method === 'OPTIONS') {\n res.writeHead(200, corsHeaders).end()\n return\n }\n\n // GET /callback — error display only (e.g. auth failed before POST)\n if (req.method === 'GET') {\n const error = url.searchParams.get('error')\n if (error) {\n res\n .writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Connection: 'close' })\n .end(ERROR_HTML(error))\n console.error(pc.red(`Login failed: ${error}`))\n cleanup(new Error(`Login failed: ${error}`))\n } else {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Connection: 'close' }).end(SUCCESS_HTML)\n }\n return\n }\n\n // POST /callback — credentials in JSON body\n if (req.method === 'POST') {\n // Validate Origin\n const origin = req.headers.origin\n if (!origin || origin !== webUrl) {\n res.writeHead(403, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Forbidden: invalid origin' }))\n return\n }\n\n let body = ''\n req.on('data', (chunk) => {\n body += chunk\n if (body.length > 64 * 1024) {\n res.writeHead(413, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Payload too large' }))\n req.destroy()\n }\n })\n req.on('end', () => {\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(body)\n } catch {\n res.writeHead(400, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Invalid JSON' }))\n return\n }\n\n const publishableKey = parsed.publishableKey\n const secretKey = parsed.secretKey\n const tenant = parsed.tenant\n const tenantIdParam = parsed.tenantId\n const receivedState = parsed.state\n\n if (receivedState !== state) {\n res.writeHead(403, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'State mismatch' }))\n console.error(pc.red('Login failed: state mismatch.'))\n cleanup(new Error('Login failed: state mismatch.'))\n return\n }\n\n if (\n typeof publishableKey !== 'string' ||\n typeof secretKey !== 'string' ||\n typeof tenant !== 'string'\n ) {\n res.writeHead(400, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Missing credentials' }))\n cleanup(new Error('Login failed: missing credentials.'))\n return\n }\n\n res.writeHead(200, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ success: true }))\n\n console.log(pc.green(`\\nLogged in successfully!`))\n console.log(pc.dim(`Tenant: ${tenant}`))\n\n cleanup(null, {\n publishableKey,\n secretKey,\n tenantName: tenant,\n ...(typeof tenantIdParam === 'string' ? { tenantId: tenantIdParam } : {}),\n })\n })\n return\n }\n\n res.writeHead(405, corsHeaders).end()\n })\n\n let timeout: ReturnType<typeof setTimeout>\n let completed = false\n\n function cleanup(\n err: Error | null,\n result?: { publishableKey: string; secretKey: string; tenantName: string; tenantId?: string },\n ) {\n if (completed) return\n completed = true\n clearTimeout(timeout)\n server.closeAllConnections?.()\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"],"mappings":"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","names":["pc","fs","path","pc","path","pc","fs","pc"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/detect.ts","../src/prompts.ts","../src/init.ts","../src/browser-auth.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({ publishableKey: 'YOUR_PUBLISHABLE_KEY' })\n\n 3. Server client (SSR / loaders / endpoints):\n import { createServerClient } from '@01.software/sdk'\n export const serverClient = createServerClient({\n publishableKey: process.env.PUBLIC_SOFTWARE_PUBLISHABLE_KEY!, // prefix varies by framework\n secretKey: process.env.SOFTWARE_SECRET_KEY!,\n })\n\n 4. Docs: https://01.software/docs/developers/sdk/client\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 || info.parseError) {\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 const result = 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 (result.installFailed) {\n console.log(pc.yellow(' Install the SDK manually:'))\n console.log(pc.cyan(` ${result.installCmd}`))\n console.log()\n }\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_PUBLISHABLE_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.PUBLISHABLE_KEY, env.SECRET_KEY)'))\n console.log()\n }\n\n const missingPublishableKey = env !== 'vanilla' && !answers.publishableKey\n const missingSecretKey = (env === 'nextjs' || env === 'node') && !answers.secretKey\n if (missingPublishableKey || missingSecretKey) {\n console.log(pc.dim(' Update .env with your API keys'))\n console.log()\n }\n if (answers.aiTools.length > 0 && (!answers.publishableKey || !answers.secretKey)) {\n console.log(pc.dim(' Update MCP config x-api-key with your sk01_... token'))\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 let parseError = 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: true, 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, parseError, 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 publishable key */\nexport function getPublishableKeyEnvVar(env: ProjectEnv): string {\n switch (env) {\n case 'nextjs':\n return 'NEXT_PUBLIC_SOFTWARE_PUBLISHABLE_KEY'\n case 'react-vite':\n return 'VITE_SOFTWARE_PUBLISHABLE_KEY'\n case 'react-cra':\n return 'REACT_APP_SOFTWARE_PUBLISHABLE_KEY'\n default:\n return 'SOFTWARE_PUBLISHABLE_KEY'\n }\n}\n","import prompts from 'prompts'\nimport type { PackageManager, ProjectEnv } from './detect'\n\nexport type AiTool =\n | 'claude'\n | 'cursor'\n | 'vscode'\n | 'windsurf'\n | 'codex'\n | 'gemini'\n\nexport type AuthMethod = 'browser' | 'manual' | 'skip'\n\nexport interface InitAnswers {\n env: ProjectEnv\n publishableKey: 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, publishableKey: '', 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: 'publishableKey',\n message: 'Publishable 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 (empty selection = skip)\n const { selectedTools } = await prompts(\n {\n type: 'multiselect',\n name: 'selectedTools',\n message: 'Connect AI tools (leave empty to skip):',\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: 'Codex CLI', description: '~/.codex/config.toml', value: 'codex' },\n { title: 'Gemini CLI', description: '~/.gemini/settings.json', value: 'gemini' },\n ],\n hint: 'space to select, enter to confirm',\n },\n { onCancel },\n )\n\n const aiTools: AiTool[] = Array.isArray(selectedTools) ? (selectedTools as AiTool[]) : []\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 publishableKey: authMethod === 'browser' ? '' : (keys.publishableKey ?? ''),\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 os from 'node:os'\nimport { execSync } from 'node:child_process'\nimport pc from 'picocolors'\nimport type { PackageManager, ProjectInfo } from './detect'\nimport {\n needsClient,\n needsServer,\n needsReactQuery,\n getPublishableKeyEnvVar,\n} from './detect'\nimport type { AiTool, InitAnswers } from './prompts'\nimport {\n getClientTemplate,\n getQueryProviderTemplate,\n getServerTemplate,\n getEnvContent,\n getMcpConfigTemplate,\n getMcpServerEntry,\n getCodexMcpTomlSection,\n CODEX_MCP_SECTION_MARKER,\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 interface InitResult {\n installFailed: boolean\n installCmd: string\n}\n\nexport async function init(\n cwd: string,\n info: ResolvedProjectInfo,\n answers: InitAnswers,\n): Promise<InitResult> {\n const { packageManager, srcDir } = info\n const env = answers.env\n const baseDir = srcDir ? path.join(cwd, 'src') : cwd\n\n const publishableKeyEnvVar = getPublishableKeyEnvVar(env)\n const wantsClient = needsClient(env)\n const wantsServer = needsServer(env)\n const wantsReactQuery = needsReactQuery(env)\n\n // 1. Install dependencies (best-effort — warn and continue on failure so\n // scaffolding, .env, and MCP config still happen)\n const deps = ['@01.software/sdk']\n if (wantsReactQuery) deps.push('@tanstack/react-query')\n\n const addCmd = buildAddCmd(packageManager, hasPnpmWorkspace(cwd), deps)\n let installFailed = false\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 try {\n execSync(addCmd, { cwd, stdio: 'pipe' })\n console.log(pc.green(' Installed'), deps.join(', '))\n } catch (error) {\n installFailed = true\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.yellow(' Install failed — continuing with scaffolding'))\n const firstLines = msg.split('\\n').slice(0, 3).map((l) => ` ${l}`).join('\\n')\n if (firstLines) console.log(pc.dim(firstLines))\n console.log(pc.dim(` Run manually: ${addCmd}`))\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 writeFileIfAbsent(\n cwd,\n path.join(libDir, 'client.ts'),\n getClientTemplate(env, publishableKeyEnvVar),\n )\n }\n\n // Query Provider (React)\n if (wantsReactQuery) {\n writeFileIfAbsent(\n cwd,\n path.join(libDir, 'query-provider.tsx'),\n getQueryProviderTemplate(env),\n )\n }\n\n // Server\n if (wantsServer) {\n writeFileIfAbsent(\n cwd,\n path.join(libDir, 'server.ts'),\n getServerTemplate(env, publishableKeyEnvVar, SECRET_KEY_ENV_VAR),\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 writeEnv(\n cwd,\n answers.publishableKey || '',\n answers.secretKey || '',\n publishableKeyEnvVar,\n wantsServer ? SECRET_KEY_ENV_VAR : null,\n )\n }\n\n // 4. Browser auth — get real credentials if user chose browser login\n let publishableKey = answers.publishableKey\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 publishableKey = creds.publishableKey\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' && publishableKey) {\n writeEnv(\n cwd,\n publishableKey,\n secretKey,\n publishableKeyEnvVar,\n wantsServer ? SECRET_KEY_ENV_VAR : null,\n true,\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 // secretKey is an opaque sk01_/pat01_ bearer token — pass it as x-api-key directly.\n const apiKey = secretKey || '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, publishableKey, secretKey, tenantName)\n }\n }\n\n return { installFailed, installCmd: addCmd }\n}\n\nfunction buildAddCmd(\n pm: PackageManager,\n hasPnpmWs: boolean,\n deps: string[],\n): string {\n const pkgs = deps.join(' ')\n switch (pm) {\n case 'pnpm':\n return hasPnpmWs ? `pnpm add -w ${pkgs}` : `pnpm add ${pkgs}`\n case 'yarn':\n return `yarn add ${pkgs}`\n case 'bun':\n return `bun add ${pkgs}`\n default:\n return `npm install ${pkgs}`\n }\n}\n\nfunction writeFileIfAbsent(cwd: string, filePath: string, content: string): void {\n if (fs.existsSync(filePath)) {\n console.log(pc.yellow(' Skipped'), relativePath(cwd, filePath), pc.dim('(already exists)'))\n return\n }\n fs.writeFileSync(filePath, content)\n console.log(pc.green(' Created'), relativePath(cwd, filePath))\n}\n\nfunction writeEnv(\n cwd: string,\n publishableKey: string,\n secretKey: string,\n publishableKeyEnvVar: string,\n secretKeyEnvVar: string | null,\n afterBrowserAuth = false,\n): void {\n const envPath = path.join(cwd, '.env')\n const envContent = getEnvContent(publishableKey, secretKey, publishableKeyEnvVar, secretKeyEnvVar)\n\n if (fs.existsSync(envPath)) {\n const existing = fs.readFileSync(envPath, 'utf-8')\n if (existing.includes(publishableKeyEnvVar)) {\n if (!afterBrowserAuth) {\n console.log(pc.yellow(' Skipped'), '.env', pc.dim('(keys already present)'))\n }\n return\n }\n fs.appendFileSync(envPath, envContent)\n console.log(\n pc.green(' Updated'),\n '.env',\n afterBrowserAuth ? pc.dim('(added API keys)') : '',\n )\n } else {\n fs.writeFileSync(envPath, envContent.trimStart())\n console.log(pc.green(' Created'), '.env')\n }\n}\n\n// ── MCP targets registry ─────────────────────────────────────────────\n\ntype McpFormat = 'json' | 'toml'\ninterface McpLocation {\n kind: McpFormat\n absolutePath: string\n displayPath: string\n gitignoreEntry: string | null // null = global path, not worth ignoring\n}\n\nfunction resolveMcpLocation(tool: AiTool, cwd: string): McpLocation | null {\n const home = os.homedir()\n\n switch (tool) {\n case 'claude':\n return {\n kind: 'json',\n absolutePath: path.join(cwd, '.mcp.json'),\n displayPath: '.mcp.json',\n gitignoreEntry: '.mcp.json',\n }\n case 'cursor':\n return {\n kind: 'json',\n absolutePath: path.join(cwd, '.cursor', 'mcp.json'),\n displayPath: '.cursor/mcp.json',\n gitignoreEntry: '.cursor/mcp.json',\n }\n case 'vscode':\n return {\n kind: 'json',\n absolutePath: path.join(cwd, '.vscode', 'mcp.json'),\n displayPath: '.vscode/mcp.json',\n gitignoreEntry: '.vscode/mcp.json',\n }\n case 'windsurf': {\n if (!home) return null\n const p = path.join(home, '.codeium', 'windsurf', 'mcp_config.json')\n return { kind: 'json', absolutePath: p, displayPath: p, gitignoreEntry: null }\n }\n case 'codex': {\n if (!home) return null\n const p = path.join(home, '.codex', 'config.toml')\n return { kind: 'toml', absolutePath: p, displayPath: p, gitignoreEntry: null }\n }\n case 'gemini': {\n if (!home) return null\n const p = path.join(home, '.gemini', 'settings.json')\n return { kind: 'json', absolutePath: p, displayPath: p, gitignoreEntry: null }\n }\n }\n}\n\nfunction writeMcpConfig(tool: AiTool, cwd: string, apiKey: string): void {\n const loc = resolveMcpLocation(tool, cwd)\n if (!loc) {\n console.log(pc.yellow(` Skipped ${tool}`), pc.dim('(HOME not set)'))\n return\n }\n\n fs.mkdirSync(path.dirname(loc.absolutePath), { recursive: true })\n\n if (loc.kind === 'json') {\n writeJsonMcp(loc, apiKey)\n } else {\n writeTomlMcp(loc, apiKey)\n }\n}\n\nfunction writeJsonMcp(loc: McpLocation, apiKey: string): void {\n if (fs.existsSync(loc.absolutePath)) {\n try {\n const existing = JSON.parse(fs.readFileSync(loc.absolutePath, 'utf-8'))\n if (existing.mcpServers?.['01software']) {\n console.log(pc.yellow(' Skipped'), loc.displayPath, pc.dim('(01software already configured)'))\n return\n }\n existing.mcpServers = existing.mcpServers || {}\n existing.mcpServers['01software'] = getMcpServerEntry(apiKey)\n fs.writeFileSync(loc.absolutePath, JSON.stringify(existing, null, 2) + '\\n')\n console.log(pc.green(' Updated'), loc.displayPath)\n } catch {\n console.log(pc.yellow(' Skipped'), loc.displayPath, pc.dim('(could not parse existing file)'))\n }\n } else {\n fs.writeFileSync(loc.absolutePath, getMcpConfigTemplate(apiKey))\n console.log(pc.green(' Created'), loc.displayPath)\n }\n}\n\nfunction writeTomlMcp(loc: McpLocation, apiKey: string): void {\n const section = getCodexMcpTomlSection(apiKey)\n if (fs.existsSync(loc.absolutePath)) {\n const existing = fs.readFileSync(loc.absolutePath, 'utf-8')\n if (existing.includes(CODEX_MCP_SECTION_MARKER)) {\n console.log(pc.yellow(' Skipped'), loc.displayPath, pc.dim('(01software already configured)'))\n return\n }\n const sep = existing.endsWith('\\n') ? '' : '\\n'\n fs.appendFileSync(loc.absolutePath, sep + section)\n console.log(pc.green(' Updated'), loc.displayPath)\n } else {\n fs.writeFileSync(loc.absolutePath, section.trimStart())\n console.log(pc.green(' Created'), loc.displayPath)\n }\n}\n\nfunction addToGitignore(cwd: string, tools: AiTool[]): void {\n const entries: string[] = []\n for (const tool of tools) {\n const loc = resolveMcpLocation(tool, cwd)\n if (loc?.gitignoreEntry) entries.push(loc.gitignoreEntry)\n }\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 publishableKey: 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 (publishableKey && secretKey) {\n const fetched = await fetchTenantContext(publishableKey, 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 softwareDir = path.join(claudeDir, '01software')\n const skillsDir = path.join(claudeDir, 'skills')\n fs.mkdirSync(softwareDir, { recursive: true })\n fs.mkdirSync(skillsDir, { recursive: true })\n\n // context.md — always overwrite so re-running init refreshes tenant data\n const contextPath = path.join(softwareDir, 'context.md')\n const contextExists = fs.existsSync(contextPath)\n fs.writeFileSync(contextPath, generateClaudeMd(ctx))\n console.log(pc.green(contextExists ? ' Updated' : ' Created'), '.claude/01software/context.md')\n\n // CLAUDE.md — append @import line (idempotent, never overwrites user content)\n const claudeMdPath = path.join(claudeDir, 'CLAUDE.md')\n const importLine = '@.claude/01software/context.md'\n if (!fs.existsSync(claudeMdPath)) {\n fs.writeFileSync(claudeMdPath, importLine + '\\n')\n console.log(pc.green(' Created'), '.claude/CLAUDE.md')\n } else {\n const existing = fs.readFileSync(claudeMdPath, 'utf-8')\n if (!existing.includes(importLine)) {\n const prefix = existing.endsWith('\\n') ? '\\n' : '\\n\\n'\n fs.appendFileSync(claudeMdPath, prefix + importLine + '\\n')\n console.log(pc.green(' Updated'), '.claude/CLAUDE.md', pc.dim('(added @import)'))\n } else {\n console.log(pc.yellow(' Skipped'), '.claude/CLAUDE.md', pc.dim('(@import already present)'))\n }\n }\n\n // Skill files — skip-if-exists\n for (const { dirName, content } of getSkillFiles()) {\n const skillDir = path.join(skillsDir, dirName)\n const skillPath = path.join(skillDir, 'SKILL.md')\n if (!fs.existsSync(skillPath)) {\n fs.mkdirSync(skillDir, { recursive: true })\n fs.writeFileSync(skillPath, content)\n console.log(pc.green(' Created'), `.claude/skills/${dirName}/SKILL.md`)\n } else {\n console.log(pc.yellow(' Skipped'), `.claude/skills/${dirName}/SKILL.md`, pc.dim('(already exists)'))\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 { 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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\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<{ publishableKey: 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 corsHeaders: Record<string, string> = {\n 'Access-Control-Allow-Origin': webUrl,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n 'Access-Control-Allow-Private-Network': 'true',\n 'Access-Control-Max-Age': '600',\n Vary: 'Origin',\n }\n\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400, corsHeaders).end()\n return\n }\n\n const url = new URL(req.url, `http://localhost`)\n\n if (url.pathname !== '/callback') {\n res.writeHead(404, corsHeaders).end()\n return\n }\n\n // CORS preflight\n if (req.method === 'OPTIONS') {\n res.writeHead(200, corsHeaders).end()\n return\n }\n\n // GET /callback — error display only (e.g. auth failed before POST)\n if (req.method === 'GET') {\n const error = url.searchParams.get('error')\n if (error) {\n res\n .writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Connection: 'close' })\n .end(ERROR_HTML(error))\n console.error(pc.red(`Login failed: ${error}`))\n cleanup(new Error(`Login failed: ${error}`))\n } else {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Connection: 'close' }).end(SUCCESS_HTML)\n }\n return\n }\n\n // POST /callback — credentials in JSON body\n if (req.method === 'POST') {\n // Validate Origin\n const origin = req.headers.origin\n if (!origin || origin !== webUrl) {\n res.writeHead(403, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Forbidden: invalid origin' }))\n return\n }\n\n let body = ''\n req.on('data', (chunk) => {\n body += chunk\n if (body.length > 64 * 1024) {\n res.writeHead(413, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Payload too large' }))\n req.destroy()\n }\n })\n req.on('end', () => {\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(body)\n } catch {\n res.writeHead(400, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Invalid JSON' }))\n return\n }\n\n const publishableKey = parsed.publishableKey\n const secretKey = parsed.secretKey\n const tenant = parsed.tenant\n const tenantIdParam = parsed.tenantId\n const receivedState = parsed.state\n\n if (receivedState !== state) {\n res.writeHead(403, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'State mismatch' }))\n console.error(pc.red('Login failed: state mismatch.'))\n cleanup(new Error('Login failed: state mismatch.'))\n return\n }\n\n if (\n typeof publishableKey !== 'string' ||\n typeof secretKey !== 'string' ||\n typeof tenant !== 'string'\n ) {\n res.writeHead(400, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ error: 'Missing credentials' }))\n cleanup(new Error('Login failed: missing credentials.'))\n return\n }\n\n res.writeHead(200, { ...corsHeaders, 'Content-Type': 'application/json' })\n .end(JSON.stringify({ success: true }))\n\n console.log(pc.green(`\\nLogged in successfully!`))\n console.log(pc.dim(`Tenant: ${tenant}`))\n\n cleanup(null, {\n publishableKey,\n secretKey,\n tenantName: tenant,\n ...(typeof tenantIdParam === 'string' ? { tenantId: tenantIdParam } : {}),\n })\n })\n return\n }\n\n res.writeHead(405, corsHeaders).end()\n })\n\n let timeout: ReturnType<typeof setTimeout>\n let completed = false\n\n function cleanup(\n err: Error | null,\n result?: { publishableKey: string; secretKey: string; tenantName: string; tenantId?: string },\n ) {\n if (completed) return\n completed = true\n clearTimeout(timeout)\n server.closeAllConnections?.()\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"],"mappings":"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","names":["pc","fs","path","pc","os","path","pc","fs","pc"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
CODEX_MCP_SECTION_MARKER,
|
|
4
|
+
getClientTemplate,
|
|
5
|
+
getCodexMcpTomlSection,
|
|
6
|
+
getEnvContent,
|
|
7
|
+
getMcpConfigTemplate,
|
|
8
|
+
getMcpServerEntry,
|
|
9
|
+
getQueryProviderTemplate,
|
|
10
|
+
getServerTemplate
|
|
11
|
+
} from "./chunk-OEAQV63E.js";
|
|
12
|
+
export {
|
|
13
|
+
CODEX_MCP_SECTION_MARKER,
|
|
14
|
+
getClientTemplate,
|
|
15
|
+
getCodexMcpTomlSection,
|
|
16
|
+
getEnvContent,
|
|
17
|
+
getMcpConfigTemplate,
|
|
18
|
+
getMcpServerEntry,
|
|
19
|
+
getQueryProviderTemplate,
|
|
20
|
+
getServerTemplate
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|