create-semaphor-app 0.1.5 → 0.1.7

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/README.md CHANGED
@@ -7,9 +7,10 @@ npx create-semaphor-app@latest
7
7
  ```
8
8
 
9
9
  The CLI scaffolds the public Semaphor Data App Starter, installs local
10
- dependencies by default, installs the production Semaphor shadcn registry
11
- components, and can optionally install the Semaphor Agent Plugin for detected
12
- Codex and Claude Code installations.
10
+ dependencies by default, and can optionally install the Semaphor Agent Plugin
11
+ for detected Codex and Claude Code installations. The starter already includes
12
+ the Semaphor-specific Data App components and local samples used by agents for
13
+ first-run dashboard quality.
13
14
 
14
15
  It does not authenticate to Semaphor, write tokens, or choose a project/domain.
15
16
  The Semaphor Agent Plugin handles OAuth, project selection, runtime token
@@ -26,22 +27,20 @@ When `app-name` is omitted, the CLI creates `./semaphor-data-app`.
26
27
  Options:
27
28
 
28
29
  ```text
29
- --no-install Skip dependency installation. Requires --components none.
30
+ --no-install Skip dependency installation.
30
31
  --package-manager <name> Use npm, pnpm, yarn, or bun. Defaults to detected npm.
31
32
  --skip-plugin Skip Codex/Claude plugin install prompts.
32
33
  --install-codex-plugin Install the Codex plugin without prompting.
33
34
  --install-claude-plugin Install the Claude Code plugin without prompting.
34
35
  --template <source> Starter source. Defaults to the public starter repo.
35
36
  --template-ref <ref> Git branch/tag for the default starter repo. Defaults to main.
36
- --shadcn-preset <preset> Apply a shadcn preset before adding Semaphor components.
37
+ --shadcn-preset <preset> Apply a shadcn preset after scaffolding.
37
38
  --shadcn-base <base> Pass base or radix to shadcn init when using a preset.
38
- --components <list> Add Semaphor registry components. Defaults to all. Use none, query, metrics,
39
- filters, card, table, matrix, recommended, all, or a comma-separated list.
40
39
  --yes Use noninteractive defaults; skip optional plugin installs unless explicit.
41
40
  --help Show help.
42
41
  ```
43
42
 
44
- ## shadcn Presets And Semaphor Components
43
+ ## shadcn Presets
45
44
 
46
45
  The starter ships with a working shadcn setup. For teams that bring their own
47
46
  style, pass a shadcn preset during creation:
@@ -50,38 +49,28 @@ style, pass a shadcn preset during creation:
50
49
  npx create-semaphor-app@latest my-app --shadcn-preset <preset-id>
51
50
  ```
52
51
 
53
- Semaphor UI helpers are added from the public shadcn registry at scaffold time.
54
- By default, `create-semaphor-app` installs all production app-building
55
- components. Use `--components none` when you want the starter without Semaphor
56
- registry components:
52
+ `--shadcn-preset` runs the shadcn CLI. To skip installs entirely, pass
53
+ `--no-install`, then run dependency and shadcn commands manually later if
54
+ needed.
57
55
 
58
- ```bash
59
- npx create-semaphor-app@latest my-app
60
- npx create-semaphor-app@latest my-app --components none
61
- npx create-semaphor-app@latest my-app --components table
62
- npx create-semaphor-app@latest my-app --components query-state,view-card,metric-kpis,filter-controls,server-data-table,matrix-table
63
- ```
56
+ ## Included Semaphor Components
57
+
58
+ The generated starter includes Semaphor-specific source components under
59
+ `src/components/semaphor/*` and browsable local samples at `/samples`. The
60
+ components are normal app source files, not a separate runtime package:
61
+
62
+ - query loading/error/empty/success states;
63
+ - SDK-shaped query state boundaries;
64
+ - view cards with scoped filter affordances;
65
+ - metric KPI and multi-measure KPI helpers;
66
+ - filter controls;
67
+ - server-backed tables;
68
+ - matrix/pivot tables.
64
69
 
