@techninja/clearstack 0.3.9 → 0.3.10

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/bin/cli.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Usage:
6
6
  * clearstack init [-y] [--mode fullstack|static] [--port 3000]
7
7
  * clearstack update
8
- * clearstack check [code|docs]
8
+ * clearstack check [code|docs|imports|lint|lint es|format|types|audit|all]
9
9
  * clearstack → interactive menu
10
10
  */
11
11
 
@@ -25,16 +25,21 @@ const yes = args.includes('-y') || args.includes('--yes');
25
25
 
26
26
  /** Show interactive menu. */
27
27
  async function interactive() {
28
- const { select } = await import('@inquirer/prompts');
29
- const action = await select({
30
- message: 'clearstack what do you want to do?',
31
- choices: [
32
- { name: 'Initialize a new project', value: 'init' },
33
- { name: 'Update spec docs + configs', value: 'update' },
34
- { name: 'Run spec compliance check', value: 'check' },
35
- ],
36
- });
37
- await run(action);
28
+ try {
29
+ const { select } = await import('@inquirer/prompts');
30
+ const action = await select({
31
+ message: 'clearstack — what do you want to do?',
32
+ choices: [
33
+ { name: 'Initialize a new project', value: 'init' },
34
+ { name: 'Update spec docs + configs', value: 'update' },
35
+ { name: 'Run spec compliance check', value: 'check' },
36
+ ],
37
+ });
38
+ await run(action);
39
+ } catch (e) {
40
+ if (e?.name === 'ExitPromptError') process.exit(0);
41
+ throw e;
42
+ }
38
43
  }
39
44
 
