mythik 0.1.2 → 0.1.3
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 +47 -23
- package/dist/actions/dispatcher.d.ts.map +1 -1
- package/dist/actions/dispatcher.js +10 -0
- package/dist/actions/dispatcher.js.map +1 -1
- package/dist/expressions/handlers/let.d.ts +6 -0
- package/dist/expressions/handlers/let.d.ts.map +1 -1
- package/dist/expressions/handlers/let.js +29 -4
- package/dist/expressions/handlers/let.js.map +1 -1
- package/dist/expressions/handlers/template.d.ts.map +1 -1
- package/dist/expressions/handlers/template.js +2 -1
- package/dist/expressions/handlers/template.js.map +1 -1
- package/dist/security/api-spec-validator.d.ts.map +1 -1
- package/dist/security/api-spec-validator.js +4 -0
- package/dist/security/api-spec-validator.js.map +1 -1
- package/dist/security/spec-validator.d.ts.map +1 -1
- package/dist/security/spec-validator.js +43 -31
- package/dist/security/spec-validator.js.map +1 -1
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +3 -0
- package/dist/server.js.map +1 -1
- package/dist/spec-stores/sql-versioned.d.ts +38 -0
- package/dist/spec-stores/sql-versioned.d.ts.map +1 -0
- package/dist/spec-stores/sql-versioned.js +186 -0
- package/dist/spec-stores/sql-versioned.js.map +1 -0
- package/dist/spec-stores/sql.d.ts +21 -0
- package/dist/spec-stores/sql.d.ts.map +1 -0
- package/dist/spec-stores/sql.js +65 -0
- package/dist/spec-stores/sql.js.map +1 -0
- package/dist/spec-stores/sqlserver-versioned.d.ts +5 -30
- package/dist/spec-stores/sqlserver-versioned.d.ts.map +1 -1
- package/dist/spec-stores/sqlserver-versioned.js +16 -245
- package/dist/spec-stores/sqlserver-versioned.js.map +1 -1
- package/dist/spec-stores/sqlserver.d.ts +4 -11
- package/dist/spec-stores/sqlserver.d.ts.map +1 -1
- package/dist/spec-stores/sqlserver.js +16 -66
- package/dist/spec-stores/sqlserver.js.map +1 -1
- package/dist/sql/ddl.d.ts +7 -0
- package/dist/sql/ddl.d.ts.map +1 -0
- package/dist/sql/ddl.js +134 -0
- package/dist/sql/ddl.js.map +1 -0
- package/dist/sql/drivers/mysql.d.ts +25 -0
- package/dist/sql/drivers/mysql.d.ts.map +1 -0
- package/dist/sql/drivers/mysql.js +327 -0
- package/dist/sql/drivers/mysql.js.map +1 -0
- package/dist/sql/drivers/postgres.d.ts +30 -0
- package/dist/sql/drivers/postgres.d.ts.map +1 -0
- package/dist/sql/drivers/postgres.js +319 -0
- package/dist/sql/drivers/postgres.js.map +1 -0
- package/dist/sql/drivers/sqlite.d.ts +28 -0
- package/dist/sql/drivers/sqlite.d.ts.map +1 -0
- package/dist/sql/drivers/sqlite.js +367 -0
- package/dist/sql/drivers/sqlite.js.map +1 -0
- package/dist/sql/drivers/sqlserver.d.ts +46 -0
- package/dist/sql/drivers/sqlserver.d.ts.map +1 -0
- package/dist/sql/drivers/sqlserver.js +403 -0
- package/dist/sql/drivers/sqlserver.js.map +1 -0
- package/dist/sql/errors.d.ts +12 -0
- package/dist/sql/errors.d.ts.map +1 -0
- package/dist/sql/errors.js +13 -0
- package/dist/sql/errors.js.map +1 -0
- package/dist/sql/factory.d.ts +3 -0
- package/dist/sql/factory.d.ts.map +1 -0
- package/dist/sql/factory.js +24 -0
- package/dist/sql/factory.js.map +1 -0
- package/dist/sql/index.d.ts +17 -0
- package/dist/sql/index.d.ts.map +1 -0
- package/dist/sql/index.js +9 -0
- package/dist/sql/index.js.map +1 -0
- package/dist/sql/named-params.d.ts +8 -0
- package/dist/sql/named-params.d.ts.map +1 -0
- package/dist/sql/named-params.js +182 -0
- package/dist/sql/named-params.js.map +1 -0
- package/dist/sql/types.d.ts +49 -0
- package/dist/sql/types.d.ts.map +1 -0
- package/dist/sql/types.js +2 -0
- package/dist/sql/types.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/consumer/README.md +1 -1
- package/docs/consumer/WHERE-TO-LOOK.md +4 -4
- package/docs/consumer/ai-context-api.md +44 -0
- package/docs/consumer/ai-context-runtime-semantics.md +12 -9
- package/docs/consumer/ai-context.md +124 -50
- package/docs/consumer/reference-doc.md +41 -24
- package/docs/wiki/compiled/README.md +1 -1
- package/docs/wiki/compiled/_lint.md +13 -8
- package/docs/wiki/compiled/concept-action-chains.md +62 -24
- package/docs/wiki/compiled/concept-package-layout.md +5 -3
- package/docs/wiki/compiled/concept-public-package-names.md +4 -2
- package/docs/wiki/compiled/concept-shape-animations.md +1 -1
- package/docs/wiki/compiled/concept-spec-stores-catalog.md +28 -16
- package/docs/wiki/compiled/concept-transactions.md +20 -12
- package/docs/wiki/compiled/expression-let-ref.md +36 -18
- package/docs/wiki/compiled/expression-template.md +28 -17
- package/package.json +7 -2
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
Public npm package names are unscoped:
|
|
15
15
|
|
|
16
16
|
- Runtime/core: `mythik`
|
|
17
|
-
-
|
|
17
|
+
- Node/server helpers from core: `mythik/server`
|
|
18
18
|
- React host/runtime: `mythik-react`
|
|
19
19
|
- CLI binary package: `mythik-cli` (binary command: `mythik`)
|
|
20
20
|
- Programmatic CLI API: `mythik-cli/api`
|
|
@@ -22,6 +22,18 @@ Public npm package names are unscoped:
|
|
|
22
22
|
|
|
23
23
|
Use `npm install mythik mythik-react` for a React app, `npm install -D mythik-cli` for CLI workflows, and add `mythik-server` only when building a Mythik-backed Node server. The `mythik` npm package bundles the AI documentation corpus under `node_modules/mythik/docs`; use `mythik docs path` to locate it after install or `mythik docs copy ./mythik-docs` to copy it into the current project.
|
|
24
24
|
|
|
25
|
+
Server-side SQL helpers, SQL drivers, and SQL-backed spec stores are imported from `mythik/server`, not from the browser-safe `mythik` entry. Supported SQL dialects are `sqlserver`, `postgres`, `mysql`, and `sqlite`.
|
|
26
|
+
|
|
27
|
+
Database runtime dependencies: SQL adapters (`mssql`, `pg`, `mysql2`, and `better-sqlite3`) are optional dependencies of `mythik` and install by default with npm/pnpm unless optional dependencies are omitted. If the host installs with optional dependencies disabled, add only the adapter you use:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install pg # PostgreSQL
|
|
31
|
+
npm install mysql2 # MySQL
|
|
32
|
+
npm install better-sqlite3 # SQLite
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
MySQL support targets MySQL 8.0.19+ for generated upsert SQL. Older MySQL deployments need an explicit custom SQL path or another supported dialect.
|
|
36
|
+
|
|
25
37
|
## Spec Structure
|
|
26
38
|
|
|
27
39
|
Every screen is a flat tree: `root` ID + `elements` map + optional `initialActions`:
|
|
@@ -88,6 +100,9 @@ Every screen is a flat tree: `root` ID + `elements` map + optional `initialActio
|
|
|
88
100
|
```bash
|
|
89
101
|
mythik docs path # Locate bundled AI documentation
|
|
90
102
|
mythik docs copy ./mythik-docs # Copy docs for an AI agent / local review
|
|
103
|
+
mythik init-store --dialect sqlite --target ./mythik.db # Create local SQL store tables
|
|
104
|
+
mythik init-store --dialect postgres --dry-run # Print SQL store DDL for review/apply
|
|
105
|
+
mythik init-store --dialect sqlserver --server localhost --database Mythik --user "$DB_USER" --password "$DB_PASSWORD" --encrypt false --trust-server-certificate
|
|
91
106
|
mythik manifest <screen> # See structural tree
|
|
92
107
|
mythik elements <screen> <id1,id2> # Get element details
|
|
93
108
|
mythik patch <screen> --from-file patch.json # Apply RFC 6902 patches
|
|
@@ -114,6 +129,36 @@ Do not edit database rows directly, do not call `SpecStore.save()` from app code
|
|
|
114
129
|
|
|
115
130
|
All commands accept `--json`, `--table <name>`, `--store`, `--url`, `--key`. Never pass API keys inline — use `.mythikrc` + env vars.
|
|
116
131
|
|
|
132
|
+
### CLI store configuration
|
|
133
|
+
|
|
134
|
+
The CLI can read and write specs from `memory`, `file`, `supabase`, `sqlserver`, `postgres`, `mysql`, and `sqlite` stores. SQL stores share the same commands and the same required edit loop: `manifest -> elements -> patch -> validate`.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# SQLite: local development, tests, demos, lightweight deployments
|
|
138
|
+
mythik init-store --dialect sqlite --target ./mythik.db
|
|
139
|
+
mythik push floor-editor --from-file specs/floor-editor.json --store sqlite --filename ./mythik.db --author ai-agent
|
|
140
|
+
mythik manifest floor-editor --store sqlite --filename ./mythik.db
|
|
141
|
+
mythik elements floor-editor page,title --store sqlite --filename ./mythik.db
|
|
142
|
+
mythik patch floor-editor --from-file patch.json --store sqlite --filename ./mythik.db --author ai-agent
|
|
143
|
+
mythik validate floor-editor --store sqlite --filename ./mythik.db
|
|
144
|
+
|
|
145
|
+
# PostgreSQL
|
|
146
|
+
mythik init-store --dialect postgres --dry-run
|
|
147
|
+
mythik patch floor-editor --from-file patch.json --store postgres --url "$DATABASE_URL" --author ai-agent
|
|
148
|
+
|
|
149
|
+
# MySQL
|
|
150
|
+
mythik init-store --dialect mysql --dry-run
|
|
151
|
+
mythik patch floor-editor --from-file patch.json --store mysql --url "$DATABASE_URL" --author ai-agent
|
|
152
|
+
|
|
153
|
+
# SQL Server
|
|
154
|
+
mythik init-store --dialect sqlserver --server localhost --database Mythik --user "$DB_USER" --password "$DB_PASSWORD" --encrypt false --trust-server-certificate
|
|
155
|
+
mythik patch floor-editor --from-file patch.json --store sqlserver --server localhost --database Mythik --user "$DB_USER" --password "$DB_PASSWORD" --author ai-agent
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Environment equivalents: `MYTHIK_STORE`, `MYTHIK_DATABASE_URL`, `MYTHIK_SQLITE_FILE`, `MYTHIK_SQLSERVER_SERVER`, `MYTHIK_SQLSERVER_DATABASE`, `MYTHIK_SQLSERVER_USER`, `MYTHIK_SQLSERVER_PASSWORD`, `MYTHIK_SQLSERVER_PORT`, `MYTHIK_SQLSERVER_TRUSTED_CONNECTION`, `MYTHIK_TABLE`, `MYTHIK_VERSIONS_TABLE`, `MYTHIK_ENVIRONMENTS_TABLE`, and `MYTHIK_SNAPSHOT_INTERVAL`.
|
|
159
|
+
|
|
160
|
+
`init-store --dry-run` prints the canonical idempotent DDL for the dialect. `init-store` can initialize reachable SQL stores directly, including SQL Server through explicit flags, while production teams may still apply the dry-run DDL through their normal deployment process. Runtime reads/writes do not silently create missing tables on first use.
|
|
161
|
+
|
|
117
162
|
### CLI is the only approved path for spec writes
|
|
118
163
|
|
|
119
164
|
Per reference-doc rule 248: three approved forms.
|
|
@@ -297,14 +342,19 @@ Extended: `locale`, `notation` (compact/scientific), `signDisplay` (always/excep
|
|
|
297
342
|
|
|
298
343
|
### Named Bindings
|
|
299
344
|
|
|
300
|
-
`$let` / `$ref` — define once, use many times:
|
|
301
|
-
```json
|
|
302
|
-
{ "$let": { "total": { "$array": "count", "source": { "$state": "/items" } } }, "$in": { "$ref": "total" } }
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
```json
|
|
306
|
-
{ "$let":
|
|
307
|
-
```
|
|
345
|
+
`$let` / `$ref` — define once, use many times:
|
|
346
|
+
```json
|
|
347
|
+
{ "$let": { "total": { "$array": "count", "source": { "$state": "/items" } } }, "$in": { "$ref": "total" } }
|
|
348
|
+
```
|
|
349
|
+
`$ref` may also read nested values from an object binding with dot notation:
|
|
350
|
+
```json
|
|
351
|
+
{ "$let": { "user": { "$state": "/auth/user" } }, "$in": { "$ref": "user.name" } }
|
|
352
|
+
```
|
|
353
|
+
Inside the same `$let`, `$template` placeholders can read the same dotted binding paths, for example `${user.name}`.
|
|
354
|
+
**JSONB array format** (when stored in DB, order matters):
|
|
355
|
+
```json
|
|
356
|
+
{ "$let": [["filtered", { "$array": "filter", "source": { "$state": "/items" }, "where": { "field": "status", "eq": "active" } }], ["count", { "$array": "count", "source": { "$ref": "filtered" } }]], "$in": { "$ref": "count" } }
|
|
357
|
+
```
|
|
308
358
|
|
|
309
359
|
### Group & Selection (inside repeat)
|
|
310
360
|
|
|
@@ -341,13 +391,15 @@ All primitives accept `style`, `visible`, and `permission`. Tokens are project-d
|
|
|
341
391
|
|
|
342
392
|
Wire to events with `on`: `{ "on": { "press": { "action": "...", "params": {...} } } }`
|
|
343
393
|
|
|
344
|
-
Arrays execute sequentially: `"press": [action1, action2, action3]
|
|
394
|
+
Arrays execute sequentially: `"press": [action1, action2, action3]`. Arrays may mix normal action bindings and transaction bindings; each entry runs in order and transactions are awaited before the next entry.
|
|
345
395
|
|
|
346
396
|
**Trap:** Action chains don't stop on failure — `validateForm` marks errors but does NOT halt the chain. Use `submitForm` with `formId` instead (validates + blocks if invalid). See [ai-context-patterns.md](ai-context-patterns.md).
|
|
347
397
|
|
|
348
|
-
Add `"fireAndForget": true` to dispatch without waiting (background re-fetch after closing modal).
|
|
349
|
-
|
|
350
|
-
|
|
398
|
+
Add `"fireAndForget": true` to dispatch without waiting (background re-fetch after closing modal).
|
|
399
|
+
|
|
400
|
+
Any action binding may include `params.skipIf`. Mythik resolves `skipIf` at dispatch time before resolving the rest of the params; when truthy, that action is skipped and the surrounding action chain continues.
|
|
401
|
+
|
|
402
|
+
### Action Reference
|
|
351
403
|
|
|
352
404
|
| Action | Params | Purpose |
|
|
353
405
|
|--------|--------|---------|
|
|
@@ -1135,35 +1187,46 @@ Quick reference: `type: "api"` at root, with `auth`, `catalogs`, `endpoints` obj
|
|
|
1135
1187
|
|
|
1136
1188
|
## Storage Setup
|
|
1137
1189
|
|
|
1138
|
-
Mythik stores specs in the consumer's
|
|
1190
|
+
Mythik stores specs in the consumer's selected store. Browser-safe stores (`MemorySpecStore`, `SupabaseSpecStore`, and their versioned/environment variants) are imported from `mythik`. Node-only SQL stores (`SqlSpecStore`, `SqlVersionedSpecStore`, `SqlEnvironmentStore`, `FileSpecStore`, and SQL Server compatibility classes) are imported from `mythik/server`.
|
|
1191
|
+
|
|
1192
|
+
SQL-backed stores support `sqlserver`, `postgres`, `mysql`, and `sqlite` through one `SqlDriver` boundary. The same three tables are involved across dialects:
|
|
1139
1193
|
|
|
1140
|
-
- **`screens`** (base, **REQUIRED**) — current spec per `id`. Used by every adapter
|
|
1141
|
-
- **`screen_versions`** (opt-in) — version history. Required
|
|
1142
|
-
- **`screen_environments`** (opt-in) — environment promotions. Required
|
|
1194
|
+
- **`screens`** (base, **REQUIRED**) — current spec per `id`. Used by every SQL/Supabase adapter.
|
|
1195
|
+
- **`screen_versions`** (opt-in but recommended) — version history. Required when the CLI runs with `--author`, when `runPush`/`runPatch` receives an `author`, or when code uses `SqlVersionedSpecStore` / `SupabaseVersionedSpecStore`.
|
|
1196
|
+
- **`screen_environments`** (opt-in but recommended) — environment promotions. Required for `history`, `diff`, `rollback`, `envs`, `promote`, and `SqlEnvironmentStore` / `SupabaseEnvironmentStore` workflows.
|
|
1143
1197
|
|
|
1144
|
-
|
|
1198
|
+
Use the CLI to bootstrap SQL store tables:
|
|
1145
1199
|
|
|
1146
|
-
|
|
1200
|
+
```bash
|
|
1201
|
+
mythik init-store --dialect sqlite --target ./mythik.db
|
|
1202
|
+
mythik init-store --dialect sqlserver --server localhost --database Mythik --user "$DB_USER" --password "$DB_PASSWORD" --encrypt false --trust-server-certificate
|
|
1203
|
+
mythik init-store --dialect postgres --dry-run
|
|
1204
|
+
mythik init-store --dialect mysql --dry-run
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
`init-store --dry-run` prints the canonical idempotent DDL. `init-store` can initialize reachable SQL stores directly, including SQL Server through explicit flags. Production teams may still apply the dry-run DDL through their normal database deployment path. Runtime store reads/writes do not silently create missing tables.
|
|
1147
1208
|
|
|
1148
|
-
**
|
|
1209
|
+
**Authoritative since v0.1.0.** The framework's SQL stores require the columns below by name and meaning. Use the generated DDL where possible; if translating manually, preserve all columns, constraints, and uniqueness rules.
|
|
1210
|
+
|
|
1211
|
+
**Versioned stores extend the base store.** When `SqlVersionedSpecStore.saveVersion(id, doc, meta)` or `SupabaseVersionedSpecStore.saveVersion(id, doc, meta)` runs, it appends to `screen_versions` and updates `screens`. This means `screens` MUST exist for every consumer — there is no "versioning-only" mode that skips it.
|
|
1149
1212
|
|
|
1150
1213
|
### Table 0 — `screens` (current spec — REQUIRED for all stores)
|
|
1151
1214
|
|
|
1152
1215
|
| Column | Semantic type | Nullable | Default | Notes |
|
|
1153
1216
|
|---|---|---|---|---|
|
|
1154
1217
|
| `id` | short string (≤255) | NOT NULL | — | Spec identifier; PK. Framework reads/writes via `WHERE id = ?` |
|
|
1155
|
-
| `name` | short string (≤255) | NULL | — | Display name. Framework
|
|
1156
|
-
| `spec` | long
|
|
1157
|
-
| `version` | integer | NOT NULL | `1` | Incremented
|
|
1158
|
-
| `is_active` | boolean | NOT NULL | `true` | Framework
|
|
1218
|
+
| `name` | short string (≤255) | NULL | — | Display name. Framework inserts the same value as `id` by default. |
|
|
1219
|
+
| `spec` | JSON-capable long value | NOT NULL | — | Current spec. SQL Server and SQLite DDL store JSON as text; PostgreSQL uses `JSONB`; MySQL uses `JSON`. Generic SQL stores parse string values defensively. |
|
|
1220
|
+
| `version` | integer | NOT NULL | `1` | Incremented by the generic SQL store on every update. |
|
|
1221
|
+
| `is_active` | boolean | NOT NULL | `true` | Framework inserts active specs; current SQL store list operations do not filter by this column. |
|
|
1159
1222
|
| `created_at` | UTC timestamp | — | — | OPTIONAL — framework does not read or write this column. If you add it for consumer hygiene (audit trail), make it `NOT NULL` with a NOW UTC default; otherwise omit entirely. |
|
|
1160
|
-
| `updated_at` | UTC timestamp | NOT NULL | NOW UTC | Required.
|
|
1223
|
+
| `updated_at` | UTC timestamp/string | NOT NULL | NOW UTC | Required. The generic SQL store writes this value on insert and update; the database default covers manual/bootstrap inserts. |
|
|
1161
1224
|
|
|
1162
1225
|
**Constraints**:
|
|
1163
1226
|
- `PRIMARY KEY (id)` — required (every framework query filters by `id`)
|
|
1164
1227
|
|
|
1165
1228
|
**Indexes** (all RECOMMENDED, none framework-required):
|
|
1166
|
-
- `(is_active, id)` — useful for consumer queries filtering active screens. The framework's `list()` uses only `ORDER BY id`
|
|
1229
|
+
- `(is_active, id)` — useful for consumer queries filtering active screens. The framework's `list()` uses only `ORDER BY id` and does not filter by `is_active`, so this index is consumer-hygiene only.
|
|
1167
1230
|
|
|
1168
1231
|
### Table 1 — `screen_versions` (version history — opt-in: VersionedSpecStore)
|
|
1169
1232
|
|
|
@@ -1201,20 +1264,22 @@ Mythik stores specs in the consumer's database. Three tables are involved depend
|
|
|
1201
1264
|
**Constraints**:
|
|
1202
1265
|
- `PRIMARY KEY (screen_id, environment)` — one promotion record per `(spec, env)` pair; re-promote upserts via MERGE/UPSERT
|
|
1203
1266
|
|
|
1204
|
-
###
|
|
1267
|
+
### JSON column policy
|
|
1205
1268
|
|
|
1206
|
-
|
|
1269
|
+
Use the dialect-native JSON type when the dialect has one:
|
|
1207
1270
|
|
|
1208
|
-
-
|
|
1209
|
-
-
|
|
1271
|
+
- PostgreSQL / Supabase: `JSONB`
|
|
1272
|
+
- MySQL: `JSON`
|
|
1273
|
+
- SQL Server: `NVARCHAR(MAX)`
|
|
1274
|
+
- SQLite: `TEXT`
|
|
1210
1275
|
|
|
1211
|
-
SQL
|
|
1276
|
+
Generic SQL stores parse stored JSON defensively when the driver returns strings. Supabase's browser-safe REST stores consume PostgREST JSON as already-parsed objects, so Supabase tables should use `jsonb`, not `text`.
|
|
1212
1277
|
|
|
1213
|
-
###
|
|
1278
|
+
### Supabase trigger note
|
|
1214
1279
|
|
|
1215
|
-
|
|
1280
|
+
Generic SQL stores write `screens.updated_at` and `screens.version` directly. Supabase's browser-safe REST store updates only the `spec` field, so Supabase projects should keep the `BEFORE UPDATE` triggers below if they want `updated_at` and `version` to advance on Supabase REST writes.
|
|
1216
1281
|
|
|
1217
|
-
Recommended trigger pair on
|
|
1282
|
+
Recommended trigger pair on Supabase/PostgreSQL when using `SupabaseSpecStore`:
|
|
1218
1283
|
|
|
1219
1284
|
```sql
|
|
1220
1285
|
CREATE OR REPLACE FUNCTION screens_update_updated_at()
|
|
@@ -1232,16 +1297,17 @@ CREATE TRIGGER screens_version_trigger
|
|
|
1232
1297
|
FOR EACH ROW EXECUTE FUNCTION screens_increment_version();
|
|
1233
1298
|
```
|
|
1234
1299
|
|
|
1235
|
-
Trigger function names are arbitrary (use any unique name); the framework does not introspect them.
|
|
1300
|
+
Trigger function names are arbitrary (use any unique name); the framework does not introspect them. Plain PostgreSQL consumers using `SqlSpecStore` through `mythik/server` do not need these triggers for framework writes.
|
|
1236
1301
|
|
|
1237
|
-
`screen_versions` and `screen_environments` do NOT need such triggers — those tables are append-only / upsert-on-PK and the framework writes all columns explicitly on each INSERT/UPSERT
|
|
1302
|
+
`screen_versions` and `screen_environments` do NOT need such triggers — those tables are append-only / upsert-on-PK and the framework writes all columns explicitly on each INSERT/UPSERT.
|
|
1238
1303
|
|
|
1239
|
-
###
|
|
1304
|
+
### Initialization and idempotency
|
|
1240
1305
|
|
|
1241
|
-
|
|
1242
|
-
- SQL Server: `IF
|
|
1306
|
+
`mythik init-store` uses canonical idempotent DDL, so re-running it on a database that already has the tables does not fail and does not recreate existing tables. If translating the DDL manually into a deployment script, preserve the target dialect's "if not exists" guard:
|
|
1307
|
+
- SQL Server: `IF OBJECT_ID(N'...', N'U') IS NULL CREATE TABLE ...`
|
|
1243
1308
|
- Postgres / Supabase: `CREATE TABLE IF NOT EXISTS ...`
|
|
1244
1309
|
- MySQL / MariaDB: `CREATE TABLE IF NOT EXISTS ...`
|
|
1310
|
+
- SQLite: `CREATE TABLE IF NOT EXISTS ...`
|
|
1245
1311
|
|
|
1246
1312
|
### Verification (post-apply)
|
|
1247
1313
|
|
|
@@ -1255,29 +1321,33 @@ WHERE TABLE_NAME IN ('screens', 'screen_versions', 'screen_environments')
|
|
|
1255
1321
|
ORDER BY TABLE_NAME, ORDINAL_POSITION;
|
|
1256
1322
|
```
|
|
1257
1323
|
|
|
1258
|
-
Confirm:
|
|
1324
|
+
Confirm: 6 required columns for `screens` (`id`, `name`, `spec`, `version`, `is_active`, `updated_at`), 10 columns for `screen_versions` (`id` through `created_at`), and 5 columns for `screen_environments` (`screen_id` through `promoted_by`). `created_at` on `screens` is optional. If any required column is missing or has a wrong NULL/NOT NULL flag, abort and report — the framework's INSERT/SELECT/UPDATE will fail at runtime otherwise.
|
|
1259
1325
|
|
|
1260
|
-
On
|
|
1326
|
+
On Supabase projects using `SupabaseSpecStore`, additionally verify the two triggers on `screens` are present (`information_schema.triggers` WHERE `event_object_table = 'screens'`); without them, `updated_at` and `version` will not advance on Supabase REST writes.
|
|
1261
1327
|
|
|
1262
1328
|
### Custom table names
|
|
1263
1329
|
|
|
1264
1330
|
All three table names are independently configurable; overriding one does not require overriding the others:
|
|
1265
1331
|
|
|
1266
1332
|
```ts
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1333
|
+
import { createSqlDriver, SqlEnvironmentStore, SqlSpecStore, SqlVersionedSpecStore } from 'mythik/server';
|
|
1334
|
+
|
|
1335
|
+
const driver = createSqlDriver({ dialect: 'postgres', connection: process.env.DATABASE_URL });
|
|
1336
|
+
|
|
1337
|
+
new SqlSpecStore({ driver, table: 'my_screens' });
|
|
1338
|
+
new SqlVersionedSpecStore({ driver, table: 'my_screens', versionsTable: 'my_versions' });
|
|
1339
|
+
new SqlEnvironmentStore({ driver, table: 'my_envs' });
|
|
1270
1340
|
```
|
|
1271
1341
|
|
|
1272
|
-
|
|
1342
|
+
`SqlVersionedSpecStore` accepts both `table` from the base config and `versionsTable` from its own config, since it extends `SqlSpecStore`.
|
|
1273
1343
|
|
|
1274
1344
|
If a consumer overrides any name, AI applies the same schema under the consumer-chosen name.
|
|
1275
1345
|
|
|
1276
|
-
**Identifier safety scope**: SQL
|
|
1346
|
+
**Identifier safety scope**: generic SQL stores enforce identifier validation on configured table names (regex `/^[a-zA-Z_][a-zA-Z0-9_.]*$/`, max 128 chars). This blocks SQL injection via table-name interpolation before dialect quoting runs. Supabase stores do not validate configured table names; consumer code passing user-controlled table names to a Supabase store must validate them upstream.
|
|
1277
1347
|
|
|
1278
|
-
### Canonical reference
|
|
1348
|
+
### Canonical reference
|
|
1279
1349
|
|
|
1280
|
-
|
|
1350
|
+
The canonical SQL store DDL ships in the installed package. Use `mythik init-store --dialect <sqlserver|postgres|mysql|sqlite> --dry-run` or `getSqlStoreDdl(dialect)` from `mythik/server` to inspect it. Do not copy DDL from unrelated local artifacts.
|
|
1281
1351
|
|
|
1282
1352
|
### Schema evolution
|
|
1283
1353
|
|
|
@@ -1375,5 +1445,9 @@ When the framework changes the schema in a future version, this section will gai
|
|
|
1375
1445
|
85. For existing spec edits, the required AI loop is `mythik manifest` -> `mythik elements` -> `mythik patch --from-file` -> verify. Manifest tells you the structure; elements gives the exact JSON you are changing; patch is the validated write path. Do not skip directly to full-spec `pull`/rewrite/push for a local change, do not mutate DB rows manually, and do not call `SpecStore.save()` from app code. Use `push` for new specs or intentional full replacement only.
|
|
1376
1446
|
86. Mythik's AI documentation ships with the `mythik` npm package. Before generating or modifying specs, locate it with `mythik docs path` and start from `docs/llms.txt`, `docs/consumer/ai-context.md`, and `docs/wiki/compiled/README.md`. Use `mythik docs copy ./mythik-docs` when a project-local copy is easier to hand to an AI agent.
|
|
1377
1447
|
87. DNA numeric seeds (`roundness`, `density`, `depth`, `formality`) are canonical `0–1` values. Generate `0.7`, not `70`. The runtime tolerates legacy `0–100` values by normalizing any numeric seed greater than `1` with `/100` during DNA derivation, including initial AppSpec load and runtime `updateTokens`.
|
|
1378
|
-
88. API query endpoints can combine `pagination: "offset"` with `scopeFilter`. For generated counts, Mythik applies the scope filter to the source query before `COUNT(*)`, so paginated totals remain tenant-scoped. Prefer generated counts. If a custom `endpoint.count` is truly needed with `scopeFilter`, include `{{scopeWhere[:alias]}}` or `{{scopeAnd[:alias]}}`; Mythik expands the macro to the correct scope predicate and removes it for bypass roles. Other custom count SQL is left verbatim. Use `:alias` for JOIN/subquery counts, and do not reference internal scope params directly.
|
|
1379
|
-
89. Transaction `confirm` failures from `fetch` preserve backend error details for `onError`. Read `/tx/error/message` for the best available message; when the backend returns `{ error: { code, message } }`, Mythik keeps that message, `code`, HTTP `status`, and raw `data` after rollback. Do not parse `/ui/lastError` from transaction specs.
|
|
1448
|
+
88. API query endpoints can combine `pagination: "offset"` with `scopeFilter`. For generated counts, Mythik applies the scope filter to the source query before `COUNT(*)`, so paginated totals remain tenant-scoped. Prefer generated counts. If a custom `endpoint.count` is truly needed with `scopeFilter`, include `{{scopeWhere[:alias]}}` or `{{scopeAnd[:alias]}}`; Mythik expands the macro to the correct scope predicate and removes it for bypass roles. Other custom count SQL is left verbatim. Use `:alias` for JOIN/subquery counts, and do not reference internal scope params directly.
|
|
1449
|
+
89. Transaction `confirm` failures from `fetch` preserve backend error details for `onError`. Read `/tx/error/message` for the best available message; when the backend returns `{ error: { code, message } }`, Mythik keeps that message, `code`, HTTP `status`, and raw `data` after rollback. Do not parse `/ui/lastError` from transaction specs.
|
|
1450
|
+
90. For SQL-backed stores and servers, use the generic `mythik/server` SQL boundary. Initialize tables with `mythik init-store --dialect <sqlserver|postgres|mysql|sqlite>` or inspect DDL with `--dry-run`; configure the CLI with `--store`, `--url`/`--filename`/SQL Server flags, or `MYTHIK_*` environment variables; and keep spec edits on the required `manifest -> elements -> patch --from-file -> validate` loop. Write custom API SQL in the selected dialect with Mythik named params (`@name`); Mythik does not translate custom SQL between dialects.
|
|
1451
|
+
91. Event arrays may mix normal actions and transaction bindings. Mythik executes them sequentially and awaits each transaction before continuing. Use this when a flow needs a small action before or after an optimistic transaction; do not wrap a transaction inside another transaction phase.
|
|
1452
|
+
92. `$ref` and `$template` placeholders can read nested values from `$let` object bindings with dot notation, for example `{ "$ref": "user.name" }` or `${user.name}`. If a dotted `$ref` segment is missing, runtime throws an unknown `$ref` error rather than silently returning undefined.
|
|
1453
|
+
93. Use `params.skipIf` for a dispatch-time action guard when an action should be skipped but the surrounding action chain should continue. `skipIf` is resolved before other params and is removed before the action handler runs. Do not use `skipIf` as a substitute for form validation or transaction rollback.
|
|
@@ -309,9 +309,9 @@ Nested conditionals for multi-branch logic:
|
|
|
309
309
|
```json
|
|
310
310
|
{ "$template": "Hello, ${/user/name}! You have ${/inbox/count} messages." }
|
|
311
311
|
```
|
|
312
|
-
Interpolates values into a string. Supports two reference types:
|
|
313
|
-
- State paths: `${/user/name}` — reads from application state
|
|
314
|
-
- `$let` bindings: `${age}` — reads from a named binding defined with `$let`
|
|
312
|
+
Interpolates values into a string. Supports two reference types:
|
|
313
|
+
- State paths: `${/user/name}` — reads from application state
|
|
314
|
+
- `$let` bindings: `${age}` or `${user.name}` — reads from a named binding defined with `$let`
|
|
315
315
|
|
|
316
316
|
### `$computed` — Registered function
|
|
317
317
|
```json
|
|
@@ -326,11 +326,20 @@ Calls a registered function with resolved arguments. **Prefer `$math`, `$array`,
|
|
|
326
326
|
"$in": { "$ref": "bmi" }
|
|
327
327
|
}
|
|
328
328
|
```
|
|
329
|
-
Define a named value once, reference it multiple times. Avoids repetition.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
```json
|
|
333
|
-
{
|
|
329
|
+
Define a named value once, reference it multiple times. Avoids repetition.
|
|
330
|
+
|
|
331
|
+
`$ref` can read nested values from an object binding with dot notation:
|
|
332
|
+
```json
|
|
333
|
+
{
|
|
334
|
+
"$let": { "user": { "$state": "/auth/user" } },
|
|
335
|
+
"$in": { "$ref": "user.name" }
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
The same dotted binding lookup is available inside `$template` placeholders, for example `${user.name}`.
|
|
339
|
+
|
|
340
|
+
**Later bindings can reference earlier ones:**
|
|
341
|
+
```json
|
|
342
|
+
{
|
|
334
343
|
"$let": {
|
|
335
344
|
"total": { "$array": "count", "source": { "$state": "/items" } },
|
|
336
345
|
"label": { "$template": "${total} items" }
|
|
@@ -853,9 +862,9 @@ Wire actions to events with the `on` property:
|
|
|
853
862
|
}
|
|
854
863
|
```
|
|
855
864
|
|
|
856
|
-
### Multiple Actions (Sequential)
|
|
857
|
-
|
|
858
|
-
Actions in an array execute sequentially — each async action (like `fetch`) completes before the next one starts:
|
|
865
|
+
### Multiple Actions (Sequential)
|
|
866
|
+
|
|
867
|
+
Actions in an array execute sequentially — each async action (like `fetch`) completes before the next one starts:
|
|
859
868
|
```json
|
|
860
869
|
{
|
|
861
870
|
"on": {
|
|
@@ -937,10 +946,14 @@ The `fetch` action supports:
|
|
|
937
946
|
},
|
|
938
947
|
"target": "/lastResult"
|
|
939
948
|
}
|
|
940
|
-
}
|
|
941
|
-
```
|
|
942
|
-
|
|
943
|
-
|
|
949
|
+
}
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
Action arrays may also mix normal action bindings and transaction bindings. Mythik runs each entry in order and waits for a transaction to finish before dispatching the next entry.
|
|
953
|
+
|
|
954
|
+
Any action binding can include `params.skipIf`. Mythik resolves `skipIf` at dispatch time before the rest of the params; if it is truthy, that action is skipped and the surrounding action chain continues.
|
|
955
|
+
|
|
956
|
+
### Transactions (Optimistic Updates)
|
|
944
957
|
|
|
945
958
|
Use `transaction` for CRUD operations that need instant UI feedback. The framework takes a state snapshot, applies your changes instantly, then confirms with the server. On failure, it rolls back automatically.
|
|
946
959
|
|
|
@@ -1950,11 +1963,11 @@ Reference tokens or write custom values:
|
|
|
1950
1963
|
64. **CLI warns on unknown prop names** — `mythik push` and `mythik validate` check prop names against known schemas for all 38 primitives. Unknown props generate warnings (not errors) with Levenshtein suggestions: `⚠ unknown prop "inputType" for type "input" — did you mean "type"?`. Warnings don't block saves
|
|
1951
1964
|
65. **Use `audit` config for automatic change tracking** — endpoint-level config that auto-injects username and timestamp into CRUD INSERT and UPDATE operations. Column names are configurable per table. All fields are optional — only configured fields are injected. Audit values override client-sent values (prevents spoofing)
|
|
1952
1965
|
66. **Audit `timezone` for correct local timestamps** — set `"timezone": "America/El_Salvador"` (IANA string) in audit config. Without timezone, timestamps are UTC. Use timezone when the database stores local time. The framework converts using `Intl.DateTimeFormat` — works regardless of server location
|
|
1953
|
-
67. **CRUD queries are
|
|
1966
|
+
67. **CRUD queries are dialect-aware** — Generated CRUD routes compile through the active SQL driver. SQL Server uses trigger-safe identity retrieval; PostgreSQL/SQLite use `RETURNING` where available; MySQL uses the driver insert id path and targets MySQL 8.0.19+ for generated upsert SQL. Custom SQL remains dialect-native and is not translated between databases.
|
|
1954
1967
|
68. **CustomJWTProvider maps response paths explicitly** — `tokenPath`, `refreshTokenPath`, and `userPath` are dot paths against the full login/refresh response. `rolePath` and `rolesPath` are compat dual: plain keys (`"role"`, `"roles"`) resolve inside the extracted user object, dotted paths (`"user.role"`, `"data.user.role"`) resolve against the full response. If no role/roles are found, `defaultRole` is used and development logs a warning. HTTP errors read `response.error.message` first, then `response.message`
|
|
1955
1968
|
69. **ApiSpec is pure declarative — no connection, no secrets** — `createServer` receives database connection and JWT secret in `MythikServerConfig`, not in the ApiSpec. The ApiSpec only contains endpoints, catalogs, auth model (provider, policies, scopeFilter), and audit config. This allows the ApiSpec to be stored safely in the database
|
|
1956
1969
|
70. **Server loads api-spec from SpecStore** — `createServer({ spec: { store: myStore, id: 'my-api' }, database: {...}, auth: {...} })`. Supports three modes: file path (string), ApiSpec object (testing), or `{ store, id }` (database). The server never owns a SpecStore — the caller provides one
|
|
1957
|
-
71. **SpecStore table is configurable** — `new
|
|
1970
|
+
71. **SpecStore table is configurable** — Generic SQL stores use `new SqlSpecStore({ driver, table: 'api_specs' })` from `mythik/server`; Supabase uses `new SupabaseSpecStore({ ..., table: 'api_specs' })` from `mythik`. Default: `'screens'`. Enables separate tables for frontend specs and backend specs with different DB permissions.
|
|
1958
1971
|
72. **Api-specs are never served to the browser** — `GET /api/screens/:id` and `GET /api/app/:id` return 404 for documents with `type: "api"`. Prevents information disclosure of table names, SQL queries, and auth config
|
|
1959
1972
|
73. **CLI operates on api-specs automatically** — `mythik validate my-api`, `mythik pull my-api`, `mythik push my-api` detect `type: "api"` and use the apiHandler. Manifest shows catalogs, endpoints, auth config. Elements support dot-notation: `mythik elements my-api endpoints.records-crud`
|
|
1960
1973
|
74. **Use `mythik contract` for frontend↔backend validation** — `mythik contract --app app-demo --api records-api`. Cross-validates screen fetch URLs against api-spec endpoints. Supports multiple api-specs (comma-separated). Use `--api-table` when api-specs are in a separate table. Use `--base-url` to strip host from URLs. Use `--json` for CI/CD integration
|
|
@@ -1974,12 +1987,12 @@ Reference tokens or write custom values:
|
|
|
1974
1987
|
88. **Rollback creates new version, never rewrites history** — `executeRollback(specId, toVersion)` creates vN+1 with the content of the target version. All intermediate versions are preserved. Impact analysis shows lost changes with author attribution and affected environments. Moving an environment pointer is a separate operation via `envs --set`
|
|
1975
1988
|
89. **Lazy bootstrap for existing specs** — first versioned save on an existing spec with no history automatically creates v1 (snapshot of current spec), then saves the change as v2. No migration script needed. Specs without history continue working via base `SpecStore.load()`
|
|
1976
1989
|
90. **Use `navigateScreen` and `goBackScreen` in specs** — `navigateScreen` and `goBackScreen` are registered by MythikApp and call the AppEngine directly. The built-in `navigate` and `goBack` only set state intents. Always use `navigateScreen`/`goBackScreen` in specs for navigation that works. Example: `{ "action": "goBackScreen" }` goes back to the previous screen in the navigation history, regardless of which screen navigated to the current one
|
|
1977
|
-
91. **CLI `--table` flag overrides
|
|
1990
|
+
91. **CLI `--table` flag overrides the current spec table** — all commands accept `--table <name>` to read/write from a different base table. Use `--table api_specs` to operate on api-specs. The flag overrides the base table for Supabase, SQL Server, PostgreSQL, MySQL, and SQLite stores. Version and environment tables are configured separately with `MYTHIK_VERSIONS_TABLE`, `MYTHIK_ENVIRONMENTS_TABLE`, or the equivalent `.mythikrc` SQL settings.
|
|
1978
1991
|
92. **`push` and `patch` version automatically with `--author`** — when `--author` is provided, both commands use `VersionedSpecStore.saveVersion()` instead of `SpecStore.save()`. The version includes author, source type (`push`/`patch`), and optional `--description`. Without `--author`, commands work as before (no versioning). Example: `mythik patch screen-id --author alice --description "Fixed layout"`
|
|
1979
1992
|
93. **`mythik history` shows inline diffs** — each version in the history output shows the actual changes (before/after values), not just a summary. Uses `computeStructuralDiff` between consecutive versions. Example output: `~ element "btn" prop content: "Send" → "Submit"`
|
|
1980
1993
|
95. **`ai-context.md` is the AI-optimized spec reference** — compressed from this reference-doc (1145 lines vs 2658). Use ai-context.md for spec generation, reference-doc for full human reference. Validated via agent-based testing with progressive difficulty levels (L1-L4). Test scenarios in `../ai-context-test-scenarios.md`, results in `../ai-context-test-results.md` (framework-dev, not part of consumer publish surface)
|
|
1981
1994
|
|
|
1982
|
-
94. **
|
|
1995
|
+
94. **Generic SQL versioned stores are available** — `resolveVersionedStore` supports `sqlserver`, `postgres`, `mysql`, and `sqlite` store types. It creates a driver-backed `SqlVersionedSpecStore` (specs + version history) plus `SqlEnvironmentStore` (environment pointers). Requires `screens`, `screen_versions`, and `screen_environments`; initialize with `mythik init-store` or apply the DDL from `mythik init-store --dry-run`.
|
|
1983
1996
|
96. **SupabaseVersionedSpecStore available** — `resolveVersionedStore` supports `supabase` store type. Uses PostgREST REST API (no `@supabase/supabase-js` dependency). Same snapshot+patches pattern as SqlServer. Environment upsert uses `on_conflict=screen_id,environment` for PostgREST compatibility. Requires `screen_versions` and `screen_environments` tables created in Supabase dashboard
|
|
1984
1997
|
97. **`variant` is a universal prop** — any primitive can use `variant` when component variants are defined in `tokens.components.{type}.{variant}`. The validator accepts `variant` on all primitives (via `COMMON_PROPS`). The render engine resolves variants before passing props to the primitive
|
|
1985
1998
|
98. **Use DNA seeds for app identity** — define `tokens.dna` in AppSpec with 1-8 seed values. The framework derives all visual tokens (colors via OKLCH tonal palette, shape, typography, spacing, elevation, motion, opacity) plus auto dark mode. No manual color palette or radius scale needed — DNA generates it from `{ "primary": "#0D9488" }`
|
|
@@ -3043,7 +3056,7 @@ The current background and motion stack combines app-level `LayerBackground`, an
|
|
|
3043
3056
|
|
|
3044
3057
|
211. **`useShapeAnimations(ref, animations, options)` — Layer 3 web runner** — Exported from `mythik-react` via `packages/react/src/animation/useShapeAnimations.ts`. React hook for SVG-child animations (`<path>`/`<circle>`/`<rect>`/`<g>`…). Consumes the same `ElementAnimations` contract as `useElementAnimations` but narrowed to the `ambient` trigger ONLY; shape children have no hover/focus/active contract and no distinct mount ceremony. Attaches CSS animations via `el.style.animation` (surgical, preserves other inline styles); keyframes register once through the CSSOM singleton (zero `dangerouslySetInnerHTML`) and dedupe by hash so multiple shape instances with the same recipe share one CSS rule. Dev mode warns when non-ambient triggers are passed. Production silently ignores them. `options.recipes` SHOULD be stable for useMemo performance.
|
|
3045
3058
|
|
|
3046
|
-
212. **`useShapeAnimations(animations, options)` — Layer 3 RN runner** — Repository-preview implementation in `packages/react-native/src/animation/useShapeAnimations.ts`; it is not part of the
|
|
3059
|
+
212. **`useShapeAnimations(animations, options)` — Layer 3 RN runner** — Repository-preview implementation in `packages/react-native/src/animation/useShapeAnimations.ts`; it is not part of the supported npm publish surface yet. Reanimated parity of rule 211: returns `{ animatedProps }` that the consumer spreads onto `Animated.createAnimatedComponent(Path)` from `react-native-svg`. Uses the `HARD_PER_TRIGGER` (=6) fixed-pool `useSharedValue` pattern (`useSharedValueArray` helper, also exported) so React Hook count stays stable. Reuses `composeRNStyle(contributions, interpolate, interpolateColor)` shared with `useElementAnimations` — single composition pipeline for View-style and animated SVG props. Relies on `react-native-svg` v13+ auto-translating the transform array into SVG `transform="..."` strings. Same dev-mode non-ambient-trigger warning as the web hook.
|
|
3047
3060
|
|
|
3048
3061
|
213. **Cross-platform Layer 3 parity pins** — `buildCSSKeyframes` (web) and `buildReanimatedSpec` (RN) interpret the same resolved `AnimationSpec` identically on load-bearing invariants: duration agreement (ms count matches regardless of input form `'28s'`/`'28000'`), keyframe stop count (web `%` markers match RN `inputRange` length), direction semantic (`'alternate'` token ⇔ `timing.reverse=true`), iterations `'infinite'`/numeric count, animated-prop enumeration (`translateX/Y`/`rotateDeg`/`scale`).
|
|
3049
3062
|
|
|
@@ -3115,7 +3128,7 @@ The current background and motion stack combines app-level `LayerBackground`, an
|
|
|
3115
3128
|
243. **CRUD endpoint generates 3 routes from 1 declaration** — an endpoint with `crud: { table, primaryKey, insertable, updatable }` generates `POST <path>`, `PUT <path>/:id`, `DELETE <path>/:id`. Do not declare 3 endpoints. See `ai-context-runtime-semantics.md § 3.1`.
|
|
3116
3129
|
244. **`/api/auth/login` expects `{ username, password }`** — not `email`. Use `loginBody` template to map consumer email convention → framework username. See `ai-context-runtime-semantics.md § 3.2`.
|
|
3117
3130
|
245. **Query endpoints envelope responses in `{ data: [...] }`** — shape is `{ data, total?, page?, pageSize?, totals? }`. Consumer specs read `response.data` via state; envelope is NOT auto-unwrapped. See `ai-context-runtime-semantics.md § 3.3`.
|
|
3118
|
-
246. **Browser vs Server entries — `mythik` vs `mythik/server`** (v0.1.0). The default `mythik` entry is browser-safe by construction: zero transitive Node-only imports. `FileSpecStore`, `
|
|
3131
|
+
246. **Browser vs Server entries — `mythik` vs `mythik/server`** (v0.1.0). The default `mythik` entry is browser-safe by construction: zero transitive Node-only imports. `FileSpecStore`, generic SQL stores (`SqlSpecStore`, `SqlVersionedSpecStore`, `SqlEnvironmentStore`), SQL drivers (`createSqlDriver`, `getSqlStoreDdl`), and SQL Server compatibility stores live in `mythik/server`.
|
|
3119
3132
|
|
|
3120
3133
|
247. **`derive` and `dataSources` are processed at runtime per spec mount** (v0.1.0). When `spec.derive` is present, the framework instantiates a `DeriveEngine`, evaluates all derive paths in topological order at mount, and re-evaluates dirty paths reactively on state changes. Derive paths are protected: setState targeting a derive path errors at validate time and runtime. When `spec.dataSources` is present, the framework instantiates a `DataSourcesEngine`, performs initial fetches (deferred to reactive resolution when URL template deps are undefined), and re-fetches reactively when dependencies change. The action `refreshDataSource` (params: `{ id: string }`) is automatically registered for any spec with dataSources. URL templating requires the explicit `{ $template: '...' }` form — plain strings with `${...}` are NOT substituted (validator catches at load). See `ai-context-runtime-semantics.md` for lifecycle, ordering, error degradation, and state protection details.
|
|
3121
3134
|
|
|
@@ -3144,7 +3157,7 @@ Exit codes: 0 = no errors, 1 = errors found, 2 = runtime error (e.g., unreadable
|
|
|
3144
3157
|
|
|
3145
3158
|
See `ai-context.md` for spec-gen anti-patterns the AI must NOT generate.
|
|
3146
3159
|
|
|
3147
|
-
250. **Storage tables are
|
|
3160
|
+
250. **Storage tables are initialized explicitly, never silently at runtime** (v0.1.0). SQL-backed stores operate against three tables the consumer database must already have: `screens` (base, required), `screen_versions` (version history), and `screen_environments` (environment promotions). Use `mythik init-store --dialect <sqlserver|postgres|mysql|sqlite> --dry-run` to inspect canonical idempotent DDL, initialize a local SQLite file with `mythik init-store --dialect sqlite --target ./mythik.db`, or initialize a reachable SQL Server store with explicit `--server`, `--database`, `--user`, `--password`, `--encrypt`, and `--trust-server-certificate` flags. The same schema is described in `ai-context.md § Storage Setup`. Runtime reads/writes do not create missing tables. Production deployment scripts should verify required columns after apply.
|
|
3148
3161
|
251. **`security.exposeErrors` controls render error detail** (v0.1.0). Default is `true`; set `createMythik({ security: { exposeErrors: false } })` for production-like hosts that must avoid leaking error messages/stacks. `_error` render nodes write diagnostics to `/ui/renderErrors` only when exposure is enabled. Primitive/component exceptions are caught by `MythikRenderer`'s error boundary: development + exposed mode shows an overlay with message and component stack; production or `exposeErrors: false` shows a neutral placeholder. The overlay resets when the spec changes so a corrected spec can recover without remounting the host.
|
|
3149
3162
|
252. **Icon packs register through `plugins.setIconRenderer`** (v0.1.0). Mythik does not bundle Phosphor/Lucide/etc. Register one host-level renderer from `MythikApp.onPlugins`; the built-in `icon` primitive keeps identity behavior and calls the renderer with `{ name, size, weight, color, style }`. If the placeholder circle renders, verify `onPlugins` registered the renderer and the consumer is not validating against stale tarballs or source aliases.
|
|
3150
3163
|
253. **`overridePrimitive('icon')` returns a RenderNode, not JSX** (v0.1.0). Use it only for full primitive replacement. The renderer function must return `{ type, props, children }` with `_component` in props when targeting React. Returning `<Icon />` directly is not the primitive renderer contract and bypasses the built-in icon identity wrapper.
|
|
@@ -3202,5 +3215,9 @@ See `ai-context.md` for spec-gen anti-patterns the AI must NOT generate.
|
|
|
3202
3215
|
282. **Existing spec edits must use the CLI inspection-then-patch loop** - For an existing screen/app/api spec, AI agents should run `mythik manifest <id>` first, inspect only the target nodes with `mythik elements <id> <ids>`, apply a small RFC 6902 patch with `mythik patch <id> --from-file patch.json`, and verify with `manifest` or `elements`. This keeps edits surgical, validated, versionable, and reviewable. `pull` is for backup, migration, review, or full-document work; `push` is for new specs or intentional full replacement. Direct database edits and direct `SpecStore.save()` calls bypass validation and are not approved spec-write paths.
|
|
3203
3216
|
283. **Bundled AI docs are part of the install surface** - The `mythik` package includes `docs/llms.txt`, `docs/consumer/*`, and `docs/wiki/compiled/*`. Agents should run `mythik docs path` before spec generation and read the bundled docs rather than guessing from package source. Use `mythik docs copy ./mythik-docs` to create a project-local copy when the host workflow needs explicit files.
|
|
3204
3217
|
284. **DNA numeric seeds are canonical `0–1`, with legacy `0–100` normalization** - Generate `tokens.dna.roundness`, `density`, `depth`, and `formality` as `0–1` numbers (`0.7`, not `70`). The runtime normalizes numeric seed values greater than `1` by dividing by `100` inside DNA derivation, so initial AppSpec load and runtime `updateTokens` share the same backward-compatible behavior.
|
|
3205
|
-
285. **Scoped pagination counts filter before aggregation** - Query endpoints may combine `pagination: "offset"` with `scopeFilter`. For generated counts, the server applies the scope filter to the query source first and then counts the scoped source, so the response `total` matches the same tenant/role slice as `data`. Prefer generated counts. If custom `endpoint.count` is truly needed with `scopeFilter`, it must include `{{scopeWhere[:alias]}}` or `{{scopeAnd[:alias]}}`; Mythik expands the macro to the correct scope predicate and removes it for bypass roles. Other custom count SQL is left verbatim. Specs should use `:alias` for JOIN/subquery counts and should not reference internal scope parameter names directly.
|
|
3206
|
-
286. **Transaction fetch failures preserve backend error details** - When a transaction `confirm` uses `fetch` and the backend returns an HTTP error payload such as `{ error: { code, message } }`, `/tx/error` is written after rollback with the best backend message plus `code`, HTTP `status`, and raw `data`. `onError` should read `/tx/error/message`; transaction specs should not read global `/ui/lastError`.
|
|
3218
|
+
285. **Scoped pagination counts filter before aggregation** - Query endpoints may combine `pagination: "offset"` with `scopeFilter`. For generated counts, the server applies the scope filter to the query source first and then counts the scoped source, so the response `total` matches the same tenant/role slice as `data`. Prefer generated counts. If custom `endpoint.count` is truly needed with `scopeFilter`, it must include `{{scopeWhere[:alias]}}` or `{{scopeAnd[:alias]}}`; Mythik expands the macro to the correct scope predicate and removes it for bypass roles. Other custom count SQL is left verbatim. Specs should use `:alias` for JOIN/subquery counts and should not reference internal scope parameter names directly.
|
|
3219
|
+
286. **Transaction fetch failures preserve backend error details** - When a transaction `confirm` uses `fetch` and the backend returns an HTTP error payload such as `{ error: { code, message } }`, `/tx/error` is written after rollback with the best backend message plus `code`, HTTP `status`, and raw `data`. `onError` should read `/tx/error/message`; transaction specs should not read global `/ui/lastError`.
|
|
3220
|
+
287. **SQL-backed stores and servers use one dialect-aware `mythik/server` boundary** - Import `createSqlDriver`, `SqlSpecStore`, `SqlVersionedSpecStore`, `SqlEnvironmentStore`, and `getSqlStoreDdl` from `mythik/server` for Node-side SQL work. Supported dialects are `sqlserver`, `postgres`, `mysql`, and `sqlite`. Initialize store tables with `mythik init-store --dialect <dialect>` for reachable SQL stores, `--target` for SQLite, or `--dry-run` for review/apply through a deployment process. SQL Server `init-store` accepts explicit `--server`, `--database`, `--user`, `--password`, `--encrypt`, and `--trust-server-certificate` flags. CLI commands share the same store flags/env vars and must keep existing-spec edits on the `manifest -> elements -> patch --from-file -> validate` loop. ApiSpec `dialect` controls generated CRUD/catalog/pagination/scope SQL; custom SQL remains dialect-native with Mythik named params (`@name`) and is not translated between dialects.
|
|
3221
|
+
288. **Event arrays may mix actions and transactions** - Event bindings can be a single action, a single transaction, or an array containing both normal action bindings and transaction bindings. Mythik executes the array sequentially and awaits each transaction before continuing. Transaction phases cannot contain nested transactions.
|
|
3222
|
+
289. **`$let` dotted references read nested binding values** - A `$ref` may target an object binding path such as `{ "$ref": "user.name" }`, and `$template` placeholders may read the same path as `${user.name}`. Use this for object values produced by `$let`; missing dotted `$ref` segments are invalid references and should be fixed instead of treated as optional data.
|
|
3223
|
+
290. **`params.skipIf` is a dispatch-time action guard** - Any action binding may include `params.skipIf`. Mythik resolves it before resolving the rest of the params; when truthy, the action is skipped and the action chain continues. The action handler never receives `skipIf`.
|
|
@@ -15,7 +15,7 @@ Compiled from `docs/consumer/` into **327 atomic articles**. The wiki is optimiz
|
|
|
15
15
|
## Publish notes
|
|
16
16
|
|
|
17
17
|
- Public package names are unscoped: `mythik`, `mythik-react`, `mythik-cli`, `mythik-server`.
|
|
18
|
-
- React Native work is a repository preview track, not part of the
|
|
18
|
+
- React Native work is a repository preview track, not part of the supported npm publish surface yet.
|
|
19
19
|
- The wiki metadata folder is not publish content.
|
|
20
20
|
- `docs/consumer` remains the canonical source.
|
|
21
21
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Lint Report -
|
|
2
|
-
|
|
3
|
-
Validation of cross-references, stale public references, and generated wiki shape after refreshing
|
|
1
|
+
# Lint Report - Event Binding Guard Refresh
|
|
2
|
+
|
|
3
|
+
Validation of cross-references, stale public references, and generated wiki shape after refreshing the compiled wiki delta from `docs/consumer` on 2026-05-09.
|
|
4
4
|
|
|
5
5
|
## Broken Cross-References
|
|
6
6
|
|
|
@@ -24,11 +24,16 @@ Validation of cross-references, stale public references, and generated wiki shap
|
|
|
24
24
|
- Migration pages removed: **yes** (`migration-*.md` no longer publish)
|
|
25
25
|
- Metadata folder publish status: **excluded**
|
|
26
26
|
|
|
27
|
-
## Key Refresh Additions
|
|
28
|
-
|
|
29
|
-
- `
|
|
30
|
-
-
|
|
31
|
-
- `
|
|
27
|
+
## Key Refresh Additions
|
|
28
|
+
|
|
29
|
+
- Dotted `$let` binding reads for `$ref` and `$template`
|
|
30
|
+
- Mixed event arrays containing actions plus transactions
|
|
31
|
+
- `params.skipIf` dispatch-time action guards
|
|
32
|
+
- Optional SQL adapter dependency wording
|
|
33
|
+
- Generic SQL store / driver package-layout pages
|
|
34
|
+
- `concept-public-package-names`
|
|
35
|
+
- `cli-existing-spec-edit-loop`
|
|
36
|
+
- `primitive-spatial-map`
|
|
32
37
|
- `concept-spatial-map-editor`
|
|
33
38
|
- `concept-spatial-map-zones`
|
|
34
39
|
- `concept-editor-sessions`
|