@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 +13 -4
- package/package.json +1 -1
- package/src/tools/setup-netsuite.ts +49 -32
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
|
|
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
|
-
|
|
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
|
@@ -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
|
-
* -
|
|
10
|
-
*
|
|
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
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
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
|
|
1306
|
-
"
|
|
1307
|
-
"
|
|
1308
|
-
"
|
|
1309
|
-
"
|
|
1310
|
-
"This login uses NetSuite Integration
|
|
1311
|
-
"(scope: rest_webservices) -- a SEPARATE record from the
|
|
1312
|
-
"(scope: mcp) that was used only to BUILD the app; do not
|
|
1313
|
-
"them. Real OAuth from day one -- never replace <AuthLayout>
|
|
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
|
-
//
|
|
1320
|
-
//
|
|
1321
|
-
//
|
|
1322
|
-
// Worker
|
|
1323
|
-
//
|
|
1324
|
-
//
|
|
1325
|
-
|
|
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);
|