Skip to content

Commit 8a75f61

Browse files
committed
release: v0.2.17
1 parent 06ac2f8 commit 8a75f61

11 files changed

Lines changed: 348 additions & 380 deletions

‎CHANGELOG.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

77
## [Unreleased]
88

9+
## [0.2.17] - 2026-04-02
10+
11+
- Add Style and Markdown linting, templates, fixes
12+
- Refactor for scaffolding tests
13+
14+
915
## [0.2.16] - 2026-04-02
1016

1117
- Trusting some random gist

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@techninja/clearstack",
3-
"version": "0.2.16",
3+
"version": "0.2.17",
44
"type": "module",
55
"description": "A no-build web component framework specification — scaffold, validate, and evolve spec-compliant projects",
66
"bin": {

‎templates/shared/docs/clearstack/BACKEND_API_SPEC.md‎

Lines changed: 48 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -71,25 +71,25 @@ The `Allow` header is also set for HTTP compliance.
7171
The frontend can fetch the schema at runtime and generate form fields
7272
automatically. The schema provides:
7373

74-
| JSON Schema keyword | Form behavior |
75-
| ------------------------- | ---------------------------------------------- |
76-
| `type: "string"` | `<input type="text">` |
77-
| `format: "email"` | `<input type="email">` |
78-
| `format: "date-time"` | `<input type="datetime-local">` |
79-
| `enum: [...]` | `<select>` with options |
80-
| `minLength` / `maxLength` | Validation constraints |
81-
| `readOnly: true` | Field displayed but not editable |
82-
| `required: [...]` | Native `required` attribute + visual indicator |
74+
| JSON Schema keyword | Form behavior |
75+
|---|---|
76+
| `type: "string"` | `<input type="text">` |
77+
| `format: "email"` | `<input type="email">` |
78+
| `format: "date-time"` | `<input type="datetime-local">` |
79+
| `enum: [...]` | `<select>` with options |
80+
| `minLength` / `maxLength` | Validation constraints |
81+
| `readOnly: true` | Field displayed but not editable |
82+
| `required: [...]` | Native `required` attribute + visual indicator |
8383

8484
JSON Schema constraints map directly to HTML validation attributes:
8585

8686
| JSON Schema | HTML attribute |
87-
| ----------- | -------------- |
88-
| `minLength` | `minlength` |
89-
| `maxLength` | `maxlength` |
90-
| `minimum` | `min` |
91-
| `maximum` | `max` |
92-
| `pattern` | `pattern` |
87+
|---|---|
88+
| `minLength` | `minlength` |
89+
| `maxLength` | `maxlength` |
90+
| `minimum` | `min` |
91+
| `maximum` | `max` |
92+
| `pattern` | `pattern` |
9393

9494
The browser's native constraint validation API enforces these — no custom
9595
JS validation needed for client-side checks.
@@ -116,13 +116,13 @@ The `schema-form` component maps `fields` entries to the corresponding
116116

117117
### Error Response Contract
118118

119-
| Status | Body | Meaning |
120-
| ------ | ------------------- | --------------------------------------------------- |
121-
| `422` | `{ error, fields }` | Validation failed — `fields` maps names to messages |
122-
| `404` | `{ error }` | Entity or collection not found |
123-
| `201` | Entity JSON | Created successfully |
124-
| `200` | Entity JSON | Updated successfully |
125-
| `204` | Empty | Deleted successfully |
119+
| Status | Body | Meaning |
120+
|---|---|---|
121+
| `422` | `{ error, fields }` | Validation failed — `fields` maps names to messages |
122+
| `404` | `{ error }` | Entity or collection not found |
123+
| `201` | Entity JSON | Created successfully |
124+
| `200` | Entity JSON | Updated successfully |
125+
| `204` | Empty | Deleted successfully |
126126

127127
This allows a single generic `schema-form` component to render any entity's
128128
create/edit form without entity-specific template code.
@@ -135,12 +135,12 @@ create/edit form without entity-specific template code.
135135

136136
Query params for filtering, sorting, pagination:
137137

138-
| Param | Example | Purpose |
139-
| -------- | ------------------ | ------------------------------- |
140-
| `limit` | `?limit=20` | Page size (default: 20) |
141-
| `offset` | `?offset=40` | Skip N records |
142-
| `sort` | `?sort=-createdAt` | Sort field, `-` prefix for desc |
143-
| `filter` | `?role=admin` | Field equality filter |
138+
| Param | Example | Purpose |
139+
|---|---|---|
140+
| `limit` | `?limit=20` | Page size (default: 20) |
141+
| `offset` | `?offset=40` | Skip N records |
142+
| `sort` | `?sort=-createdAt` | Sort field, `-` prefix for desc |
143+
| `filter` | `?role=admin` | Field equality filter |
144144

145145
Response:
146146

@@ -201,11 +201,11 @@ event: update
201201
data: {"type":"user","id":"2","action":"deleted"}
202202
```
203203

204-
| Field | Value |
205-
| -------- | ------------------------------------------------- |
206-
| `type` | Entity name (lowercase, singular): `user`, `post` |
207-
| `id` | Entity ID that changed |
208-
| `action` | `created`, `updated`, or `deleted` |
204+
| Field | Value |
205+
|---|---|
206+
| `type` | Entity name (lowercase, singular): `user`, `post` |
207+
| `id` | Entity ID that changed |
208+
| `action` | `created`, `updated`, or `deleted` |
209209

210210
### Frontend Integration
211211

@@ -227,44 +227,11 @@ required.
227227
const db = new Map();
228228

229229
// Seed with dummy users
230-
db.set(
231-
'users',
232-
new Map([
233-
[
234-
'1',
235-
{
236-
id: '1',
237-
firstName: 'Jane',
238-
lastName: 'Doe',
239-
email: 'jane@example.com',
240-
role: 'admin',
241-
createdAt: '2024-01-15T09:00:00Z',
242-
},
243-
],
244-
[
245-
'2',
246-
{
247-
id: '2',
248-
firstName: 'John',
249-
lastName: 'Smith',
250-
email: 'john@example.com',
251-
role: 'editor',
252-
createdAt: '2024-02-20T14:30:00Z',
253-
},
254-
],
255-
[
256-
'3',
257-
{
258-
id: '3',
259-
firstName: 'Alex',
260-
lastName: 'Chen',
261-
email: 'alex@example.com',
262-
role: 'viewer',
263-
createdAt: '2024-03-10T11:15:00Z',
264-
},
265-
],
266-
]),
267-
);
230+
db.set('users', new Map([
231+
['1', { id: '1', firstName: 'Jane', lastName: 'Doe', email: 'jane@example.com', role: 'admin', createdAt: '2024-01-15T09:00:00Z' }],
232+
['2', { id: '2', firstName: 'John', lastName: 'Smith', email: 'john@example.com', role: 'editor', createdAt: '2024-02-20T14:30:00Z' }],
233+
['3', { id: '3', firstName: 'Alex', lastName: 'Chen', email: 'alex@example.com', role: 'viewer', createdAt: '2024-03-10T11:15:00Z' }],
234+
]));
268235
```
269236

270237
### Schema Registry (server-side)
@@ -278,9 +245,7 @@ schemas.set('users', {
278245
title: 'User',
279246
type: 'object',
280247
required: ['firstName', 'lastName', 'email'],
281-
properties: {
282-
/* ... as above ... */
283-
},
248+
properties: { /* ... as above ... */ },
284249
});
285250
```
286251

@@ -298,15 +263,15 @@ router that works for any entity registered in the schema map.
298263

299264
## Frontend ↔ Backend Contract
300265

301-
| Frontend (Hybrids Store) | Backend (Express) |
302-
| --------------------------------- | -------------------------- |
303-
| `[store.connect].get(id)` | `GET /api/:entity/:id` |
304-
| `[store.connect].set(id, values)` | `PUT /api/:entity/:id` |
305-
| `[store.connect].list(params)` | `GET /api/:entity?...` |
306-
| `store.set(model, null)` (delete) | `DELETE /api/:entity/:id` |
307-
| Schema fetch for forms | `OPTIONS /api/:entity` |
308-
| Schema fetch for item | `OPTIONS /api/:entity/:id` |
309-
| Realtime invalidation | `GET /api/events` (SSE) |
266+
| Frontend (Hybrids Store) | Backend (Express) |
267+
|---|---|
268+
| `[store.connect].get(id)` | `GET /api/:entity/:id` |
269+
| `[store.connect].set(id, values)` | `PUT /api/:entity/:id` |
270+
| `[store.connect].list(params)` | `GET /api/:entity?...` |
271+
| `store.set(model, null)` (delete) | `DELETE /api/:entity/:id` |
272+
| Schema fetch for forms | `OPTIONS /api/:entity` |
273+
| Schema fetch for item | `OPTIONS /api/:entity/:id` |
274+
| Realtime invalidation | `GET /api/events` (SSE) |
310275

311276
This contract means adding a new entity type requires:
312277

‎templates/shared/docs/clearstack/BUILD_LOG.md‎

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -172,26 +172,26 @@ These are the significant corrections:
172172

173173
## Metrics
174174

175-
| Metric | Value |
176-
| ---------------------------- | ------------------------------------------------ |
177-
| Total source files | 108 |
178-
| Utility modules | 25 |
179-
| Component files | 13 |
180-
| Style sheets | 6 |
181-
| API modules | 6 |
182-
| Page views | 2 |
183-
| Test files | 14 |
184-
| Node tests | 65 |
185-
| Browser tests | 41 |
186-
| Spec documents | 10 |
187-
| Max lines per file | 150 (enforced) |
188-
| Max lines per doc | 500 (enforced) |
189-
| Automated checks | 7 (line counts, lint, format, types, tests) |
190-
| Build phases | 8 + whiteboard |
191-
| Bugs found & fixed | ~25 significant |
175+
| Metric | Value |
176+
|---|---|
177+
| Total source files | 108 |
178+
| Utility modules | 25 |
179+
| Component files | 13 |
180+
| Style sheets | 6 |
181+
| API modules | 6 |
182+
| Page views | 2 |
183+
| Test files | 14 |
184+
| Node tests | 65 |
185+
| Browser tests | 41 |
186+
| Spec documents | 10 |
187+
| Max lines per file | 150 (enforced) |
188+
| Max lines per doc | 500 (enforced) |
189+
| Automated checks | 7 (line counts, lint, format, types, tests) |
190+
| Build phases | 8 + whiteboard |
191+
| Bugs found & fixed | ~25 significant |
192192
| Bugs requiring >4 iterations | 3 (drag reorder, event bubbling, SVG transforms) |
193-
| External dependencies | 4 runtime (hybrids, express, ws, lucide-static) |
194-
| Build tools | 0 |
193+
| External dependencies | 4 runtime (hybrids, express, ws, lucide-static) |
194+
| Build tools | 0 |
195195

196196
---
197197

0 commit comments

Comments
 (0)