@helloleo/plugins 0.2.19 → 0.2.20

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/index.js CHANGED
@@ -25561,6 +25561,17 @@ async function readScaffoldId2(dir) {
25561
25561
  return null;
25562
25562
  }
25563
25563
  }
25564
+ async function isStartScaffold(dir) {
25565
+ const scaffoldId = await readScaffoldId2(dir);
25566
+ if (scaffoldId)
25567
+ return scaffoldId.startsWith("tanstack-start");
25568
+ try {
25569
+ const pkg = await Bun.file(path7.join(dir, "package.json")).json();
25570
+ return Boolean(pkg?.dependencies?.["@tanstack/react-start"] ?? pkg?.devDependencies?.["@tanstack/react-start"]);
25571
+ } catch {
25572
+ return false;
25573
+ }
25574
+ }
25564
25575
  function schemaAppend() {
25565
25576
  return `
25566
25577
  // --- NetSuite OAuth (added by setup_netsuite) ---
@@ -26773,13 +26784,11 @@ async function executeSpa(dir) {
26773
26784
  `);
26774
26785
  }
26775
26786
  var setupNetsuite = tool({
26776
- description: "Add NetSuite runtime OAuth (end-user LOGIN) to an existing project. " + "Call scaffold first, then this. Works on both scaffold types: it " + "writes the client + auth components, and the OAuth backend is the " + "project's HelloLeo Cloud Worker (VITE_WORKER_URL) -- the platform " + "wizard registers the Worker's fixed /auth/netsuite/callback on the " + "Integration Record, so the app never hosts the OAuth routes itself. " + "This login uses NetSuite Integration Record #2 " + "(scope: rest_webservices) -- a SEPARATE record from the MCP one " + "(scope: mcp) that was used only to BUILD the app; do not confuse " + "them. Real OAuth from day one -- never replace <AuthLayout> with a " + "password placeholder. Setup guide (link the user to it): " + "https://docs.helloleo.dev/integrations/netsuite",
26787
+ description: "Add NetSuite runtime OAuth (end-user LOGIN) to an existing project. " + "Call scaffold first, then this. Works on both scaffold types and " + "picks the variant automatically: on tanstack-start the app hosts " + "its own OAuth routes (/auth/netsuite/* + /api/me, same-origin " + "client); on tanstack-router (SPA) it writes the client + auth " + "components and the OAuth backend is the project's HelloLeo Cloud " + "Worker (VITE_WORKER_URL). This login uses NetSuite Integration " + "Record #2 (scope: rest_webservices) -- a SEPARATE record from the " + "MCP one (scope: mcp) that was used only to BUILD the app; do not " + "confuse them. Real OAuth from day one -- never replace <AuthLayout> " + "with a password placeholder. Setup guide (link the user to it): " + "https://docs.helloleo.dev/integrations/netsuite",
26777
26788
  args: {},
26778
26789
  async execute(_args, context) {
26779
26790
  const dir = context.directory;
26780
- const scaffoldId = await readScaffoldId2(dir);
26781
- const inAppOptIn = process.env.PLUGINS_NETSUITE_IN_APP === "1";
26782
- if (inAppOptIn && scaffoldId?.startsWith("tanstack-start")) {
26791
+ if (await isStartScaffold(dir)) {
26783
26792
  return executeStart(dir);
26784
26793
  }
26785
26794
  return executeSpa(dir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helloleo/plugins",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "description": "OpenCode plugins for HelloLeo",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -4,19 +4,20 @@ import type { Plugin } from "@opencode-ai/plugin";
4
4
  import { tool } from "@opencode-ai/plugin";
5
5
 
6
6
  /**
7
- * NetSuite runtime OAuth (end-user LOGIN). Two variants:
7
+ * NetSuite runtime OAuth (end-user LOGIN). Two variants, picked automatically
8
+ * from the project's scaffold -- never from env:
8
9
  *
9
- * - DEFAULT (every scaffold type): client-only files; the OAuth backend is
10
- * the per-project HelloLeo Cloud Worker (VITE_WORKER_URL), sign-in runs in
10
+ * - tanstack-start (SSR): the app IS the backend. Emits server routes
11
+ * (/auth/netsuite/* + /api/me), netsuite_flows + netsuite_sessions drizzle
12
+ * tables, and a same-origin client. The redirect URI registered on
13
+ * Integration Record #2 must be the APP's own /auth/netsuite/callback
14
+ * (read it from GET /auth/netsuite/config).
15
+ * - tanstack-router (SPA): client-only files; the OAuth backend is the
16
+ * per-project HelloLeo Cloud Worker (VITE_WORKER_URL), sign-in runs in
11
17
  * a popup + postMessage so it works inside the HelloLeo preview iframe.
12
- * This matches prod: the platform wizard registers the Worker's fixed
13
- * /auth/netsuite/callback as the ONE redirect URI on Integration Record #2
14
- * (provision-first, see webapp netsuiteRuntimeSetup).
15
- * - IN-APP (opt-in: PLUGINS_NETSUITE_IN_APP=1 + tanstack-start scaffold):
16
- * the app IS the backend. Emits server routes (/auth/netsuite/* + /api/me),
17
- * netsuite_flows + netsuite_sessions drizzle tables, and a same-origin
18
- * client. Only valid when the deployment registers the APP's own callback
19
- * on the Integration Record instead of the Worker's.
18
+ * The wizard registers the Worker's fixed /auth/netsuite/callback as the
19
+ * ONE redirect URI on Integration Record #2 (provision-first, see webapp
20
+ * netsuiteRuntimeSetup).
20
21
  *
21
22
  * Both variants share the same component names (AuthLayout / LoginPage /
22
23
  * SignInWithNetSuite) and the same wiring step: wrap the root route's
@@ -42,6 +43,26 @@ async function readScaffoldId(dir: string): Promise<string | null> {
42
43
  }
43
44
  }
44
45
 
46
+ /**
47
+ * Is this project a tanstack-start (SSR) app? Primary signal: the scaffold id
48
+ * in .leo/project.json. Fallback for pre-project.json workspaces: only the
49
+ * start scaffold depends on @tanstack/react-start -- the router SPA ships
50
+ * @tanstack/react-router alone.
51
+ */
52
+ async function isStartScaffold(dir: string): Promise<boolean> {
53
+ const scaffoldId = await readScaffoldId(dir);
54
+ if (scaffoldId) return scaffoldId.startsWith("tanstack-start");
55
+ try {
56
+ const pkg = await Bun.file(path.join(dir, "package.json")).json();
57
+ return Boolean(
58
+ pkg?.dependencies?.["@tanstack/react-start"] ??
59
+ pkg?.devDependencies?.["@tanstack/react-start"],
60
+ );
61
+ } catch {
62
+ return false;
63
+ }
64
+ }
65
+
45
66
  // --- emitted: src/db/schema.ts (appended) --------------------------------
46
67
  function schemaAppend(): string {
47
68
  return `
@@ -1302,31 +1323,27 @@ async function executeSpa(dir: string): Promise<string> {
1302
1323
  export const setupNetsuite = tool({
1303
1324
  description:
1304
1325
  "Add NetSuite runtime OAuth (end-user LOGIN) to an existing project. " +
1305
- "Call scaffold first, then this. Works on both scaffold types: it " +
1306
- "writes the client + auth components, and the OAuth backend is the " +
1307
- "project's HelloLeo Cloud Worker (VITE_WORKER_URL) -- the platform " +
1308
- "wizard registers the Worker's fixed /auth/netsuite/callback on the " +
1309
- "Integration Record, so the app never hosts the OAuth routes itself. " +
1310
- "This login uses NetSuite Integration Record #2 " +
1311
- "(scope: rest_webservices) -- a SEPARATE record from the MCP one " +
1312
- "(scope: mcp) that was used only to BUILD the app; do not confuse " +
1313
- "them. Real OAuth from day one -- never replace <AuthLayout> with a " +
1314
- "password placeholder. Setup guide (link the user to it): " +
1326
+ "Call scaffold first, then this. Works on both scaffold types and " +
1327
+ "picks the variant automatically: on tanstack-start the app hosts " +
1328
+ "its own OAuth routes (/auth/netsuite/* + /api/me, same-origin " +
1329
+ "client); on tanstack-router (SPA) it writes the client + auth " +
1330
+ "components and the OAuth backend is the project's HelloLeo Cloud " +
1331
+ "Worker (VITE_WORKER_URL). This login uses NetSuite Integration " +
1332
+ "Record #2 (scope: rest_webservices) -- a SEPARATE record from the " +
1333
+ "MCP one (scope: mcp) that was used only to BUILD the app; do not " +
1334
+ "confuse them. Real OAuth from day one -- never replace <AuthLayout> " +
1335
+ "with a password placeholder. Setup guide (link the user to it): " +
1315
1336
  "https://docs.helloleo.dev/integrations/netsuite",
1316
1337
  args: {},
1317
1338
  async execute(_args, context) {
1318
1339
  const dir = context.directory;
1319
- // Prod model: Integration Record #2 carries ONE fixed redirect URI --
1320
- // the per-project HelloLeo Cloud Worker's /auth/netsuite/callback
1321
- // (provision-first wizard, see webapp netsuiteRuntimeSetup). So the
1322
- // Worker variant is the default for EVERY scaffold type. The in-app
1323
- // server-route variant (app-origin redirect URI) only makes sense when
1324
- // a deployment's wizard registers the app's own callback instead --
1325
- // opt in per deployment with PLUGINS_NETSUITE_IN_APP=1 on a
1326
- // tanstack-start scaffold.
1327
- const scaffoldId = await readScaffoldId(dir);
1328
- const inAppOptIn = process.env.PLUGINS_NETSUITE_IN_APP === "1";
1329
- if (inAppOptIn && scaffoldId?.startsWith("tanstack-start")) {
1340
+ // The variant follows the scaffold, never an env flag: a start app has
1341
+ // a server (TanStack Start routes + D1) so it hosts the OAuth itself;
1342
+ // the router SPA has no server, so the per-project HelloLeo Cloud
1343
+ // Worker is the backend. The redirect URI registered on Integration
1344
+ // Record #2 must match: the app's own /auth/netsuite/callback for
1345
+ // start, the Worker's fixed callback for the SPA.
1346
+ if (await isStartScaffold(dir)) {
1330
1347
  return executeStart(dir);
1331
1348
  }
1332
1349
  return executeSpa(dir);