65
- Component presets:
66
-
67
- | Value | Installs |
68
- | --- | --- |
69
- | `none` | No Semaphor registry components. |
70
- | `query` | `query-state` |
71
- | `metrics` | `query-state-boundary`, `metric-kpis` |
72
- | `filters` | `filter-controls` |
73
- | `card` | `view-card` |
74
- | `table` | `query-state`, `server-data-table` |
75
- | `matrix` | `query-state`, `matrix-table` |
76
- | `recommended` | `query-state`, `query-state-boundary`, `view-card`, `metric-kpis`, `filter-controls`, `server-data-table` |
77
- | `all` | `query-state`, `query-state-boundary`, `view-card`, `metric-kpis`, `filter-controls`, `server-data-table`, `matrix-table`. This is the default. |
78
-
79
- Registry components install as source into the generated app. They are optional
80
- UI accelerators and do not replace `react-semaphor/data-app-sdk`.
81
-
82
- `--shadcn-preset` and installed registry components run the shadcn CLI. To skip
83
- installs, pass `--no-install --components none`, then run the shadcn commands
84
- manually later if needed.
70
+ This keeps the default scaffold fast and avoids shadcn overwrite prompts for
71
+ Semaphor components. Customers can still customize shadcn primitives or apply a
72
+ preset, but the default path does not require installing a second component
73
+ registry.
85
74
 
86
75
  ## Local Validation
87
76
 
@@ -13,47 +13,6 @@ const DEFAULT_TEMPLATE_REF = 'main';
13
13
  const DEFAULT_APP_NAME = 'semaphor-data-app';
14
14
  const MARKETPLACE = 'semaphor-analytics/agent-plugin';
15
15
  const PLUGIN_ID = 'semaphor@semaphor-analytics';
16
- const SEMAPHOR_COMPONENT_REGISTRY = 'semaphor-analytics/semaphor-data-app-components';
17
- const SEMAPHOR_COMPONENT_PRESETS = Object.freeze({
18
- none: [],
19
- query: ['query-state'],
20
- table: ['query-state', 'server-data-table'],
21
- metrics: ['query-state-boundary', 'metric-kpis'],
22
- filters: ['filter-controls'],
23
- card: ['view-card'],
24
- matrix: ['query-state', 'matrix-table'],
25
- recommended: [
26
- 'query-state',
27
- 'query-state-boundary',
28
- 'view-card',
29
- 'metric-kpis',
30
- 'filter-controls',
31
- 'server-data-table',
32
- ],
33
- all: [
34
- 'query-state',
35
- 'query-state-boundary',
36
- 'view-card',
37
- 'metric-kpis',
38
- 'filter-controls',
39
- 'server-data-table',
40
- 'matrix-table',
41
- ],
42
- });
43
- const SEMAPHOR_COMPONENT_ALIASES = Object.freeze({
44
- 'query-state': 'query-state',
45
- 'query-state-boundary': 'query-state-boundary',
46
- 'view-card': 'view-card',
47
- card: 'view-card',
48
- 'server-data-table': 'server-data-table',
49
- table: 'server-data-table',
50
- 'metric-kpis': 'metric-kpis',
51
- kpis: 'metric-kpis',
52
- 'filter-controls': 'filter-controls',
53
- filters: 'filter-controls',
54
- 'matrix-table': 'matrix-table',
55
- matrix: 'matrix-table',
56
- });
57
16
  const canPrompt = Boolean(process.stdin.isTTY && process.stdout.isTTY);
58
17
 
59
18
  const cwd = process.cwd();
@@ -65,17 +24,15 @@ Usage:
65
24
  npx create-semaphor-app@latest [app-name] [options]
66
25
 
67
26
  Options:
68
- --no-install Skip dependency installation. Requires --components none.
27
+ --no-install Skip dependency installation.
69
28
  --package-manager <name> Use npm, pnpm, yarn, or bun.
70
29
  --skip-plugin Skip Codex/Claude plugin install prompts.
71
30
  --install-codex-plugin Install the Codex plugin without prompting.
72
31
  --install-claude-plugin Install the Claude Code plugin without prompting.
73
32
  --template <source> Starter source. Can be a local directory or git URL.
74
33
  --template-ref <ref> Git branch/tag for the default starter repo.
