@rip-lang/schema 0.2.1
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 +1042 -0
- package/SCHEMA.md +1113 -0
- package/emit-sql.js +460 -0
- package/emit-types.js +366 -0
- package/generate.js +144 -0
- package/grammar.rip +504 -0
- package/index.js +39 -0
- package/lexer.js +438 -0
- package/orm.js +916 -0
- package/package.json +62 -0
- package/parser.js +246 -0
- package/runtime.js +494 -0
package/grammar.rip
ADDED
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Schema Grammar - S-Expression Output for Rip Schema Definitions
|
|
3
|
+
#
|
|
4
|
+
# A unified schema language for types, validation, database models, and UI.
|
|
5
|
+
# Inspired by SPOT/Sage, rip-schema, TypeScript, and Zod.
|
|
6
|
+
#
|
|
7
|
+
# Author: Steve Shreeve <steve.shreeve@gmail.com>
|
|
8
|
+
# Date: January 2026
|
|
9
|
+
#
|
|
10
|
+
# Key syntax:
|
|
11
|
+
# @enum Role: admin, user, guest
|
|
12
|
+
# @type Address
|
|
13
|
+
# @model User
|
|
14
|
+
# name! string, [1, 100] # ! = required, [min, max]
|
|
15
|
+
# email!# email # # = unique
|
|
16
|
+
# role? Role, [user] # ? = optional, [default]
|
|
17
|
+
# ==============================================================================
|
|
18
|
+
|
|
19
|
+
o = (pattern, action, options) ->
|
|
20
|
+
pattern = pattern.trim().replace /\s{2,}/g, ' '
|
|
21
|
+
[pattern, action ?? 1, options]
|
|
22
|
+
|
|
23
|
+
mode = 'sexp'
|
|
24
|
+
|
|
25
|
+
grammar =
|
|
26
|
+
|
|
27
|
+
# ============================================================================
|
|
28
|
+
# Top-Level Structure
|
|
29
|
+
# ============================================================================
|
|
30
|
+
|
|
31
|
+
Schema: [
|
|
32
|
+
o '' , '["schema"]'
|
|
33
|
+
o 'Definitions', '["schema", ...1]'
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
Definitions: [
|
|
37
|
+
o 'Definition' , '[1]'
|
|
38
|
+
o 'Definitions TERMINATOR Definition' , '[...1, 3]'
|
|
39
|
+
o 'Definitions TERMINATOR'
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
Definition: [
|
|
43
|
+
o 'Import'
|
|
44
|
+
o 'EnumDef'
|
|
45
|
+
o 'TypeDef'
|
|
46
|
+
o 'ModelDef'
|
|
47
|
+
o 'MixinDef'
|
|
48
|
+
o 'WidgetDef'
|
|
49
|
+
o 'FormDef'
|
|
50
|
+
o 'StateDef'
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
# ============================================================================
|
|
54
|
+
# Import Statements
|
|
55
|
+
# ============================================================================
|
|
56
|
+
|
|
57
|
+
Import: [
|
|
58
|
+
o 'IMPORT STRING', '["import", 2]'
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# ============================================================================
|
|
62
|
+
# Helper: Optional Terminator before INDENT
|
|
63
|
+
# ============================================================================
|
|
64
|
+
|
|
65
|
+
Block: [
|
|
66
|
+
o 'INDENT Body OUTDENT' , 2
|
|
67
|
+
o 'TERMINATOR INDENT Body OUTDENT' , 3
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
# ============================================================================
|
|
71
|
+
# Enum Definitions
|
|
72
|
+
# ============================================================================
|
|
73
|
+
|
|
74
|
+
# @enum Role: admin, user, guest
|
|
75
|
+
# @enum Status
|
|
76
|
+
# pending: 0
|
|
77
|
+
# active: 1
|
|
78
|
+
|
|
79
|
+
EnumDef: [
|
|
80
|
+
o 'ENUM Identifier : EnumValues' , '["enum", 2, 4]'
|
|
81
|
+
o 'ENUM Identifier INDENT EnumMembers OUTDENT' , '["enum", 2, 4]'
|
|
82
|
+
o 'ENUM Identifier TERMINATOR INDENT EnumMembers OUTDENT', '["enum", 2, 5]'
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
EnumValues: [
|
|
86
|
+
o 'Identifier' , '[1]'
|
|
87
|
+
o 'EnumValues , Identifier' , '[...1, 3]'
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
EnumMembers: [
|
|
91
|
+
o 'EnumMember' , '[1]'
|
|
92
|
+
o 'EnumMembers TERMINATOR EnumMember' , '[...1, 3]'
|
|
93
|
+
o 'EnumMembers TERMINATOR'
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
EnumMember: [
|
|
97
|
+
o 'Identifier : Literal', '[1, 3]'
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
# ============================================================================
|
|
101
|
+
# Type Definitions (reusable structures, no DB)
|
|
102
|
+
# ============================================================================
|
|
103
|
+
|
|
104
|
+
TypeDef: [
|
|
105
|
+
o 'TYPE Identifier Block' , '["type", 2, null, 3]'
|
|
106
|
+
o 'TYPE Identifier : Identifier Block' , '["type", 2, 4, 5]'
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
# ============================================================================
|
|
110
|
+
# Model Definitions (database-backed entities)
|
|
111
|
+
# ============================================================================
|
|
112
|
+
|
|
113
|
+
ModelDef: [
|
|
114
|
+
o 'MODEL Identifier Block' , '["model", 2, null, 3]'
|
|
115
|
+
o 'MODEL Identifier : Identifier Block' , '["model", 2, 4, 5]'
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
# ============================================================================
|
|
119
|
+
# Mixin Definitions (reusable field groups)
|
|
120
|
+
# ============================================================================
|
|
121
|
+
|
|
122
|
+
MixinDef: [
|
|
123
|
+
o 'MIXIN Identifier Block', '["mixin", 2, 3]'
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
# ============================================================================
|
|
127
|
+
# Widget Definitions (UI components)
|
|
128
|
+
# ============================================================================
|
|
129
|
+
|
|
130
|
+
WidgetDef: [
|
|
131
|
+
o 'WIDGET Identifier Block' , '["widget", 2, null, 3]'
|
|
132
|
+
o 'WIDGET Identifier : Identifier Block' , '["widget", 2, 4, 5]'
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
# ============================================================================
|
|
136
|
+
# Form Definitions (model + layout)
|
|
137
|
+
# ============================================================================
|
|
138
|
+
|
|
139
|
+
FormDef: [
|
|
140
|
+
o 'FORM Identifier : Identifier Block' , '["form", 2, 4, 5]'
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
# ============================================================================
|
|
144
|
+
# State Definitions (reactive state)
|
|
145
|
+
# ============================================================================
|
|
146
|
+
|
|
147
|
+
StateDef: [
|
|
148
|
+
o 'STATE Identifier Block', '["state", 2, 3]'
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
# ============================================================================
|
|
152
|
+
# Body - List of members (fields, directives, etc.)
|
|
153
|
+
# ============================================================================
|
|
154
|
+
|
|
155
|
+
Body: [
|
|
156
|
+
o 'Member' , '[1]'
|
|
157
|
+
o 'Body TERMINATOR Member' , '[...1, 3]'
|
|
158
|
+
o 'Body TERMINATOR'
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
Member: [
|
|
162
|
+
o 'Field'
|
|
163
|
+
o 'Directive'
|
|
164
|
+
o 'Relation'
|
|
165
|
+
o 'IndexDef'
|
|
166
|
+
o 'ComputedBlock'
|
|
167
|
+
o 'ValidateBlock'
|
|
168
|
+
o 'EventsDef'
|
|
169
|
+
o 'ActionsBlock'
|
|
170
|
+
o 'FormField'
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
# ============================================================================
|
|
174
|
+
# Field Definitions
|
|
175
|
+
# ============================================================================
|
|
176
|
+
|
|
177
|
+
# Syntax: name[!#?] type[, constraints][, attributes]
|
|
178
|
+
#
|
|
179
|
+
# Examples:
|
|
180
|
+
# name! string Required string
|
|
181
|
+
# email!# email Required + unique
|
|
182
|
+
# bio? text, [0, 1000] Optional with max length
|
|
183
|
+
# role Role, [user] Enum with default
|
|
184
|
+
# items Item[] Array type
|
|
185
|
+
# data json, [{}] JSON with default
|
|
186
|
+
# phone string, { mask: "###" } With UI attributes
|
|
187
|
+
|
|
188
|
+
# Field definition - handles both regular fields and computed fields
|
|
189
|
+
Field: [
|
|
190
|
+
# Regular field: name type
|
|
191
|
+
o 'IDENTIFIER FieldType' , '["field", 1, [], 2, null, null]'
|
|
192
|
+
o 'IDENTIFIER FieldType , Constraints' , '["field", 1, [], 2, 4, null]'
|
|
193
|
+
o 'IDENTIFIER FieldType , Attrs' , '["field", 1, [], 2, null, 4]'
|
|
194
|
+
o 'IDENTIFIER FieldType , Constraints , Attrs' , '["field", 1, [], 2, 4, 6]'
|
|
195
|
+
# Field with modifiers: name! type, name!# type, etc.
|
|
196
|
+
o 'IDENTIFIER FieldModifiers FieldType' , '["field", 1, 2, 3, null, null]'
|
|
197
|
+
o 'IDENTIFIER FieldModifiers FieldType , Constraints' , '["field", 1, 2, 3, 5, null]'
|
|
198
|
+
o 'IDENTIFIER FieldModifiers FieldType , Attrs' , '["field", 1, 2, 3, null, 5]'
|
|
199
|
+
o 'IDENTIFIER FieldModifiers FieldType , Constraints , Attrs' , '["field", 1, 2, 3, 5, 7]'
|
|
200
|
+
# Computed field: name -> expr
|
|
201
|
+
o 'IDENTIFIER ArrowFunc' , '["computed", 1, 2]'
|
|
202
|
+
]
|
|
203
|
+
|
|
204
|
+
FieldModifiers: [
|
|
205
|
+
o '!' , '["!"]'
|
|
206
|
+
o '#' , '["#"]'
|
|
207
|
+
o '?' , '["?"]'
|
|
208
|
+
o 'FieldModifiers !' , '[...1, "!"]'
|
|
209
|
+
o 'FieldModifiers #' , '[...1, "#"]'
|
|
210
|
+
o 'FieldModifiers ?' , '[...1, "?"]'
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
# Field type (supports arrays via [])
|
|
214
|
+
FieldType: [
|
|
215
|
+
o 'IDENTIFIER' # string, email, User, etc.
|
|
216
|
+
o 'IDENTIFIER [ ]' , '["array", 1]'
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
# Constraints in brackets: [min, max], [default], [min, max, default]
|
|
220
|
+
Constraints: [
|
|
221
|
+
o '[ ConstraintList ]', 2
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
ConstraintList: [
|
|
225
|
+
o 'ConstraintValue' , '[1]'
|
|
226
|
+
o 'ConstraintList , ConstraintValue' , '[...1, 3]'
|
|
227
|
+
]
|
|
228
|
+
|
|
229
|
+
ConstraintValue: [
|
|
230
|
+
o 'Literal'
|
|
231
|
+
o 'IDENTIFIER' # Enum values like [user]
|
|
232
|
+
o 'Object'
|
|
233
|
+
o 'Array'
|
|
234
|
+
o 'Regex'
|
|
235
|
+
o 'ArrowFunc'
|
|
236
|
+
]
|
|
237
|
+
|
|
238
|
+
# Attributes in braces (for UI hints)
|
|
239
|
+
Attrs: [
|
|
240
|
+
o 'Object'
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
# ============================================================================
|
|
244
|
+
# Directives (@timestamps, @softDelete, etc.)
|
|
245
|
+
# ============================================================================
|
|
246
|
+
|
|
247
|
+
Directive: [
|
|
248
|
+
o 'TIMESTAMPS' , '["timestamps"]'
|
|
249
|
+
o 'SOFT_DELETE' , '["softDelete"]'
|
|
250
|
+
o 'INCLUDE IDENTIFIER' , '["include", 2]'
|
|
251
|
+
o 'PATTERN Regex' , '["pattern", 2]'
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
# ============================================================================
|
|
255
|
+
# Relationships
|
|
256
|
+
# ============================================================================
|
|
257
|
+
|
|
258
|
+
Relation: [
|
|
259
|
+
o 'BELONGS_TO IDENTIFIER' , '["belongs_to", 2, null]'
|
|
260
|
+
o 'BELONGS_TO IDENTIFIER , RelationOpts' , '["belongs_to", 2, 4]'
|
|
261
|
+
o 'HAS_ONE IDENTIFIER' , '["has_one", 2, null]'
|
|
262
|
+
o 'HAS_ONE IDENTIFIER , RelationOpts' , '["has_one", 2, 4]'
|
|
263
|
+
o 'HAS_MANY IDENTIFIER' , '["has_many", 2, null]'
|
|
264
|
+
o 'HAS_MANY IDENTIFIER , RelationOpts' , '["has_many", 2, 4]'
|
|
265
|
+
o 'ONE IDENTIFIER' , '["has_one", 2, null]'
|
|
266
|
+
o 'ONE IDENTIFIER , RelationOpts' , '["has_one", 2, 4]'
|
|
267
|
+
o 'MANY IDENTIFIER' , '["has_many", 2, null]'
|
|
268
|
+
o 'MANY IDENTIFIER , RelationOpts' , '["has_many", 2, 4]'
|
|
269
|
+
o 'LINK STRING , IDENTIFIER' , '["link", 2, 4, null]'
|
|
270
|
+
o 'LINK STRING , IDENTIFIER , RelationOpts' , '["link", 2, 4, 6]'
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
RelationOpts: [
|
|
274
|
+
o 'Object'
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
# ============================================================================
|
|
278
|
+
# Indexes
|
|
279
|
+
# ============================================================================
|
|
280
|
+
|
|
281
|
+
IndexDef: [
|
|
282
|
+
o 'INDEX IDENTIFIER' , '["index", [2], false]'
|
|
283
|
+
o 'INDEX IDENTIFIER #' , '["index", [2], true]'
|
|
284
|
+
o 'INDEX [ IndexFields ]' , '["index", 3, false]'
|
|
285
|
+
o 'INDEX [ IndexFields ] #' , '["index", 3, true]'
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
IndexFields: [
|
|
289
|
+
o 'IDENTIFIER' , '[1]'
|
|
290
|
+
o 'IndexFields , IDENTIFIER' , '[...1, 3]'
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
# ============================================================================
|
|
294
|
+
# Computed Fields Block
|
|
295
|
+
# ============================================================================
|
|
296
|
+
|
|
297
|
+
ComputedBlock: [
|
|
298
|
+
o 'COMPUTED Block', '["computed", 2]'
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
# ============================================================================
|
|
302
|
+
# Validation Block
|
|
303
|
+
# ============================================================================
|
|
304
|
+
|
|
305
|
+
ValidateBlock: [
|
|
306
|
+
o 'VALIDATE Block', '["validate", 2]'
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
# ============================================================================
|
|
310
|
+
# Events (for widgets)
|
|
311
|
+
# ============================================================================
|
|
312
|
+
|
|
313
|
+
EventsDef: [
|
|
314
|
+
o 'EVENTS EventList', '["events", 2]'
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
EventList: [
|
|
318
|
+
o 'IDENTIFIER' , '[1]'
|
|
319
|
+
o 'EventList , IDENTIFIER' , '[...1, 3]'
|
|
320
|
+
]
|
|
321
|
+
|
|
322
|
+
# ============================================================================
|
|
323
|
+
# Actions Block (for forms/state)
|
|
324
|
+
# ============================================================================
|
|
325
|
+
|
|
326
|
+
ActionsBlock: [
|
|
327
|
+
o 'ACTIONS Block', '["actions", 2]'
|
|
328
|
+
]
|
|
329
|
+
|
|
330
|
+
# ============================================================================
|
|
331
|
+
# Form Fields (field with placement)
|
|
332
|
+
# ============================================================================
|
|
333
|
+
|
|
334
|
+
FormField: [
|
|
335
|
+
o 'IDENTIFIER Object', '["placement", 1, 2]'
|
|
336
|
+
]
|
|
337
|
+
|
|
338
|
+
# ============================================================================
|
|
339
|
+
# Literals and Values
|
|
340
|
+
# ============================================================================
|
|
341
|
+
|
|
342
|
+
Identifier: [
|
|
343
|
+
o 'IDENTIFIER'
|
|
344
|
+
]
|
|
345
|
+
|
|
346
|
+
Literal: [
|
|
347
|
+
o 'NUMBER'
|
|
348
|
+
o 'STRING'
|
|
349
|
+
o 'BOOL'
|
|
350
|
+
o 'NULL'
|
|
351
|
+
o 'UNDEFINED'
|
|
352
|
+
]
|
|
353
|
+
|
|
354
|
+
Regex: [
|
|
355
|
+
o 'REGEX'
|
|
356
|
+
]
|
|
357
|
+
|
|
358
|
+
# ============================================================================
|
|
359
|
+
# Object Literals: { key: value, ... }
|
|
360
|
+
# ============================================================================
|
|
361
|
+
|
|
362
|
+
Object: [
|
|
363
|
+
o '{ }' , '["object"]'
|
|
364
|
+
o '{ ObjectEntries }' , '["object", ...2]'
|
|
365
|
+
]
|
|
366
|
+
|
|
367
|
+
ObjectEntries: [
|
|
368
|
+
o 'ObjectEntry' , '[1]'
|
|
369
|
+
o 'ObjectEntries , ObjectEntry' , '[...1, 3]'
|
|
370
|
+
o 'ObjectEntries OptComma TERMINATOR ObjectEntry' , '[...1, 4]'
|
|
371
|
+
o 'ObjectEntries OptComma TERMINATOR'
|
|
372
|
+
o 'INDENT ObjectEntries OptComma OUTDENT' , 2
|
|
373
|
+
]
|
|
374
|
+
|
|
375
|
+
ObjectEntry: [
|
|
376
|
+
o 'IDENTIFIER' , '[1, 1]' # Shorthand { x }
|
|
377
|
+
o 'IDENTIFIER : Value' , '[1, 3]'
|
|
378
|
+
o 'STRING : Value' , '[1, 3]'
|
|
379
|
+
o '... IDENTIFIER' , '["...", 2]' # Spread
|
|
380
|
+
]
|
|
381
|
+
|
|
382
|
+
OptComma: [
|
|
383
|
+
o ''
|
|
384
|
+
o ','
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
# ============================================================================
|
|
388
|
+
# Array Literals: [a, b, c]
|
|
389
|
+
# ============================================================================
|
|
390
|
+
|
|
391
|
+
Array: [
|
|
392
|
+
o '[ ]' , '["array"]'
|
|
393
|
+
o '[ ArrayItems ]' , '["array", ...2]'
|
|
394
|
+
]
|
|
395
|
+
|
|
396
|
+
ArrayItems: [
|
|
397
|
+
o 'Value' , '[1]'
|
|
398
|
+
o 'ArrayItems , Value' , '[...1, 3]'
|
|
399
|
+
o 'ArrayItems OptComma TERMINATOR Value', '[...1, 4]'
|
|
400
|
+
o 'ArrayItems OptComma TERMINATOR'
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
# ============================================================================
|
|
404
|
+
# Arrow Functions: -> expr or (params) -> expr
|
|
405
|
+
# ============================================================================
|
|
406
|
+
|
|
407
|
+
ArrowFunc: [
|
|
408
|
+
o '-> Value' , '["->", [], 2]'
|
|
409
|
+
o '-> INDENT Value OUTDENT' , '["->", [], 3]'
|
|
410
|
+
o '( Params ) -> Value' , '["->", 2, 5]'
|
|
411
|
+
o '( Params ) -> INDENT Value OUTDENT' , '["->", 2, 6]'
|
|
412
|
+
]
|
|
413
|
+
|
|
414
|
+
Params: [
|
|
415
|
+
o '' , '[]'
|
|
416
|
+
o 'IDENTIFIER' , '[1]'
|
|
417
|
+
o 'Params , IDENTIFIER' , '[...1, 3]'
|
|
418
|
+
]
|
|
419
|
+
|
|
420
|
+
# ============================================================================
|
|
421
|
+
# Values (simplified expressions for schemas)
|
|
422
|
+
# ============================================================================
|
|
423
|
+
|
|
424
|
+
# Value is what can appear in constraints, defaults, computed fields, etc.
|
|
425
|
+
# This is intentionally simpler than full expressions to reduce conflicts.
|
|
426
|
+
|
|
427
|
+
Value: [
|
|
428
|
+
o 'Primary'
|
|
429
|
+
o 'Value . IDENTIFIER' , '[".", 1, 3]' # Property access
|
|
430
|
+
o 'Value ?. IDENTIFIER' , '["?.", 1, 3]' # Optional chaining
|
|
431
|
+
o 'Value [ Value ]' , '["[]", 1, 3]' # Index access
|
|
432
|
+
o 'Value ( )' , '["call", 1, []]' # Function call
|
|
433
|
+
o 'Value ( Args )' , '["call", 1, 3]'
|
|
434
|
+
o 'Value BinOp Value' , '[2, 1, 3]' # Binary operators
|
|
435
|
+
o 'UnaryOp Value' , '[1, 2]', prec: 'UNARY'
|
|
436
|
+
o '( Value )' , 2 # Grouping
|
|
437
|
+
]
|
|
438
|
+
|
|
439
|
+
Primary: [
|
|
440
|
+
o 'Literal'
|
|
441
|
+
o 'IDENTIFIER'
|
|
442
|
+
o 'Object'
|
|
443
|
+
o 'Array'
|
|
444
|
+
o 'Regex'
|
|
445
|
+
o 'ArrowFunc'
|
|
446
|
+
o '@ IDENTIFIER' , '[".", "this", 2]' # @field → this.field
|
|
447
|
+
o '@' , '"this"' # @ → this
|
|
448
|
+
]
|
|
449
|
+
|
|
450
|
+
Args: [
|
|
451
|
+
o 'Value' , '[1]'
|
|
452
|
+
o 'Args , Value' , '[...1, 3]'
|
|
453
|
+
]
|
|
454
|
+
|
|
455
|
+
# Binary operators (single rule to reduce states)
|
|
456
|
+
BinOp: [
|
|
457
|
+
o '+' , '"+"'
|
|
458
|
+
o '-' , '"-"'
|
|
459
|
+
o '*' , '"*"'
|
|
460
|
+
o '/' , '"/"'
|
|
461
|
+
o '==' , '"=="'
|
|
462
|
+
o '!=' , '"!="'
|
|
463
|
+
o '<' , '"<"'
|
|
464
|
+
o '>' , '">"'
|
|
465
|
+
o '<=' , '"<="'
|
|
466
|
+
o '>=' , '">="'
|
|
467
|
+
o '&&' , '"&&"'
|
|
468
|
+
o '||' , '"||"'
|
|
469
|
+
o '??' , '"??"'
|
|
470
|
+
o 'IS' , '"is"'
|
|
471
|
+
o 'ISNT', '"isnt"'
|
|
472
|
+
]
|
|
473
|
+
|
|
474
|
+
# Unary operators
|
|
475
|
+
UnaryOp: [
|
|
476
|
+
o 'NOT' , '"not"'
|
|
477
|
+
o '!' , '"!"'
|
|
478
|
+
o '-' , '"-"'
|
|
479
|
+
]
|
|
480
|
+
|
|
481
|
+
# ==============================================================================
|
|
482
|
+
# Operator Precedence (low to high - reversed for solar)
|
|
483
|
+
# ==============================================================================
|
|
484
|
+
|
|
485
|
+
operators = """
|
|
486
|
+
right ,
|
|
487
|
+
right :
|
|
488
|
+
right ->
|
|
489
|
+
left ??
|
|
490
|
+
left ||
|
|
491
|
+
left &&
|
|
492
|
+
left == != IS ISNT
|
|
493
|
+
left < > <= >=
|
|
494
|
+
left + -
|
|
495
|
+
left * /
|
|
496
|
+
right UNARY NOT
|
|
497
|
+
left . ?. [ ] ( )
|
|
498
|
+
""".trim().split('\n').reverse().map (line) -> line.trim().split /\s+/
|
|
499
|
+
|
|
500
|
+
# ==============================================================================
|
|
501
|
+
# Export
|
|
502
|
+
# ==============================================================================
|
|
503
|
+
|
|
504
|
+
export default {mode, grammar, operators}
|
package/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ==============================================================================
|
|
2
|
+
// @rip-lang/schema — Unified schema language
|
|
3
|
+
//
|
|
4
|
+
// One definition → TypeScript types + SQL DDL + runtime validation + ORM models
|
|
5
|
+
//
|
|
6
|
+
// Code generation:
|
|
7
|
+
// import { Schema } from '@rip-lang/schema'
|
|
8
|
+
// const schema = Schema.load('app.schema')
|
|
9
|
+
// const ts = schema.toTypes()
|
|
10
|
+
// const sql = schema.toSQL()
|
|
11
|
+
//
|
|
12
|
+
// ORM (with database):
|
|
13
|
+
// import { Schema } from '@rip-lang/schema/orm'
|
|
14
|
+
// const schema = Schema.load('app.schema')
|
|
15
|
+
// schema.connect('http://localhost:4213')
|
|
16
|
+
// const User = schema.model('User', { ... })
|
|
17
|
+
//
|
|
18
|
+
// Author: Steve Shreeve <steve.shreeve@gmail.com>
|
|
19
|
+
// Date: January 2026
|
|
20
|
+
// ==============================================================================
|
|
21
|
+
|
|
22
|
+
import { parse as _rawParse, parser, Parser } from './parser.js'
|
|
23
|
+
import { formatParseError } from './errors.js'
|
|
24
|
+
|
|
25
|
+
export { parser, Parser }
|
|
26
|
+
export { SchemaLexer } from './lexer.js'
|
|
27
|
+
export { Schema } from './runtime.js'
|
|
28
|
+
export { generateTypes } from './emit-types.js'
|
|
29
|
+
export { generateSQL } from './emit-sql.js'
|
|
30
|
+
export { generateZod } from './emit-zod.js'
|
|
31
|
+
export { formatParseError } from './errors.js'
|
|
32
|
+
|
|
33
|
+
export function parse(source, filename) {
|
|
34
|
+
try {
|
|
35
|
+
return _rawParse(source)
|
|
36
|
+
} catch (err) {
|
|
37
|
+
throw formatParseError(err, source, filename)
|
|
38
|
+
}
|
|
39
|
+
}
|