@gurulu/cli 1.0.0 → 1.0.1
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/bin.js +355 -14
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +355 -14
- package/dist/lib/detect.d.ts +27 -0
- package/dist/lib/detect.d.ts.map +1 -0
- package/dist/lib/detect.js +106 -0
- package/dist/lib/exec-install.d.ts +21 -0
- package/dist/lib/exec-install.d.ts.map +1 -0
- package/dist/lib/install-plan.d.ts +25 -0
- package/dist/lib/install-plan.d.ts.map +1 -0
- package/dist/lib/install-plan.js +161 -0
- package/package.json +13 -2
package/dist/bin.js
CHANGED
|
@@ -25055,8 +25055,324 @@ var doctorCmd = defineCommand({
|
|
|
25055
25055
|
});
|
|
25056
25056
|
|
|
25057
25057
|
// src/commands/init.ts
|
|
25058
|
-
import { existsSync as
|
|
25059
|
-
import { dirname as
|
|
25058
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
25059
|
+
import { dirname as dirname3 } from "node:path";
|
|
25060
|
+
|
|
25061
|
+
// src/lib/detect.ts
|
|
25062
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
25063
|
+
import { dirname as dirname2, join as join4, parse } from "node:path";
|
|
25064
|
+
function readPackageJson(dir) {
|
|
25065
|
+
const p = join4(dir, "package.json");
|
|
25066
|
+
if (!existsSync4(p))
|
|
25067
|
+
return null;
|
|
25068
|
+
try {
|
|
25069
|
+
return JSON.parse(readFileSync4(p, "utf8"));
|
|
25070
|
+
} catch {
|
|
25071
|
+
return null;
|
|
25072
|
+
}
|
|
25073
|
+
}
|
|
25074
|
+
function hasDep(pkg, name) {
|
|
25075
|
+
if (!pkg)
|
|
25076
|
+
return false;
|
|
25077
|
+
return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);
|
|
25078
|
+
}
|
|
25079
|
+
function detectPackageManager(dir) {
|
|
25080
|
+
const root = parse(dir).root;
|
|
25081
|
+
let cur = dir;
|
|
25082
|
+
for (let i2 = 0;i2 < 6; i2++) {
|
|
25083
|
+
if (existsSync4(join4(cur, "bun.lock")) || existsSync4(join4(cur, "bun.lockb")))
|
|
25084
|
+
return "bun";
|
|
25085
|
+
if (existsSync4(join4(cur, "pnpm-lock.yaml")))
|
|
25086
|
+
return "pnpm";
|
|
25087
|
+
if (existsSync4(join4(cur, "yarn.lock")))
|
|
25088
|
+
return "yarn";
|
|
25089
|
+
if (existsSync4(join4(cur, "package-lock.json")))
|
|
25090
|
+
return "npm";
|
|
25091
|
+
if (cur === root)
|
|
25092
|
+
break;
|
|
25093
|
+
const parent = dirname2(cur);
|
|
25094
|
+
if (parent === cur)
|
|
25095
|
+
break;
|
|
25096
|
+
cur = parent;
|
|
25097
|
+
}
|
|
25098
|
+
return "npm";
|
|
25099
|
+
}
|
|
25100
|
+
function detectFramework(pkg, dir) {
|
|
25101
|
+
if (!pkg)
|
|
25102
|
+
return "unknown";
|
|
25103
|
+
if (hasDep(pkg, "next"))
|
|
25104
|
+
return "next";
|
|
25105
|
+
if (hasDep(pkg, "nuxt"))
|
|
25106
|
+
return "nuxt";
|
|
25107
|
+
if (hasDep(pkg, "@sveltejs/kit") || hasDep(pkg, "svelte"))
|
|
25108
|
+
return "svelte";
|
|
25109
|
+
if (hasDep(pkg, "astro"))
|
|
25110
|
+
return "astro";
|
|
25111
|
+
if (hasDep(pkg, "vite") && (hasDep(pkg, "vue") || hasDep(pkg, "react")))
|
|
25112
|
+
return "vite";
|
|
25113
|
+
if (hasDep(pkg, "vue"))
|
|
25114
|
+
return "vue";
|
|
25115
|
+
if (hasDep(pkg, "react"))
|
|
25116
|
+
return "react";
|
|
25117
|
+
if (hasDep(pkg, "hono"))
|
|
25118
|
+
return "hono";
|
|
25119
|
+
if (hasDep(pkg, "fastify"))
|
|
25120
|
+
return "fastify";
|
|
25121
|
+
if (hasDep(pkg, "express"))
|
|
25122
|
+
return "express";
|
|
25123
|
+
if (hasDep(pkg, "koa"))
|
|
25124
|
+
return "koa";
|
|
25125
|
+
if (existsSync4(join4(dir, "server.js")) || existsSync4(join4(dir, "server.ts")))
|
|
25126
|
+
return "node-server";
|
|
25127
|
+
return "unknown";
|
|
25128
|
+
}
|
|
25129
|
+
function frameworkRuntime(fw) {
|
|
25130
|
+
switch (fw) {
|
|
25131
|
+
case "next":
|
|
25132
|
+
case "react":
|
|
25133
|
+
case "vue":
|
|
25134
|
+
case "nuxt":
|
|
25135
|
+
case "svelte":
|
|
25136
|
+
case "astro":
|
|
25137
|
+
case "vite":
|
|
25138
|
+
return "browser";
|
|
25139
|
+
case "express":
|
|
25140
|
+
case "fastify":
|
|
25141
|
+
case "hono":
|
|
25142
|
+
case "koa":
|
|
25143
|
+
case "node-server":
|
|
25144
|
+
return "node";
|
|
25145
|
+
default:
|
|
25146
|
+
return "unknown";
|
|
25147
|
+
}
|
|
25148
|
+
}
|
|
25149
|
+
function detectProject(dir) {
|
|
25150
|
+
const pkg = readPackageJson(dir);
|
|
25151
|
+
const framework = detectFramework(pkg, dir);
|
|
25152
|
+
return {
|
|
25153
|
+
dir,
|
|
25154
|
+
hasPackageJson: pkg !== null,
|
|
25155
|
+
framework,
|
|
25156
|
+
runtime: frameworkRuntime(framework),
|
|
25157
|
+
packageManager: detectPackageManager(dir),
|
|
25158
|
+
packageJson: pkg
|
|
25159
|
+
};
|
|
25160
|
+
}
|
|
25161
|
+
|
|
25162
|
+
// src/lib/exec-install.ts
|
|
25163
|
+
import { spawn } from "node:child_process";
|
|
25164
|
+
async function execInstall(plan, opts) {
|
|
25165
|
+
const [bin, ...args] = plan.installCommand.split(/\s+/);
|
|
25166
|
+
if (!bin) {
|
|
25167
|
+
return {
|
|
25168
|
+
ok: false,
|
|
25169
|
+
exitCode: null,
|
|
25170
|
+
durationMs: 0,
|
|
25171
|
+
command: plan.installCommand,
|
|
25172
|
+
stderr: "empty install command"
|
|
25173
|
+
};
|
|
25174
|
+
}
|
|
25175
|
+
const started = Date.now();
|
|
25176
|
+
return new Promise((resolve) => {
|
|
25177
|
+
const child = spawn(bin, args, {
|
|
25178
|
+
cwd: opts.cwd,
|
|
25179
|
+
stdio: opts.silent ? ["ignore", "pipe", "pipe"] : ["inherit", "inherit", "pipe"],
|
|
25180
|
+
shell: process.platform === "win32"
|
|
25181
|
+
});
|
|
25182
|
+
let stderr = "";
|
|
25183
|
+
if (child.stderr) {
|
|
25184
|
+
child.stderr.on("data", (chunk) => {
|
|
25185
|
+
const text = chunk.toString("utf8");
|
|
25186
|
+
stderr += text;
|
|
25187
|
+
if (!opts.silent) {
|
|
25188
|
+
process.stderr.write(text);
|
|
25189
|
+
}
|
|
25190
|
+
});
|
|
25191
|
+
}
|
|
25192
|
+
const timeout = setTimeout(() => {
|
|
25193
|
+
child.kill("SIGTERM");
|
|
25194
|
+
}, opts.timeoutMs ?? 120000);
|
|
25195
|
+
child.on("error", (err) => {
|
|
25196
|
+
clearTimeout(timeout);
|
|
25197
|
+
resolve({
|
|
25198
|
+
ok: false,
|
|
25199
|
+
exitCode: null,
|
|
25200
|
+
durationMs: Date.now() - started,
|
|
25201
|
+
command: plan.installCommand,
|
|
25202
|
+
stderr: err.message
|
|
25203
|
+
});
|
|
25204
|
+
});
|
|
25205
|
+
child.on("close", (code) => {
|
|
25206
|
+
clearTimeout(timeout);
|
|
25207
|
+
resolve({
|
|
25208
|
+
ok: code === 0,
|
|
25209
|
+
exitCode: code,
|
|
25210
|
+
durationMs: Date.now() - started,
|
|
25211
|
+
command: plan.installCommand,
|
|
25212
|
+
...stderr ? { stderr } : {}
|
|
25213
|
+
});
|
|
25214
|
+
});
|
|
25215
|
+
});
|
|
25216
|
+
}
|
|
25217
|
+
|
|
25218
|
+
// src/lib/install-plan.ts
|
|
25219
|
+
function installCmdFor(pm, pkg) {
|
|
25220
|
+
switch (pm) {
|
|
25221
|
+
case "bun":
|
|
25222
|
+
return `bun add ${pkg}`;
|
|
25223
|
+
case "pnpm":
|
|
25224
|
+
return `pnpm add ${pkg}`;
|
|
25225
|
+
case "yarn":
|
|
25226
|
+
return `yarn add ${pkg}`;
|
|
25227
|
+
default:
|
|
25228
|
+
return `npm install ${pkg}`;
|
|
25229
|
+
}
|
|
25230
|
+
}
|
|
25231
|
+
function sdkFor(framework) {
|
|
25232
|
+
switch (framework) {
|
|
25233
|
+
case "express":
|
|
25234
|
+
case "fastify":
|
|
25235
|
+
case "hono":
|
|
25236
|
+
case "koa":
|
|
25237
|
+
case "node-server":
|
|
25238
|
+
return "@gurulu/node";
|
|
25239
|
+
default:
|
|
25240
|
+
return "@gurulu/web";
|
|
25241
|
+
}
|
|
25242
|
+
}
|
|
25243
|
+
function snippetWeb(workspaceKey) {
|
|
25244
|
+
return `import { createGurulu } from '@gurulu/web';
|
|
25245
|
+
|
|
25246
|
+
const gurulu = createGurulu();
|
|
25247
|
+
gurulu.init({ workspace: '${workspaceKey}' });`;
|
|
25248
|
+
}
|
|
25249
|
+
function snippetNext(workspaceKey) {
|
|
25250
|
+
return `// app/layout.tsx (or pages/_app.tsx)
|
|
25251
|
+
'use client';
|
|
25252
|
+
import { useEffect } from 'react';
|
|
25253
|
+
import { createGurulu } from '@gurulu/web';
|
|
25254
|
+
|
|
25255
|
+
const gurulu = createGurulu();
|
|
25256
|
+
|
|
25257
|
+
export function GuruluProvider({ children }: { children: React.ReactNode }) {
|
|
25258
|
+
useEffect(() => {
|
|
25259
|
+
gurulu.init({ workspace: '${workspaceKey}' });
|
|
25260
|
+
}, []);
|
|
25261
|
+
return <>{children}</>;
|
|
25262
|
+
}`;
|
|
25263
|
+
}
|
|
25264
|
+
function snippetNode(workspaceKey) {
|
|
25265
|
+
return `import { createGurulu } from '@gurulu/node';
|
|
25266
|
+
|
|
25267
|
+
const gurulu = createGurulu({
|
|
25268
|
+
workspace: '${workspaceKey}',
|
|
25269
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
25270
|
+
});
|
|
25271
|
+
|
|
25272
|
+
// In your handler:
|
|
25273
|
+
await gurulu.track('purchase.completed', {
|
|
25274
|
+
user_id: 'u_42',
|
|
25275
|
+
order_id: 'o_123',
|
|
25276
|
+
total: 49.99,
|
|
25277
|
+
});`;
|
|
25278
|
+
}
|
|
25279
|
+
function snippetExpress(workspaceKey) {
|
|
25280
|
+
return `import express from 'express';
|
|
25281
|
+
import { guruluMiddleware } from '@gurulu/node/middleware/express';
|
|
25282
|
+
|
|
25283
|
+
const app = express();
|
|
25284
|
+
app.use(guruluMiddleware({
|
|
25285
|
+
workspace: '${workspaceKey}',
|
|
25286
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
25287
|
+
}));`;
|
|
25288
|
+
}
|
|
25289
|
+
function snippetHono(workspaceKey) {
|
|
25290
|
+
return `import { Hono } from 'hono';
|
|
25291
|
+
import { createGurulu } from '@gurulu/node';
|
|
25292
|
+
|
|
25293
|
+
const gurulu = createGurulu({
|
|
25294
|
+
workspace: '${workspaceKey}',
|
|
25295
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
25296
|
+
});
|
|
25297
|
+
|
|
25298
|
+
const app = new Hono();
|
|
25299
|
+
app.post('/checkout/complete', async (c) => {
|
|
25300
|
+
await gurulu.track('purchase.completed', await c.req.json());
|
|
25301
|
+
return c.json({ ok: true });
|
|
25302
|
+
});`;
|
|
25303
|
+
}
|
|
25304
|
+
function placementHintFor(framework) {
|
|
25305
|
+
switch (framework) {
|
|
25306
|
+
case "next":
|
|
25307
|
+
return "Add the GuruluProvider to app/layout.tsx (App Router) or pages/_app.tsx (Pages Router) and wrap children.";
|
|
25308
|
+
case "nuxt":
|
|
25309
|
+
return "Add to plugins/gurulu.client.ts and register in nuxt.config.ts.";
|
|
25310
|
+
case "svelte":
|
|
25311
|
+
return "Add to src/routes/+layout.svelte inside onMount().";
|
|
25312
|
+
case "astro":
|
|
25313
|
+
return "Add to src/layouts/Base.astro inside a <script> tag (or use a hydrated component).";
|
|
25314
|
+
case "vite":
|
|
25315
|
+
case "react":
|
|
25316
|
+
case "vue":
|
|
25317
|
+
return "Add to src/main.ts (or your entry file) before mounting the app.";
|
|
25318
|
+
case "express":
|
|
25319
|
+
return "Register guruluMiddleware before your route handlers in your app entry file.";
|
|
25320
|
+
case "fastify":
|
|
25321
|
+
return "Register the Gurulu plugin via fastify.register() before route definitions.";
|
|
25322
|
+
case "hono":
|
|
25323
|
+
return "Initialize the SDK at the top of your app file; call track() inside route handlers.";
|
|
25324
|
+
case "koa":
|
|
25325
|
+
return "Add as Koa middleware (app.use) before your routes.";
|
|
25326
|
+
case "node-server":
|
|
25327
|
+
return "Initialize the SDK at startup; call track() from your handlers.";
|
|
25328
|
+
default:
|
|
25329
|
+
return "Initialize the SDK at your app entry point.";
|
|
25330
|
+
}
|
|
25331
|
+
}
|
|
25332
|
+
function initSnippetFor(framework, sdk, workspaceKey) {
|
|
25333
|
+
if (sdk === "@gurulu/node") {
|
|
25334
|
+
if (framework === "express")
|
|
25335
|
+
return snippetExpress(workspaceKey);
|
|
25336
|
+
if (framework === "hono")
|
|
25337
|
+
return snippetHono(workspaceKey);
|
|
25338
|
+
return snippetNode(workspaceKey);
|
|
25339
|
+
}
|
|
25340
|
+
if (framework === "next")
|
|
25341
|
+
return snippetNext(workspaceKey);
|
|
25342
|
+
return snippetWeb(workspaceKey);
|
|
25343
|
+
}
|
|
25344
|
+
function envKeysFor(sdk, framework) {
|
|
25345
|
+
if (sdk === "@gurulu/node") {
|
|
25346
|
+
return [
|
|
25347
|
+
{
|
|
25348
|
+
key: "GURULU_API_KEY",
|
|
25349
|
+
example: "sk_live_xxxxxxxxxxxx",
|
|
25350
|
+
required: true
|
|
25351
|
+
}
|
|
25352
|
+
];
|
|
25353
|
+
}
|
|
25354
|
+
const envKey = framework === "next" ? "NEXT_PUBLIC_GURULU_WORKSPACE" : "VITE_GURULU_WORKSPACE";
|
|
25355
|
+
return [
|
|
25356
|
+
{
|
|
25357
|
+
key: envKey,
|
|
25358
|
+
example: "pk_live_xxxxxxxxxxxx",
|
|
25359
|
+
required: false
|
|
25360
|
+
}
|
|
25361
|
+
];
|
|
25362
|
+
}
|
|
25363
|
+
function buildInstallPlan(detected, ctx = {}) {
|
|
25364
|
+
const sdk = sdkFor(detected.framework);
|
|
25365
|
+
const workspaceKey = ctx.writeKey ?? "pk_xxxxxxxxxxxx";
|
|
25366
|
+
return {
|
|
25367
|
+
sdk,
|
|
25368
|
+
packageManager: detected.packageManager,
|
|
25369
|
+
installCommand: installCmdFor(detected.packageManager, sdk),
|
|
25370
|
+
initSnippet: initSnippetFor(detected.framework, sdk, workspaceKey),
|
|
25371
|
+
envKeys: envKeysFor(sdk, detected.framework),
|
|
25372
|
+
placementHint: placementHintFor(detected.framework),
|
|
25373
|
+
framework: detected.framework
|
|
25374
|
+
};
|
|
25375
|
+
}
|
|
25060
25376
|
|
|
25061
25377
|
// src/commands/pull.ts
|
|
25062
25378
|
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
@@ -25206,7 +25522,9 @@ var initCmd = defineCommand({
|
|
|
25206
25522
|
args: {
|
|
25207
25523
|
workspace: { type: "string", description: "Workspace ID (uuid)" },
|
|
25208
25524
|
endpoint: { type: "string", description: "API endpoint", default: DEFAULT_ENDPOINT },
|
|
25209
|
-
sdk: { type: "string", description: "SDK preference (web|node|
|
|
25525
|
+
sdk: { type: "string", description: "SDK preference (web|node|auto)", default: "auto" },
|
|
25526
|
+
"write-key": { type: "string", description: "Workspace write key (pk_xxx) for init snippet" },
|
|
25527
|
+
"no-install": { type: "boolean", description: "Skip SDK install (config files only)" },
|
|
25210
25528
|
"no-pull": { type: "boolean", description: "Skip first registry pull" },
|
|
25211
25529
|
force: { type: "boolean", description: "Overwrite existing config" }
|
|
25212
25530
|
},
|
|
@@ -25222,40 +25540,63 @@ var initCmd = defineCommand({
|
|
|
25222
25540
|
console.error("[gurulu] --workspace <uuid> required (workspace ID from dashboard)");
|
|
25223
25541
|
process.exit(1);
|
|
25224
25542
|
}
|
|
25225
|
-
const
|
|
25226
|
-
if (!["web", "node", "
|
|
25227
|
-
console.error(`[gurulu] invalid --sdk: ${
|
|
25543
|
+
const sdkArg = String(args.sdk ?? "auto");
|
|
25544
|
+
if (!["web", "node", "auto"].includes(sdkArg)) {
|
|
25545
|
+
console.error(`[gurulu] invalid --sdk: ${sdkArg} (use web|node|auto)`);
|
|
25228
25546
|
process.exit(1);
|
|
25229
25547
|
}
|
|
25548
|
+
const detected = detectProject(cwd);
|
|
25549
|
+
const writeKey = String(args["write-key"] ?? "").trim() || "pk_xxxxxxxxxxxx";
|
|
25550
|
+
const plan = buildInstallPlan(detected, { writeKey, workspaceId });
|
|
25551
|
+
const effectiveSdkPref = sdkArg === "auto" ? plan.sdk === "@gurulu/node" ? "node" : "web" : sdkArg;
|
|
25230
25552
|
const config = {
|
|
25231
25553
|
workspace_id: workspaceId,
|
|
25232
25554
|
endpoint: String(args.endpoint),
|
|
25233
|
-
sdk_preference:
|
|
25555
|
+
sdk_preference: effectiveSdkPref,
|
|
25234
25556
|
registry_path: ".gurulu/event-registry.json",
|
|
25235
25557
|
generated_path: ".gurulu/generated.d.ts",
|
|
25236
25558
|
manifest_lock_path: ".gurulu/manifest.lock",
|
|
25237
25559
|
auto_pull_on_init: true
|
|
25238
25560
|
};
|
|
25239
25561
|
writeProjectConfig(config, cwd);
|
|
25240
|
-
const dir =
|
|
25241
|
-
if (!
|
|
25562
|
+
const dir = dirname3(projectConfigPath(cwd));
|
|
25563
|
+
if (!existsSync5(dir))
|
|
25242
25564
|
mkdirSync2(dir, { recursive: true });
|
|
25243
|
-
if (!
|
|
25565
|
+
if (!existsSync5(projectRegistryPath(cwd))) {
|
|
25244
25566
|
writeFileSync3(projectRegistryPath(cwd), `{}
|
|
25245
25567
|
`, "utf-8");
|
|
25246
25568
|
}
|
|
25247
|
-
if (!
|
|
25569
|
+
if (!existsSync5(projectGeneratedPath(cwd))) {
|
|
25248
25570
|
writeFileSync3(projectGeneratedPath(cwd), "// Run `gurulu pull` to populate typed events.\n", "utf-8");
|
|
25249
25571
|
}
|
|
25250
|
-
if (!
|
|
25572
|
+
if (!existsSync5(projectManifestLockPath(cwd))) {
|
|
25251
25573
|
writeFileSync3(projectManifestLockPath(cwd), `0.0.0
|
|
25252
25574
|
`, "utf-8");
|
|
25253
25575
|
}
|
|
25254
25576
|
console.log(`[gurulu] initialized ${projectConfigPath(cwd)}`);
|
|
25577
|
+
if (args["no-install"]) {
|
|
25578
|
+
console.log(`[gurulu] skipping SDK install (--no-install).`);
|
|
25579
|
+
console.log(` manual: ${plan.installCommand}`);
|
|
25580
|
+
} else if (!detected.hasPackageJson) {
|
|
25581
|
+
console.log(`[gurulu] no package.json found in ${cwd} — skipping SDK install.`);
|
|
25582
|
+
console.log(` use the script tag: <script src="https://cdn.gurulu.io/t.js" data-workspace="${writeKey}"></script>`);
|
|
25583
|
+
} else {
|
|
25584
|
+
console.log(`[gurulu] detected ${detected.framework} (${detected.packageManager}) — installing ${plan.sdk}…`);
|
|
25585
|
+
const result = await execInstall(plan, { cwd });
|
|
25586
|
+
if (result.ok) {
|
|
25587
|
+
console.log(`[gurulu] ${plan.sdk} installed (${(result.durationMs / 1000).toFixed(1)}s).`);
|
|
25588
|
+
} else {
|
|
25589
|
+
console.warn(`[gurulu] install failed (exit ${result.exitCode ?? "n/a"}) — run manually: ${plan.installCommand}`);
|
|
25590
|
+
}
|
|
25591
|
+
}
|
|
25592
|
+
console.log("");
|
|
25255
25593
|
console.log("[gurulu] next steps:");
|
|
25256
25594
|
console.log(" 1. gurulu login — authenticate (or store API key)");
|
|
25257
25595
|
console.log(" 2. gurulu pull — fetch registry + code-gen");
|
|
25258
|
-
console.log(
|
|
25596
|
+
console.log(` 3. ${plan.placementHint}`);
|
|
25597
|
+
console.log("");
|
|
25598
|
+
console.log("[gurulu] init snippet:");
|
|
25599
|
+
console.log(plan.initSnippet);
|
|
25259
25600
|
if (!args["no-pull"]) {
|
|
25260
25601
|
try {
|
|
25261
25602
|
await runPull({ cwd });
|
|
@@ -25365,7 +25706,7 @@ var pushCmd = defineCommand({
|
|
|
25365
25706
|
});
|
|
25366
25707
|
|
|
25367
25708
|
// src/index.ts
|
|
25368
|
-
var VERSION = "1.0.
|
|
25709
|
+
var VERSION = "1.0.1";
|
|
25369
25710
|
var mcpCmd = defineCommand({
|
|
25370
25711
|
meta: {
|
|
25371
25712
|
name: "mcp",
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -13,6 +13,14 @@ export declare const initCmd: import("citty").CommandDef<{
|
|
|
13
13
|
description: string;
|
|
14
14
|
default: string;
|
|
15
15
|
};
|
|
16
|
+
'write-key': {
|
|
17
|
+
type: "string";
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
'no-install': {
|
|
21
|
+
type: "boolean";
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
16
24
|
'no-pull': {
|
|
17
25
|
type: "boolean";
|
|
18
26
|
description: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgJlB,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -24632,8 +24632,324 @@ var doctorCmd = defineCommand({
|
|
|
24632
24632
|
});
|
|
24633
24633
|
|
|
24634
24634
|
// src/commands/init.ts
|
|
24635
|
-
import { existsSync as
|
|
24636
|
-
import { dirname as
|
|
24635
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
24636
|
+
import { dirname as dirname3 } from "node:path";
|
|
24637
|
+
|
|
24638
|
+
// src/lib/detect.ts
|
|
24639
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
24640
|
+
import { dirname as dirname2, join as join4, parse } from "node:path";
|
|
24641
|
+
function readPackageJson(dir) {
|
|
24642
|
+
const p = join4(dir, "package.json");
|
|
24643
|
+
if (!existsSync4(p))
|
|
24644
|
+
return null;
|
|
24645
|
+
try {
|
|
24646
|
+
return JSON.parse(readFileSync4(p, "utf8"));
|
|
24647
|
+
} catch {
|
|
24648
|
+
return null;
|
|
24649
|
+
}
|
|
24650
|
+
}
|
|
24651
|
+
function hasDep(pkg, name) {
|
|
24652
|
+
if (!pkg)
|
|
24653
|
+
return false;
|
|
24654
|
+
return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);
|
|
24655
|
+
}
|
|
24656
|
+
function detectPackageManager(dir) {
|
|
24657
|
+
const root = parse(dir).root;
|
|
24658
|
+
let cur = dir;
|
|
24659
|
+
for (let i2 = 0;i2 < 6; i2++) {
|
|
24660
|
+
if (existsSync4(join4(cur, "bun.lock")) || existsSync4(join4(cur, "bun.lockb")))
|
|
24661
|
+
return "bun";
|
|
24662
|
+
if (existsSync4(join4(cur, "pnpm-lock.yaml")))
|
|
24663
|
+
return "pnpm";
|
|
24664
|
+
if (existsSync4(join4(cur, "yarn.lock")))
|
|
24665
|
+
return "yarn";
|
|
24666
|
+
if (existsSync4(join4(cur, "package-lock.json")))
|
|
24667
|
+
return "npm";
|
|
24668
|
+
if (cur === root)
|
|
24669
|
+
break;
|
|
24670
|
+
const parent = dirname2(cur);
|
|
24671
|
+
if (parent === cur)
|
|
24672
|
+
break;
|
|
24673
|
+
cur = parent;
|
|
24674
|
+
}
|
|
24675
|
+
return "npm";
|
|
24676
|
+
}
|
|
24677
|
+
function detectFramework(pkg, dir) {
|
|
24678
|
+
if (!pkg)
|
|
24679
|
+
return "unknown";
|
|
24680
|
+
if (hasDep(pkg, "next"))
|
|
24681
|
+
return "next";
|
|
24682
|
+
if (hasDep(pkg, "nuxt"))
|
|
24683
|
+
return "nuxt";
|
|
24684
|
+
if (hasDep(pkg, "@sveltejs/kit") || hasDep(pkg, "svelte"))
|
|
24685
|
+
return "svelte";
|
|
24686
|
+
if (hasDep(pkg, "astro"))
|
|
24687
|
+
return "astro";
|
|
24688
|
+
if (hasDep(pkg, "vite") && (hasDep(pkg, "vue") || hasDep(pkg, "react")))
|
|
24689
|
+
return "vite";
|
|
24690
|
+
if (hasDep(pkg, "vue"))
|
|
24691
|
+
return "vue";
|
|
24692
|
+
if (hasDep(pkg, "react"))
|
|
24693
|
+
return "react";
|
|
24694
|
+
if (hasDep(pkg, "hono"))
|
|
24695
|
+
return "hono";
|
|
24696
|
+
if (hasDep(pkg, "fastify"))
|
|
24697
|
+
return "fastify";
|
|
24698
|
+
if (hasDep(pkg, "express"))
|
|
24699
|
+
return "express";
|
|
24700
|
+
if (hasDep(pkg, "koa"))
|
|
24701
|
+
return "koa";
|
|
24702
|
+
if (existsSync4(join4(dir, "server.js")) || existsSync4(join4(dir, "server.ts")))
|
|
24703
|
+
return "node-server";
|
|
24704
|
+
return "unknown";
|
|
24705
|
+
}
|
|
24706
|
+
function frameworkRuntime(fw) {
|
|
24707
|
+
switch (fw) {
|
|
24708
|
+
case "next":
|
|
24709
|
+
case "react":
|
|
24710
|
+
case "vue":
|
|
24711
|
+
case "nuxt":
|
|
24712
|
+
case "svelte":
|
|
24713
|
+
case "astro":
|
|
24714
|
+
case "vite":
|
|
24715
|
+
return "browser";
|
|
24716
|
+
case "express":
|
|
24717
|
+
case "fastify":
|
|
24718
|
+
case "hono":
|
|
24719
|
+
case "koa":
|
|
24720
|
+
case "node-server":
|
|
24721
|
+
return "node";
|
|
24722
|
+
default:
|
|
24723
|
+
return "unknown";
|
|
24724
|
+
}
|
|
24725
|
+
}
|
|
24726
|
+
function detectProject(dir) {
|
|
24727
|
+
const pkg = readPackageJson(dir);
|
|
24728
|
+
const framework = detectFramework(pkg, dir);
|
|
24729
|
+
return {
|
|
24730
|
+
dir,
|
|
24731
|
+
hasPackageJson: pkg !== null,
|
|
24732
|
+
framework,
|
|
24733
|
+
runtime: frameworkRuntime(framework),
|
|
24734
|
+
packageManager: detectPackageManager(dir),
|
|
24735
|
+
packageJson: pkg
|
|
24736
|
+
};
|
|
24737
|
+
}
|
|
24738
|
+
|
|
24739
|
+
// src/lib/exec-install.ts
|
|
24740
|
+
import { spawn } from "node:child_process";
|
|
24741
|
+
async function execInstall(plan, opts) {
|
|
24742
|
+
const [bin, ...args] = plan.installCommand.split(/\s+/);
|
|
24743
|
+
if (!bin) {
|
|
24744
|
+
return {
|
|
24745
|
+
ok: false,
|
|
24746
|
+
exitCode: null,
|
|
24747
|
+
durationMs: 0,
|
|
24748
|
+
command: plan.installCommand,
|
|
24749
|
+
stderr: "empty install command"
|
|
24750
|
+
};
|
|
24751
|
+
}
|
|
24752
|
+
const started = Date.now();
|
|
24753
|
+
return new Promise((resolve) => {
|
|
24754
|
+
const child = spawn(bin, args, {
|
|
24755
|
+
cwd: opts.cwd,
|
|
24756
|
+
stdio: opts.silent ? ["ignore", "pipe", "pipe"] : ["inherit", "inherit", "pipe"],
|
|
24757
|
+
shell: process.platform === "win32"
|
|
24758
|
+
});
|
|
24759
|
+
let stderr = "";
|
|
24760
|
+
if (child.stderr) {
|
|
24761
|
+
child.stderr.on("data", (chunk) => {
|
|
24762
|
+
const text = chunk.toString("utf8");
|
|
24763
|
+
stderr += text;
|
|
24764
|
+
if (!opts.silent) {
|
|
24765
|
+
process.stderr.write(text);
|
|
24766
|
+
}
|
|
24767
|
+
});
|
|
24768
|
+
}
|
|
24769
|
+
const timeout = setTimeout(() => {
|
|
24770
|
+
child.kill("SIGTERM");
|
|
24771
|
+
}, opts.timeoutMs ?? 120000);
|
|
24772
|
+
child.on("error", (err) => {
|
|
24773
|
+
clearTimeout(timeout);
|
|
24774
|
+
resolve({
|
|
24775
|
+
ok: false,
|
|
24776
|
+
exitCode: null,
|
|
24777
|
+
durationMs: Date.now() - started,
|
|
24778
|
+
command: plan.installCommand,
|
|
24779
|
+
stderr: err.message
|
|
24780
|
+
});
|
|
24781
|
+
});
|
|
24782
|
+
child.on("close", (code) => {
|
|
24783
|
+
clearTimeout(timeout);
|
|
24784
|
+
resolve({
|
|
24785
|
+
ok: code === 0,
|
|
24786
|
+
exitCode: code,
|
|
24787
|
+
durationMs: Date.now() - started,
|
|
24788
|
+
command: plan.installCommand,
|
|
24789
|
+
...stderr ? { stderr } : {}
|
|
24790
|
+
});
|
|
24791
|
+
});
|
|
24792
|
+
});
|
|
24793
|
+
}
|
|
24794
|
+
|
|
24795
|
+
// src/lib/install-plan.ts
|
|
24796
|
+
function installCmdFor(pm, pkg) {
|
|
24797
|
+
switch (pm) {
|
|
24798
|
+
case "bun":
|
|
24799
|
+
return `bun add ${pkg}`;
|
|
24800
|
+
case "pnpm":
|
|
24801
|
+
return `pnpm add ${pkg}`;
|
|
24802
|
+
case "yarn":
|
|
24803
|
+
return `yarn add ${pkg}`;
|
|
24804
|
+
default:
|
|
24805
|
+
return `npm install ${pkg}`;
|
|
24806
|
+
}
|
|
24807
|
+
}
|
|
24808
|
+
function sdkFor(framework) {
|
|
24809
|
+
switch (framework) {
|
|
24810
|
+
case "express":
|
|
24811
|
+
case "fastify":
|
|
24812
|
+
case "hono":
|
|
24813
|
+
case "koa":
|
|
24814
|
+
case "node-server":
|
|
24815
|
+
return "@gurulu/node";
|
|
24816
|
+
default:
|
|
24817
|
+
return "@gurulu/web";
|
|
24818
|
+
}
|
|
24819
|
+
}
|
|
24820
|
+
function snippetWeb(workspaceKey) {
|
|
24821
|
+
return `import { createGurulu } from '@gurulu/web';
|
|
24822
|
+
|
|
24823
|
+
const gurulu = createGurulu();
|
|
24824
|
+
gurulu.init({ workspace: '${workspaceKey}' });`;
|
|
24825
|
+
}
|
|
24826
|
+
function snippetNext(workspaceKey) {
|
|
24827
|
+
return `// app/layout.tsx (or pages/_app.tsx)
|
|
24828
|
+
'use client';
|
|
24829
|
+
import { useEffect } from 'react';
|
|
24830
|
+
import { createGurulu } from '@gurulu/web';
|
|
24831
|
+
|
|
24832
|
+
const gurulu = createGurulu();
|
|
24833
|
+
|
|
24834
|
+
export function GuruluProvider({ children }: { children: React.ReactNode }) {
|
|
24835
|
+
useEffect(() => {
|
|
24836
|
+
gurulu.init({ workspace: '${workspaceKey}' });
|
|
24837
|
+
}, []);
|
|
24838
|
+
return <>{children}</>;
|
|
24839
|
+
}`;
|
|
24840
|
+
}
|
|
24841
|
+
function snippetNode(workspaceKey) {
|
|
24842
|
+
return `import { createGurulu } from '@gurulu/node';
|
|
24843
|
+
|
|
24844
|
+
const gurulu = createGurulu({
|
|
24845
|
+
workspace: '${workspaceKey}',
|
|
24846
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
24847
|
+
});
|
|
24848
|
+
|
|
24849
|
+
// In your handler:
|
|
24850
|
+
await gurulu.track('purchase.completed', {
|
|
24851
|
+
user_id: 'u_42',
|
|
24852
|
+
order_id: 'o_123',
|
|
24853
|
+
total: 49.99,
|
|
24854
|
+
});`;
|
|
24855
|
+
}
|
|
24856
|
+
function snippetExpress(workspaceKey) {
|
|
24857
|
+
return `import express from 'express';
|
|
24858
|
+
import { guruluMiddleware } from '@gurulu/node/middleware/express';
|
|
24859
|
+
|
|
24860
|
+
const app = express();
|
|
24861
|
+
app.use(guruluMiddleware({
|
|
24862
|
+
workspace: '${workspaceKey}',
|
|
24863
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
24864
|
+
}));`;
|
|
24865
|
+
}
|
|
24866
|
+
function snippetHono(workspaceKey) {
|
|
24867
|
+
return `import { Hono } from 'hono';
|
|
24868
|
+
import { createGurulu } from '@gurulu/node';
|
|
24869
|
+
|
|
24870
|
+
const gurulu = createGurulu({
|
|
24871
|
+
workspace: '${workspaceKey}',
|
|
24872
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
24873
|
+
});
|
|
24874
|
+
|
|
24875
|
+
const app = new Hono();
|
|
24876
|
+
app.post('/checkout/complete', async (c) => {
|
|
24877
|
+
await gurulu.track('purchase.completed', await c.req.json());
|
|
24878
|
+
return c.json({ ok: true });
|
|
24879
|
+
});`;
|
|
24880
|
+
}
|
|
24881
|
+
function placementHintFor(framework) {
|
|
24882
|
+
switch (framework) {
|
|
24883
|
+
case "next":
|
|
24884
|
+
return "Add the GuruluProvider to app/layout.tsx (App Router) or pages/_app.tsx (Pages Router) and wrap children.";
|
|
24885
|
+
case "nuxt":
|
|
24886
|
+
return "Add to plugins/gurulu.client.ts and register in nuxt.config.ts.";
|
|
24887
|
+
case "svelte":
|
|
24888
|
+
return "Add to src/routes/+layout.svelte inside onMount().";
|
|
24889
|
+
case "astro":
|
|
24890
|
+
return "Add to src/layouts/Base.astro inside a <script> tag (or use a hydrated component).";
|
|
24891
|
+
case "vite":
|
|
24892
|
+
case "react":
|
|
24893
|
+
case "vue":
|
|
24894
|
+
return "Add to src/main.ts (or your entry file) before mounting the app.";
|
|
24895
|
+
case "express":
|
|
24896
|
+
return "Register guruluMiddleware before your route handlers in your app entry file.";
|
|
24897
|
+
case "fastify":
|
|
24898
|
+
return "Register the Gurulu plugin via fastify.register() before route definitions.";
|
|
24899
|
+
case "hono":
|
|
24900
|
+
return "Initialize the SDK at the top of your app file; call track() inside route handlers.";
|
|
24901
|
+
case "koa":
|
|
24902
|
+
return "Add as Koa middleware (app.use) before your routes.";
|
|
24903
|
+
case "node-server":
|
|
24904
|
+
return "Initialize the SDK at startup; call track() from your handlers.";
|
|
24905
|
+
default:
|
|
24906
|
+
return "Initialize the SDK at your app entry point.";
|
|
24907
|
+
}
|
|
24908
|
+
}
|
|
24909
|
+
function initSnippetFor(framework, sdk, workspaceKey) {
|
|
24910
|
+
if (sdk === "@gurulu/node") {
|
|
24911
|
+
if (framework === "express")
|
|
24912
|
+
return snippetExpress(workspaceKey);
|
|
24913
|
+
if (framework === "hono")
|
|
24914
|
+
return snippetHono(workspaceKey);
|
|
24915
|
+
return snippetNode(workspaceKey);
|
|
24916
|
+
}
|
|
24917
|
+
if (framework === "next")
|
|
24918
|
+
return snippetNext(workspaceKey);
|
|
24919
|
+
return snippetWeb(workspaceKey);
|
|
24920
|
+
}
|
|
24921
|
+
function envKeysFor(sdk, framework) {
|
|
24922
|
+
if (sdk === "@gurulu/node") {
|
|
24923
|
+
return [
|
|
24924
|
+
{
|
|
24925
|
+
key: "GURULU_API_KEY",
|
|
24926
|
+
example: "sk_live_xxxxxxxxxxxx",
|
|
24927
|
+
required: true
|
|
24928
|
+
}
|
|
24929
|
+
];
|
|
24930
|
+
}
|
|
24931
|
+
const envKey = framework === "next" ? "NEXT_PUBLIC_GURULU_WORKSPACE" : "VITE_GURULU_WORKSPACE";
|
|
24932
|
+
return [
|
|
24933
|
+
{
|
|
24934
|
+
key: envKey,
|
|
24935
|
+
example: "pk_live_xxxxxxxxxxxx",
|
|
24936
|
+
required: false
|
|
24937
|
+
}
|
|
24938
|
+
];
|
|
24939
|
+
}
|
|
24940
|
+
function buildInstallPlan(detected, ctx = {}) {
|
|
24941
|
+
const sdk = sdkFor(detected.framework);
|
|
24942
|
+
const workspaceKey = ctx.writeKey ?? "pk_xxxxxxxxxxxx";
|
|
24943
|
+
return {
|
|
24944
|
+
sdk,
|
|
24945
|
+
packageManager: detected.packageManager,
|
|
24946
|
+
installCommand: installCmdFor(detected.packageManager, sdk),
|
|
24947
|
+
initSnippet: initSnippetFor(detected.framework, sdk, workspaceKey),
|
|
24948
|
+
envKeys: envKeysFor(sdk, detected.framework),
|
|
24949
|
+
placementHint: placementHintFor(detected.framework),
|
|
24950
|
+
framework: detected.framework
|
|
24951
|
+
};
|
|
24952
|
+
}
|
|
24637
24953
|
|
|
24638
24954
|
// src/commands/pull.ts
|
|
24639
24955
|
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
@@ -24783,7 +25099,9 @@ var initCmd = defineCommand({
|
|
|
24783
25099
|
args: {
|
|
24784
25100
|
workspace: { type: "string", description: "Workspace ID (uuid)" },
|
|
24785
25101
|
endpoint: { type: "string", description: "API endpoint", default: DEFAULT_ENDPOINT },
|
|
24786
|
-
sdk: { type: "string", description: "SDK preference (web|node|
|
|
25102
|
+
sdk: { type: "string", description: "SDK preference (web|node|auto)", default: "auto" },
|
|
25103
|
+
"write-key": { type: "string", description: "Workspace write key (pk_xxx) for init snippet" },
|
|
25104
|
+
"no-install": { type: "boolean", description: "Skip SDK install (config files only)" },
|
|
24787
25105
|
"no-pull": { type: "boolean", description: "Skip first registry pull" },
|
|
24788
25106
|
force: { type: "boolean", description: "Overwrite existing config" }
|
|
24789
25107
|
},
|
|
@@ -24799,40 +25117,63 @@ var initCmd = defineCommand({
|
|
|
24799
25117
|
console.error("[gurulu] --workspace <uuid> required (workspace ID from dashboard)");
|
|
24800
25118
|
process.exit(1);
|
|
24801
25119
|
}
|
|
24802
|
-
const
|
|
24803
|
-
if (!["web", "node", "
|
|
24804
|
-
console.error(`[gurulu] invalid --sdk: ${
|
|
25120
|
+
const sdkArg = String(args.sdk ?? "auto");
|
|
25121
|
+
if (!["web", "node", "auto"].includes(sdkArg)) {
|
|
25122
|
+
console.error(`[gurulu] invalid --sdk: ${sdkArg} (use web|node|auto)`);
|
|
24805
25123
|
process.exit(1);
|
|
24806
25124
|
}
|
|
25125
|
+
const detected = detectProject(cwd);
|
|
25126
|
+
const writeKey = String(args["write-key"] ?? "").trim() || "pk_xxxxxxxxxxxx";
|
|
25127
|
+
const plan = buildInstallPlan(detected, { writeKey, workspaceId });
|
|
25128
|
+
const effectiveSdkPref = sdkArg === "auto" ? plan.sdk === "@gurulu/node" ? "node" : "web" : sdkArg;
|
|
24807
25129
|
const config = {
|
|
24808
25130
|
workspace_id: workspaceId,
|
|
24809
25131
|
endpoint: String(args.endpoint),
|
|
24810
|
-
sdk_preference:
|
|
25132
|
+
sdk_preference: effectiveSdkPref,
|
|
24811
25133
|
registry_path: ".gurulu/event-registry.json",
|
|
24812
25134
|
generated_path: ".gurulu/generated.d.ts",
|
|
24813
25135
|
manifest_lock_path: ".gurulu/manifest.lock",
|
|
24814
25136
|
auto_pull_on_init: true
|
|
24815
25137
|
};
|
|
24816
25138
|
writeProjectConfig(config, cwd);
|
|
24817
|
-
const dir =
|
|
24818
|
-
if (!
|
|
25139
|
+
const dir = dirname3(projectConfigPath(cwd));
|
|
25140
|
+
if (!existsSync5(dir))
|
|
24819
25141
|
mkdirSync2(dir, { recursive: true });
|
|
24820
|
-
if (!
|
|
25142
|
+
if (!existsSync5(projectRegistryPath(cwd))) {
|
|
24821
25143
|
writeFileSync3(projectRegistryPath(cwd), `{}
|
|
24822
25144
|
`, "utf-8");
|
|
24823
25145
|
}
|
|
24824
|
-
if (!
|
|
25146
|
+
if (!existsSync5(projectGeneratedPath(cwd))) {
|
|
24825
25147
|
writeFileSync3(projectGeneratedPath(cwd), "// Run `gurulu pull` to populate typed events.\n", "utf-8");
|
|
24826
25148
|
}
|
|
24827
|
-
if (!
|
|
25149
|
+
if (!existsSync5(projectManifestLockPath(cwd))) {
|
|
24828
25150
|
writeFileSync3(projectManifestLockPath(cwd), `0.0.0
|
|
24829
25151
|
`, "utf-8");
|
|
24830
25152
|
}
|
|
24831
25153
|
console.log(`[gurulu] initialized ${projectConfigPath(cwd)}`);
|
|
25154
|
+
if (args["no-install"]) {
|
|
25155
|
+
console.log(`[gurulu] skipping SDK install (--no-install).`);
|
|
25156
|
+
console.log(` manual: ${plan.installCommand}`);
|
|
25157
|
+
} else if (!detected.hasPackageJson) {
|
|
25158
|
+
console.log(`[gurulu] no package.json found in ${cwd} — skipping SDK install.`);
|
|
25159
|
+
console.log(` use the script tag: <script src="https://cdn.gurulu.io/t.js" data-workspace="${writeKey}"></script>`);
|
|
25160
|
+
} else {
|
|
25161
|
+
console.log(`[gurulu] detected ${detected.framework} (${detected.packageManager}) — installing ${plan.sdk}…`);
|
|
25162
|
+
const result = await execInstall(plan, { cwd });
|
|
25163
|
+
if (result.ok) {
|
|
25164
|
+
console.log(`[gurulu] ${plan.sdk} installed (${(result.durationMs / 1000).toFixed(1)}s).`);
|
|
25165
|
+
} else {
|
|
25166
|
+
console.warn(`[gurulu] install failed (exit ${result.exitCode ?? "n/a"}) — run manually: ${plan.installCommand}`);
|
|
25167
|
+
}
|
|
25168
|
+
}
|
|
25169
|
+
console.log("");
|
|
24832
25170
|
console.log("[gurulu] next steps:");
|
|
24833
25171
|
console.log(" 1. gurulu login — authenticate (or store API key)");
|
|
24834
25172
|
console.log(" 2. gurulu pull — fetch registry + code-gen");
|
|
24835
|
-
console.log(
|
|
25173
|
+
console.log(` 3. ${plan.placementHint}`);
|
|
25174
|
+
console.log("");
|
|
25175
|
+
console.log("[gurulu] init snippet:");
|
|
25176
|
+
console.log(plan.initSnippet);
|
|
24836
25177
|
if (!args["no-pull"]) {
|
|
24837
25178
|
try {
|
|
24838
25179
|
await runPull({ cwd });
|
|
@@ -24942,7 +25283,7 @@ var pushCmd = defineCommand({
|
|
|
24942
25283
|
});
|
|
24943
25284
|
|
|
24944
25285
|
// src/index.ts
|
|
24945
|
-
var VERSION = "1.0.
|
|
25286
|
+
var VERSION = "1.0.1";
|
|
24946
25287
|
var mcpCmd = defineCommand({
|
|
24947
25288
|
meta: {
|
|
24948
25289
|
name: "mcp",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type Framework = 'next' | 'react' | 'vue' | 'nuxt' | 'svelte' | 'astro' | 'vite' | 'express' | 'fastify' | 'hono' | 'koa' | 'node-server' | 'unknown';
|
|
2
|
+
export type Runtime = 'browser' | 'node' | 'unknown';
|
|
3
|
+
export type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';
|
|
4
|
+
export interface DetectedProject {
|
|
5
|
+
dir: string;
|
|
6
|
+
hasPackageJson: boolean;
|
|
7
|
+
framework: Framework;
|
|
8
|
+
runtime: Runtime;
|
|
9
|
+
packageManager: PackageManager;
|
|
10
|
+
packageJson: PackageJsonShape | null;
|
|
11
|
+
}
|
|
12
|
+
interface PackageJsonShape {
|
|
13
|
+
name?: string;
|
|
14
|
+
type?: 'module' | 'commonjs';
|
|
15
|
+
dependencies?: Record<string, string>;
|
|
16
|
+
devDependencies?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Walk up the directory tree (max 6 levels) looking for a lockfile.
|
|
20
|
+
* Monorepo workspaces typically have the lockfile at the repo root.
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectPackageManager(dir: string): PackageManager;
|
|
23
|
+
export declare function detectFramework(pkg: PackageJsonShape | null, dir: string): Framework;
|
|
24
|
+
export declare function frameworkRuntime(fw: Framework): Runtime;
|
|
25
|
+
export declare function detectProject(dir: string): DetectedProject;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/lib/detect.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,OAAO,GACP,KAAK,GACL,MAAM,GACN,QAAQ,GACR,OAAO,GACP,MAAM,GACN,SAAS,GACT,SAAS,GACT,MAAM,GACN,KAAK,GACL,aAAa,GACb,SAAS,CAAC;AAEd,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAErD,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACtC;AAED,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAiBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAchE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAkBpF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAmBvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAW1D"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// src/lib/detect.ts
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, parse } from "node:path";
|
|
4
|
+
function readPackageJson(dir) {
|
|
5
|
+
const p = join(dir, "package.json");
|
|
6
|
+
if (!existsSync(p))
|
|
7
|
+
return null;
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function hasDep(pkg, name) {
|
|
15
|
+
if (!pkg)
|
|
16
|
+
return false;
|
|
17
|
+
return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);
|
|
18
|
+
}
|
|
19
|
+
function detectPackageManager(dir) {
|
|
20
|
+
const root = parse(dir).root;
|
|
21
|
+
let cur = dir;
|
|
22
|
+
for (let i = 0;i < 6; i++) {
|
|
23
|
+
if (existsSync(join(cur, "bun.lock")) || existsSync(join(cur, "bun.lockb")))
|
|
24
|
+
return "bun";
|
|
25
|
+
if (existsSync(join(cur, "pnpm-lock.yaml")))
|
|
26
|
+
return "pnpm";
|
|
27
|
+
if (existsSync(join(cur, "yarn.lock")))
|
|
28
|
+
return "yarn";
|
|
29
|
+
if (existsSync(join(cur, "package-lock.json")))
|
|
30
|
+
return "npm";
|
|
31
|
+
if (cur === root)
|
|
32
|
+
break;
|
|
33
|
+
const parent = dirname(cur);
|
|
34
|
+
if (parent === cur)
|
|
35
|
+
break;
|
|
36
|
+
cur = parent;
|
|
37
|
+
}
|
|
38
|
+
return "npm";
|
|
39
|
+
}
|
|
40
|
+
function detectFramework(pkg, dir) {
|
|
41
|
+
if (!pkg)
|
|
42
|
+
return "unknown";
|
|
43
|
+
if (hasDep(pkg, "next"))
|
|
44
|
+
return "next";
|
|
45
|
+
if (hasDep(pkg, "nuxt"))
|
|
46
|
+
return "nuxt";
|
|
47
|
+
if (hasDep(pkg, "@sveltejs/kit") || hasDep(pkg, "svelte"))
|
|
48
|
+
return "svelte";
|
|
49
|
+
if (hasDep(pkg, "astro"))
|
|
50
|
+
return "astro";
|
|
51
|
+
if (hasDep(pkg, "vite") && (hasDep(pkg, "vue") || hasDep(pkg, "react")))
|
|
52
|
+
return "vite";
|
|
53
|
+
if (hasDep(pkg, "vue"))
|
|
54
|
+
return "vue";
|
|
55
|
+
if (hasDep(pkg, "react"))
|
|
56
|
+
return "react";
|
|
57
|
+
if (hasDep(pkg, "hono"))
|
|
58
|
+
return "hono";
|
|
59
|
+
if (hasDep(pkg, "fastify"))
|
|
60
|
+
return "fastify";
|
|
61
|
+
if (hasDep(pkg, "express"))
|
|
62
|
+
return "express";
|
|
63
|
+
if (hasDep(pkg, "koa"))
|
|
64
|
+
return "koa";
|
|
65
|
+
if (existsSync(join(dir, "server.js")) || existsSync(join(dir, "server.ts")))
|
|
66
|
+
return "node-server";
|
|
67
|
+
return "unknown";
|
|
68
|
+
}
|
|
69
|
+
function frameworkRuntime(fw) {
|
|
70
|
+
switch (fw) {
|
|
71
|
+
case "next":
|
|
72
|
+
case "react":
|
|
73
|
+
case "vue":
|
|
74
|
+
case "nuxt":
|
|
75
|
+
case "svelte":
|
|
76
|
+
case "astro":
|
|
77
|
+
case "vite":
|
|
78
|
+
return "browser";
|
|
79
|
+
case "express":
|
|
80
|
+
case "fastify":
|
|
81
|
+
case "hono":
|
|
82
|
+
case "koa":
|
|
83
|
+
case "node-server":
|
|
84
|
+
return "node";
|
|
85
|
+
default:
|
|
86
|
+
return "unknown";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function detectProject(dir) {
|
|
90
|
+
const pkg = readPackageJson(dir);
|
|
91
|
+
const framework = detectFramework(pkg, dir);
|
|
92
|
+
return {
|
|
93
|
+
dir,
|
|
94
|
+
hasPackageJson: pkg !== null,
|
|
95
|
+
framework,
|
|
96
|
+
runtime: frameworkRuntime(framework),
|
|
97
|
+
packageManager: detectPackageManager(dir),
|
|
98
|
+
packageJson: pkg
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
frameworkRuntime,
|
|
103
|
+
detectProject,
|
|
104
|
+
detectPackageManager,
|
|
105
|
+
detectFramework
|
|
106
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { InstallPlan } from './install-plan.ts';
|
|
2
|
+
export interface ExecInstallOptions {
|
|
3
|
+
cwd: string;
|
|
4
|
+
/** Suppress stdout/stderr forwarding (still captured in result). */
|
|
5
|
+
silent?: boolean;
|
|
6
|
+
/** Hard timeout in ms (default 120s). */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ExecInstallResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
exitCode: number | null;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
command: string;
|
|
14
|
+
stderr?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Spawn the package manager install command for the planned SDK.
|
|
18
|
+
* Streams output to the parent process (unless `silent: true`).
|
|
19
|
+
*/
|
|
20
|
+
export declare function execInstall(plan: InstallPlan, opts: ExecInstallOptions): Promise<ExecInstallResult>;
|
|
21
|
+
//# sourceMappingURL=exec-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-install.d.ts","sourceRoot":"","sources":["../../src/lib/exec-install.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CA6D5B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DetectedProject, Framework, PackageManager } from './detect.ts';
|
|
2
|
+
export type SdkPackage = '@gurulu/web' | '@gurulu/node';
|
|
3
|
+
export interface InstallPlanContext {
|
|
4
|
+
/** Workspace key (pk_xxx) — script tag + init() içine inject. */
|
|
5
|
+
writeKey?: string;
|
|
6
|
+
/** Workspace UUID — CLI/MCP referansı. */
|
|
7
|
+
workspaceId?: string;
|
|
8
|
+
/** Server-side projeler için API key (sk_xxx). */
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface InstallPlan {
|
|
12
|
+
sdk: SdkPackage;
|
|
13
|
+
packageManager: PackageManager;
|
|
14
|
+
installCommand: string;
|
|
15
|
+
initSnippet: string;
|
|
16
|
+
envKeys: Array<{
|
|
17
|
+
key: string;
|
|
18
|
+
example: string;
|
|
19
|
+
required: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
placementHint: string;
|
|
22
|
+
framework: Framework;
|
|
23
|
+
}
|
|
24
|
+
export declare function buildInstallPlan(detected: DetectedProject, ctx?: InstallPlanContext): InstallPlan;
|
|
25
|
+
//# sourceMappingURL=install-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-plan.d.ts","sourceRoot":"","sources":["../../src/lib/install-plan.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9E,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,cAAc,CAAC;AAExD,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,UAAU,CAAC;IAChB,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;CACtB;AA2JD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,GAAG,GAAE,kBAAuB,GAC3B,WAAW,CAYb"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// src/lib/install-plan.ts
|
|
2
|
+
function installCmdFor(pm, pkg) {
|
|
3
|
+
switch (pm) {
|
|
4
|
+
case "bun":
|
|
5
|
+
return `bun add ${pkg}`;
|
|
6
|
+
case "pnpm":
|
|
7
|
+
return `pnpm add ${pkg}`;
|
|
8
|
+
case "yarn":
|
|
9
|
+
return `yarn add ${pkg}`;
|
|
10
|
+
default:
|
|
11
|
+
return `npm install ${pkg}`;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function sdkFor(framework) {
|
|
15
|
+
switch (framework) {
|
|
16
|
+
case "express":
|
|
17
|
+
case "fastify":
|
|
18
|
+
case "hono":
|
|
19
|
+
case "koa":
|
|
20
|
+
case "node-server":
|
|
21
|
+
return "@gurulu/node";
|
|
22
|
+
default:
|
|
23
|
+
return "@gurulu/web";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function snippetWeb(workspaceKey) {
|
|
27
|
+
return `import { createGurulu } from '@gurulu/web';
|
|
28
|
+
|
|
29
|
+
const gurulu = createGurulu();
|
|
30
|
+
gurulu.init({ workspace: '${workspaceKey}' });`;
|
|
31
|
+
}
|
|
32
|
+
function snippetNext(workspaceKey) {
|
|
33
|
+
return `// app/layout.tsx (or pages/_app.tsx)
|
|
34
|
+
'use client';
|
|
35
|
+
import { useEffect } from 'react';
|
|
36
|
+
import { createGurulu } from '@gurulu/web';
|
|
37
|
+
|
|
38
|
+
const gurulu = createGurulu();
|
|
39
|
+
|
|
40
|
+
export function GuruluProvider({ children }: { children: React.ReactNode }) {
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
gurulu.init({ workspace: '${workspaceKey}' });
|
|
43
|
+
}, []);
|
|
44
|
+
return <>{children}</>;
|
|
45
|
+
}`;
|
|
46
|
+
}
|
|
47
|
+
function snippetNode(workspaceKey) {
|
|
48
|
+
return `import { createGurulu } from '@gurulu/node';
|
|
49
|
+
|
|
50
|
+
const gurulu = createGurulu({
|
|
51
|
+
workspace: '${workspaceKey}',
|
|
52
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// In your handler:
|
|
56
|
+
await gurulu.track('purchase.completed', {
|
|
57
|
+
user_id: 'u_42',
|
|
58
|
+
order_id: 'o_123',
|
|
59
|
+
total: 49.99,
|
|
60
|
+
});`;
|
|
61
|
+
}
|
|
62
|
+
function snippetExpress(workspaceKey) {
|
|
63
|
+
return `import express from 'express';
|
|
64
|
+
import { guruluMiddleware } from '@gurulu/node/middleware/express';
|
|
65
|
+
|
|
66
|
+
const app = express();
|
|
67
|
+
app.use(guruluMiddleware({
|
|
68
|
+
workspace: '${workspaceKey}',
|
|
69
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
70
|
+
}));`;
|
|
71
|
+
}
|
|
72
|
+
function snippetHono(workspaceKey) {
|
|
73
|
+
return `import { Hono } from 'hono';
|
|
74
|
+
import { createGurulu } from '@gurulu/node';
|
|
75
|
+
|
|
76
|
+
const gurulu = createGurulu({
|
|
77
|
+
workspace: '${workspaceKey}',
|
|
78
|
+
apiKey: process.env.GURULU_API_KEY,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const app = new Hono();
|
|
82
|
+
app.post('/checkout/complete', async (c) => {
|
|
83
|
+
await gurulu.track('purchase.completed', await c.req.json());
|
|
84
|
+
return c.json({ ok: true });
|
|
85
|
+
});`;
|
|
86
|
+
}
|
|
87
|
+
function placementHintFor(framework) {
|
|
88
|
+
switch (framework) {
|
|
89
|
+
case "next":
|
|
90
|
+
return "Add the GuruluProvider to app/layout.tsx (App Router) or pages/_app.tsx (Pages Router) and wrap children.";
|
|
91
|
+
case "nuxt":
|
|
92
|
+
return "Add to plugins/gurulu.client.ts and register in nuxt.config.ts.";
|
|
93
|
+
case "svelte":
|
|
94
|
+
return "Add to src/routes/+layout.svelte inside onMount().";
|
|
95
|
+
case "astro":
|
|
96
|
+
return "Add to src/layouts/Base.astro inside a <script> tag (or use a hydrated component).";
|
|
97
|
+
case "vite":
|
|
98
|
+
case "react":
|
|
99
|
+
case "vue":
|
|
100
|
+
return "Add to src/main.ts (or your entry file) before mounting the app.";
|
|
101
|
+
case "express":
|
|
102
|
+
return "Register guruluMiddleware before your route handlers in your app entry file.";
|
|
103
|
+
case "fastify":
|
|
104
|
+
return "Register the Gurulu plugin via fastify.register() before route definitions.";
|
|
105
|
+
case "hono":
|
|
106
|
+
return "Initialize the SDK at the top of your app file; call track() inside route handlers.";
|
|
107
|
+
case "koa":
|
|
108
|
+
return "Add as Koa middleware (app.use) before your routes.";
|
|
109
|
+
case "node-server":
|
|
110
|
+
return "Initialize the SDK at startup; call track() from your handlers.";
|
|
111
|
+
default:
|
|
112
|
+
return "Initialize the SDK at your app entry point.";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function initSnippetFor(framework, sdk, workspaceKey) {
|
|
116
|
+
if (sdk === "@gurulu/node") {
|
|
117
|
+
if (framework === "express")
|
|
118
|
+
return snippetExpress(workspaceKey);
|
|
119
|
+
if (framework === "hono")
|
|
120
|
+
return snippetHono(workspaceKey);
|
|
121
|
+
return snippetNode(workspaceKey);
|
|
122
|
+
}
|
|
123
|
+
if (framework === "next")
|
|
124
|
+
return snippetNext(workspaceKey);
|
|
125
|
+
return snippetWeb(workspaceKey);
|
|
126
|
+
}
|
|
127
|
+
function envKeysFor(sdk, framework) {
|
|
128
|
+
if (sdk === "@gurulu/node") {
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
key: "GURULU_API_KEY",
|
|
132
|
+
example: "sk_live_xxxxxxxxxxxx",
|
|
133
|
+
required: true
|
|
134
|
+
}
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
const envKey = framework === "next" ? "NEXT_PUBLIC_GURULU_WORKSPACE" : "VITE_GURULU_WORKSPACE";
|
|
138
|
+
return [
|
|
139
|
+
{
|
|
140
|
+
key: envKey,
|
|
141
|
+
example: "pk_live_xxxxxxxxxxxx",
|
|
142
|
+
required: false
|
|
143
|
+
}
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
function buildInstallPlan(detected, ctx = {}) {
|
|
147
|
+
const sdk = sdkFor(detected.framework);
|
|
148
|
+
const workspaceKey = ctx.writeKey ?? "pk_xxxxxxxxxxxx";
|
|
149
|
+
return {
|
|
150
|
+
sdk,
|
|
151
|
+
packageManager: detected.packageManager,
|
|
152
|
+
installCommand: installCmdFor(detected.packageManager, sdk),
|
|
153
|
+
initSnippet: initSnippetFor(detected.framework, sdk, workspaceKey),
|
|
154
|
+
envKeys: envKeysFor(sdk, detected.framework),
|
|
155
|
+
placementHint: placementHintFor(detected.framework),
|
|
156
|
+
framework: detected.framework
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export {
|
|
160
|
+
buildInstallPlan
|
|
161
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gurulu/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"publishConfig": {
|
|
@@ -26,6 +26,16 @@
|
|
|
26
26
|
"import": "./dist/index.js",
|
|
27
27
|
"default": "./dist/index.js"
|
|
28
28
|
},
|
|
29
|
+
"./detect": {
|
|
30
|
+
"types": "./dist/lib/detect.d.ts",
|
|
31
|
+
"import": "./dist/lib/detect.js",
|
|
32
|
+
"default": "./dist/lib/detect.js"
|
|
33
|
+
},
|
|
34
|
+
"./install-plan": {
|
|
35
|
+
"types": "./dist/lib/install-plan.d.ts",
|
|
36
|
+
"import": "./dist/lib/install-plan.js",
|
|
37
|
+
"default": "./dist/lib/install-plan.js"
|
|
38
|
+
},
|
|
29
39
|
"./package.json": "./package.json"
|
|
30
40
|
},
|
|
31
41
|
"files": [
|
|
@@ -34,8 +44,9 @@
|
|
|
34
44
|
"LICENSE"
|
|
35
45
|
],
|
|
36
46
|
"scripts": {
|
|
37
|
-
"build": "rm -rf dist && bun run build:js && bun run build:types && bun run build:bin",
|
|
47
|
+
"build": "rm -rf dist && bun run build:js && bun run build:lib && bun run build:types && bun run build:bin",
|
|
38
48
|
"build:js": "bun build ./src/index.ts --outdir ./dist --target node --format=esm",
|
|
49
|
+
"build:lib": "bun build ./src/lib/detect.ts ./src/lib/install-plan.ts --outdir ./dist/lib --target node --format=esm",
|
|
39
50
|
"build:bin": "bun build ./src/bin.ts --outdir ./dist --target node --format=esm && chmod +x dist/bin.js",
|
|
40
51
|
"build:types": "tsc -p tsconfig.build.json",
|
|
41
52
|
"typecheck": "tsc --noEmit",
|