@techninja/clearstack 0.2.8 → 0.2.18
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/docs/BACKEND_API_SPEC.md +85 -48
- package/docs/BUILD_LOG.md +42 -19
- package/docs/COMPONENT_PATTERNS.md +57 -51
- package/docs/CONVENTIONS.md +43 -31
- package/docs/FRONTEND_IMPLEMENTATION_RULES.md +57 -58
- package/docs/JSDOC_TYPING.md +1 -0
- package/docs/QUICKSTART.md +20 -18
- package/docs/SERVER_AND_DEPS.md +28 -29
- package/docs/STATE_AND_ROUTING.md +53 -52
- package/docs/TESTING.md +38 -37
- package/docs/app-spec/ENTITIES.md +16 -16
- package/docs/app-spec/README.md +4 -4
- package/lib/check.js +3 -1
- package/lib/package-gen.js +3 -0
- package/package.json +5 -2
- package/templates/fullstack/data/seed.json +1 -1
- package/templates/shared/.configs/.markdownlint.jsonc +9 -0
- package/templates/shared/.configs/.stylelintrc.json +16 -0
- package/templates/shared/.configs/jsconfig.json +2 -9
- package/templates/shared/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/templates/shared/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/templates/shared/.github/ISSUE_TEMPLATE/spec_correction.md +1 -1
- package/templates/shared/.github/pull_request_template.md +3 -0
- package/templates/shared/.github/workflows/spec.yml +3 -3
- package/templates/shared/docs/app-spec/README.md +8 -8
- package/templates/shared/docs/clearstack/BACKEND_API_SPEC.md +85 -48
- package/templates/shared/docs/clearstack/BUILD_LOG.md +42 -19
- package/templates/shared/docs/clearstack/COMPONENT_PATTERNS.md +57 -51
- package/templates/shared/docs/clearstack/CONVENTIONS.md +43 -31
- package/templates/shared/docs/clearstack/FRONTEND_IMPLEMENTATION_RULES.md +57 -58
- package/templates/shared/docs/clearstack/JSDOC_TYPING.md +1 -0
- package/templates/shared/docs/clearstack/QUICKSTART.md +20 -18
- package/templates/shared/docs/clearstack/SERVER_AND_DEPS.md +28 -29
- package/templates/shared/docs/clearstack/STATE_AND_ROUTING.md +53 -52
- package/templates/shared/docs/clearstack/TESTING.md +38 -37
- package/templates/shared/src/public/index.html +23 -23
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# State & Routing
|
|
2
|
+
|
|
2
3
|
## Store, Routing, Unified App State & Realtime Sync
|
|
3
4
|
|
|
4
5
|
> How data flows through the application.
|
|
@@ -19,7 +20,11 @@ export default define({
|
|
|
19
20
|
tag: 'app-toggle',
|
|
20
21
|
open: false,
|
|
21
22
|
render: ({ open }) => html`
|
|
22
|
-
<button
|
|
23
|
+
<button
|
|
24
|
+
onclick="${(host) => {
|
|
25
|
+
host.open = !host.open;
|
|
26
|
+
}}"
|
|
27
|
+
>
|
|
23
28
|
${open ? 'Close' : 'Open'}
|
|
24
29
|
</button>
|
|
25
30
|
`,
|
|
@@ -85,9 +90,11 @@ export default define({
|
|
|
85
90
|
tag: 'theme-toggle',
|
|
86
91
|
state: store(AppState),
|
|
87
92
|
render: ({ state }) => html`
|
|
88
|
-
<button
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
<button
|
|
94
|
+
onclick="${(host) => {
|
|
95
|
+
store.set(host.state, { theme: host.state.theme === 'light' ? 'dark' : 'light' });
|
|
96
|
+
}}"
|
|
97
|
+
>
|
|
91
98
|
Theme: ${state.theme}
|
|
92
99
|
</button>
|
|
93
100
|
`,
|
|
@@ -114,13 +121,14 @@ const UserModel = {
|
|
|
114
121
|
lastName: '',
|
|
115
122
|
email: '',
|
|
116
123
|
[store.connect]: {
|
|
117
|
-
get: (id) => fetch(`/api/users/${id}`).then(r => r.json()),
|
|
118
|
-
set: (id, values) =>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
get: (id) => fetch(`/api/users/${id}`).then((r) => r.json()),
|
|
125
|
+
set: (id, values) =>
|
|
126
|
+
fetch(`/api/users/${id}`, {
|
|
127
|
+
method: 'PUT',
|
|
128
|
+
headers: { 'Content-Type': 'application/json' },
|
|
129
|
+
body: JSON.stringify(values),
|
|
130
|
+
}).then((r) => r.json()),
|
|
131
|
+
list: (id) => fetch(`/api/users?${new URLSearchParams(id)}`).then((r) => r.json()),
|
|
124
132
|
},
|
|
125
133
|
};
|
|
126
134
|
|
|
@@ -129,19 +137,19 @@ export default UserModel;
|
|
|
129
137
|
|
|
130
138
|
#### Store API Quick Reference
|
|
131
139
|
|
|
132
|
-
| Method
|
|
133
|
-
|
|
134
|
-
| `store(Model)`
|
|
135
|
-
| `store.get(Model, id)`
|
|
136
|
-
| `store.set(model, values)`
|
|
137
|
-
| `store.sync(model, values)` | Update (sync, immediate)
|
|
138
|
-
| `store.pending(model)`
|
|
139
|
-
| `store.ready(model)`
|
|
140
|
-
| `store.error(model)`
|
|
141
|
-
| `store.clear(Model)`
|
|
142
|
-
| `store.clear([Model])`
|
|
143
|
-
| `store.submit(draft)`
|
|
144
|
-
| `store.resolve(Model, id)`
|
|
140
|
+
| Method | Purpose |
|
|
141
|
+
| --------------------------- | ---------------------------------------------------- |
|
|
142
|
+
| `store(Model)` | Descriptor — binds model to a component property |
|
|
143
|
+
| `store.get(Model, id)` | Get a cached instance (triggers fetch if needed) |
|
|
144
|
+
| `store.set(model, values)` | Update (async, returns Promise) |
|
|
145
|
+
| `store.sync(model, values)` | Update (sync, immediate) |
|
|
146
|
+
| `store.pending(model)` | `false` or `Promise` while loading |
|
|
147
|
+
| `store.ready(model)` | `true` when loaded and valid |
|
|
148
|
+
| `store.error(model)` | `false` or `Error` |
|
|
149
|
+
| `store.clear(Model)` | Invalidate singular model cache |
|
|
150
|
+
| `store.clear([Model])` | Invalidate list cache — **required for list stores** |
|
|
151
|
+
| `store.submit(draft)` | Submit draft mode changes |
|
|
152
|
+
| `store.resolve(Model, id)` | Returns Promise that resolves when ready |
|
|
145
153
|
|
|
146
154
|
#### Decision Tree: Local vs Shared State
|
|
147
155
|
|
|
@@ -161,13 +169,12 @@ clear triggers re-fetch). Always guard property access on list items:
|
|
|
161
169
|
|
|
162
170
|
```javascript
|
|
163
171
|
// ❌ BAD — task may be pending, accessing .title throws
|
|
164
|
-
tasks.map((task) => html`<span>${task.title}</span>`)
|
|
172
|
+
tasks.map((task) => html`<span>${task.title}</span>`);
|
|
165
173
|
|
|
166
174
|
// ✅ GOOD — guard each item, show fallback for pending items
|
|
167
|
-
tasks.map((task) =>
|
|
168
|
-
? html`<span>${task.title}</span>`
|
|
169
|
-
|
|
170
|
-
)
|
|
175
|
+
tasks.map((task) =>
|
|
176
|
+
store.ready(task) ? html`<span>${task.title}</span>` : html`<span class="spinner"></span>`,
|
|
177
|
+
);
|
|
171
178
|
```
|
|
172
179
|
|
|
173
180
|
This is especially important after batch operations (e.g. drag reorder)
|
|
@@ -189,11 +196,7 @@ import HomeView from '../pages/home/index.js';
|
|
|
189
196
|
export default define({
|
|
190
197
|
tag: 'app-router',
|
|
191
198
|
stack: router(HomeView, { url: '/' }),
|
|
192
|
-
render: ({ stack }) => html`
|
|
193
|
-
<template layout="column height::100vh">
|
|
194
|
-
${stack}
|
|
195
|
-
</template>
|
|
196
|
-
`,
|
|
199
|
+
render: ({ stack }) => html` <template layout="column height::100vh"> ${stack} </template> `,
|
|
197
200
|
});
|
|
198
201
|
```
|
|
199
202
|
|
|
@@ -222,14 +225,14 @@ export default define({
|
|
|
222
225
|
|
|
223
226
|
### Routing Patterns
|
|
224
227
|
|
|
225
|
-
| Pattern
|
|
226
|
-
|
|
227
|
-
| Navigate to view
|
|
228
|
-
| Navigate with params | `router.url(View, { id: '42' })`
|
|
229
|
-
| Back button
|
|
230
|
-
| Check active view
|
|
231
|
-
| Guarded route
|
|
232
|
-
| Dialog overlay
|
|
228
|
+
| Pattern | Code |
|
|
229
|
+
| -------------------- | ---------------------------------------- |
|
|
230
|
+
| Navigate to view | `<a href="${router.url(View)}">` |
|
|
231
|
+
| Navigate with params | `router.url(View, { id: '42' })` |
|
|
232
|
+
| Back button | `<a href="${router.backUrl()}">Back</a>` |
|
|
233
|
+
| Check active view | `router.active(View)` |
|
|
234
|
+
| Guarded route | `guard: () => isAuthenticated()` |
|
|
235
|
+
| Dialog overlay | `dialog: true` on the view config |
|
|
233
236
|
|
|
234
237
|
---
|
|
235
238
|
|
|
@@ -253,12 +256,12 @@ DOM
|
|
|
253
256
|
|
|
254
257
|
### AppState vs Entity Models
|
|
255
258
|
|
|
256
|
-
| Concern
|
|
257
|
-
|
|
258
|
-
| Theme, sidebar, UI flags
|
|
259
|
+
| Concern | Where |
|
|
260
|
+
| ------------------------- | ------------------------------------- |
|
|
261
|
+
| Theme, sidebar, UI flags | `AppState` (singleton) |
|
|
259
262
|
| User records, posts, etc. | `UserModel`, `PostModel` (enumerable) |
|
|
260
|
-
| Form draft state
|
|
261
|
-
| Route state
|
|
263
|
+
| Form draft state | `store(Model, { draft: true })` |
|
|
264
|
+
| Route state | `router()` — managed by hybrids |
|
|
262
265
|
|
|
263
266
|
---
|
|
264
267
|
|
|
@@ -280,7 +283,7 @@ export function connectRealtime(url, modelMap) {
|
|
|
280
283
|
source.addEventListener('update', (event) => {
|
|
281
284
|
const { type } = JSON.parse(event.data);
|
|
282
285
|
const Model = modelMap[type];
|
|
283
|
-
if (Model) store.clear(Model);
|
|
286
|
+
if (Model) store.clear(Model); // full clear triggers re-fetch
|
|
284
287
|
});
|
|
285
288
|
|
|
286
289
|
source.addEventListener('error', () => {
|
|
@@ -326,9 +329,7 @@ export default define({
|
|
|
326
329
|
return disconnect;
|
|
327
330
|
},
|
|
328
331
|
},
|
|
329
|
-
render: ({ stack }) => html`
|
|
330
|
-
<template layout="column height::100vh">${stack}</template>
|
|
331
|
-
`,
|
|
332
|
+
render: ({ stack }) => html` <template layout="column height::100vh">${stack}</template> `,
|
|
332
333
|
});
|
|
333
334
|
```
|
|
334
335
|
|
|
@@ -354,7 +355,7 @@ source.addEventListener('update', (event) => {
|
|
|
354
355
|
const { type } = JSON.parse(event.data);
|
|
355
356
|
clearTimeout(timers[type]);
|
|
356
357
|
timers[type] = setTimeout(() => {
|
|
357
|
-
store.clear([Model]);
|
|
358
|
+
store.clear([Model]); // one clear after the batch settles
|
|
358
359
|
}, 300);
|
|
359
360
|
});
|
|
360
361
|
```
|
package/docs/TESTING.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Testing
|
|
2
|
+
|
|
2
3
|
## Philosophy, Tools & Patterns
|
|
3
4
|
|
|
4
5
|
> How we test in a no-build web component project.
|
|
@@ -17,15 +18,15 @@ bugs at the boundary where they're introduced, not 5 layers up.
|
|
|
17
18
|
|
|
18
19
|
### Core Principles
|
|
19
20
|
|
|
20
|
-
| Principle
|
|
21
|
-
|
|
22
|
-
| Test at the right level
|
|
23
|
-
| No mocking the framework
|
|
24
|
-
| Real browser for components
|
|
25
|
-
| Zero build for tests
|
|
26
|
-
| Small test files
|
|
27
|
-
| Test behavior, not implementation | Assert what the user sees, not internal state shape.
|
|
28
|
-
| Co-locate tests
|
|
21
|
+
| Principle | Rule |
|
|
22
|
+
| --------------------------------- | ----------------------------------------------------------- |
|
|
23
|
+
| Test at the right level | Pure logic → unit. Components → browser. API → integration. |
|
|
24
|
+
| No mocking the framework | Don't mock `html`, `store`, or `define`. Test through them. |
|
|
25
|
+
| Real browser for components | Web components need a real DOM. No jsdom, no happy-dom. |
|
|
26
|
+
| Zero build for tests | Test files are ES modules, same as app code. |
|
|
27
|
+
| Small test files | Same 150-line rule applies to test files. |
|
|
28
|
+
| Test behavior, not implementation | Assert what the user sees, not internal state shape. |
|
|
29
|
+
| Co-locate tests | Tests live next to the code they test. |
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
@@ -33,10 +34,10 @@ bugs at the boundary where they're introduced, not 5 layers up.
|
|
|
33
34
|
|
|
34
35
|
### Two Test Runners, Clear Boundaries
|
|
35
36
|
|
|
36
|
-
| Tool
|
|
37
|
-
|
|
38
|
-
| `node:test` (built-in) | Server, utils, store model shapes
|
|
39
|
-
| `@web/test-runner`
|
|
37
|
+
| Tool | Tests | Runs in |
|
|
38
|
+
| ---------------------- | -------------------------------------- | ------------- |
|
|
39
|
+
| `node:test` (built-in) | Server, utils, store model shapes | Node.js |
|
|
40
|
+
| `@web/test-runner` | Components, pages, browser integration | Real Chromium |
|
|
40
41
|
|
|
41
42
|
No other test frameworks. No Jest, no Mocha, no Jasmine.
|
|
42
43
|
|
|
@@ -77,24 +78,24 @@ server.test.js ← node:test
|
|
|
77
78
|
|
|
78
79
|
### Test File Naming
|
|
79
80
|
|
|
80
|
-
| Code file
|
|
81
|
-
|
|
81
|
+
| Code file | Test file |
|
|
82
|
+
| --------------- | -------------------- |
|
|
82
83
|
| `app-button.js` | `app-button.test.js` |
|
|
83
84
|
| `formatDate.js` | `formatDate.test.js` |
|
|
84
|
-
| `UserModel.js`
|
|
85
|
-
| `src/server.js` | `server.test.js`
|
|
85
|
+
| `UserModel.js` | `UserModel.test.js` |
|
|
86
|
+
| `src/server.js` | `server.test.js` |
|
|
86
87
|
|
|
87
88
|
### What Gets Tested
|
|
88
89
|
|
|
89
|
-
| Layer
|
|
90
|
-
|
|
91
|
-
| **Utils**
|
|
90
|
+
| Layer | What to assert |
|
|
91
|
+
| ---------------- | ------------------------------------------------------------------------- |
|
|
92
|
+
| **Utils** | Input → output. Edge cases. |
|
|
92
93
|
| **Store models** | Shape is correct. Computed fields work. Storage connector URLs are right. |
|
|
93
|
-
| **Atoms**
|
|
94
|
-
| **Molecules**
|
|
95
|
-
| **Organisms**
|
|
96
|
-
| **Server API**
|
|
97
|
-
| **Pages**
|
|
94
|
+
| **Atoms** | Renders correct HTML. Props reflect to attributes. Events fire. |
|
|
95
|
+
| **Molecules** | Child atoms are present. Composed behavior works. |
|
|
96
|
+
| **Organisms** | Store integration. Data flows to children. |
|
|
97
|
+
| **Server API** | CRUD responses. Schema endpoint. Status codes. |
|
|
98
|
+
| **Pages** | Don't unit-test pages. Test via manual or E2E if needed. |
|
|
98
99
|
|
|
99
100
|
---
|
|
100
101
|
|
|
@@ -191,7 +192,9 @@ describe('app-button', () => {
|
|
|
191
192
|
it('dispatches click event', async () => {
|
|
192
193
|
const el = await fixture(html`<app-button label="Go"></app-button>`);
|
|
193
194
|
let clicked = false;
|
|
194
|
-
el.addEventListener('click', () => {
|
|
195
|
+
el.addEventListener('click', () => {
|
|
196
|
+
clicked = true;
|
|
197
|
+
});
|
|
195
198
|
el.shadowRoot.querySelector('button').click();
|
|
196
199
|
expect(clicked).to.be.true;
|
|
197
200
|
});
|
|
@@ -230,9 +233,7 @@ import { playwrightLauncher } from '@web/test-runner-playwright';
|
|
|
230
233
|
export default {
|
|
231
234
|
files: 'src/components/**/*.test.js',
|
|
232
235
|
nodeResolve: true,
|
|
233
|
-
browsers: [
|
|
234
|
-
playwrightLauncher({ product: 'chromium' }),
|
|
235
|
-
],
|
|
236
|
+
browsers: [playwrightLauncher({ product: 'chromium' })],
|
|
236
237
|
};
|
|
237
238
|
```
|
|
238
239
|
|
|
@@ -255,14 +256,14 @@ export default {
|
|
|
255
256
|
|
|
256
257
|
Each implementation phase must pass its tests before proceeding:
|
|
257
258
|
|
|
258
|
-
| Phase
|
|
259
|
-
|
|
260
|
-
| 1. Infrastructure | server, vendor script, index.html | Server starts, routes respond, vendor files exist
|
|
261
|
-
| 2. Store + Utils
|
|
262
|
-
| 3. Atoms
|
|
263
|
-
| 4. Molecules
|
|
264
|
-
| 5. Organisms
|
|
265
|
-
| 6. Pages + Router | views, app-router
|
|
259
|
+
| Phase | Implement | Then test |
|
|
260
|
+
| ----------------- | --------------------------------- | --------------------------------------------------- |
|
|
261
|
+
| 1. Infrastructure | server, vendor script, index.html | Server starts, routes respond, vendor files exist |
|
|
262
|
+
| 2. Store + Utils | models, formatDate, realtimeSync | Model shapes, util outputs, localStorage round-trip |
|
|
263
|
+
| 3. Atoms | app-button, app-badge, app-icon | Render, props, events |
|
|
264
|
+
| 4. Molecules | task-card, project-card | Composition, slot content |
|
|
265
|
+
| 5. Organisms | task-list, project-header | Store binding, data rendering |
|
|
266
|
+
| 6. Pages + Router | views, app-router | Navigation, full page render |
|
|
266
267
|
|
|
267
268
|
**Rule: never skip a checkpoint.** If phase 3 tests fail, fix before
|
|
268
269
|
starting phase 4. Bugs compound; catch them at the boundary.
|
|
@@ -4,27 +4,27 @@
|
|
|
4
4
|
|
|
5
5
|
The top-level organizational unit.
|
|
6
6
|
|
|
7
|
-
| Field
|
|
8
|
-
|
|
9
|
-
| id
|
|
10
|
-
| name
|
|
11
|
-
| description | string
|
|
12
|
-
| status
|
|
13
|
-
| createdAt
|
|
7
|
+
| Field | Type | Required | Notes |
|
|
8
|
+
| ----------- | ------------- | -------- | ------------------------------ |
|
|
9
|
+
| id | string (uuid) | auto | Read-only, generated on create |
|
|
10
|
+
| name | string | yes | 1–200 chars |
|
|
11
|
+
| description | string | no | Max 1000 chars |
|
|
12
|
+
| status | enum | no | `active` (default), `archived` |
|
|
13
|
+
| createdAt | date-time | auto | Read-only |
|
|
14
14
|
|
|
15
15
|
## Task
|
|
16
16
|
|
|
17
17
|
A work item belonging to a Project.
|
|
18
18
|
|
|
19
|
-
| Field
|
|
20
|
-
|
|
21
|
-
| id
|
|
22
|
-
| projectId | string (uuid) | yes
|
|
23
|
-
| title
|
|
24
|
-
| status
|
|
25
|
-
| priority
|
|
26
|
-
| sortOrder | number
|
|
27
|
-
| createdAt | date-time
|
|
19
|
+
| Field | Type | Required | Notes |
|
|
20
|
+
| --------- | ------------- | -------- | --------------------------------- |
|
|
21
|
+
| id | string (uuid) | auto | Read-only, generated on create |
|
|
22
|
+
| projectId | string (uuid) | yes | Foreign key → Project.id |
|
|
23
|
+
| title | string | yes | 1–200 chars |
|
|
24
|
+
| status | enum | no | `todo` (default), `doing`, `done` |
|
|
25
|
+
| priority | enum | no | `low`, `med` (default), `high` |
|
|
26
|
+
| sortOrder | number | no | Manual ordering within a project |
|
|
27
|
+
| createdAt | date-time | auto | Read-only |
|
|
28
28
|
|
|
29
29
|
## Relationships
|
|
30
30
|
|
package/docs/app-spec/README.md
CHANGED
|
@@ -11,9 +11,9 @@ all served as raw ES modules with zero build tools.
|
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
|
-
| Feature
|
|
15
|
-
|
|
16
|
-
| Project management | Project
|
|
17
|
-
| Task tracking
|
|
14
|
+
| Feature | Entities | Patterns Exercised |
|
|
15
|
+
| ------------------ | -------- | -------------------------------------------- |
|
|
16
|
+
| Project management | Project | CRUD, schema discovery, validation, SSE sync |
|
|
17
|
+
| Task tracking | Task | Filtered lists, drag reorder, status enums |
|
|
18
18
|
|
|
19
19
|
See [ENTITIES.md](./ENTITIES.md) for field definitions and relationships.
|
package/lib/check.js
CHANGED
|
@@ -47,8 +47,10 @@ export async function check(projectDir, scope) {
|
|
|
47
47
|
const results = [
|
|
48
48
|
checkFiles(projectDir, cfg.codeExt, cfg.codeMax, cfg.ignore, `Code (max ${cfg.codeMax} lines)`),
|
|
49
49
|
checkFiles(projectDir, cfg.docsExt, cfg.docsMax, cfg.ignore, `Docs (max ${cfg.docsMax} lines)`),
|
|
50
|
-
runCmd('ESLint', 'npx eslint --config .configs/eslint.config.js .', projectDir),
|
|
50
|
+
runCmd('ESLint', 'npx eslint --config .configs/eslint.config.js . --fix', projectDir),
|
|
51
|
+
runCmd('Stylelint', 'npx stylelint --config .configs/.stylelintrc.json "src/**/*.css" --fix', projectDir),
|
|
51
52
|
runCmd('Prettier', 'npx prettier --config .configs/.prettierrc --check src', projectDir),
|
|
53
|
+
runCmd('Markdown', 'npx markdownlint-cli2 --config .configs/.markdownlint.jsonc --fix "docs/**/*.md" "*.md"', projectDir),
|
|
52
54
|
runCmd('JSDoc types', 'npx tsc --project .configs/jsconfig.json', projectDir),
|
|
53
55
|
];
|
|
54
56
|
|
package/lib/package-gen.js
CHANGED
|
@@ -43,8 +43,11 @@ export async function writePackageJson(dest, vars, existing) {
|
|
|
43
43
|
eslint: '^10.1.0',
|
|
44
44
|
'eslint-config-prettier': '^10.1.8',
|
|
45
45
|
'eslint-plugin-jsdoc': '^62.8.1',
|
|
46
|
+
'markdownlint-cli2': '^0.22.0',
|
|
46
47
|
playwright: '^1.50.0',
|
|
47
48
|
prettier: '^3.8.1',
|
|
49
|
+
stylelint: '^17.6.0',
|
|
50
|
+
'stylelint-config-standard': '^40.0.0',
|
|
48
51
|
typescript: '^6.0.2',
|
|
49
52
|
};
|
|
50
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techninja/clearstack",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A no-build web component framework specification — scaffold, validate, and evolve spec-compliant projects",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"test": "node --test tests/*.test.js src/utils/*.test.js src/store/*.test.js",
|
|
24
24
|
"spec": "node --env-file=.env scripts/spec.js",
|
|
25
25
|
"lint": "eslint --config .configs/eslint.config.js . --fix",
|
|
26
|
-
"format": "prettier --config .configs/.prettierrc --write src scripts tests",
|
|
26
|
+
"format": "prettier --config .configs/.prettierrc --write src scripts tests templates/**/*.md templates/**/*.html templates/**/*.css templates/**/*.json",
|
|
27
27
|
"typecheck": "tsc --project .configs/jsconfig.json",
|
|
28
28
|
"release": "node scripts/release.js",
|
|
29
29
|
"prepublishOnly": "node scripts/sync-docs.js"
|
|
@@ -54,8 +54,11 @@
|
|
|
54
54
|
"express": "^5.2.1",
|
|
55
55
|
"hybrids": "^9.1.22",
|
|
56
56
|
"lucide-static": "^1.7.0",
|
|
57
|
+
"markdownlint-cli2": "^0.21.0",
|
|
57
58
|
"playwright": "^1.50.0",
|
|
58
59
|
"prettier": "^3.8.1",
|
|
60
|
+
"stylelint": "^17.6.0",
|
|
61
|
+
"stylelint-config-standard": "^40.0.0",
|
|
59
62
|
"typescript": "^6.0.2",
|
|
60
63
|
"ws": "^8.20.0"
|
|
61
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"example": {}}
|
|
1
|
+
{ "example": {} }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "stylelint-config-standard",
|
|
3
|
+
"rules": {
|
|
4
|
+
"import-notation": "string",
|
|
5
|
+
"selector-class-pattern": null,
|
|
6
|
+
"custom-property-pattern": null,
|
|
7
|
+
"no-descending-specificity": null,
|
|
8
|
+
"rule-empty-line-before": [
|
|
9
|
+
"always",
|
|
10
|
+
{
|
|
11
|
+
"except": ["first-nested"],
|
|
12
|
+
"ignore": ["after-comment"]
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -13,13 +13,6 @@
|
|
|
13
13
|
"hybrids": ["../node_modules/hybrids/types/index.d.ts"]
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
|
-
"include": [
|
|
17
|
-
|
|
18
|
-
"../scripts/**/*.js"
|
|
19
|
-
],
|
|
20
|
-
"exclude": [
|
|
21
|
-
"../node_modules",
|
|
22
|
-
"../src/public/vendor",
|
|
23
|
-
"../**/*.test.js"
|
|
24
|
-
]
|
|
16
|
+
"include": ["../src/**/*.js", "../scripts/**/*.js"],
|
|
17
|
+
"exclude": ["../node_modules", "../src/public/vendor", "../**/*.test.js"]
|
|
25
18
|
}
|
|
@@ -12,11 +12,11 @@ jobs:
|
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
16
|
|
|
17
|
-
- uses: actions/setup-node@
|
|
17
|
+
- uses: actions/setup-node@v6
|
|
18
18
|
with:
|
|
19
|
-
node-version:
|
|
19
|
+
node-version: 24
|
|
20
20
|
cache: npm
|
|
21
21
|
|
|
22
22
|
- run: npm ci
|
|
@@ -12,14 +12,14 @@ and architectural decisions live.
|
|
|
12
12
|
|
|
13
13
|
## What to Document
|
|
14
14
|
|
|
15
|
-
| Document
|
|
16
|
-
|
|
17
|
-
| `ENTITIES.md`
|
|
18
|
-
| `PATTERNS.md`
|
|
19
|
-
| `API.md`
|
|
20
|
-
| `DEPLOYMENT.md` | How this project is built, deployed, and monitored
|
|
21
|
-
| `DECISIONS.md`
|
|
22
|
-
| `OVERRIDES.md`
|
|
15
|
+
| Document | Example content |
|
|
16
|
+
| --------------- | -------------------------------------------------------------------- |
|
|
17
|
+
| `ENTITIES.md` | Your domain entities, their relationships, field descriptions |
|
|
18
|
+
| `PATTERNS.md` | Project-specific component patterns, naming overrides |
|
|
19
|
+
| `API.md` | Custom API endpoints beyond the generic CRUD |
|
|
20
|
+
| `DEPLOYMENT.md` | How this project is built, deployed, and monitored |
|
|
21
|
+
| `DECISIONS.md` | Architecture Decision Records — why you chose X over Y |
|
|
22
|
+
| `OVERRIDES.md` | Where your project intentionally deviates from the base spec and why |
|
|
23
23
|
|
|
24
24
|
## Rules
|
|
25
25
|
|