@cero-base/cero 0.8.8 → 0.8.10
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 +24 -4
- package/package.json +2 -2
- package/src/build/index.js +19 -3
package/README.md
CHANGED
|
@@ -85,6 +85,15 @@ const recovered = await cero.restore(me, 'twelve words …')
|
|
|
85
85
|
| `{ … }` (plain object) | a child handle — its own scope, share by invite |
|
|
86
86
|
| `local: { … }` | device-only — never leaves this device |
|
|
87
87
|
|
|
88
|
+
A collection can declare **secondary indexes** for fast exact-field lookups:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
cero.t.collection(
|
|
92
|
+
{ text: cero.t.string },
|
|
93
|
+
{ indexes: { 'by-text': ['text'] } } // name → field(s); query via `cero.get(ref, { text: '…' })`
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
88
97
|
## Operators
|
|
89
98
|
|
|
90
99
|
Every operator takes a `ref` (e.g. `me.profile`, `room.messages`) as the first arg.
|
|
@@ -110,19 +119,30 @@ await cero.set(room.messages, { id: 'abc', text: 'edited' }) // upsert by id
|
|
|
110
119
|
|
|
111
120
|
### `cero.get(ref, q?)`
|
|
112
121
|
|
|
113
|
-
Read.
|
|
122
|
+
Read. The shape of `q` decides what comes back:
|
|
114
123
|
|
|
115
124
|
```js
|
|
116
125
|
const { data } = await cero.get(me.profile) // single → the row (or null)
|
|
117
126
|
const { data } = await cero.get(room.messages, 'abc') // by id → the row (or null)
|
|
127
|
+
|
|
128
|
+
// collection → paginated, with range filters
|
|
118
129
|
const { data, total, size } = await cero.get(room.messages, {
|
|
119
|
-
gt: 'm-2025', //
|
|
130
|
+
gt: 'm-2025', // range: gt / gte / lt / lte
|
|
120
131
|
limit: 20,
|
|
121
132
|
reverse: true
|
|
122
|
-
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// search → case-insensitive substring across string fields
|
|
136
|
+
const { data } = await cero.get(room.messages, { search: 'jo sm' })
|
|
137
|
+
// every space-separated term must match (AND); folds case + diacritics ('jose' ⇢ 'José').
|
|
138
|
+
// `fields` restricts which fields are searched (default: all string fields):
|
|
139
|
+
const { data } = await cero.get(room.guests, { search: 'jose', fields: ['name'] })
|
|
140
|
+
|
|
141
|
+
// exact field match → routed through a declared secondary index when the field has one
|
|
142
|
+
const { data } = await cero.get(room.messages, { text: 'alpha' })
|
|
123
143
|
```
|
|
124
144
|
|
|
125
|
-
`total` is the unfiltered row count; `size` is what came back after `limit`.
|
|
145
|
+
`total` is the unfiltered row count; `size` is what came back after `limit`. `search` and exact-field filters compose with `limit` / `reverse`, and `cero.count(ref, q)` honors them too.
|
|
126
146
|
|
|
127
147
|
### `cero.del(ref, id)`
|
|
128
148
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cero-base/cero",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"description": "The ideal p2p API — everything is a handle, handles contain refs, refs contain rows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"test": "ls test/*.test.js | xargs -P1 -n1 brittle-node"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@cero-base/core": "^0.8.
|
|
81
|
+
"@cero-base/core": "^0.8.10",
|
|
82
82
|
"b4a": "^1.8.1",
|
|
83
83
|
"bare-abort-controller": "^1.1.2",
|
|
84
84
|
"bare-crypto": "^1.14.1",
|
package/src/build/index.js
CHANGED
|
@@ -120,7 +120,14 @@ function isPlainHandle(v) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
function compile(root, ns, scope = 'main') {
|
|
123
|
-
const ctx = {
|
|
123
|
+
const ctx = {
|
|
124
|
+
types: [],
|
|
125
|
+
collections: [],
|
|
126
|
+
dispatches: [],
|
|
127
|
+
indexes: [],
|
|
128
|
+
meta: { ns, refs: {} },
|
|
129
|
+
ns
|
|
130
|
+
}
|
|
124
131
|
|
|
125
132
|
Object.assign(ctx.meta.refs, builtinRefs(ns, scope))
|
|
126
133
|
|
|
@@ -136,6 +143,7 @@ function compile(root, ns, scope = 'main') {
|
|
|
136
143
|
types: ctx.types,
|
|
137
144
|
collections: ctx.collections,
|
|
138
145
|
dispatches: ctx.dispatches,
|
|
146
|
+
indexes: ctx.indexes,
|
|
139
147
|
meta: ctx.meta
|
|
140
148
|
}
|
|
141
149
|
}
|
|
@@ -173,6 +181,12 @@ function register(name, node, ctx) {
|
|
|
173
181
|
ctx.dispatches.push({ name: `set-${name}`, requestType: fqn })
|
|
174
182
|
ctx.dispatches.push({ name: `del-${name}`, requestType: `@${ctx.ns}/del-by-id` })
|
|
175
183
|
ctx.meta.refs[name] = { kind: 'collection', path: [name], schema: fqn }
|
|
184
|
+
if (node.indexes) {
|
|
185
|
+
for (const [idx, fields] of Object.entries(node.indexes)) {
|
|
186
|
+
ctx.indexes.push({ name: `${name}-${idx}`, collection: fqn, key: fields })
|
|
187
|
+
}
|
|
188
|
+
ctx.meta.refs[name].indexes = node.indexes
|
|
189
|
+
}
|
|
176
190
|
}
|
|
177
191
|
}
|
|
178
192
|
|
|
@@ -184,7 +198,7 @@ function fieldsFor(fields) {
|
|
|
184
198
|
}))
|
|
185
199
|
}
|
|
186
200
|
|
|
187
|
-
function emitMain(dir, ns, { types, collections, dispatches }, { rpc, extend = {} }) {
|
|
201
|
+
function emitMain(dir, ns, { types, collections, dispatches, indexes = [] }, { rpc, extend = {} }) {
|
|
188
202
|
const schemaDir = join(dir, 'schema')
|
|
189
203
|
const dbDir = join(dir, 'db')
|
|
190
204
|
const dispatchDir = join(dir, 'dispatch')
|
|
@@ -201,6 +215,7 @@ function emitMain(dir, ns, { types, collections, dispatches }, { rpc, extend = {
|
|
|
201
215
|
const dns = db.namespace(ns)
|
|
202
216
|
for (const desc of builtinCollections(ns, 'main')) dns.collections.register(desc)
|
|
203
217
|
for (const desc of collections) dns.collections.register(desc)
|
|
218
|
+
for (const desc of indexes) dns.indexes.register(desc)
|
|
204
219
|
HyperdbBuilder.toDisk(db, dbDir, { esm: true })
|
|
205
220
|
|
|
206
221
|
const d = Hyperdispatch.from(schemaDir, dispatchDir)
|
|
@@ -217,7 +232,7 @@ function emitMain(dir, ns, { types, collections, dispatches }, { rpc, extend = {
|
|
|
217
232
|
}
|
|
218
233
|
}
|
|
219
234
|
|
|
220
|
-
function emitLocal(dir, ns, { types, collections }) {
|
|
235
|
+
function emitLocal(dir, ns, { types, collections, indexes = [] }) {
|
|
221
236
|
const schemaDir = join(dir, 'schema')
|
|
222
237
|
const dbDir = join(dir, 'db')
|
|
223
238
|
|
|
@@ -231,6 +246,7 @@ function emitLocal(dir, ns, { types, collections }) {
|
|
|
231
246
|
const dns = db.namespace(ns)
|
|
232
247
|
for (const desc of builtinCollections(ns, 'local')) dns.collections.register(desc)
|
|
233
248
|
for (const desc of collections) dns.collections.register(desc)
|
|
249
|
+
for (const desc of indexes) dns.indexes.register(desc)
|
|
234
250
|
HyperdbBuilder.toDisk(db, dbDir, { esm: true })
|
|
235
251
|
}
|
|
236
252
|
|