@svgrid/studio 0.4.0 → 0.6.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +70 -20
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises';
14
14
  import { spawnSync } from 'node:child_process';
15
15
  import { createInterface } from 'node:readline/promises';
16
16
  import { dirname, resolve } from 'node:path';
17
- import { buildStudioBugReport, createProject, deployCommands, emitStudioAppBundle, emitStudioFragment, introspectDatabase, introspectOpenApi, runtimeDeps, listDatabaseTables, missingEnvKeys, parseProject, resolveDeployTarget, resolveSchemas, runStudioAdd, runStudioAddApp, runStudioInit, serializeProject, setEntityDataSource, summarizeVerify, } from '@svgrid/enterprise/studio';
17
+ import { buildStudioBugReport, createProject, deployCommands, emitStudioAppBundle, emitStudioFragment, introspectDatabase, introspectOpenApi, isUserError, runtimeDeps, listDatabaseTables, missingEnvKeys, parseProject, resolveDeployTarget, resolveSchemas, runStudioAdd, runStudioAddApp, runStudioInit, sampleApps, serializeProject, setEntityDataSource, summarizeVerify, UserError, } from '@svgrid/enterprise/studio';
18
18
  import { connect } from './db-connect.js';
19
19
  import { ensureDriverInstalled } from './driver-install.js';
20
20
  import { startDesignerServer } from './designer-server.js';
