@jarenjs/db 0.34.0

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.
Files changed (83) hide show
  1. package/ARCHITECTURE.md +397 -0
  2. package/README.md +218 -0
  3. package/dist/types/algebra.d.ts +133 -0
  4. package/dist/types/app.d.ts +49 -0
  5. package/dist/types/capture.d.ts +85 -0
  6. package/dist/types/cli.d.ts +2 -0
  7. package/dist/types/dag-job.d.ts +40 -0
  8. package/dist/types/ddl.d.ts +170 -0
  9. package/dist/types/dialect.d.ts +130 -0
  10. package/dist/types/dialects/sqlite.d.ts +9 -0
  11. package/dist/types/driver.d.ts +128 -0
  12. package/dist/types/drivers/bun.d.ts +47 -0
  13. package/dist/types/drivers/node.d.ts +37 -0
  14. package/dist/types/drivers/wasm.d.ts +65 -0
  15. package/dist/types/emit-model.d.ts +44 -0
  16. package/dist/types/emit.d.ts +72 -0
  17. package/dist/types/entity.d.ts +23 -0
  18. package/dist/types/errors.d.ts +165 -0
  19. package/dist/types/graph.d.ts +28 -0
  20. package/dist/types/index.d.ts +35 -0
  21. package/dist/types/jobs.d.ts +134 -0
  22. package/dist/types/live.d.ts +62 -0
  23. package/dist/types/migrate.d.ts +163 -0
  24. package/dist/types/model.d.ts +36 -0
  25. package/dist/types/patch-sql.d.ts +37 -0
  26. package/dist/types/plan.d.ts +119 -0
  27. package/dist/types/profile.d.ts +80 -0
  28. package/dist/types/query.d.ts +100 -0
  29. package/dist/types/residual.d.ts +50 -0
  30. package/dist/types/store.d.ts +53 -0
  31. package/dist/types/tracker.d.ts +43 -0
  32. package/dist/types/typed.d.ts +15 -0
  33. package/dist/types/types.d.ts +26 -0
  34. package/dist/types/udf.d.ts +70 -0
  35. package/dist/types/window.d.ts +52 -0
  36. package/docs/JOBS-FORMAT.md +218 -0
  37. package/docs/LIVE-FORMAT.md +348 -0
  38. package/docs/MIGRATION-FORMAT.md +302 -0
  39. package/docs/MODEL-FORMAT.md +928 -0
  40. package/package.json +81 -0
  41. package/schemas/jaren-migration.draft-07.schema.json +144 -0
  42. package/schemas/jaren-migration.schema.json +144 -0
  43. package/schemas/jaren-model.draft-07.schema.json +149 -0
  44. package/schemas/jaren-model.schema.json +149 -0
  45. package/src/algebra.js +105 -0
  46. package/src/app.js +108 -0
  47. package/src/capture.js +584 -0
  48. package/src/cli.js +264 -0
  49. package/src/dag-job.js +86 -0
  50. package/src/ddl.js +588 -0
  51. package/src/dialect.js +297 -0
  52. package/src/dialects/sqlite.js +175 -0
  53. package/src/driver.js +419 -0
  54. package/src/drivers/bun.js +101 -0
  55. package/src/drivers/node.js +93 -0
  56. package/src/drivers/wasm.js +178 -0
  57. package/src/emit-model.js +208 -0
  58. package/src/emit.js +393 -0
  59. package/src/entity.js +367 -0
  60. package/src/errors.js +173 -0
  61. package/src/graph.js +101 -0
  62. package/src/index.js +64 -0
  63. package/src/jobs.js +507 -0
  64. package/src/live.js +899 -0
  65. package/src/migrate.js +1411 -0
  66. package/src/model.js +476 -0
  67. package/src/patch-sql.js +150 -0
  68. package/src/plan.js +1038 -0
  69. package/src/profile.js +131 -0
  70. package/src/query.js +1010 -0
  71. package/src/residual.js +91 -0
  72. package/src/store.js +1422 -0
  73. package/src/tracker.js +776 -0
  74. package/src/typed.js +19 -0
  75. package/src/types.js +36 -0
  76. package/src/udf.js +132 -0
  77. package/src/window.js +125 -0
  78. package/types/app.d.ts +36 -0
  79. package/types/bun.d.ts +9 -0
  80. package/types/index.d.ts +592 -0
  81. package/types/node.d.ts +15 -0
  82. package/types/typed.d.ts +108 -0
  83. package/types/wasm.d.ts +5 -0
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@jarenjs/db",
3
+ "private": false,
4
+ "version": "0.34.0",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "types": "./types/index.d.ts",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./types/index.d.ts",
12
+ "default": "./src/index.js"
13
+ },
14
+ "./node": {
15
+ "types": "./types/node.d.ts",
16
+ "default": "./src/drivers/node.js"
17
+ },
18
+ "./bun": {
19
+ "types": "./types/bun.d.ts",
20
+ "default": "./src/drivers/bun.js"
21
+ },
22
+ "./wasm": {
23
+ "types": "./types/wasm.d.ts",
24
+ "default": "./src/drivers/wasm.js"
25
+ },
26
+ "./typed": {
27
+ "types": "./types/typed.d.ts",
28
+ "default": "./src/typed.js"
29
+ },
30
+ "./app": {
31
+ "types": "./types/app.d.ts",
32
+ "default": "./src/app.js"
33
+ },
34
+ "./schemas/*": "./schemas/*",
35
+ "./package.json": "./package.json"
36
+ },
37
+ "files": [
38
+ "types/",
39
+ "dist/types/",
40
+ "src/",
41
+ "schemas/",
42
+ "docs/",
43
+ "ARCHITECTURE.md"
44
+ ],
45
+ "description": "Document storage for the Jaren suite: a model document declares collections as JSON Schemas with indexes; openStore applies DDL through a dialect and gives transactional, schema-validated reads and writes over SQLite on Node, Bun, or an injected wasm handle",
46
+ "author": "joham",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/jklarenbeek/jarenjs.git",
50
+ "directory": "packages/db"
51
+ },
52
+ "license": "MIT",
53
+ "engines": {
54
+ "node": ">=24"
55
+ },
56
+ "publishConfig": {
57
+ "access": "public",
58
+ "registry": "https://registry.npmjs.org/"
59
+ },
60
+ "keywords": [
61
+ "jaren",
62
+ "json",
63
+ "sqlite",
64
+ "document-store",
65
+ "json-schema",
66
+ "database"
67
+ ],
68
+ "scripts": {
69
+ "build": "npm run build:types",
70
+ "build:types": "tsc -p tsconfig.json",
71
+ "prepack": "npm run build:types"
72
+ },
73
+ "dependencies": {
74
+ "@jarenjs/core": "^0.34.0",
75
+ "@jarenjs/json": "^0.34.0",
76
+ "@jarenjs/validate": "^0.34.0"
77
+ },
78
+ "bin": {
79
+ "jaren-db": "./src/cli.js"
80
+ }
81
+ }
@@ -0,0 +1,144 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://jarenjs.dev/schemas/jaren-migration/draft-07",
4
+ "title": "Jaren migration document",
5
+ "description": "A jaren-migration document evolves a store from one shape to another: ordered steps of rendered DDL, JSLT data transforms and query assertions, between two shape hashes. The hashes identify SHAPES (hashContent over the canonicalized model document), not version numbers a human must remember to bump; a migration whose from-hash does not match the database's recorded shape refuses to run.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$migration": {
9
+ "description": "The migration format version.",
10
+ "const": "0.1"
11
+ },
12
+ "id": {
13
+ "description": "The migration's unique identifier, recorded in the history table.",
14
+ "type": "string",
15
+ "minLength": 1
16
+ },
17
+ "from": {
18
+ "description": "The shape hash this migration applies to.",
19
+ "type": "string",
20
+ "minLength": 1
21
+ },
22
+ "to": {
23
+ "description": "The shape hash this migration produces.",
24
+ "type": "string",
25
+ "minLength": 1
26
+ },
27
+ "note": {
28
+ "description": "Free prose for the reader; ignored by the runner.",
29
+ "type": "string"
30
+ },
31
+ "steps": {
32
+ "description": "Ordered steps; the order is the contract. A pure widening may carry NO steps — the migration then only moves the recorded shape.",
33
+ "type": "array",
34
+ "items": {
35
+ "$ref": "#/definitions/step"
36
+ }
37
+ }
38
+ },
39
+ "required": [
40
+ "$migration",
41
+ "id",
42
+ "from",
43
+ "to",
44
+ "steps"
45
+ ],
46
+ "additionalProperties": false,
47
+ "definitions": {
48
+ "step": {
49
+ "oneOf": [
50
+ {
51
+ "$ref": "#/definitions/ddlStep"
52
+ },
53
+ {
54
+ "$ref": "#/definitions/jsltStep"
55
+ },
56
+ {
57
+ "$ref": "#/definitions/queryStep"
58
+ }
59
+ ]
60
+ },
61
+ "ddlStep": {
62
+ "description": "One rendered DDL statement, produced by the planner through the dialect and shown before it is executed.",
63
+ "type": "object",
64
+ "properties": {
65
+ "kind": {
66
+ "const": "ddl"
67
+ },
68
+ "sql": {
69
+ "type": "string",
70
+ "minLength": 1
71
+ },
72
+ "note": {
73
+ "type": "string"
74
+ }
75
+ },
76
+ "required": [
77
+ "kind",
78
+ "sql"
79
+ ],
80
+ "additionalProperties": false
81
+ },
82
+ "jsltStep": {
83
+ "description": "Rewrite every document of a collection through a compiled JSLT stylesheet, in batches, inside the migration's transaction. A draft step (the planner's identity placeholder) refuses to run until the author fills it in.",
84
+ "type": "object",
85
+ "properties": {
86
+ "kind": {
87
+ "const": "jslt"
88
+ },
89
+ "collection": {
90
+ "type": "string",
91
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
92
+ },
93
+ "stylesheet": {
94
+ "description": "A JSLT stylesheet (an array of match/body rules; the empty array is the identity transform).",
95
+ "type": "array"
96
+ },
97
+ "draft": {
98
+ "description": "True on a planner-emitted placeholder: the schema changed and no transform can be inferred. The runner refuses a draft step.",
99
+ "type": "boolean"
100
+ },
101
+ "note": {
102
+ "type": "string"
103
+ }
104
+ },
105
+ "required": [
106
+ "kind",
107
+ "collection",
108
+ "stylesheet"
109
+ ],
110
+ "additionalProperties": false
111
+ },
112
+ "queryStep": {
113
+ "description": "An assertion: the query runs over the collection's documents and must answer an empty sequence (expect 'empty', the default) or an EBV-true value (expect 'ebv') for the migration to proceed. This is how a migration states its own precondition.",
114
+ "type": "object",
115
+ "properties": {
116
+ "kind": {
117
+ "const": "query"
118
+ },
119
+ "collection": {
120
+ "type": "string",
121
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
122
+ },
123
+ "assert": {
124
+ "description": "A Jaren query document over the collection's documents."
125
+ },
126
+ "expect": {
127
+ "enum": [
128
+ "empty",
129
+ "ebv"
130
+ ]
131
+ },
132
+ "note": {
133
+ "type": "string"
134
+ }
135
+ },
136
+ "required": [
137
+ "kind",
138
+ "collection",
139
+ "assert"
140
+ ],
141
+ "additionalProperties": false
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,144 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://jarenjs.dev/schemas/jaren-migration",
4
+ "title": "Jaren migration document",
5
+ "description": "A jaren-migration document evolves a store from one shape to another: ordered steps of rendered DDL, JSLT data transforms and query assertions, between two shape hashes. The hashes identify SHAPES (hashContent over the canonicalized model document), not version numbers a human must remember to bump; a migration whose from-hash does not match the database's recorded shape refuses to run.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$migration": {
9
+ "description": "The migration format version.",
10
+ "const": "0.1"
11
+ },
12
+ "id": {
13
+ "description": "The migration's unique identifier, recorded in the history table.",
14
+ "type": "string",
15
+ "minLength": 1
16
+ },
17
+ "from": {
18
+ "description": "The shape hash this migration applies to.",
19
+ "type": "string",
20
+ "minLength": 1
21
+ },
22
+ "to": {
23
+ "description": "The shape hash this migration produces.",
24
+ "type": "string",
25
+ "minLength": 1
26
+ },
27
+ "note": {
28
+ "description": "Free prose for the reader; ignored by the runner.",
29
+ "type": "string"
30
+ },
31
+ "steps": {
32
+ "description": "Ordered steps; the order is the contract. A pure widening may carry NO steps — the migration then only moves the recorded shape.",
33
+ "type": "array",
34
+ "items": {
35
+ "$ref": "#/$defs/step"
36
+ }
37
+ }
38
+ },
39
+ "required": [
40
+ "$migration",
41
+ "id",
42
+ "from",
43
+ "to",
44
+ "steps"
45
+ ],
46
+ "additionalProperties": false,
47
+ "$defs": {
48
+ "step": {
49
+ "oneOf": [
50
+ {
51
+ "$ref": "#/$defs/ddlStep"
52
+ },
53
+ {
54
+ "$ref": "#/$defs/jsltStep"
55
+ },
56
+ {
57
+ "$ref": "#/$defs/queryStep"
58
+ }
59
+ ]
60
+ },
61
+ "ddlStep": {
62
+ "description": "One rendered DDL statement, produced by the planner through the dialect and shown before it is executed.",
63
+ "type": "object",
64
+ "properties": {
65
+ "kind": {
66
+ "const": "ddl"
67
+ },
68
+ "sql": {
69
+ "type": "string",
70
+ "minLength": 1
71
+ },
72
+ "note": {
73
+ "type": "string"
74
+ }
75
+ },
76
+ "required": [
77
+ "kind",
78
+ "sql"
79
+ ],
80
+ "additionalProperties": false
81
+ },
82
+ "jsltStep": {
83
+ "description": "Rewrite every document of a collection through a compiled JSLT stylesheet, in batches, inside the migration's transaction. A draft step (the planner's identity placeholder) refuses to run until the author fills it in.",
84
+ "type": "object",
85
+ "properties": {
86
+ "kind": {
87
+ "const": "jslt"
88
+ },
89
+ "collection": {
90
+ "type": "string",
91
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
92
+ },
93
+ "stylesheet": {
94
+ "description": "A JSLT stylesheet (an array of match/body rules; the empty array is the identity transform).",
95
+ "type": "array"
96
+ },
97
+ "draft": {
98
+ "description": "True on a planner-emitted placeholder: the schema changed and no transform can be inferred. The runner refuses a draft step.",
99
+ "type": "boolean"
100
+ },
101
+ "note": {
102
+ "type": "string"
103
+ }
104
+ },
105
+ "required": [
106
+ "kind",
107
+ "collection",
108
+ "stylesheet"
109
+ ],
110
+ "additionalProperties": false
111
+ },
112
+ "queryStep": {
113
+ "description": "An assertion: the query runs over the collection's documents and must answer an empty sequence (expect 'empty', the default) or an EBV-true value (expect 'ebv') for the migration to proceed. This is how a migration states its own precondition.",
114
+ "type": "object",
115
+ "properties": {
116
+ "kind": {
117
+ "const": "query"
118
+ },
119
+ "collection": {
120
+ "type": "string",
121
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
122
+ },
123
+ "assert": {
124
+ "description": "A Jaren query document over the collection's documents."
125
+ },
126
+ "expect": {
127
+ "enum": [
128
+ "empty",
129
+ "ebv"
130
+ ]
131
+ },
132
+ "note": {
133
+ "type": "string"
134
+ }
135
+ },
136
+ "required": [
137
+ "kind",
138
+ "collection",
139
+ "assert"
140
+ ],
141
+ "additionalProperties": false
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,149 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://jarenjs.dev/schemas/jaren-model/draft-07",
4
+ "title": "Jaren model document",
5
+ "description": "A jaren-model document declares the collections of a store: each collection is a JSON Schema for its documents, a key declaration (an RFC 6901 pointer for caller-supplied keys, or null with a declared identity for store-allocated ones), and the indexes over singular JSONPath expressions. A model declares collections (the storage subset: every property JSONB, no relations), entities (the relational subset: keys, typed columns, relations via the x-entity vocabulary), or both; vocabulary is added to THIS format, never as a second format.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$model": {
9
+ "description": "The model format version.",
10
+ "const": "0.1"
11
+ },
12
+ "collections": {
13
+ "description": "Collection name (an identifier) to collection declaration.",
14
+ "type": "object",
15
+ "minProperties": 1,
16
+ "propertyNames": {
17
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
18
+ },
19
+ "additionalProperties": {
20
+ "$ref": "#/definitions/collection"
21
+ }
22
+ },
23
+ "entities": {
24
+ "description": "Entity name (an identifier) to entity declaration. The x-entity vocabulary lives INSIDE each entity schema's property subschemas and is documented in MODEL-FORMAT.md §9; stripping it leaves a plain JSON Schema.",
25
+ "type": "object",
26
+ "minProperties": 1,
27
+ "propertyNames": {
28
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
29
+ },
30
+ "additionalProperties": {
31
+ "$ref": "#/definitions/entity"
32
+ }
33
+ }
34
+ },
35
+ "required": [
36
+ "$model"
37
+ ],
38
+ "additionalProperties": false,
39
+ "definitions": {
40
+ "collection": {
41
+ "description": "One collection: a document schema, the key declaration, and the declared indexes. A collection without a key pointer MUST declare how keys are allocated; allocation is declared, never guessed.",
42
+ "type": "object",
43
+ "properties": {
44
+ "schema": {
45
+ "description": "The JSON Schema every stored document validates against (through the injected hook). Also the type source for indexed paths.",
46
+ "type": "object"
47
+ },
48
+ "key": {
49
+ "description": "Where the caller-supplied key lives in the document, as an RFC 6901 pointer selecting at least one member — or null when the store allocates.",
50
+ "type": [
51
+ "string",
52
+ "null"
53
+ ],
54
+ "pattern": "^/"
55
+ },
56
+ "identity": {
57
+ "description": "How keys come to be: 'caller' (the default when a key pointer is declared), or — only with \"key\": null — 'uuid' (crypto.randomUUID) or 'integer' (database-allocated).",
58
+ "enum": [
59
+ "caller",
60
+ "uuid",
61
+ "integer"
62
+ ]
63
+ },
64
+ "indexes": {
65
+ "description": "Declared indexes; each singular path becomes a generated column plus an index.",
66
+ "type": "array",
67
+ "items": {
68
+ "$ref": "#/definitions/index"
69
+ }
70
+ },
71
+ "x-rename": {
72
+ "description": "Migration hint: this collection was previously named the given identifier. Read by the migration planner (a rename cannot be inferred from a diff); ignored by the store.",
73
+ "type": "string",
74
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
75
+ }
76
+ },
77
+ "required": [
78
+ "schema"
79
+ ],
80
+ "additionalProperties": false
81
+ },
82
+ "index": {
83
+ "description": "One index over a singular JSONPath expression (or a composite over several). A non-singular path is rejected at open (JD0004).",
84
+ "type": "object",
85
+ "properties": {
86
+ "name": {
87
+ "description": "The index name, unique within its collection.",
88
+ "type": "string",
89
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
90
+ },
91
+ "path": {
92
+ "description": "A singular JSONPath expression into the stored document ($.email), or a non-empty array of them for a composite index.",
93
+ "oneOf": [
94
+ {
95
+ "type": "string",
96
+ "minLength": 1
97
+ },
98
+ {
99
+ "type": "array",
100
+ "items": {
101
+ "type": "string",
102
+ "minLength": 1
103
+ },
104
+ "minItems": 1
105
+ }
106
+ ]
107
+ },
108
+ "unique": {
109
+ "description": "Whether the index enforces uniqueness. Defaults to false.",
110
+ "type": "boolean"
111
+ }
112
+ },
113
+ "required": [
114
+ "name",
115
+ "path"
116
+ ],
117
+ "additionalProperties": false
118
+ },
119
+ "entity": {
120
+ "description": "One entity: an object schema whose top-level properties map to columns per the hybrid rule (scalars become typed columns, nested shapes stay JSONB); keys, indexes, defaults and relations are declared with x-entity inside the schema.",
121
+ "type": "object",
122
+ "properties": {
123
+ "schema": {
124
+ "type": "object"
125
+ },
126
+ "x-rename": {
127
+ "type": "string",
128
+ "description": "Declares this entity as the rename of the named from-model entity (MIGRATION-FORMAT §9): a rename is declared, never inferred."
129
+ }
130
+ },
131
+ "required": [
132
+ "schema"
133
+ ],
134
+ "additionalProperties": false
135
+ }
136
+ },
137
+ "anyOf": [
138
+ {
139
+ "required": [
140
+ "collections"
141
+ ]
142
+ },
143
+ {
144
+ "required": [
145
+ "entities"
146
+ ]
147
+ }
148
+ ]
149
+ }
@@ -0,0 +1,149 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://jarenjs.dev/schemas/jaren-model",
4
+ "title": "Jaren model document",
5
+ "description": "A jaren-model document declares the collections of a store: each collection is a JSON Schema for its documents, a key declaration (an RFC 6901 pointer for caller-supplied keys, or null with a declared identity for store-allocated ones), and the indexes over singular JSONPath expressions. A model declares collections (the storage subset: every property JSONB, no relations), entities (the relational subset: keys, typed columns, relations via the x-entity vocabulary), or both; vocabulary is added to THIS format, never as a second format.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$model": {
9
+ "description": "The model format version.",
10
+ "const": "0.1"
11
+ },
12
+ "collections": {
13
+ "description": "Collection name (an identifier) to collection declaration.",
14
+ "type": "object",
15
+ "minProperties": 1,
16
+ "propertyNames": {
17
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
18
+ },
19
+ "additionalProperties": {
20
+ "$ref": "#/$defs/collection"
21
+ }
22
+ },
23
+ "entities": {
24
+ "description": "Entity name (an identifier) to entity declaration. The x-entity vocabulary lives INSIDE each entity schema's property subschemas and is documented in MODEL-FORMAT.md \u00a79; stripping it leaves a plain JSON Schema.",
25
+ "type": "object",
26
+ "minProperties": 1,
27
+ "propertyNames": {
28
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
29
+ },
30
+ "additionalProperties": {
31
+ "$ref": "#/$defs/entity"
32
+ }
33
+ }
34
+ },
35
+ "required": [
36
+ "$model"
37
+ ],
38
+ "additionalProperties": false,
39
+ "$defs": {
40
+ "collection": {
41
+ "description": "One collection: a document schema, the key declaration, and the declared indexes. A collection without a key pointer MUST declare how keys are allocated; allocation is declared, never guessed.",
42
+ "type": "object",
43
+ "properties": {
44
+ "schema": {
45
+ "description": "The JSON Schema every stored document validates against (through the injected hook). Also the type source for indexed paths.",
46
+ "type": "object"
47
+ },
48
+ "key": {
49
+ "description": "Where the caller-supplied key lives in the document, as an RFC 6901 pointer selecting at least one member \u2014 or null when the store allocates.",
50
+ "type": [
51
+ "string",
52
+ "null"
53
+ ],
54
+ "pattern": "^/"
55
+ },
56
+ "identity": {
57
+ "description": "How keys come to be: 'caller' (the default when a key pointer is declared), or \u2014 only with \"key\": null \u2014 'uuid' (crypto.randomUUID) or 'integer' (database-allocated).",
58
+ "enum": [
59
+ "caller",
60
+ "uuid",
61
+ "integer"
62
+ ]
63
+ },
64
+ "indexes": {
65
+ "description": "Declared indexes; each singular path becomes a generated column plus an index.",
66
+ "type": "array",
67
+ "items": {
68
+ "$ref": "#/$defs/index"
69
+ }
70
+ },
71
+ "x-rename": {
72
+ "description": "Migration hint: this collection was previously named the given identifier. Read by the migration planner (a rename cannot be inferred from a diff); ignored by the store.",
73
+ "type": "string",
74
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
75
+ }
76
+ },
77
+ "required": [
78
+ "schema"
79
+ ],
80
+ "additionalProperties": false
81
+ },
82
+ "index": {
83
+ "description": "One index over a singular JSONPath expression (or a composite over several). A non-singular path is rejected at open (JD0004).",
84
+ "type": "object",
85
+ "properties": {
86
+ "name": {
87
+ "description": "The index name, unique within its collection.",
88
+ "type": "string",
89
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
90
+ },
91
+ "path": {
92
+ "description": "A singular JSONPath expression into the stored document ($.email), or a non-empty array of them for a composite index.",
93
+ "oneOf": [
94
+ {
95
+ "type": "string",
96
+ "minLength": 1
97
+ },
98
+ {
99
+ "type": "array",
100
+ "items": {
101
+ "type": "string",
102
+ "minLength": 1
103
+ },
104
+ "minItems": 1
105
+ }
106
+ ]
107
+ },
108
+ "unique": {
109
+ "description": "Whether the index enforces uniqueness. Defaults to false.",
110
+ "type": "boolean"
111
+ }
112
+ },
113
+ "required": [
114
+ "name",
115
+ "path"
116
+ ],
117
+ "additionalProperties": false
118
+ },
119
+ "entity": {
120
+ "description": "One entity: an object schema whose top-level properties map to columns per the hybrid rule (scalars become typed columns, nested shapes stay JSONB); keys, indexes, defaults and relations are declared with x-entity inside the schema.",
121
+ "type": "object",
122
+ "properties": {
123
+ "schema": {
124
+ "type": "object"
125
+ },
126
+ "x-rename": {
127
+ "type": "string",
128
+ "description": "Declares this entity as the rename of the named from-model entity (MIGRATION-FORMAT \u00a79): a rename is declared, never inferred."
129
+ }
130
+ },
131
+ "required": [
132
+ "schema"
133
+ ],
134
+ "additionalProperties": false
135
+ }
136
+ },
137
+ "anyOf": [
138
+ {
139
+ "required": [
140
+ "collections"
141
+ ]
142
+ },
143
+ {
144
+ "required": [
145
+ "entities"
146
+ ]
147
+ }
148
+ ]
149
+ }