create-graphene 0.0.17 → 0.0.19
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/cli.js +159 -19
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { styleText } from "node:util";
|
|
|
11
11
|
// ../cli/package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@graphenedata/cli",
|
|
14
|
-
version: "0.0.
|
|
14
|
+
version: "0.0.19",
|
|
15
15
|
private: true,
|
|
16
16
|
license: "Elastic-2.0",
|
|
17
17
|
author: "Graphene Systems Inc",
|
|
@@ -57,32 +57,42 @@ var package_default = {
|
|
|
57
57
|
"js-yaml": "^3.14.2",
|
|
58
58
|
json5: "^2.2.3",
|
|
59
59
|
mdsvex: "^0.12.6",
|
|
60
|
-
"
|
|
60
|
+
"playwright-core": "1.58.2",
|
|
61
|
+
"sanitize-html": "^2.17.4",
|
|
62
|
+
svelte: "5.55.7",
|
|
61
63
|
unified: "^11.0.5",
|
|
62
64
|
"unist-util-visit": "4.1.2",
|
|
63
65
|
vite: "7.3.2",
|
|
64
|
-
ws: "^8.
|
|
66
|
+
ws: "^8.20.1"
|
|
65
67
|
},
|
|
66
68
|
devDependencies: {
|
|
69
|
+
"@aws-sdk/client-athena": "^3.1049.0",
|
|
67
70
|
"@clickhouse/client": "^1.18.2",
|
|
68
71
|
"@duckdb/node-api": "1.3.2-alpha.26",
|
|
69
|
-
"@google-cloud/bigquery": "^8.
|
|
72
|
+
"@google-cloud/bigquery": "^8.3.1",
|
|
70
73
|
"@types/fs-extra": "^11.0.4",
|
|
71
74
|
"@types/node": "^20.0.0",
|
|
75
|
+
"@types/pg": "8.11.11",
|
|
72
76
|
"@types/sanitize-html": "^2.16.0",
|
|
73
77
|
"@types/ws": "^8.18.1",
|
|
74
78
|
esbuild: "^0.27.2",
|
|
79
|
+
pg: "8.13.3",
|
|
75
80
|
"snowflake-sdk": "2.4.0",
|
|
76
81
|
vitest: "4.0.18",
|
|
77
82
|
"vscode-languageserver-types": "^3.17.0"
|
|
78
83
|
},
|
|
79
84
|
peerDependencies: {
|
|
85
|
+
"@aws-sdk/client-athena": "^3.1049.0",
|
|
80
86
|
"@clickhouse/client": "^1.18.2",
|
|
81
87
|
"@duckdb/node-api": "1.3.2-alpha.26",
|
|
82
88
|
"@google-cloud/bigquery": "^8.2.0",
|
|
89
|
+
pg: "8.13.3",
|
|
83
90
|
"snowflake-sdk": "2.4.0"
|
|
84
91
|
},
|
|
85
92
|
peerDependenciesMeta: {
|
|
93
|
+
"@aws-sdk/client-athena": {
|
|
94
|
+
optional: true
|
|
95
|
+
},
|
|
86
96
|
"@clickhouse/client": {
|
|
87
97
|
optional: true
|
|
88
98
|
},
|
|
@@ -92,6 +102,9 @@ var package_default = {
|
|
|
92
102
|
"@google-cloud/bigquery": {
|
|
93
103
|
optional: true
|
|
94
104
|
},
|
|
105
|
+
pg: {
|
|
106
|
+
optional: true
|
|
107
|
+
},
|
|
95
108
|
"snowflake-sdk": {
|
|
96
109
|
optional: true
|
|
97
110
|
}
|
|
@@ -178,8 +191,16 @@ function renderTemplate({ answers, cliVersion }) {
|
|
|
178
191
|
graphene.snowflake = { account: answers.snowflakeAccount || "", username: answers.snowflakeUsername || "" };
|
|
179
192
|
} else if (answers.database === "bigquery") {
|
|
180
193
|
graphene.bigquery = { projectId: answers.bigqueryProjectId || "" };
|
|
181
|
-
} else {
|
|
194
|
+
} else if (answers.database === "clickhouse") {
|
|
182
195
|
graphene.clickhouse = { url: answers.clickhouseUrl || "", username: answers.clickhouseUsername || "" };
|
|
196
|
+
} else {
|
|
197
|
+
graphene.postgres = {
|
|
198
|
+
host: answers.postgresHost || "",
|
|
199
|
+
port: Number(answers.postgresPort || 5432),
|
|
200
|
+
database: answers.postgresDatabase || "",
|
|
201
|
+
user: answers.postgresUsername || ""
|
|
202
|
+
};
|
|
203
|
+
if (answers.postgresSsl) graphene.postgres.ssl = true;
|
|
183
204
|
}
|
|
184
205
|
let pkg = {
|
|
185
206
|
name: answers.projectName,
|
|
@@ -202,9 +223,10 @@ function renderTemplate({ answers, cliVersion }) {
|
|
|
202
223
|
let files = {
|
|
203
224
|
"package.json": JSON.stringify(pkg, null, 2) + "\n",
|
|
204
225
|
".gitignore": ["node_modules", ".env", "*.duckdb"].join("\n") + "\n",
|
|
205
|
-
[agentsFileName(answers.
|
|
226
|
+
[agentsFileName(answers.agentSetup)]: renderAgents(answers),
|
|
206
227
|
"index.md": renderIndex(answers)
|
|
207
228
|
};
|
|
229
|
+
if (answers.agentSetup === "codex") files[".codex/config.toml"] = renderCodexConfig();
|
|
208
230
|
if (answers.packageManager?.name === "yarn") files[".yarnrc.yml"] = "nodeLinker: node-modules\n";
|
|
209
231
|
let envFile = renderEnvFile(answers);
|
|
210
232
|
if (envFile) files[".env"] = envFile;
|
|
@@ -216,8 +238,8 @@ function grapheneCommand(packageManager, args) {
|
|
|
216
238
|
if (packageManager?.name === "bun") return `bun run graphene ${args}`;
|
|
217
239
|
return `npx graphene ${args}`;
|
|
218
240
|
}
|
|
219
|
-
function agentsFileName(
|
|
220
|
-
if (
|
|
241
|
+
function agentsFileName(agentSetup) {
|
|
242
|
+
if (agentSetup === "claude") return "CLAUDE.md";
|
|
221
243
|
return "AGENTS.md";
|
|
222
244
|
}
|
|
223
245
|
function renderAgents(answers) {
|
|
@@ -233,10 +255,32 @@ function renderAgents(answers) {
|
|
|
233
255
|
`- ${grapheneCommand(answers.packageManager, "serve --bg")} - start or restart the local dev server`
|
|
234
256
|
].join("\n") + "\n";
|
|
235
257
|
}
|
|
258
|
+
function renderCodexConfig() {
|
|
259
|
+
return [
|
|
260
|
+
"# Enable Graphene page screenshots in Codex by allowing the local dev server.",
|
|
261
|
+
'default_permissions = "graphene"',
|
|
262
|
+
"",
|
|
263
|
+
"[permissions.graphene.filesystem]",
|
|
264
|
+
'":root" = "read"',
|
|
265
|
+
'":project_roots" = { "." = "write" }',
|
|
266
|
+
'":tmpdir" = "write"',
|
|
267
|
+
"",
|
|
268
|
+
"[permissions.graphene.network]",
|
|
269
|
+
"enabled = true",
|
|
270
|
+
'mode = "full"',
|
|
271
|
+
"allow_local_binding = true",
|
|
272
|
+
"",
|
|
273
|
+
"[permissions.graphene.network.domains]",
|
|
274
|
+
'"localhost" = "allow"',
|
|
275
|
+
'"127.0.0.1" = "allow"',
|
|
276
|
+
'"::1" = "allow"'
|
|
277
|
+
].join("\n") + "\n";
|
|
278
|
+
}
|
|
236
279
|
function databaseLabel(database) {
|
|
237
280
|
if (database === "snowflake") return "Snowflake";
|
|
238
281
|
if (database === "bigquery") return "BigQuery";
|
|
239
282
|
if (database === "clickhouse") return "ClickHouse";
|
|
283
|
+
if (database === "postgres") return "Postgres";
|
|
240
284
|
return "DuckDB";
|
|
241
285
|
}
|
|
242
286
|
function renderIndex(answers) {
|
|
@@ -251,6 +295,8 @@ function renderEnvFile(answers) {
|
|
|
251
295
|
lines.push(`GOOGLE_APPLICATION_CREDENTIALS=${answers.bigqueryKeyPath || ""}`);
|
|
252
296
|
} else if (answers.database === "clickhouse") {
|
|
253
297
|
lines.push(`CLICKHOUSE_PASSWORD=${answers.clickhousePassword || ""}`);
|
|
298
|
+
} else if (answers.database === "postgres") {
|
|
299
|
+
lines.push(`POSTGRES_PASSWORD=${answers.postgresPassword || ""}`);
|
|
254
300
|
}
|
|
255
301
|
return lines.length ? lines.join("\n") + "\n" : null;
|
|
256
302
|
}
|
|
@@ -327,6 +373,7 @@ function getWarehouseClient(database) {
|
|
|
327
373
|
if (database === "snowflake") return "snowflake-sdk";
|
|
328
374
|
if (database === "bigquery") return "@google-cloud/bigquery";
|
|
329
375
|
if (database === "clickhouse") return "@clickhouse/client";
|
|
376
|
+
if (database === "postgres") return "pg";
|
|
330
377
|
return "@duckdb/node-api";
|
|
331
378
|
}
|
|
332
379
|
function getWarehouseClientVersion(packageName) {
|
|
@@ -403,6 +450,71 @@ async function promptWarehouseCredentials(answers, input, output) {
|
|
|
403
450
|
...promptOptions(input, output)
|
|
404
451
|
})
|
|
405
452
|
);
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
if (answers.database === "postgres") {
|
|
456
|
+
answers.postgresHost = unwrapPrompt(
|
|
457
|
+
await clack.text({
|
|
458
|
+
message: "Postgres host",
|
|
459
|
+
placeholder: "localhost",
|
|
460
|
+
initialValue: answers.postgresHost || "localhost",
|
|
461
|
+
validate: validateRequired("Postgres host is required"),
|
|
462
|
+
...promptOptions(input, output)
|
|
463
|
+
})
|
|
464
|
+
);
|
|
465
|
+
answers.postgresPort = unwrapPrompt(
|
|
466
|
+
await clack.text({
|
|
467
|
+
message: "Postgres port",
|
|
468
|
+
placeholder: "5432",
|
|
469
|
+
initialValue: answers.postgresPort || "5432",
|
|
470
|
+
validate: (value) => {
|
|
471
|
+
if (!value) return "Postgres port is required";
|
|
472
|
+
if (!/^\d+$/.test(value)) return "Postgres port must be a number";
|
|
473
|
+
},
|
|
474
|
+
...promptOptions(input, output)
|
|
475
|
+
})
|
|
476
|
+
);
|
|
477
|
+
answers.postgresDatabase = unwrapPrompt(
|
|
478
|
+
await clack.text({
|
|
479
|
+
message: "Postgres database",
|
|
480
|
+
placeholder: "analytics",
|
|
481
|
+
initialValue: answers.postgresDatabase,
|
|
482
|
+
validate: validateRequired("Postgres database is required"),
|
|
483
|
+
...promptOptions(input, output)
|
|
484
|
+
})
|
|
485
|
+
);
|
|
486
|
+
answers.postgresUsername = unwrapPrompt(
|
|
487
|
+
await clack.text({
|
|
488
|
+
message: "Postgres username",
|
|
489
|
+
placeholder: "graphene_user",
|
|
490
|
+
initialValue: answers.postgresUsername,
|
|
491
|
+
validate: validateRequired("Postgres username is required"),
|
|
492
|
+
...promptOptions(input, output)
|
|
493
|
+
})
|
|
494
|
+
);
|
|
495
|
+
answers.postgresPassword = unwrapPrompt(
|
|
496
|
+
await clack.password({
|
|
497
|
+
message: "Postgres password",
|
|
498
|
+
validate: validateRequired("Postgres password is required"),
|
|
499
|
+
...promptOptions(input, output)
|
|
500
|
+
})
|
|
501
|
+
);
|
|
502
|
+
answers.defaultNamespace = unwrapPrompt(
|
|
503
|
+
await clack.text({
|
|
504
|
+
message: "Postgres schema",
|
|
505
|
+
placeholder: "public",
|
|
506
|
+
initialValue: answers.defaultNamespace || "public",
|
|
507
|
+
validate: validateRequired("Postgres schema is required"),
|
|
508
|
+
...promptOptions(input, output)
|
|
509
|
+
})
|
|
510
|
+
);
|
|
511
|
+
answers.postgresSsl = unwrapPrompt(
|
|
512
|
+
await clack.confirm({
|
|
513
|
+
message: "Use SSL for Postgres?",
|
|
514
|
+
initialValue: answers.postgresSsl || false,
|
|
515
|
+
...promptOptions(input, output)
|
|
516
|
+
})
|
|
517
|
+
);
|
|
406
518
|
}
|
|
407
519
|
}
|
|
408
520
|
async function collectWarehouseCredentials(answers, options, input, output) {
|
|
@@ -453,6 +565,7 @@ function runWarehouseCredentialTest(answers) {
|
|
|
453
565
|
if (answers.database === "snowflake") return testSnowflakeCredentials(answers);
|
|
454
566
|
if (answers.database === "bigquery") return testBigQueryCredentials(answers);
|
|
455
567
|
if (answers.database === "clickhouse") return testClickHouseCredentials(answers);
|
|
568
|
+
if (answers.database === "postgres") return testPostgresCredentials(answers);
|
|
456
569
|
return Promise.resolve();
|
|
457
570
|
}
|
|
458
571
|
async function testSnowflakeCredentials(answers) {
|
|
@@ -499,6 +612,25 @@ async function testClickHouseCredentials(answers) {
|
|
|
499
612
|
await client.close();
|
|
500
613
|
}
|
|
501
614
|
}
|
|
615
|
+
async function testPostgresCredentials(answers) {
|
|
616
|
+
let pg = (await import("pg")).default;
|
|
617
|
+
let client = new pg.Client({
|
|
618
|
+
host: answers.postgresHost,
|
|
619
|
+
port: Number(answers.postgresPort || 5432),
|
|
620
|
+
database: answers.postgresDatabase,
|
|
621
|
+
user: answers.postgresUsername,
|
|
622
|
+
password: answers.postgresPassword,
|
|
623
|
+
ssl: answers.postgresSsl,
|
|
624
|
+
application_name: "Graphene"
|
|
625
|
+
});
|
|
626
|
+
try {
|
|
627
|
+
await client.connect();
|
|
628
|
+
await client.query("SELECT 1");
|
|
629
|
+
} finally {
|
|
630
|
+
await client.end().catch(() => {
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
}
|
|
502
634
|
function formatCredentialError(err) {
|
|
503
635
|
if (err instanceof Error && err.message) return err.message;
|
|
504
636
|
return String(err || "Unknown error");
|
|
@@ -511,7 +643,7 @@ async function collectAnswers({ options, packageManager, input, output }) {
|
|
|
511
643
|
projectName: options.name || defaultProjectName(targetDir2),
|
|
512
644
|
packageManager,
|
|
513
645
|
database: "duckdb",
|
|
514
|
-
|
|
646
|
+
agentSetup: "none"
|
|
515
647
|
};
|
|
516
648
|
}
|
|
517
649
|
let targetDir = options.targetDir;
|
|
@@ -534,6 +666,7 @@ async function collectAnswers({ options, packageManager, input, output }) {
|
|
|
534
666
|
{ value: "snowflake", label: "Snowflake" },
|
|
535
667
|
{ value: "bigquery", label: "BigQuery" },
|
|
536
668
|
{ value: "clickhouse", label: "ClickHouse" },
|
|
669
|
+
{ value: "postgres", label: "Postgres" },
|
|
537
670
|
{ value: "duckdb", label: "DuckDB (local file)" }
|
|
538
671
|
],
|
|
539
672
|
...promptOptions(input, output)
|
|
@@ -544,19 +677,20 @@ async function collectAnswers({ options, packageManager, input, output }) {
|
|
|
544
677
|
projectName,
|
|
545
678
|
packageManager,
|
|
546
679
|
database,
|
|
547
|
-
|
|
680
|
+
agentSetup: "none"
|
|
548
681
|
};
|
|
549
682
|
if (database !== "duckdb") {
|
|
550
683
|
await collectWarehouseCredentials(answers, options, input, output);
|
|
551
684
|
}
|
|
552
685
|
if (options.install) {
|
|
553
|
-
answers.
|
|
686
|
+
answers.agentSetup = unwrapPrompt(
|
|
554
687
|
await clack.select({
|
|
555
|
-
message: "
|
|
688
|
+
message: "Configure which agent?",
|
|
556
689
|
options: [
|
|
557
|
-
{ value: "
|
|
558
|
-
{ value: "
|
|
559
|
-
{ value: "
|
|
690
|
+
{ value: "codex", label: "Codex" },
|
|
691
|
+
{ value: "claude", label: "Claude" },
|
|
692
|
+
{ value: "other", label: "Other agent" },
|
|
693
|
+
{ value: "none", label: "Skip extra setup" }
|
|
560
694
|
],
|
|
561
695
|
...promptOptions(input, output)
|
|
562
696
|
})
|
|
@@ -611,10 +745,16 @@ async function installDeps(targetDir, packageManager, env) {
|
|
|
611
745
|
else task.error(`${command} install failed`, { showLog: true });
|
|
612
746
|
return { code, stderr };
|
|
613
747
|
}
|
|
614
|
-
|
|
615
|
-
if (
|
|
748
|
+
function skillLinkDirectory(agentSetup) {
|
|
749
|
+
if (agentSetup === "codex" || agentSetup === "other") return ".agents";
|
|
750
|
+
if (agentSetup === "claude") return ".claude";
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
async function symlinkGrapheneSkill(targetDir, agentSetup) {
|
|
754
|
+
let linkDirectory = skillLinkDirectory(agentSetup);
|
|
755
|
+
if (!linkDirectory) return;
|
|
616
756
|
let sourcePath = path2.join(targetDir, "node_modules/@graphenedata/cli/dist/skills/graphene");
|
|
617
|
-
let linkPath = path2.join(targetDir,
|
|
757
|
+
let linkPath = path2.join(targetDir, linkDirectory, "skills/graphene");
|
|
618
758
|
let relativeSourcePath = path2.relative(path2.dirname(linkPath), sourcePath);
|
|
619
759
|
await mkdir(path2.dirname(linkPath), { recursive: true });
|
|
620
760
|
try {
|
|
@@ -643,7 +783,7 @@ async function runCreate({ argv, cwd, env = {}, stdin, stdout }) {
|
|
|
643
783
|
if (options.install) {
|
|
644
784
|
let install = await installDeps(targetDir, packageManager, env);
|
|
645
785
|
if (install.code !== 0) throw new Error(install.stderr.trim() || `${packageManager.name} install failed with code ${install.code}`);
|
|
646
|
-
await symlinkGrapheneSkill(targetDir, answers.
|
|
786
|
+
await symlinkGrapheneSkill(targetDir, answers.agentSetup);
|
|
647
787
|
}
|
|
648
788
|
clack.outro(completionMessage(answers), { output: stdout });
|
|
649
789
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-graphene",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"author": "Graphene Systems Inc",
|
|
6
6
|
"repository": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@clack/prompts": "^1.2.0",
|
|
29
29
|
"@clickhouse/client": "^1.18.2",
|
|
30
|
-
"@google-cloud/bigquery": "^8.
|
|
30
|
+
"@google-cloud/bigquery": "^8.3.1",
|
|
31
|
+
"pg": "8.13.3",
|
|
31
32
|
"snowflake-sdk": "2.4.0"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|