40
45
  /**
@@ -49,9 +54,9 @@ async function run(action) {
49
54
  const { update } = await import('../lib/update.js');
50
55
  await update(PKG_ROOT);
51
56
  } else if (action === 'check') {
52
- const sub = args.find((a) => a !== cmd && !a.startsWith('-'));
57
+ const subs = args.filter((a) => a !== cmd && !a.startsWith('-'));
53
58
  const { check } = await import('../lib/check.js');
54
- await check(process.cwd(), sub);
59
+ await check(process.cwd(), subs.join(' ') || undefined);
55
60
  } else {
56
61
  console.log('Usage: clearstack [init|update|check] [-y]');
57
62
  }
@@ -117,15 +117,15 @@ relative paths like `../../../utils/foo.js`.
117
117
 
118
118
  ### Available Prefixes
119
119
 
120
- | Prefix | Resolves to |
121
- | --------------- | ------------------------------ |
122
- | `#store/` | `/store/` |
123
- | `#utils/` | `/utils/` |
124
- | `#atoms/` | `/components/atoms/` |
125
- | `#molecules/` | `/components/molecules/` |
126
- | `#organisms/` | `/components/organisms/` |
127
- | `#templates/` | `/components/templates/` |
128
- | `#pages/` | `/pages/` |
120
+ | Prefix | Resolves to |
121
+ | ------------- | ------------------------ |
122
+ | `#store/` | `/store/` |
123
+ | `#utils/` | `/utils/` |
124
+ | `#atoms/` | `/components/atoms/` |
125
+ | `#molecules/` | `/components/molecules/` |
126
+ | `#organisms/` | `/components/organisms/` |
127
+ | `#templates/` | `/components/templates/` |
128
+ | `#pages/` | `/pages/` |
129
129
 
130
130
  ### Rules
131
131
 
@@ -43,12 +43,12 @@ If a property is defined as `undefined` or later set to `null`, this crashes:
43
43
  // ❌ BAD — undefined has no type info, null crashes .toString()
44
44
  export default define({
45
45
  tag: 'my-view',
46
- _data: undefined, // no type info for hybrids to work with
46
+ _data: undefined, // no type info for hybrids to work with
47
47
  // ...
48
48
  });
49
49
 
50
50
  // Later in a handler:
51
- host._data = null; // TypeError: Cannot read properties of null (reading 'toString')
51
+ host._data = null; // TypeError: Cannot read properties of null (reading 'toString')
52
52
  ```
53
53
 
54
54
  Always provide a typed default value, and reset to the same type:
@@ -62,7 +62,7 @@ export default define({
62
62
  });
63
63
 
64
64
  // Later in a handler:
65
- host._data = []; // safe — same type as default
65
+ host._data = []; // safe — same type as default
66
66
  ```
67
67
 
68
68
  The `connect: () => {}` no-op prevents hybrids from doing anything special
@@ -232,14 +232,16 @@ export default define({
232
232
  items: {
233
233
  value: [],
234
234
  connect: (host, _key, invalidate) => {
235
- fetchItems().then((list) => { host.items = list; invalidate(); });
235
+ fetchItems().then((list) => {
236
+ host.items = list;
237
+ invalidate();
238
+ });
236
239
  },
237
240
  },
238
241
  render: ({ items }) => html`
239
242
  // ❌ BAD — items may not be an array yet when render fires
240
- ${items.filter((i) => i.active).map((i) => html`<span>${i.name}</span>`)}
241
-
242
- // ✅ GOOD — guard before calling array methods
243
+ ${items.filter((i) => i.active).map((i) => html`<span>${i.name}</span>`)} // ✅ GOOD — guard
244
+ before calling array methods
243
245
  ${Array.isArray(items) && items.length > 0
244
246
  ? items.filter((i) => i.active).map((i) => html`<span>${i.name}</span>`)
245
247
  : html``}
@@ -350,7 +352,7 @@ properties holding complex objects (arrays of records, parsed data, etc.),
350
352
  the URL becomes enormous — potentially megabytes — and the browser locks
351
353
  up just rendering the `<a>` element.
352
354
 
353
- The `connect: () => {}` no-op prevents hybrids from *observing* a property,
355
+ The `connect: () => {}` no-op prevents hybrids from _observing_ a property,
354
356
  but the router still serializes it. The only way to fully exclude a
355
357
  property from URL serialization is to not define it on the routed view at
356
358
  all (use a module-level variable or a separate store).
@@ -361,10 +363,10 @@ direct href instead of `router.backUrl()`:
361
363
  ```javascript
362
364
  // ❌ BAD — serializes ALL parent properties into the href
363
365
  // If parent has a 700K-item array, the URL is megabytes
364
- html`<a href="${router.backUrl()}">← Back</a>`
366
+ html`<a href="${router.backUrl()}">← Back</a>`;
365
367
 
366
368
  // ✅ GOOD — direct link, no serialization
367
- html`<a href="/dashboard">← Back</a>`
369
+ html`<a href="/dashboard">← Back</a>`;
368
370
  ```
369
371
 
370
372
  Use `router.backUrl()` only when the parent view has simple scalar
package/lib/check.js CHANGED
@@ -114,7 +114,7 @@ export async function check(projectDir, scope) {
114
114
  const cmds = buildCmds(detectRunner(projectDir));
115
115
  const checks = buildChecks(projectDir, cfg, cmds);
116
116
 
117
- if (scope) {
117
+ if (scope && scope !== 'all') {
118
118
  const matched = resolveChecks(checks, scope);
119
119
  if (!matched) {
120
120
  console.log(`Unknown check: ${scope}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techninja/clearstack",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "type": "module",
5
5
  "description": "A no-build web component framework specification — scaffold, validate, and evolve spec-compliant projects",
6
6
  "bin": {
@@ -117,15 +117,15 @@ relative paths like `../../../utils/foo.js`.
117
117
 
118
118
  ### Available Prefixes
119
119
 
120
- | Prefix | Resolves to |
121
- | --------------- | ------------------------------ |
122
- | `#store/` | `/store/` |
123
- | `#utils/` | `/utils/` |
124
- | `#atoms/` | `/components/atoms/` |
125
- | `#molecules/` | `/components/molecules/` |
126
- | `#organisms/` | `/components/organisms/` |
127
- | `#templates/` | `/components/templates/` |
128
- | `#pages/` | `/pages/` |
120
+ | Prefix | Resolves to |
121
+ | ------------- | ------------------------ |
122
+ | `#store/` | `/store/` |
123
+ | `#utils/` | `/utils/` |
124
+ | `#atoms/` | `/components/atoms/` |
125
+ | `#molecules/` | `/components/molecules/` |
126
+ | `#organisms/` | `/components/organisms/` |
127
+ | `#templates/` | `/components/templates/` |
128
+ | `#pages/` | `/pages/` |
129
129
 
130
130
  ### Rules
131
131
 
@@ -43,12 +43,12 @@ If a property is defined as `undefined` or later set to `null`, this crashes:
43
43
  // ❌ BAD — undefined has no type info, null crashes .toString()
44
44
  export default define({
45
45
  tag: 'my-view',
46
- _data: undefined, // no type info for hybrids to work with
46
+ _data: undefined, // no type info for hybrids to work with
47
47
  // ...
48
48
  });
49
49
 
50
50
  // Later in a handler:
51
- host._data = null; // TypeError: Cannot read properties of null (reading 'toString')
51
+ host._data = null; // TypeError: Cannot read properties of null (reading 'toString')
52
52
  ```
53
53
 
54
54
  Always provide a typed default value, and reset to the same type:
@@ -62,7 +62,7 @@ export default define({
62
62
  });
63
63
 
64
64
  // Later in a handler:
65
- host._data = []; // safe — same type as default
65
+ host._data = []; // safe — same type as default
66
66
  ```
67
67
 
68
68
  The `connect: () => {}` no-op prevents hybrids from doing anything special
@@ -232,14 +232,16 @@ export default define({
232
232
  items: {
233
233
  value: [],
234
234
  connect: (host, _key, invalidate) => {
235
- fetchItems().then((list) => { host.items = list; invalidate(); });
235
+ fetchItems().then((list) => {
236
+ host.items = list;
237
+ invalidate();
238
+ });
236
239
  },
237
240
  },
238
241
  render: ({ items }) => html`
239
242
  // ❌ BAD — items may not be an array yet when render fires
240
- ${items.filter((i) => i.active).map((i) => html`<span>${i.name}</span>`)}
241
-
242
- // ✅ GOOD — guard before calling array methods
243
+ ${items.filter((i) => i.active).map((i) => html`<span>${i.name}</span>`)} // ✅ GOOD — guard
244
+ before calling array methods
243
245
  ${Array.isArray(items) && items.length > 0
244
246
  ? items.filter((i) => i.active).map((i) => html`<span>${i.name}</span>`)
245
247
  : html``}
@@ -350,7 +352,7 @@ properties holding complex objects (arrays of records, parsed data, etc.),
350
352
  the URL becomes enormous — potentially megabytes — and the browser locks
351
353
  up just rendering the `<a>` element.
352
354
 
353
- The `connect: () => {}` no-op prevents hybrids from *observing* a property,
355
+ The `connect: () => {}` no-op prevents hybrids from _observing_ a property,
354
356
  but the router still serializes it. The only way to fully exclude a
355
357
  property from URL serialization is to not define it on the routed view at
356
358
  all (use a module-level variable or a separate store).
@@ -361,10 +363,10 @@ direct href instead of `router.backUrl()`:
361
363
  ```javascript
362
364
  // ❌ BAD — serializes ALL parent properties into the href
363
365
  // If parent has a 700K-item array, the URL is megabytes
364
- html`<a href="${router.backUrl()}">← Back</a>`
366
+ html`<a href="${router.backUrl()}">← Back</a>`;
365
367
 
366
368
  // ✅ GOOD — direct link, no serialization
367
- html`<a href="/dashboard">← Back</a>`
369
+ html`<a href="/dashboard">← Back</a>`;
368
370
  ```
369
371
 
370
372
  Use `router.backUrl()` only when the parent view has simple scalar