rip-lang 3.14.0 → 3.14.2
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 +42 -32
- package/docs/RIP-LANG.md +89 -4
- package/docs/RIP-SCHEMA.md +98 -8
- package/docs/dist/rip.js +724 -455
- package/docs/dist/rip.min.js +232 -177
- package/docs/dist/rip.min.js.br +0 -0
- package/docs/extensions/duckdb/index.html +97 -0
- package/docs/extensions/duckdb/manifest.json +11 -0
- package/docs/extensions/duckdb/v1.5.2/linux_amd64/ripdb.duckdb_extension.gz +0 -0
- package/docs/extensions/duckdb/v1.5.2/osx_arm64/ripdb.duckdb_extension.gz +0 -0
- package/docs/extensions/index.html +82 -0
- package/docs/extensions/vscode/print/index.html +40 -0
- package/docs/extensions/vscode/print/print-1.0.13.vsix +0 -0
- package/docs/extensions/vscode/print/print-latest.vsix +0 -0
- package/docs/extensions/vscode/rip/index.html +40 -0
- package/docs/extensions/vscode/rip/rip-0.5.15.vsix +0 -0
- package/docs/extensions/vscode/rip/rip-latest.vsix +0 -0
- package/package.json +3 -2
- package/src/AGENTS.md +32 -0
- package/src/compiler.js +140 -22
- package/src/grammar/grammar.rip +41 -0
- package/src/lexer.js +146 -17
- package/src/parser.js +213 -205
- package/src/schema.js +104 -13
- package/src/typecheck.js +532 -3
- package/src/sourcemap-utils.js +0 -521
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="https://github.com/shreeve/rip-lang/commits/main"><img src="https://img.shields.io/badge/version-3.14.
|
|
12
|
+
<a href="https://github.com/shreeve/rip-lang/commits/main"><img src="https://img.shields.io/badge/version-3.14.2-blue.svg" alt="Version"></a>
|
|
13
13
|
<a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
|
|
14
14
|
<a href="#"><img src="https://img.shields.io/badge/tests-1%2C436%2F1%2C436-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
|
@@ -60,6 +60,34 @@ rip -c file.rip # Compile to JavaScript
|
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
+
## Extensions
|
|
64
|
+
|
|
65
|
+
Pre-built binaries and VS Code / Cursor extensions are published via GitHub Pages — see the [extensions hub](https://shreeve.github.io/rip-lang/extensions/) for details.
|
|
66
|
+
|
|
67
|
+
**`ripdb`** — DuckDB extension that exposes a rip-db server as a first-class attached database:
|
|
68
|
+
|
|
69
|
+
```sql
|
|
70
|
+
SET allow_unsigned_extensions = true;
|
|
71
|
+
INSTALL ripdb FROM 'https://shreeve.github.io/rip-lang/extensions/duckdb';
|
|
72
|
+
LOAD ripdb;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**`rip-lang.print`** — syntax-highlighted source printer for VS Code / Cursor:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
curl -LO https://shreeve.github.io/rip-lang/extensions/vscode/print/print-latest.vsix
|
|
79
|
+
cursor --install-extension ./print-latest.vsix
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**`rip-lang.rip`** — Rip language support for VS Code / Cursor:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
curl -LO https://shreeve.github.io/rip-lang/extensions/vscode/rip/rip-latest.vsix
|
|
86
|
+
cursor --install-extension ./rip-latest.vsix
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
63
91
|
## Language
|
|
64
92
|
|
|
65
93
|
### Functions & Classes
|
|
@@ -405,9 +433,6 @@ The UI framework is built into rip-lang: file-based router, reactive stash, comp
|
|
|
405
433
|
| **Reactivity** | None | Built-in |
|
|
406
434
|
| **Dependencies** | Multiple | Zero |
|
|
407
435
|
| **Self-hosting** | No | Yes |
|
|
408
|
-
| **Lexer** | 3,558 LOC | 2,024 LOC |
|
|
409
|
-
| **Compiler** | 10,346 LOC | 3,293 LOC |
|
|
410
|
-
| **Total** | 17,760 LOC | ~11,890 LOC |
|
|
411
436
|
|
|
412
437
|
Smaller codebase, modern output, built-in reactivity.
|
|
413
438
|
|
|
@@ -442,25 +467,10 @@ await rip("res = fetch! 'https://api.example.com/todos/1'; res.json!") // → {
|
|
|
442
467
|
|
|
443
468
|
```
|
|
444
469
|
Source -> Lexer -> emitTypes -> Parser -> S-Expressions -> Codegen -> JavaScript
|
|
445
|
-
|
|
470
|
+
(types.js) ["=", "x", 42] + source map
|
|
446
471
|
```
|
|
447
472
|
|
|
448
|
-
Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-hosting — `bun run parser` rebuilds from source.
|
|
449
|
-
|
|
450
|
-
| Component | File | Lines |
|
|
451
|
-
|-----------|------|-------|
|
|
452
|
-
| Lexer + Rewriter | `src/lexer.js` | 1,778 |
|
|
453
|
-
| Grammar | `src/grammar/grammar.rip` | 948 |
|
|
454
|
-
| Parser Generator | `src/grammar/solar.rip` | 929 |
|
|
455
|
-
| Parser (generated) | `src/parser.js` | 359 |
|
|
456
|
-
| Compiler + Codegen | `src/compiler.js` | 3,334 |
|
|
457
|
-
| Component System | `src/components.js` | 2,026 |
|
|
458
|
-
| Browser Engine | `src/browser.js` | 194 |
|
|
459
|
-
| Source Maps | `src/sourcemaps.js` | 189 |
|
|
460
|
-
| Type System | `src/types.js` | 1,091 |
|
|
461
|
-
| Type Checking | `src/typecheck.js` | 442 |
|
|
462
|
-
| REPL | `src/repl.js` | 600 |
|
|
463
|
-
| **Total** | | **~11,890** |
|
|
473
|
+
Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-hosting — `bun run parser` rebuilds from source. The implementation lives across a handful of focused modules under `src/` — lexer, compiler, schema, types, typecheck, components, parser, browser, REPL — plus the grammar sources under `src/grammar/`. Run `wc -l src/*.js` for current sizes.
|
|
464
474
|
|
|
465
475
|
---
|
|
466
476
|
|
|
@@ -468,16 +478,16 @@ Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-ho
|
|
|
468
478
|
|
|
469
479
|
Rip includes optional packages for full-stack development:
|
|
470
480
|
|
|
471
|
-
| Package |
|
|
472
|
-
|
|
473
|
-
| [rip-lang](https://www.npmjs.com/package/rip-lang) |
|
|
474
|
-
| [@rip-lang/server](packages/server/) |
|
|
475
|
-
| [@rip-lang/db](packages/db/) |
|
|
476
|
-
| [@rip-lang/ui](packages/ui/) |
|
|
477
|
-
| [@rip-lang/swarm](packages/swarm/) |
|
|
478
|
-
| [@rip-lang/csv](packages/csv/) |
|
|
479
|
-
| [@rip-lang/time](packages/time/) |
|
|
480
|
-
| [VS Code Extension](packages/vscode/) |
|
|
481
|
+
| Package | Purpose |
|
|
482
|
+
|---------|---------|
|
|
483
|
+
| [rip-lang](https://www.npmjs.com/package/rip-lang) | Core language compiler |
|
|
484
|
+
| [@rip-lang/server](packages/server/) | Multi-worker app server (web framework, hot reload, HTTPS, mDNS) |
|
|
485
|
+
| [@rip-lang/db](packages/db/) | DuckDB server with official UI + ActiveRecord-style client |
|
|
486
|
+
| [@rip-lang/ui](packages/ui/) | Unified UI system — browser widgets, email components, shared helpers, Tailwind integration |
|
|
487
|
+
| [@rip-lang/swarm](packages/swarm/) | Parallel job runner with worker pool |
|
|
488
|
+
| [@rip-lang/csv](packages/csv/) | CSV parser + writer |
|
|
489
|
+
| [@rip-lang/time](packages/time/) | Immutable date/time with IANA timezones + `Duration` (US-English, zero runtime deps) |
|
|
490
|
+
| [VS Code Extension](packages/vscode/) | Syntax highlighting, type intelligence, source maps |
|
|
481
491
|
|
|
482
492
|
```bash
|
|
483
493
|
bun add -g @rip-lang/db # Installs everything (rip-lang + server + db)
|
|
@@ -515,7 +525,7 @@ rip file.rip # Run
|
|
|
515
525
|
rip -c file.rip # Compile
|
|
516
526
|
rip -t file.rip # Tokens
|
|
517
527
|
rip -s file.rip # S-expressions
|
|
518
|
-
bun run test
|
|
528
|
+
bun run test:all # full test suite
|
|
519
529
|
bun run parser # Rebuild parser
|
|
520
530
|
bun run build # Build browser bundle
|
|
521
531
|
```
|
package/docs/RIP-LANG.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Rip Language Reference
|
|
4
4
|
|
|
5
|
-
Rip is a modern reactive language that compiles to ES2022 JavaScript. It combines CoffeeScript's elegant syntax with built-in reactivity primitives. Zero dependencies, self-hosting
|
|
5
|
+
Rip is a modern reactive language that compiles to ES2022 JavaScript. It combines CoffeeScript's elegant syntax with built-in reactivity primitives. Zero dependencies, self-hosting.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -556,6 +556,93 @@ Common use cases: config objects, options bags, state initialization, DOM
|
|
|
556
556
|
styling, merging defaults with overrides — anywhere you're setting multiple
|
|
557
557
|
properties on an existing object.
|
|
558
558
|
|
|
559
|
+
## Pick Operator (`.{ }`)
|
|
560
|
+
|
|
561
|
+
A Rip original. Project a subset of an object's properties into a new object,
|
|
562
|
+
with optional renaming and defaults — sugar for the common
|
|
563
|
+
destructure-then-construct pattern:
|
|
564
|
+
|
|
565
|
+
```coffee
|
|
566
|
+
# Without .{ } — repetitive
|
|
567
|
+
response = { firstName: user.firstName, lastName: user.lastName, dob: user.dob }
|
|
568
|
+
|
|
569
|
+
# With .{ } — clean
|
|
570
|
+
response = user.{firstName, lastName, dob}
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
`obj.{a, b, c}` compiles to `{ a: obj.a, b: obj.b, c: obj.c }`. The source is
|
|
574
|
+
evaluated once — if it's a complex expression (call, member access, indexed),
|
|
575
|
+
an arrow IIFE binds a single temp so getters and reactive reads fire exactly
|
|
576
|
+
once.
|
|
577
|
+
|
|
578
|
+
### Forms
|
|
579
|
+
|
|
580
|
+
```coffee
|
|
581
|
+
# Bare keys — project as-is
|
|
582
|
+
user.{firstName, lastName}
|
|
583
|
+
# → {firstName: user.firstName, lastName: user.lastName}
|
|
584
|
+
|
|
585
|
+
# Rename — left side is source key, right side is destination key
|
|
586
|
+
user.{firstName: given, lastName: family}
|
|
587
|
+
# → {given: user.firstName, family: user.lastName}
|
|
588
|
+
|
|
589
|
+
# Nullish default — fires on undefined OR null (deliberately broader than
|
|
590
|
+
# JS destructure's undefined-only default, to match DB NULL reality)
|
|
591
|
+
user.{role = 'guest', active = true}
|
|
592
|
+
# → {role: (user.role ?? 'guest'), active: (user.active ?? true)}
|
|
593
|
+
|
|
594
|
+
# Rename + default combined
|
|
595
|
+
user.{role: r = 'guest'}
|
|
596
|
+
# → {r: (user.role ?? 'guest')}
|
|
597
|
+
|
|
598
|
+
# Multi-line
|
|
599
|
+
response = user.{
|
|
600
|
+
firstName
|
|
601
|
+
lastName
|
|
602
|
+
dob
|
|
603
|
+
role = 'patient'
|
|
604
|
+
}
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### Optional chain (`?.{ }`)
|
|
608
|
+
|
|
609
|
+
Returns `undefined` when the source is null/undefined, preserving the
|
|
610
|
+
distinction from a present-but-empty result:
|
|
611
|
+
|
|
612
|
+
```coffee
|
|
613
|
+
maybeUser?.{firstName, lastName}
|
|
614
|
+
# → maybeUser == null ? undefined : {firstName: maybeUser.firstName, ...}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### Reserved words work
|
|
618
|
+
|
|
619
|
+
Reserved-word keys like `default`, `class`, `delete`, `new`, `typeof`, `if`
|
|
620
|
+
are automatically treated as property names inside a pick body — the same
|
|
621
|
+
way they work after a `.` for plain member access:
|
|
622
|
+
|
|
623
|
+
```coffee
|
|
624
|
+
# Common real-world case (HTML/DOM/frameworks use `class`, `default`, …)
|
|
625
|
+
props.{class, default, onClick}
|
|
626
|
+
# → {class: props.class, default: props.default, onClick: props.onClick}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Semantics
|
|
630
|
+
|
|
631
|
+
- **Missing keys** read as `undefined` (normal property read on the source).
|
|
632
|
+
- **Source evaluated once** for complex expressions (`getUser().{a, b}` only
|
|
633
|
+
calls `getUser()` one time).
|
|
634
|
+
- **Defaults fire on nullish** (`??`) — both `undefined` and `null` trigger,
|
|
635
|
+
unlike JS destructure which only fires on `undefined`.
|
|
636
|
+
- **Chainable** — `user.{firstName, role}.role` works.
|
|
637
|
+
|
|
638
|
+
### Not supported (use explicit objects for these)
|
|
639
|
+
|
|
640
|
+
- Spread inside body: `user.{...rest}` is rejected.
|
|
641
|
+
- Computed or string/number keys: `user.{[k]}`, `user.{'a'}`, `user.{0}` are
|
|
642
|
+
rejected.
|
|
643
|
+
- Nested picks: `user.{address.{city, zip}}` is not supported in v1 — use an
|
|
644
|
+
explicit object or a helper for now.
|
|
645
|
+
|
|
559
646
|
## Prototype Operator (`::`)
|
|
560
647
|
|
|
561
648
|
Access `.prototype` with `::` (CoffeeScript-style). Disambiguated from type annotations by spacing:
|
|
@@ -2201,8 +2288,6 @@ count = 10 # Logs: "Count: 10, Doubled: 20"
|
|
|
2201
2288
|
|
|
2202
2289
|
Ideas and candidates that have been discussed but not yet implemented.
|
|
2203
2290
|
|
|
2204
|
-
> **Note:** The standard library was implemented in v3.13.0. See [Section 14](#14-standard-library).
|
|
2205
|
-
|
|
2206
2291
|
## Future Syntax Ideas
|
|
2207
2292
|
|
|
2208
2293
|
Each would need design discussion before building.
|
|
@@ -2238,4 +2323,4 @@ Each would need design discussion before building.
|
|
|
2238
2323
|
|
|
2239
2324
|
---
|
|
2240
2325
|
|
|
2241
|
-
*Rip
|
|
2326
|
+
*Rip — Zero dependencies — Self-hosting*
|
package/docs/RIP-SCHEMA.md
CHANGED
|
@@ -269,6 +269,36 @@ behavior is dropped** — methods, computed getters (`~>`), eager
|
|
|
269
269
|
derived fields (`!>`), hooks, and ORM methods don't carry through.
|
|
270
270
|
Algebra is a structural operation on fields, not a behavioral one.
|
|
271
271
|
|
|
272
|
+
### Idiomatic shorthands
|
|
273
|
+
|
|
274
|
+
Most production code uses a few syntactic sugars. All are optional;
|
|
275
|
+
the Quick Tour above works as written.
|
|
276
|
+
|
|
277
|
+
```coffee
|
|
278
|
+
# Open-ended ranges. With `!` (required), `..N` implies `min=1`.
|
|
279
|
+
User = schema
|
|
280
|
+
firstName! ..50 # required, 1..50 chars
|
|
281
|
+
bio? text # `text` is unbounded by design
|
|
282
|
+
phone? 1..20
|
|
283
|
+
|
|
284
|
+
# File-level default cap for uncapped VARCHAR-like fields.
|
|
285
|
+
schema.defaultMaxString = 500
|
|
286
|
+
|
|
287
|
+
Profile = schema :model
|
|
288
|
+
name! # → {min: 1, max: 500}
|
|
289
|
+
email!# email # → {max: 500}
|
|
290
|
+
bio? text # → uncapped (text opts out)
|
|
291
|
+
|
|
292
|
+
# One-line small shapes, plus a registered schema used as a field type.
|
|
293
|
+
Address = schema :shape; street? ..200; city? ..100; zip? ..10
|
|
294
|
+
|
|
295
|
+
Order = schema :shape
|
|
296
|
+
address! Address # validation recurses; errors like "address.street"
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
See §5 for body-syntax details, §17 for nested type references, and
|
|
300
|
+
§20 for constraint and pragma rules.
|
|
301
|
+
|
|
272
302
|
---
|
|
273
303
|
|
|
274
304
|
## 3. Schemas vs types
|
|
@@ -517,6 +547,7 @@ kind (see [§18](#18-directives)). Examples:
|
|
|
517
547
|
@timestamps # adds createdAt/updatedAt columns (:model only)
|
|
518
548
|
@softDelete # adds deletedAt, soft-deletes on .destroy() (:model only)
|
|
519
549
|
@index [role, active] # composite index (:model only)
|
|
550
|
+
@idStart 10001 # seed for the auto-id sequence (:model only, .toSQL())
|
|
520
551
|
@belongs_to Organization? # nullable FK (:model only)
|
|
521
552
|
@has_many Order # has-many relation (:model only)
|
|
522
553
|
@mixin Timestamps # pull in a mixin's fields (any fielded kind)
|
|
@@ -864,7 +895,10 @@ user.save! # validate, run hooks, INSERT or UPDATE
|
|
|
864
895
|
user.destroy! # run hooks, DELETE (or UPDATE deleted_at for @softDelete)
|
|
865
896
|
user.ok() # boolean — current fields validate
|
|
866
897
|
user.errors() # SchemaIssue[] — current fields' errors
|
|
867
|
-
user.toJSON() # plain object of
|
|
898
|
+
user.toJSON() # plain object of own enumerable properties
|
|
899
|
+
# (id, declared fields, @timestamps columns, @softDelete
|
|
900
|
+
# deletedAt, @belongs_to FKs, !> eager-derived — but NOT
|
|
901
|
+
# methods, ~> computed getters, or internal state)
|
|
868
902
|
```
|
|
869
903
|
|
|
870
904
|
Plus any methods, computed getters, and relation accessors you declared
|
|
@@ -976,6 +1010,25 @@ User.toSQL()
|
|
|
976
1010
|
`.toSQL()` works independently of the ORM. A migration script that never
|
|
977
1011
|
calls `.find()` or `.create()` can still emit full DDL.
|
|
978
1012
|
|
|
1013
|
+
#### Sequence start value
|
|
1014
|
+
|
|
1015
|
+
The auto-id sequence seeds at `1` by default. Override per-model with the
|
|
1016
|
+
`@idStart N` directive, or per-call with the `idStart` option (the option
|
|
1017
|
+
wins):
|
|
1018
|
+
|
|
1019
|
+
```coffee
|
|
1020
|
+
User = schema :model
|
|
1021
|
+
name! string
|
|
1022
|
+
@idStart 10001 # customer-facing IDs start at 10001
|
|
1023
|
+
|
|
1024
|
+
User.toSQL() # → CREATE SEQUENCE users_seq START 10001;
|
|
1025
|
+
User.toSQL(idStart: 50000) # → CREATE SEQUENCE users_seq START 50000;
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
Required because DuckDB (as of 1.5.2) does not implement
|
|
1029
|
+
`ALTER SEQUENCE … RESTART WITH N` — so the seed has to be baked into the
|
|
1030
|
+
initial `CREATE SEQUENCE` rather than bumped in a follow-up migration.
|
|
1031
|
+
|
|
979
1032
|
To emit a whole application's schema, call `.toSQL()` per model and join.
|
|
980
1033
|
Order by FK dependency (models referenced via `@belongs_to` come first):
|
|
981
1034
|
|
|
@@ -1615,6 +1668,41 @@ p "[migrate] schema created"
|
|
|
1615
1668
|
Because `.toSQL()` doesn't call the adapter, migration scripts work
|
|
1616
1669
|
before the database exists or before the ORM is wired.
|
|
1617
1670
|
|
|
1671
|
+
### Composing nested shapes
|
|
1672
|
+
|
|
1673
|
+
Small sub-shapes referenced by name compose into a larger contract.
|
|
1674
|
+
Validation recurses into each referenced schema; errors carry
|
|
1675
|
+
path-prefixed `field` entries so callers can pinpoint the failing
|
|
1676
|
+
sub-field:
|
|
1677
|
+
|
|
1678
|
+
```coffee
|
|
1679
|
+
Address = schema :shape
|
|
1680
|
+
street! ..200
|
|
1681
|
+
city! ..100
|
|
1682
|
+
state? ..2
|
|
1683
|
+
zip? ..10
|
|
1684
|
+
|
|
1685
|
+
Customer = schema :shape
|
|
1686
|
+
id? integer
|
|
1687
|
+
name! ..100
|
|
1688
|
+
address! Address
|
|
1689
|
+
|
|
1690
|
+
OrderRequest = schema :shape
|
|
1691
|
+
customer! Customer
|
|
1692
|
+
notes? ..500
|
|
1693
|
+
|
|
1694
|
+
r = OrderRequest.safe body
|
|
1695
|
+
if r.ok
|
|
1696
|
+
process r.value
|
|
1697
|
+
else
|
|
1698
|
+
for e in r.errors
|
|
1699
|
+
# e.g. field: "customer.address.street" error: "required"
|
|
1700
|
+
console.log e.field, e.error, e.message
|
|
1701
|
+
```
|
|
1702
|
+
|
|
1703
|
+
Registered `:shape` / `:input` / `:model` names can all be referenced
|
|
1704
|
+
as field types — see §17 for resolution rules.
|
|
1705
|
+
|
|
1618
1706
|
---
|
|
1619
1707
|
|
|
1620
1708
|
## 15. What's not here yet
|
|
@@ -1735,9 +1823,10 @@ Built-in type names and their runtime / SQL / TypeScript mappings:
|
|
|
1735
1823
|
|
|
1736
1824
|
Arrays: `type[]`. SQL stores as `JSON` (DuckDB native), TS is `T[]`.
|
|
1737
1825
|
|
|
1738
|
-
**Nested-schema identifiers.**
|
|
1739
|
-
|
|
1740
|
-
|
|
1826
|
+
**Nested-schema identifiers.** A field's type name may be another
|
|
1827
|
+
schema declared with `:shape`, `:input`, or `:model`. When the name
|
|
1828
|
+
resolves to one of those in the process-global `__SchemaRegistry`,
|
|
1829
|
+
the validator recurses into the referenced schema:
|
|
1741
1830
|
|
|
1742
1831
|
```coffee
|
|
1743
1832
|
Address = schema :shape
|
|
@@ -1789,6 +1878,7 @@ user-defined enums or shapes compose incrementally.
|
|
|
1789
1878
|
| `@index [a, b, c]` | Composite index on the listed columns |
|
|
1790
1879
|
| `@index column` | Single-column index (same as `@index [column]`) |
|
|
1791
1880
|
| `@index [...] #` | Unique index |
|
|
1881
|
+
| `@idStart N` | Seed value for the auto-id sequence in `.toSQL()` output (default `1`). Overridden per-call by `toSQL(idStart: N)`. |
|
|
1792
1882
|
| `@belongs_to Target` | FK column `target_id` referencing `targets.id`, NOT NULL |
|
|
1793
1883
|
| `@belongs_to Target?` | Same, nullable |
|
|
1794
1884
|
| `@has_one Target` | Accessor `target()` returning one |
|
|
@@ -2320,10 +2410,10 @@ preamble (under `SCHEMA_RUNTIME` in `src/schema.js`) that defines
|
|
|
2320
2410
|
helpers. No import statement, no package dependency, no bootstrap call.
|
|
2321
2411
|
|
|
2322
2412
|
**How big is the runtime?**
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2413
|
+
It includes the validator plan, registry, hydration logic, ORM
|
|
2414
|
+
support, and DDL emission. In multi-bundle processes, Rip binds
|
|
2415
|
+
`schema` to a shared `globalThis.__ripSchema` singleton, so bundles
|
|
2416
|
+
share one registry and one adapter per process.
|
|
2327
2417
|
|
|
2328
2418
|
**Is `.parse()` strict or permissive with extra keys?**
|
|
2329
2419
|
Permissive with stripping. Unknown keys are silently dropped — they
|