75
- --shadcn-preset <preset> Apply a shadcn preset before adding Semaphor components.
34
+ --shadcn-preset <preset> Apply a shadcn preset after scaffolding.
76
35
  --shadcn-base <base> Pass base or radix to shadcn init when using a preset.
77
- --components <list> Add Semaphor registry components. Defaults to all. Use none, query, metrics,
78
- filters, card, table, matrix, recommended, all, or a comma-separated list.
79
36
  --yes, -y Use noninteractive defaults; skip optional plugin installs unless explicit.
80
37
  --help, -h Show this help.
81
38
  `;
@@ -93,7 +50,6 @@ function parseArgs(argv) {
93
50
  templateRef: DEFAULT_TEMPLATE_REF,
94
51
  shadcnPreset: null,
95
52
  shadcnBase: null,
96
- components: 'all',
97
53
  yes: false,
98
54
  help: false,
99
55
  };
@@ -130,10 +86,6 @@ function parseArgs(argv) {
130
86
  parsed.shadcnBase = readRequiredValue(argv, ++i, arg);
131
87
  } else if (arg.startsWith('--shadcn-base=')) {
132
88
  parsed.shadcnBase = arg.slice('--shadcn-base='.length);
133
- } else if (arg === '--components') {
134
- parsed.components = readRequiredValue(argv, ++i, arg);
135
- } else if (arg.startsWith('--components=')) {
136
- parsed.components = arg.slice('--components='.length);
137
89
  } else if (arg === '--yes' || arg === '-y') {
138
90
  parsed.yes = true;
139
91
  } else if (arg.startsWith('-')) {
@@ -285,10 +237,6 @@ function resolvePackageManager(requested) {
285
237
  return 'npm';
286
238
  }
287
239
 
288
- function hasOwn(object, key) {
289
- return Object.prototype.hasOwnProperty.call(object, key);
290
- }
291
-
292
240
  function resolveShadcnRunner(packageManager) {
293
241
  if (packageManager === 'pnpm') {
294
242
  return { command: 'pnpm', args: ['dlx', 'shadcn@latest'] };
@@ -392,30 +340,6 @@ function loadTemplate(template, templateRef) {
392
340
  return { tempRoot, templateDir };
393
341
  }
394
342
 
395
- function normalizeSemaphorComponents(value) {
396
- const raw = String(value || 'none')
397
- .split(',')
398
- .map((entry) => entry.trim().toLowerCase())
399
- .filter(Boolean);
400
- if (raw.length === 0) return [];
401
-
402
- const components = [];
403
- for (const entry of raw) {
404
- if (hasOwn(SEMAPHOR_COMPONENT_PRESETS, entry)) {
405
- components.push(...SEMAPHOR_COMPONENT_PRESETS[entry]);
406
- continue;
407
- }
408
- if (!hasOwn(SEMAPHOR_COMPONENT_ALIASES, entry)) {
409
- throw new Error(
410
- `Unsupported Semaphor component "${entry}". Use none, query, metrics, filters, card, table, matrix, recommended, all, or one of ${Object.keys(SEMAPHOR_COMPONENT_ALIASES).join(', ')}.`,
411
- );
412
- }
413
- components.push(SEMAPHOR_COMPONENT_ALIASES[entry]);
414
- }
415
-
416
- return Array.from(new Set(components));
417
- }
418
-
419
343
  function normalizeShadcnBase(value) {
420
344
  if (!value) return null;
421
345
  const normalized = String(value).trim().toLowerCase();
@@ -426,7 +350,6 @@ function normalizeShadcnBase(value) {
426
350
  }
427
351
 
428
352
  function validateScaffoldOptions(args) {
429
- const components = normalizeSemaphorComponents(args.components);
430
353
  normalizeShadcnBase(args.shadcnBase);
431
354
 
432
355
  if (args.shadcnBase && !args.shadcnPreset) {
@@ -437,9 +360,9 @@ function validateScaffoldOptions(args) {
437
360
  throw new Error('--shadcn-preset requires a non-empty preset id.');
438
361
  }
439
362
 
440
- if (!args.install && (args.shadcnPreset || components.length > 0)) {
363
+ if (!args.install && args.shadcnPreset) {
441
364
  throw new Error(
442
- '--no-install cannot be combined with --shadcn-preset or --components. Run create-semaphor-app with installs enabled, or add shadcn components manually after scaffolding.',
365
+ '--no-install cannot be combined with --shadcn-preset. Run create-semaphor-app with installs enabled, or apply the shadcn preset manually after scaffolding.',
443
366
  );
444
367
  }
445
368
  }
@@ -454,11 +377,10 @@ function runShadcn(packageManager, targetDir, args) {
454
377
  }
455
378
 
456
379
  function customizeShadcn(args, packageManager, targetDir) {
457
- const components = normalizeSemaphorComponents(args.components);
458
380
  const shadcnBase = normalizeShadcnBase(args.shadcnBase);
459
381
 
460
- if (!args.shadcnPreset && components.length === 0) {
461
- return { presetApplied: false, components };
382
+ if (!args.shadcnPreset) {
383
+ return { presetApplied: false };
462
384
  }
463
385
 
464
386
  if (args.shadcnPreset) {
@@ -479,18 +401,7 @@ function customizeShadcn(args, packageManager, targetDir) {
479
401
  console.log('✓ Applied shadcn preset');
480
402
  }
481
403
 
482
- if (components.length > 0) {
483
- console.log('\nAdding Semaphor registry components...');
484
- for (const component of components) {
485
- runShadcn(packageManager, targetDir, [
486
- 'add',
487
- `${SEMAPHOR_COMPONENT_REGISTRY}/${component}`,
488
- ]);
489
- console.log(`✓ Added ${component}`);
490
- }
491
- }
492
-
493
- return { presetApplied: Boolean(args.shadcnPreset), components };
404
+ return { presetApplied: true };
494
405
  }
495
406
 
496
407
  function detectAgents() {
@@ -595,14 +506,9 @@ function printNextSteps({ targetDir, packageManager, pluginSummary, shadcnSummar
595
506
  console.log(` cd ${relativeTarget}`);
596
507
  console.log(` ${packageManager} run dev`);
597
508
 
598
- if (shadcnSummary?.presetApplied || shadcnSummary?.components?.length > 0) {
509
+ if (shadcnSummary?.presetApplied) {
599
510
  console.log('\nConfigured shadcn:');
600
- if (shadcnSummary.presetApplied) {
601
- console.log(' - Applied custom preset');
602
- }
603
- for (const component of shadcnSummary.components ?? []) {
604
- console.log(` - Added Semaphor ${component}`);
605
- }
511
+ console.log(' - Applied custom preset');
606
512
  }
607
513
 
608
514
  if (pluginSummary?.skipped) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-semaphor-app",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Create a Semaphor Data App starter project.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -98,8 +98,6 @@ async function main() {
98
98
  '--template',
99
99
  defaultLocalStarterPath,
100
100
  '--no-install',
101
- '--components',
102
- 'none',
103
101
  '--skip-plugin',
104
102
  '--yes',
105
103
  ], { cwd: root });
@@ -115,8 +113,6 @@ async function main() {
115
113
  '--template',
116
114
  defaultLocalStarterPath,
117
115
  '--no-install',
118
- '--components',
119
- 'none',
120
116
  '--skip-plugin',
121
117
  '--yes',
122
118
  ], { cwd: root });
@@ -130,8 +126,6 @@ async function main() {
130
126
  const result = runCli([
131
127
  'github-template-app',
132
128
  '--no-install',
133
- '--components',
134
- 'none',
135
129
  '--skip-plugin',
136
130
  '--yes',
137
131
  ], { cwd: root });
@@ -152,8 +146,6 @@ async function main() {
152
146
  '--template',
153
147
  defaultLocalStarterPath,
154
148
  '--no-install',
155
- '--components',
156
- 'none',
157
149
  '--install-codex-plugin',
158
150
  ], {
159
151
  cwd: root,
@@ -176,52 +168,6 @@ async function main() {
176
168
  console.log('✓ fake Codex plugin install path');
177
169
  }
178
170
 
179
- {
180
- const root = createTempRoot('default-components-');
181
- const binDir = path.join(root, 'bin');
182
- fs.mkdirSync(binDir, { recursive: true });
183
- const shadcnLog = path.join(root, 'shadcn.log');
184
- const npmLog = path.join(root, 'npm.log');
185
- createFakeCommand(binDir, 'npx', shadcnLog);
186
- createFakeCommand(binDir, 'npm', npmLog);
187
-
188
- const result = runCli([
189
- 'default-components-app',
190
- '--template',
191
- defaultLocalStarterPath,
192
- '--skip-plugin',
193
- '--yes',
194
- '--package-manager',
195
- 'npm',
196
- ], {
197
- cwd: root,
198
- env: {
199
- ...process.env,
200
- PATH: `${binDir}${path.delimiter}${process.env.PATH || ''}`,
201
- },
202
- });
203
- assertSuccess(result, 'default component install');
204
- assertScaffold(root, 'default-components-app');
205
- const npmInstallLog = fs.readFileSync(npmLog, 'utf8');
206
- assert(npmInstallLog.includes('npm install'), 'expected npm install command');
207
- const log = fs.readFileSync(shadcnLog, 'utf8');
208
- for (const component of [
209
- 'query-state',
210
- 'query-state-boundary',
211
- 'view-card',
212
- 'metric-kpis',
213
- 'filter-controls',
214
- 'server-data-table',
215
- 'matrix-table',
216
- ]) {
217
- assert(
218
- log.includes(`npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/${component}`),
219
- `expected default ${component} registry add command`,
220
- );
221
- }
222
- console.log('✓ default Semaphor registry component install');
223
- }
224
-
225
171
  {
226
172
  const root = createTempRoot('shadcn-');
227
173
  const binDir = path.join(root, 'bin');
@@ -243,8 +189,6 @@ async function main() {
243
189
  'test-preset',
244
190
  '--shadcn-base',
245
191
  'base',
246
- '--components',
247
- 'recommended,matrix-table',
248
192
  ], {
249
193
  cwd: root,
250
194
  env: {
@@ -252,7 +196,7 @@ async function main() {
252
196
  PATH: `${binDir}${path.delimiter}${process.env.PATH || ''}`,
253
197
  },
254
198
  });
255
- assertSuccess(result, 'shadcn preset and component install');
199
+ assertSuccess(result, 'shadcn preset install');
256
200
  assertScaffold(root, 'styled-app');
257
201
  const npmInstallLog = fs.readFileSync(npmLog, 'utf8');
258
202
  assert(npmInstallLog.includes('npm install'), 'expected npm install command');
@@ -262,34 +206,10 @@ async function main() {
262
206
  'expected shadcn preset init command',
263
207
  );
264
208
  assert(
265
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/query-state'),
266
- 'expected query-state registry add command',
267
- );
268
- assert(
269
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/query-state-boundary'),
270
- 'expected query-state-boundary registry add command',
271
- );
272
- assert(
273
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/view-card'),
274
- 'expected view-card registry add command',
209
+ !log.includes('npx shadcn@latest add'),
210
+ 'create-semaphor-app should not run shadcn add during scaffold',
275
211
  );
276
- assert(
277
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/metric-kpis'),
278
- 'expected metric-kpis registry add command',
279
- );
280
- assert(
281
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/filter-controls'),
282
- 'expected filter-controls registry add command',
283
- );
284
- assert(
285
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/server-data-table'),
286
- 'expected server-data-table registry add command',
287
- );
288
- assert(
289
- log.includes('npx shadcn@latest add semaphor-analytics/semaphor-data-app-components/matrix-table'),
290
- 'expected matrix-table registry add command',
291
- );
292
- console.log('✓ shadcn preset and registry component path');
212
+ console.log('✓ shadcn preset path');
293
213
  }
294
214
 
295
215
  {
@@ -301,8 +221,8 @@ async function main() {
301
221
  '--no-install',
302
222
  '--skip-plugin',
303
223
  '--yes',
304
- '--components',
305
- 'table',
224
+ '--shadcn-preset',
225
+ 'test-preset',
306
226
  ], { cwd: root });
307
227
  assert(result.status !== 0, 'expected shadcn options with --no-install to fail');
308
228
  assert(