@@ -36,56 +36,73 @@ const io = {
36
36
  function parse(args) {
37
37
  const out = {};
38
38
  const positional = [];
39
- for (let i = 0; i < args.length; i++) {
39
+ /**
40
+ * Read the value that follows a flag. A missing or flag-shaped value used to
41
+ * come back as `undefined` and read as "not passed", so `--url` at the end of
42
+ * the line silently fell through to a different code path instead of saying
43
+ * what was wrong.
44
+ */
45
+ let i = 0;
46
+ const value = (flag) => {
47
+ const next = args[i + 1];
48
+ if (next === undefined || next.startsWith('-')) {
49
+ throw new UserError(`${flag} needs a value.`, 'Run `svgrid-studio --help` to see what each flag expects.');
50
+ }
51
+ i++;
52
+ return next;
53
+ };
54
+ for (i = 0; i < args.length; i++) {
40
55
  const a = args[i];
41
56
  if (a === '--from')
42
- out.from = args[++i];
57
+ out.from = value(a);
43
58
  else if (a === '--table')
44
- out.table = args[++i];
59
+ out.table = value(a);
45
60
  else if (a === '--route')
46
- out.route = args[++i];
61
+ out.route = value(a);
47
62
  else if (a === '--api')
48
- out.apiRoute = args[++i];
63
+ out.apiRoute = value(a);
49
64
  else if (a === '--sql')
50
65
  out.dataSource = 'sql';
51
66
  else if (a === '--db')
52
- out.db = args[++i];
67
+ out.db = value(a);
53
68
  else if (a === '--url')
54
- out.url = args[++i];
69
+ out.url = value(a);
55
70
  else if (a === '--all')
56
71
  out.all = true;
57
72
  else if (a === '--config')
58
- out.config = args[++i];
73
+ out.config = value(a);
59
74
  else if (a === '--out')
60
- out.outDir = args[++i];
75
+ out.outDir = value(a);
61
76
  else if (a === '--port')
62
- out.port = Number(args[++i]);
77
+ out.port = Number(value(a));
63
78
  else if (a === '--template')
64
- out.template = args[++i];
79
+ out.template = value(a);
65
80
  else if (a === '--no-open')
66
81
  out.noOpen = true;
67
82
  else if (a === '--target')
68
- out.target = args[++i];
83
+ out.target = value(a);
69
84
  else if (a === '--dry-run')
70
85
  out.dryRun = true;
71
86
  else if (a === '--ai')
72
87
  out.ai = true;
73
88
  else if (a === '--app-port')
74
- out.appPort = Number(args[++i]);
89
+ out.appPort = Number(value(a));
75
90
  else if (a === '--fragment')
76
91
  out.fragment = true;
77
92
  else if (a === '--supabase-url')
78
- out.supabaseUrl = args[++i];
93
+ out.supabaseUrl = value(a);
79
94
  else if (a === '--supabase-key')
80
- out.supabaseKey = args[++i];
95
+ out.supabaseKey = value(a);
81
96
  else if (a === '--dataset')
82
- out.dataset = args[++i];
97
+ out.dataset = value(a);
83
98
  else if (a === '--theme')
84
- out.theme = args[++i];
99
+ out.theme = value(a);
85
100
  else if (a === '--dark')
86
101
  out.dark = true;
87
102
  else if (a === '--title')
88
- out.title = args[++i];
103
+ out.title = value(a);
104
+ else if (a === '-f' || a === '--force')
105
+ out.force = true;
89
106
  else if (a === '-y' || a === '--yes')
90
107
  out.yes = true;
91
108
  else if (a === '-h' || a === '--help')
@@ -100,6 +117,28 @@ function parse(args) {
100
117
  out.table = name;
101
118
  return out;
102
119
  }
120
+ /**
121
+ * Every sample id, wrapped so the help stays readable. Built from the registry
122
+ * rather than a hand-kept list: a new sample used to be invisible here until
123
+ * someone remembered to update the sentence.
124
+ */
125
+ function templateIds(width = 62) {
126
+ const lines = [];
127
+ let line = '';
128
+ for (const id of sampleApps.map((s) => s.id)) {
129
+ const next = line ? `${line} | ${id}` : id;
130
+ if (next.length > width) {
131
+ lines.push(line);
132
+ line = id;
133
+ }
134
+ else {
135
+ line = next;
136
+ }
137
+ }
138
+ if (line)
139
+ lines.push(line);
140
+ return lines.join('\n ');
141
+ }
103
142
  const HELP = `svgrid-studio - scaffold CRUD screens from a schema file or a live database
104
143
 
105
144
  Usage:
@@ -126,6 +165,7 @@ Running \`svgrid-studio\` with no arguments starts it too.
126
165
  --out <dir> folder to write the app into (default: .)
127
166
  --theme <id> design-system preset --dark dark mode
128
167
  -y, --yes take every default, ask nothing
168
+ -f, --force write into a folder that already holds another app
129
169
 
130
170
  Deploy (build first, then the provider CLI; target from --target, else
131
171
  studio.config.json, else the adapter in svelte.config.js):
@@ -133,7 +173,8 @@ studio.config.json, else the adapter in svelte.config.js):
133
173
  --dry-run print the resolved commands without running anything
134
174
 
135
175
  Designer (visual app builder, auto-saves to studio.config.json):
136
- --template <id> open a ready-made sample app (crm | ecommerce | projects | support)
176
+ --template <id> open a ready-made sample app:
177
+ ${templateIds()}
137
178
  --config <path> studio.config.json to load + auto-save (default: ./studio.config.json)
138
179
  --out <dir> folder to write the generated app into (default: .)
139
180
  --port <n> port to serve on (default: 4321)
@@ -255,6 +296,7 @@ async function main() {
255
296
  ...(opts.dark ? { dark: true } : {}),
256
297
  ...(opts.title ? { title: opts.title } : {}),
257
298
  ...(opts.yes ? { yes: true } : {}),
299
+ ...(opts.force ? { force: true } : {}),
258
300
  });
259
301
  return;
260
302
  }
@@ -494,6 +536,14 @@ async function writeCrashReport(err) {
494
536
  }
495
537
  main().catch(async (err) => {
496
538
  process.stderr.write(`svgrid-studio: ${err instanceof Error ? err.message : String(err)}\n`);
539
+ // A mistyped connection string is not a bug. Only real crashes earn a report -
540
+ // otherwise ordinary fat-fingering ends with "report this on GitHub", which
541
+ // teaches people to distrust the message and file noise.
542
+ if (isUserError(err)) {
543
+ if (err.hint)
544
+ process.stderr.write(` ${err.hint}\n`);
545
+ process.exit(1);
546
+ }
497
547
  try {
498
548
  await writeCrashReport(err);
499
549
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "commercial",
5
5
  "url": "https://svgrid.com/pricing"
6
6
  },
7
- "version": "0.4.0",
7
+ "version": "0.6.0",
8
8
  "description": "SvGrid Studio CLI: scaffold a full CRUD screen (grid + edit panel + SvelteKit API route) from a Drizzle schema in one command.",
9
9
  "license": "SEE LICENSE IN LICENSE",
10
10
  "author": "jQWidgets <sales@jqwidgets.com>",
@@ -27,7 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@svgrid/enterprise": "^2.4.0"
30
+ "@svgrid/enterprise": "^2.6.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^22.10.7",