create-graphene 0.0.18 → 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 -20
- 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,33 +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
|
-
"
|
|
61
|
-
|
|
60
|
+
"playwright-core": "1.58.2",
|
|
61
|
+
"sanitize-html": "^2.17.4",
|
|
62
|
+
svelte: "5.55.7",
|
|
62
63
|
unified: "^11.0.5",
|
|
63
64
|
"unist-util-visit": "4.1.2",
|
|
64
65
|
vite: "7.3.2",
|
|
65
|
-
ws: "^8.
|
|
66
|
+
ws: "^8.20.1"
|
|
66
67
|
},
|
|
67
68
|
devDependencies: {
|
|
69
|
+
"@aws-sdk/client-athena": "^3.1049.0",
|
|
68
70
|
"@clickhouse/client": "^1.18.2",
|
|
69
71
|
"@duckdb/node-api": "1.3.2-alpha.26",
|
|
70
|
-
"@google-cloud/bigquery": "^8.
|
|
72
|
+
"@google-cloud/bigquery": "^8.3.1",
|
|
71
73
|
"@types/fs-extra": "^11.0.4",
|
|
72
74
|
"@types/node": "^20.0.0",
|
|
75
|
+
"@types/pg": "8.11.11",
|
|
73
76
|
"@types/sanitize-html": "^2.16.0",
|
|
74
77
|
"@types/ws": "^8.18.1",
|
|
75
78
|
esbuild: "^0.27.2",
|
|
79
|
+
pg: "8.13.3",
|
|
76
80
|
"snowflake-sdk": "2.4.0",
|
|
77
81
|
vitest: "4.0.18",
|
|
78
82
|
"vscode-languageserver-types": "^3.17.0"
|
|
79
83
|
},
|
|
80
84
|
peerDependencies: {
|
|
85
|
+
"@aws-sdk/client-athena": "^3.1049.0",
|
|
81
86
|
"@clickhouse/client": "^1.18.2",
|
|
82
87
|
"@duckdb/node-api": "1.3.2-alpha.26",
|
|
83
88
|
"@google-cloud/bigquery": "^8.2.0",
|
|
89
|
+
pg: "8.13.3",
|
|
84
90
|
"snowflake-sdk": "2.4.0"
|
|
85
91
|
},
|
|
86
92
|
peerDependenciesMeta: {
|
|
93
|
+
"@aws-sdk/client-athena": {
|
|
94
|
+
optional: true
|
|
95
|
+
},
|
|
87
96
|
"@clickhouse/client": {
|
|
88
97
|
optional: true
|
|
89
98
|
},
|
|
@@ -93,6 +102,9 @@ var package_default = {
|
|
|
93
102
|
"@google-cloud/bigquery": {
|
|
94
103
|
optional: true
|
|
95
104
|
},
|
|
105
|
+
pg: {
|
|
106
|
+
optional: true
|
|
107
|
+
},
|
|
96
108
|
"snowflake-sdk": {
|
|
97
109
|
optional: true
|
|
98
110
|
}
|
|
@@ -179,8 +191,16 @@ function renderTemplate({ answers, cliVersion }) {
|
|
|
179
191
|
graphene.snowflake = { account: answers.snowflakeAccount || "", username: answers.snowflakeUsername || "" };
|
|
180
192
|
} else if (answers.database === "bigquery") {
|
|
181
193
|
graphene.bigquery = { projectId: answers.bigqueryProjectId || "" };
|
|
182
|
-
} else {
|
|
194
|
+
} else if (answers.database === "clickhouse") {
|
|
183
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;
|
|
184
204
|
}
|
|
185
205
|
let pkg = {
|
|
186
206
|
name: answers.projectName,
|
|
@@ -203,9 +223,10 @@ function renderTemplate({ answers, cliVersion }) {
|
|
|
203
223
|
let files = {
|
|
204
224
|
"package.json": JSON.stringify(pkg, null, 2) + "\n",
|
|
205
225
|
".gitignore": ["node_modules", ".env", "*.duckdb"].join("\n") + "\n",
|
|
206
|
-
[agentsFileName(answers.
|
|
226
|
+
[agentsFileName(answers.agentSetup)]: renderAgents(answers),
|
|
207
227
|
"index.md": renderIndex(answers)
|
|
208
228
|
};
|
|
229
|
+
if (answers.agentSetup === "codex") files[".codex/config.toml"] = renderCodexConfig();
|
|
209
230
|
if (answers.packageManager?.name === "yarn") files[".yarnrc.yml"] = "nodeLinker: node-modules\n";
|
|
210
231
|
let envFile = renderEnvFile(answers);
|
|
211
232
|
if (envFile) files[".env"] = envFile;
|
|
@@ -217,8 +238,8 @@ function grapheneCommand(packageManager, args) {
|
|
|
217
238
|
if (packageManager?.name === "bun") return `bun run graphene ${args}`;
|
|
218
239
|
return `npx graphene ${args}`;
|
|
219
240
|
}
|
|
220
|
-
function agentsFileName(
|
|
221
|
-
if (
|
|
241
|
+
function agentsFileName(agentSetup) {
|
|
242
|
+
if (agentSetup === "claude") return "CLAUDE.md";
|
|
222
243
|
return "AGENTS.md";
|
|
223
244
|
}
|
|
224
245
|
function renderAgents(answers) {
|
|
@@ -234,10 +255,32 @@ function renderAgents(answers) {
|
|
|
234
255
|
`- ${grapheneCommand(answers.packageManager, "serve --bg")} - start or restart the local dev server`
|
|
235
256
|
].join("\n") + "\n";
|
|
236
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
|
+
}
|
|
237
279
|
function databaseLabel(database) {
|
|
238
280
|
if (database === "snowflake") return "Snowflake";
|
|
239
281
|
if (database === "bigquery") return "BigQuery";
|
|
240
282
|
if (database === "clickhouse") return "ClickHouse";
|
|
283
|
+
if (database === "postgres") return "Postgres";
|
|
241
284
|
return "DuckDB";
|
|
242
285
|
}
|
|
243
286
|
function renderIndex(answers) {
|
|
@@ -252,6 +295,8 @@ function renderEnvFile(answers) {
|
|
|
252
295
|
lines.push(`GOOGLE_APPLICATION_CREDENTIALS=${answers.bigqueryKeyPath || ""}`);
|
|
253
296
|
} else if (answers.database === "clickhouse") {
|
|
254
297
|
lines.push(`CLICKHOUSE_PASSWORD=${answers.clickhousePassword || ""}`);
|
|
298
|
+
} else if (answers.database === "postgres") {
|
|
299
|
+
lines.push(`POSTGRES_PASSWORD=${answers.postgresPassword || ""}`);
|
|
255
300
|
}
|
|
256
301
|
return lines.length ? lines.join("\n") + "\n" : null;
|
|
257
302
|
}
|
|
@@ -328,6 +373,7 @@ function getWarehouseClient(database) {
|
|
|
328
373
|
if (database === "snowflake") return "snowflake-sdk";
|
|
329
374
|
if (database === "bigquery") return "@google-cloud/bigquery";
|
|
330
375
|
if (database === "clickhouse") return "@clickhouse/client";
|
|
376
|
+
if (database === "postgres") return "pg";
|
|
331
377
|
return "@duckdb/node-api";
|
|
332
378
|
}
|
|
333
379
|
function getWarehouseClientVersion(packageName) {
|
|
@@ -404,6 +450,71 @@ async function promptWarehouseCredentials(answers, input, output) {
|
|
|
404
450
|
...promptOptions(input, output)
|
|
405
451
|
})
|
|
406
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
|
+
);
|
|
407
518
|
}
|
|
408
519
|
}
|
|
409
520
|
async function collectWarehouseCredentials(answers, options, input, output) {
|
|
@@ -454,6 +565,7 @@ function runWarehouseCredentialTest(answers) {
|
|
|
454
565
|
if (answers.database === "snowflake") return testSnowflakeCredentials(answers);
|
|
455
566
|
if (answers.database === "bigquery") return testBigQueryCredentials(answers);
|
|
456
567
|
if (answers.database === "clickhouse") return testClickHouseCredentials(answers);
|
|
568
|
+
if (answers.database === "postgres") return testPostgresCredentials(answers);
|
|
457
569
|
return Promise.resolve();
|
|
458
570
|
}
|
|
459
571
|
async function testSnowflakeCredentials(answers) {
|
|
@@ -500,6 +612,25 @@ async function testClickHouseCredentials(answers) {
|
|
|
500
612
|
await client.close();
|
|
501
613
|
}
|
|
502
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
|
+
}
|
|
503
634
|
function formatCredentialError(err) {
|
|
504
635
|
if (err instanceof Error && err.message) return err.message;
|
|
505
636
|
return String(err || "Unknown error");
|
|
@@ -512,7 +643,7 @@ async function collectAnswers({ options, packageManager, input, output }) {
|
|
|
512
643
|
projectName: options.name || defaultProjectName(targetDir2),
|
|
513
644
|
packageManager,
|
|
514
645
|
database: "duckdb",
|
|
515
|
-
|
|
646
|
+
agentSetup: "none"
|
|
516
647
|
};
|
|
517
648
|
}
|
|
518
649
|
let targetDir = options.targetDir;
|
|
@@ -535,6 +666,7 @@ async function collectAnswers({ options, packageManager, input, output }) {
|
|
|
535
666
|
{ value: "snowflake", label: "Snowflake" },
|
|
536
667
|
{ value: "bigquery", label: "BigQuery" },
|
|
537
668
|
{ value: "clickhouse", label: "ClickHouse" },
|
|
669
|
+
{ value: "postgres", label: "Postgres" },
|
|
538
670
|
{ value: "duckdb", label: "DuckDB (local file)" }
|
|
539
671
|
],
|
|
540
672
|
...promptOptions(input, output)
|
|
@@ -545,19 +677,20 @@ async function collectAnswers({ options, packageManager, input, output }) {
|
|
|
545
677
|
projectName,
|
|
546
678
|
packageManager,
|
|
547
679
|
database,
|
|
548
|
-
|
|
680
|
+
agentSetup: "none"
|
|
549
681
|
};
|
|
550
682
|
if (database !== "duckdb") {
|
|
551
683
|
await collectWarehouseCredentials(answers, options, input, output);
|
|
552
684
|
}
|
|
553
685
|
if (options.install) {
|
|
554
|
-
answers.
|
|
686
|
+
answers.agentSetup = unwrapPrompt(
|
|
555
687
|
await clack.select({
|
|
556
|
-
message: "
|
|
688
|
+
message: "Configure which agent?",
|
|
557
689
|
options: [
|
|
558
|
-
{ value: "
|
|
559
|
-
{ value: "
|
|
560
|
-
{ value: "
|
|
690
|
+
{ value: "codex", label: "Codex" },
|
|
691
|
+
{ value: "claude", label: "Claude" },
|
|
692
|
+
{ value: "other", label: "Other agent" },
|
|
693
|
+
{ value: "none", label: "Skip extra setup" }
|
|
561
694
|
],
|
|
562
695
|
...promptOptions(input, output)
|
|
563
696
|
})
|
|
@@ -612,10 +745,16 @@ async function installDeps(targetDir, packageManager, env) {
|
|
|
612
745
|
else task.error(`${command} install failed`, { showLog: true });
|
|
613
746
|
return { code, stderr };
|
|
614
747
|
}
|
|
615
|
-
|
|
616
|
-
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;
|
|
617
756
|
let sourcePath = path2.join(targetDir, "node_modules/@graphenedata/cli/dist/skills/graphene");
|
|
618
|
-
let linkPath = path2.join(targetDir,
|
|
757
|
+
let linkPath = path2.join(targetDir, linkDirectory, "skills/graphene");
|
|
619
758
|
let relativeSourcePath = path2.relative(path2.dirname(linkPath), sourcePath);
|
|
620
759
|
await mkdir(path2.dirname(linkPath), { recursive: true });
|
|
621
760
|
try {
|
|
@@ -644,7 +783,7 @@ async function runCreate({ argv, cwd, env = {}, stdin, stdout }) {
|
|
|
644
783
|
if (options.install) {
|
|
645
784
|
let install = await installDeps(targetDir, packageManager, env);
|
|
646
785
|
if (install.code !== 0) throw new Error(install.stderr.trim() || `${packageManager.name} install failed with code ${install.code}`);
|
|
647
|
-
await symlinkGrapheneSkill(targetDir, answers.
|
|
786
|
+
await symlinkGrapheneSkill(targetDir, answers.agentSetup);
|
|
648
787
|
}
|
|
649
788
|
clack.outro(completionMessage(answers), { output: stdout });
|
|
650
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": {
|