lecodes-cli 0.19.0 → 0.20.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.
- package/README.md +1 -0
- package/dist/index.js +1069 -396
- package/package.json +14 -13
- package/runtime/scene-harness.json +1 -1
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/assets/Roboto-Variable-DHm9jpd-.woff2 +0 -0
- package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/runtime/web/assets/basis-C64VHDVD.js +1 -0
- package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
- package/runtime/web/assets/createViewerLite-BvHobVhp.js +852 -0
- package/runtime/web/assets/draco-BiISTFcR.js +118 -0
- package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/runtime/web/assets/index-CfNCCBjN.js +2 -0
- package/runtime/web/assets/mapViewImpl-B2JcES8l.js +810 -0
- package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +8 -0
- package/runtime/web/assets/neutral_ibl128-D-lzdkLN.ktx +0 -0
- package/runtime/web/assets/worker-Caf-yYEI.js +2 -0
- package/runtime/web/embed.html +32 -0
- package/runtime/web/embed.js +171 -0
- package/src/api.ts +302 -0
- package/src/browserAuth.ts +87 -0
- package/src/cmgenTool.ts +104 -0
- package/src/commands/app.ts +896 -0
- package/src/commands/appAndroid.ts +603 -0
- package/src/commands/appDesktop.ts +339 -0
- package/src/commands/appDesktopMac.ts +470 -0
- package/src/commands/appIcon.ts +187 -0
- package/src/commands/appShared.ts +542 -0
- package/src/commands/appTemplates.ts +907 -0
- package/src/commands/appTemplatesAndroid.ts +599 -0
- package/src/commands/appTemplatesGradlew.ts +9 -0
- package/src/commands/assets.ts +28 -0
- package/src/commands/clone.ts +60 -0
- package/src/commands/compile.ts +253 -0
- package/src/commands/create.ts +59 -0
- package/src/commands/design.ts +863 -0
- package/src/commands/designTemplates.ts +11 -0
- package/src/commands/desktop.ts +127 -0
- package/src/commands/dev.ts +236 -0
- package/src/commands/diff.ts +59 -0
- package/src/commands/init.ts +191 -0
- package/src/commands/install.ts +198 -0
- package/src/commands/lightmap.ts +290 -0
- package/src/commands/link.ts +147 -0
- package/src/commands/login.ts +24 -0
- package/src/commands/navmesh.ts +225 -0
- package/src/commands/pn.ts +305 -0
- package/src/commands/projectTemplates.ts +130 -0
- package/src/commands/pull.ts +109 -0
- package/src/commands/push.ts +173 -0
- package/src/commands/render.ts +416 -0
- package/src/commands/scene.ts +148 -0
- package/src/commands/shaders.ts +157 -0
- package/src/commands/status.ts +29 -0
- package/src/commands/test.ts +371 -0
- package/src/commands/thumbs.ts +178 -0
- package/src/commands/types.ts +87 -0
- package/src/commands/update.ts +190 -0
- package/src/compile/assetIcons.ts +214 -0
- package/src/compile/collect.ts +46 -0
- package/src/compile/collectLocal.ts +37 -0
- package/src/compile/designCompile.ts +104 -0
- package/src/compile/fonts.ts +156 -0
- package/src/compile/headlessBundle.ts +129 -0
- package/src/compile/nativeStack.ts +21 -0
- package/src/compile/projectCompile.ts +109 -0
- package/src/compile/sceneCompile.ts +113 -0
- package/src/compile/screenEntry.ts +127 -0
- package/src/compile/shaders.ts +245 -0
- package/src/config.ts +42 -0
- package/src/designMeta.ts +35 -0
- package/src/desktopRenderer.ts +545 -0
- package/src/desktopScript.ts +276 -0
- package/src/dev/clientTemplates.ts +160 -0
- package/src/dev/devServer.ts +333 -0
- package/src/dev/webRunner.ts +22 -0
- package/src/dev/wsServer.ts +144 -0
- package/src/distRoot.ts +20 -0
- package/src/ignore.ts +163 -0
- package/src/index.ts +494 -0
- package/src/lecodes-3d-editor.d.ts +41 -0
- package/src/lecodes-assets.d.ts +7 -0
- package/src/lecodes-design.d.ts +191 -0
- package/src/lecodes-renderer.d.ts +131 -0
- package/src/localFiles.ts +144 -0
- package/src/manifest.ts +46 -0
- package/src/matcTool.ts +137 -0
- package/src/peers.ts +40 -0
- package/src/project.ts +61 -0
- package/src/projectEnv.ts +94 -0
- package/src/qrcode-terminal.d.ts +9 -0
- package/src/releases.ts +125 -0
- package/src/serverDiff.ts +78 -0
- package/src/textDiff.ts +103 -0
- package/src/types.ts +0 -0
- package/src/util.ts +146 -0
- package/runtime/sdk/animate/animate.ts +0 -238
- package/runtime/sdk/animate/bezier.ts +0 -138
- package/runtime/sdk/animate/easings.ts +0 -126
- package/runtime/sdk/canvas/Canvas.ts +0 -305
- package/runtime/sdk/compile/aspectMacro.ts +0 -86
- package/runtime/sdk/compile/assetIconMacro.ts +0 -384
- package/runtime/sdk/compile/assetMacro.ts +0 -146
- package/runtime/sdk/compile/assetName.ts +0 -50
- package/runtime/sdk/compile/bundler.ts +0 -287
- package/runtime/sdk/compile/compileProject.ts +0 -129
- package/runtime/sdk/compile/detectEntry.ts +0 -128
- package/runtime/sdk/compile/fontMacro.ts +0 -459
- package/runtime/sdk/compile/fontRegistry.ts +0 -78
- package/runtime/sdk/compile/header.ts +0 -67
- package/runtime/sdk/compile/index.ts +0 -100
- package/runtime/sdk/compile/libraryImports.ts +0 -52
- package/runtime/sdk/compile/liteMaterial.ts +0 -247
- package/runtime/sdk/compile/sceneEditor.ts +0 -88
- package/runtime/sdk/compile/serverSplit.ts +0 -233
- package/runtime/sdk/compile/serverTypes.ts +0 -227
- package/runtime/sdk/compile/sfnt.ts +0 -98
- package/runtime/sdk/compile/shaderSchema.ts +0 -202
- package/runtime/sdk/compile/shaderTargets.ts +0 -81
- package/runtime/sdk/compile/sourcemap.ts +0 -25
- package/runtime/sdk/core/Aspect.ts +0 -568
- package/runtime/sdk/core/InspectorUI.ts +0 -212
- package/runtime/sdk/core/StateMachine.ts +0 -308
- package/runtime/sdk/core/color.ts +0 -66
- package/runtime/sdk/core/compWrite.ts +0 -42
- package/runtime/sdk/core/events.ts +0 -38
- package/runtime/sdk/core/fields.ts +0 -120
- package/runtime/sdk/core/registry.ts +0 -23
- package/runtime/sdk/core/signals.ts +0 -277
- package/runtime/sdk/core/time.ts +0 -84
- package/runtime/sdk/g2/Camera2D.ts +0 -40
- package/runtime/sdk/g2/CharacterController2D.ts +0 -276
- package/runtime/sdk/g2/Node2D.ts +0 -267
- package/runtime/sdk/g2/OneWay2D.ts +0 -66
- package/runtime/sdk/g2/Physics2D.ts +0 -346
- package/runtime/sdk/g2/Scene2D.ts +0 -209
- package/runtime/sdk/g2/Shape2D.ts +0 -259
- package/runtime/sdk/g2/Sprite.ts +0 -89
- package/runtime/sdk/g2/SpriteAnimation.ts +0 -171
- package/runtime/sdk/g2/SpriteSheet.ts +0 -166
- package/runtime/sdk/g2/Texture2D.ts +0 -47
- package/runtime/sdk/g2/Tilemap.ts +0 -41
- package/runtime/sdk/g2/Tileset.ts +0 -71
- package/runtime/sdk/g2/Trigger2D.ts +0 -77
- package/runtime/sdk/g2/autotile.ts +0 -433
- package/runtime/sdk/g2/cells.ts +0 -91
- package/runtime/sdk/g2/defineScene2d.ts +0 -381
- package/runtime/sdk/g2/groups2d.ts +0 -106
- package/runtime/sdk/g2/loop.ts +0 -50
- package/runtime/sdk/g2/scenarios2d.ts +0 -69
- package/runtime/sdk/g2/touch.ts +0 -83
- package/runtime/sdk/gl/Camera.ts +0 -160
- package/runtime/sdk/gl/CameraPlace.ts +0 -52
- package/runtime/sdk/gl/CharacterController.ts +0 -238
- package/runtime/sdk/gl/Gearbox.ts +0 -212
- package/runtime/sdk/gl/Geometry.ts +0 -279
- package/runtime/sdk/gl/IK.ts +0 -193
- package/runtime/sdk/gl/InstancedMesh.ts +0 -132
- package/runtime/sdk/gl/Light.ts +0 -107
- package/runtime/sdk/gl/Lightmap.ts +0 -256
- package/runtime/sdk/gl/Material.ts +0 -260
- package/runtime/sdk/gl/Mesh.ts +0 -83
- package/runtime/sdk/gl/Model.ts +0 -124
- package/runtime/sdk/gl/NavAgent.ts +0 -337
- package/runtime/sdk/gl/NavMesh.ts +0 -397
- package/runtime/sdk/gl/Node.ts +0 -350
- package/runtime/sdk/gl/Noise.ts +0 -30
- package/runtime/sdk/gl/Particles.ts +0 -676
- package/runtime/sdk/gl/Physics.ts +0 -222
- package/runtime/sdk/gl/Plane.ts +0 -53
- package/runtime/sdk/gl/Ragdoll.ts +0 -270
- package/runtime/sdk/gl/Ray.ts +0 -16
- package/runtime/sdk/gl/Scene.ts +0 -486
- package/runtime/sdk/gl/Shape.ts +0 -409
- package/runtime/sdk/gl/Terrain.ts +0 -1092
- package/runtime/sdk/gl/Texture.ts +0 -63
- package/runtime/sdk/gl/Trigger.ts +0 -45
- package/runtime/sdk/gl/Vehicle.ts +0 -473
- package/runtime/sdk/gl/Wheel.ts +0 -240
- package/runtime/sdk/gl/animation/AnimationClip.ts +0 -204
- package/runtime/sdk/gl/animation/Animator.ts +0 -120
- package/runtime/sdk/gl/animation/Layer.ts +0 -31
- package/runtime/sdk/gl/animation/Loop.ts +0 -30
- package/runtime/sdk/gl/animation/Playback.ts +0 -44
- package/runtime/sdk/gl/animation/core.ts +0 -336
- package/runtime/sdk/gl/controls.ts +0 -95
- package/runtime/sdk/gl/physicsEvents.ts +0 -20
- package/runtime/sdk/gl/scenarios.ts +0 -291
- package/runtime/sdk/gl/state.ts +0 -6
- package/runtime/sdk/gl/terrainMesh.ts +0 -219
- package/runtime/sdk/gl/touch.ts +0 -68
- package/runtime/sdk/inject.ts +0 -197
- package/runtime/sdk/math/Mathf.ts +0 -118
- package/runtime/sdk/math/mat4.ts +0 -278
- package/runtime/sdk/math/quat.ts +0 -232
- package/runtime/sdk/math/vec.ts +0 -255
- package/runtime/sdk/net/codec.ts +0 -119
- package/runtime/sdk/net/core.ts +0 -384
- package/runtime/sdk/net/index.ts +0 -181
- package/runtime/sdk/net/replication.ts +0 -622
- package/runtime/sdk/plugins/camera.ts +0 -81
- package/runtime/sdk/plugins/geolocation.ts +0 -123
- package/runtime/sdk/plugins/oauth.ts +0 -61
- package/runtime/sdk/plugins/permission.ts +0 -7
- package/runtime/sdk/plugins/push.ts +0 -132
- package/runtime/sdk/plugins/qr.ts +0 -73
- package/runtime/sdk/plugins/service.ts +0 -47
- package/runtime/sdk/runtime/app.ts +0 -101
- package/runtime/sdk/runtime/appEvents.ts +0 -54
- package/runtime/sdk/runtime/channel.ts +0 -61
- package/runtime/sdk/runtime/clipboard.ts +0 -20
- package/runtime/sdk/runtime/datetime.ts +0 -329
- package/runtime/sdk/runtime/device.ts +0 -293
- package/runtime/sdk/runtime/fetch.ts +0 -77
- package/runtime/sdk/runtime/files.ts +0 -23
- package/runtime/sdk/runtime/input.ts +0 -175
- package/runtime/sdk/runtime/media.ts +0 -111
- package/runtime/sdk/runtime/misc.ts +0 -16
- package/runtime/sdk/runtime/net.ts +0 -36
- package/runtime/sdk/runtime/rpc.ts +0 -218
- package/runtime/sdk/runtime/service.ts +0 -83
- package/runtime/sdk/runtime/share.ts +0 -9
- package/runtime/sdk/runtime/storage.ts +0 -13
- package/runtime/sdk/runtime/touch.ts +0 -76
- package/runtime/sdk/scene/defineScene.ts +0 -1353
- package/runtime/sdk/scene/editorPlugins.ts +0 -110
- package/runtime/sdk/scene/gizmos.ts +0 -148
- package/runtime/sdk/scene/grammar.ts +0 -120
- package/runtime/sdk/scene/material.ts +0 -188
- package/runtime/sdk/server/auth/appConfig.ts +0 -12
- package/runtime/sdk/server/auth/global.ts +0 -80
- package/runtime/sdk/server/auth/host.ts +0 -318
- package/runtime/sdk/server/auth/models.ts +0 -83
- package/runtime/sdk/server/auth/types.ts +0 -50
- package/runtime/sdk/server/channel.ts +0 -56
- package/runtime/sdk/server/context.ts +0 -36
- package/runtime/sdk/server/db/defineDb.ts +0 -237
- package/runtime/sdk/server/db/fields.ts +0 -132
- package/runtime/sdk/server/db/httpTransport.ts +0 -93
- package/runtime/sdk/server/db/index.ts +0 -7
- package/runtime/sdk/server/db/marci/query.ts +0 -412
- package/runtime/sdk/server/db/types.ts +0 -202
- package/runtime/sdk/server/errors.ts +0 -12
- package/runtime/sdk/server/host.ts +0 -74
- package/runtime/sdk/server/inject.ts +0 -13
- package/runtime/sdk/server/runtime.ts +0 -133
- package/runtime/sdk/server/validate.ts +0 -87
- package/runtime/sdk/ui/NativeView.ts +0 -142
- package/runtime/sdk/ui/UI.ts +0 -39
- package/runtime/sdk/ui/UIBottomSheet.ts +0 -139
- package/runtime/sdk/ui/UIButton.ts +0 -101
- package/runtime/sdk/ui/UIContainer.ts +0 -60
- package/runtime/sdk/ui/UIImage.ts +0 -83
- package/runtime/sdk/ui/UIInput.ts +0 -185
- package/runtime/sdk/ui/UIModal.ts +0 -139
- package/runtime/sdk/ui/UINode.ts +0 -830
- package/runtime/sdk/ui/UIPager.ts +0 -362
- package/runtime/sdk/ui/UIPopover.ts +0 -100
- package/runtime/sdk/ui/UIScreen.ts +0 -123
- package/runtime/sdk/ui/UIScrollable.ts +0 -87
- package/runtime/sdk/ui/UISpacer.ts +0 -14
- package/runtime/sdk/ui/UITabs.ts +0 -236
- package/runtime/sdk/ui/UIText.ts +0 -51
- package/runtime/sdk/ui/UIVideo.ts +0 -88
- package/runtime/sdk/ui/UIVirtualizedList.ts +0 -241
- package/runtime/sdk/ui/UIWidget.ts +0 -127
- package/runtime/sdk/ui/fonts.ts +0 -13
- package/runtime/sdk/ui/presentable.ts +0 -117
- package/runtime/sdk/ui/router.ts +0 -132
- package/runtime/sdk/ui/theme.ts +0 -84
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
// GENERATED by scripts/sync-marcidb.ts from marci-db packages/marcidb-client/src/query.ts — do not edit here.
|
|
2
|
-
// Change it in the marci-db repo, then `bun run sync:marcidb`.
|
|
3
|
-
|
|
4
|
-
// The generic query layer of the marcidb client: the query-language types every generated client is built
|
|
5
|
-
// on (where / update operators, `GetResult`, `Op`, the query builder `Query<T>`) and the builder runtime
|
|
6
|
-
// (`createQueryLayer`). Everything here is schema-agnostic — the codegen (crates/marcidb-ts) emits the
|
|
7
|
-
// per-model type bags and MODELS metadata this file is parametrised by.
|
|
8
|
-
//
|
|
9
|
-
// Keep it dependency-free: besides shipping in `marcidb-client/runtime`, this file is vendored verbatim
|
|
10
|
-
// into the lecodes SDK (`packages/sdk/src/server/db/marci/query.ts`, `bun run sync:marcidb` there), which
|
|
11
|
-
// derives its model types from TS builders instead of codegen and plugs them into the same generics.
|
|
12
|
-
|
|
13
|
-
// ───────────────────────────── query language types ─────────────────────────────
|
|
14
|
-
|
|
15
|
-
export type ServiceKeys = "$where" | "$order" | "$limit" | "$skip" | "$cursor";
|
|
16
|
-
|
|
17
|
-
// A `Json` field: any JSON value. Stored as a JSONB binary blob server-side; on the wire it is a plain
|
|
18
|
-
// decoded JSON value.
|
|
19
|
-
export type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
|
|
20
|
-
|
|
21
|
-
// Aggregate query over related records inside select
|
|
22
|
-
export type AggregateKeys = { $count: true } | { $sum: string } | { $avg: string } | { $min: string } | { $max: string }
|
|
23
|
-
|
|
24
|
-
// Distributive over union models (discriminated union for payload enums):
|
|
25
|
-
// keys not present in the current union branch are dropped
|
|
26
|
-
export type GetResult<TModel, TSelect> = TModel extends any ? {
|
|
27
|
-
-readonly [K in keyof Omit<TSelect, ServiceKeys> as TSelect[K] extends false | undefined ? never : K extends keyof TModel ? K : never]:
|
|
28
|
-
K extends keyof TModel
|
|
29
|
-
? TSelect[K] extends true
|
|
30
|
-
? TModel[K] // selected the whole field
|
|
31
|
-
: TSelect[K] extends Record<string, any>
|
|
32
|
-
? TModel[K] extends readonly object[]
|
|
33
|
-
? TSelect[K] extends AggregateKeys
|
|
34
|
-
? AggregateResult<NonNullable<TModel[K][number]>, TSelect[K]> // aggregate over the relation
|
|
35
|
-
: GetResult<NonNullable<TModel[K][number]>, TSelect[K]>[]
|
|
36
|
-
: GetResult<NonNullable<TModel[K]>, TSelect[K]> | Extract<TModel[K], null>
|
|
37
|
-
: TModel[K] // fallback
|
|
38
|
-
: never
|
|
39
|
-
} : never
|
|
40
|
-
|
|
41
|
-
export type RefUpdate<I> = {
|
|
42
|
-
"$connect"?: I
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type RefUpdateStruct<I,U> = {
|
|
46
|
-
"$update"?: U,
|
|
47
|
-
"$ensure"?: I,
|
|
48
|
-
"$set"?: I
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Relation to independent rows — link operations only, the rows themselves are never created
|
|
52
|
-
* or deleted. `$set` replaces link membership with exactly the given set (missing links are
|
|
53
|
-
* disconnected, new ones connected); `$connect` links (idempotent); `$remove` unlinks. */
|
|
54
|
-
export type RefListUpdate<I> = {
|
|
55
|
-
"$set"?: I[],
|
|
56
|
-
"$connect"?: I | I[],
|
|
57
|
-
"$remove"?: I | I[],
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** `@list` relation: an ordered inline id array — a sequence, so the same id may appear several
|
|
61
|
-
* times. `$set` replaces the whole array (also the reorder operation); `$connect` appends at the
|
|
62
|
-
* end (an already-present id gains another occurrence); `$connectUnique` appends only ids not
|
|
63
|
-
* already present; `$remove` removes every occurrence. */
|
|
64
|
-
export type RefListUpdateOrdered<I> = {
|
|
65
|
-
"$set"?: I[],
|
|
66
|
-
"$connect"?: I | I[],
|
|
67
|
-
"$connectUnique"?: I | I[],
|
|
68
|
-
"$remove"?: I | I[],
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** Owned (struct) list: the children live and die with the parent. `$push` creates children,
|
|
72
|
-
* `$update` edits single children in place (each item is the child's id fields — the shape
|
|
73
|
-
* query results return — plus the changes under `data`), `$remove` deletes children by id,
|
|
74
|
-
* `$set` replaces all children (deletes the current ones, creates the new). */
|
|
75
|
-
export type RefListUpdateStruct<I,U,Id> = {
|
|
76
|
-
"$push"?: I | I[],
|
|
77
|
-
"$update"?: (Id & { data: U }) | (Id & { data: U })[],
|
|
78
|
-
"$remove"?: Id | Id[],
|
|
79
|
-
"$set"?: I[]
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Variable-length primitive array — a sequence, so the same value may appear several times.
|
|
83
|
-
* `$push` appends at the end (duplicates kept); `$pushUnique` appends only values not already
|
|
84
|
-
* present; `$remove` removes every occurrence; `$set` replaces the whole array (also the
|
|
85
|
-
* positional-edit path — send the full new array). One operator per update. */
|
|
86
|
-
export type PrimitiveListUpdate<T> = {
|
|
87
|
-
"$set"?: T[],
|
|
88
|
-
"$push"?: T | T[],
|
|
89
|
-
"$pushUnique"?: T | T[],
|
|
90
|
-
"$remove"?: T | T[],
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Marks a set of keys as forbidden. Needed because TypeScript's excess-property check against a *union*
|
|
94
|
-
// permits any key present in some member: a plain union of single-key objects accepts `{ $gte, $lt }`,
|
|
95
|
-
// and a plain `T | { $and: T[] }` accepts a field sitting next to `$and`. Both are runtime errors or
|
|
96
|
-
// silently-wrong queries, so every branch below spells out the keys it excludes.
|
|
97
|
-
export type Never<T> = { [K in keyof T]?: never }
|
|
98
|
-
|
|
99
|
-
// Every field-level operator, so a field's condition can exclude the ones its type doesn't support.
|
|
100
|
-
export type FieldOps = {
|
|
101
|
-
"$eq": unknown, "$ne": unknown, "$not": unknown, "$in": unknown, "$notIn": unknown,
|
|
102
|
-
"$gt": unknown, "$gte": unknown, "$lt": unknown, "$lte": unknown,
|
|
103
|
-
"$startsWith": unknown, "$includes": unknown,
|
|
104
|
-
"$every": unknown, "$some": unknown, "$none": unknown,
|
|
105
|
-
"$near": unknown, "$search": unknown
|
|
106
|
-
}
|
|
107
|
-
export type Only<K extends keyof FieldOps, V> = { [P in K]: V } & Never<Omit<FieldOps, K>>
|
|
108
|
-
|
|
109
|
-
// A `$where` is either a set of field conditions or exactly one boolean combinator wrapping more of the
|
|
110
|
-
// same. Conditions belong *inside* the array: the engine returns on the first combinator it finds, so a
|
|
111
|
-
// sibling key next to `$and`/`$or` would be silently ignored — here it is a type error instead.
|
|
112
|
-
export type WhereValue<T> =
|
|
113
|
-
| (T & Never<{ "$and": unknown, "$or": unknown, "$not": unknown }>)
|
|
114
|
-
| ({ "$and": WhereValue<T>[] } & Never<T> & Never<{ "$or": unknown, "$not": unknown }>)
|
|
115
|
-
| ({ "$or": WhereValue<T>[] } & Never<T> & Never<{ "$and": unknown, "$not": unknown }>)
|
|
116
|
-
| ({ "$not": WhereValue<T> } & Never<T> & Never<{ "$and": unknown, "$or": unknown }>)
|
|
117
|
-
|
|
118
|
-
// Operators on one field are ANDed, so they combine freely: `{ $gte: 18, $lt: 65 }` is a half-open
|
|
119
|
-
// range and `{ $gte: 18, $ne: 30 }` punches a hole in one. Each group below is all-optional; a field's
|
|
120
|
-
// condition type intersects the groups its type supports and marks every remaining operator forbidden,
|
|
121
|
-
// so a string operator on a number is still a type error.
|
|
122
|
-
export type ValueOps<T> = { "$eq"?: T, "$ne"?: T, "$not"?: T, "$in"?: T[], "$notIn"?: T[] }
|
|
123
|
-
export type NumOps<T> = { "$gt"?: T, "$gte"?: T, "$lt"?: T, "$lte"?: T }
|
|
124
|
-
export type StrOps = { "$includes"?: string, "$startsWith"?: string }
|
|
125
|
-
|
|
126
|
-
// The numeric and string variants re-admit the type-agnostic operators, so a mixed condition such as
|
|
127
|
-
// `{ $gte: 18, $ne: 30 }` still matches a single member of the union the field's type resolves to.
|
|
128
|
-
export type CompareValue<T> = T | (ValueOps<T> & Never<Omit<FieldOps, keyof ValueOps<T>>>)
|
|
129
|
-
export type CompareNumValue<T> = ValueOps<T> & NumOps<T> & Never<Omit<FieldOps, keyof ValueOps<T> | keyof NumOps<T>>>
|
|
130
|
-
export type CompareStrValue<T> = ValueOps<T> & StrOps & Never<Omit<FieldOps, keyof ValueOps<T> | keyof StrOps>>
|
|
131
|
-
|
|
132
|
-
// A numeric field can also be updated in place: `{ balance: { $increment: -800 } }` reads, adds and writes
|
|
133
|
-
// inside the update's own transaction, so it is atomic against concurrent writers. The delta is signed, so
|
|
134
|
-
// decrementing requires a signed field (`Int`) — a negative delta on an unsigned field is rejected.
|
|
135
|
-
// Incrementing a field that is currently null is a no-op.
|
|
136
|
-
export type UpdateNumValue = { "$increment": number }
|
|
137
|
-
|
|
138
|
-
// Filtering into a Json field by dot-path. Keys are JSON paths (e.g. "address.city", "items.0"); a numeric
|
|
139
|
-
// segment indexes an array. A bare value is shorthand for `$eq` (a plain object matches the whole subtree).
|
|
140
|
-
// Path keys must not start with `$`. A missing leaf or a type mismatch simply doesn't match.
|
|
141
|
-
export type JsonType = "string" | "number" | "boolean" | "object" | "array" | "null"
|
|
142
|
-
// As on scalar fields, operators on one path are ANDed and may be combined.
|
|
143
|
-
export type JsonCondition =
|
|
144
|
-
| JsonValue
|
|
145
|
-
| {
|
|
146
|
-
"$eq"?: JsonValue, "$ne"?: JsonValue, "$not"?: JsonValue,
|
|
147
|
-
"$gt"?: number | string, "$gte"?: number | string,
|
|
148
|
-
"$lt"?: number | string, "$lte"?: number | string,
|
|
149
|
-
"$in"?: JsonValue[], "$notIn"?: JsonValue[],
|
|
150
|
-
"$startsWith"?: string, "$includes"?: string,
|
|
151
|
-
"$contains"?: JsonValue,
|
|
152
|
-
"$exists"?: boolean,
|
|
153
|
-
"$type"?: JsonType
|
|
154
|
-
}
|
|
155
|
-
export type JsonPathWhere = { [path: string]: JsonCondition }
|
|
156
|
-
export type CompareRefValue<T> = T | Only<"$not", T>
|
|
157
|
-
export type CompareRefListValue<T> = Only<"$every", T> | Only<"$some", T> | Only<"$none", T>
|
|
158
|
-
|
|
159
|
-
// Module-index search (@custom): $near/$search hand a raw payload to the field's index provider.
|
|
160
|
-
export type VectorSearch = { vector: number[], k?: number, threshold?: number } // @custom(vector, …)
|
|
161
|
-
export type FullTextSearch = string | { query: string, limit?: number } // @custom(fulltext, …)
|
|
162
|
-
export type CustomSearch = Record<string, any> // other providers
|
|
163
|
-
export type CustomSearchValue<P> = Only<"$near", P> | Only<"$search", P>
|
|
164
|
-
|
|
165
|
-
// Aggregate result: only the requested keys; an empty set yields null (except count)
|
|
166
|
-
export type AggregateResult<TModel, T> =
|
|
167
|
-
(T extends { $count: true } ? { count: number } : {}) &
|
|
168
|
-
(T extends { $sum: string } ? { sum: number | null } : {}) &
|
|
169
|
-
(T extends { $avg: string } ? { avg: number | null } : {}) &
|
|
170
|
-
(T extends { $min: infer F } ? { min: (F extends keyof TModel ? TModel[F] : never) | null } : {}) &
|
|
171
|
-
(T extends { $max: infer F } ? { max: (F extends keyof TModel ? TModel[F] : never) | null } : {})
|
|
172
|
-
|
|
173
|
-
// A lazily-executed operation. `await` runs it as a single request;
|
|
174
|
-
// passing it into `db.$transaction([...])` bundles it into one atomic transaction
|
|
175
|
-
declare const __op: unique symbol
|
|
176
|
-
export type Op<T> = PromiseLike<T> & { readonly [__op]: T }
|
|
177
|
-
|
|
178
|
-
// A transport-neutral operation descriptor and the pluggable transport that runs it. The HTTP transport
|
|
179
|
-
// is selected by passing a URL string; marcidb-embedded provides an in-process FFI transport.
|
|
180
|
-
export type MarciOp = { model: string, action: string, query?: any, data?: any, id?: any }
|
|
181
|
-
export type MarciTransport = {
|
|
182
|
-
exec(op: MarciOp): Promise<any>
|
|
183
|
-
batch(ops: MarciOp[]): Promise<any[]>
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// ───────────────────────────── query builder ─────────────────────────────
|
|
187
|
-
|
|
188
|
-
// The per-model type bag the codegen emits (`UserTypes`) and `Query<T>` below is parametrised by.
|
|
189
|
-
export type ModelTypes = {
|
|
190
|
-
name: string
|
|
191
|
-
model: any
|
|
192
|
-
id: Record<string, any>
|
|
193
|
-
/** What an empty select returns: id + every scalar field, as a `{ field: true }` shape. */
|
|
194
|
-
scalars: Record<string, true>
|
|
195
|
-
select: Record<string, any>
|
|
196
|
-
query: Record<string, any>
|
|
197
|
-
where: any
|
|
198
|
-
order: Record<string, any>
|
|
199
|
-
insert: any
|
|
200
|
-
update: any
|
|
201
|
-
aggregate: Record<string, any>
|
|
202
|
-
reindex: boolean
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// A sub-query placed as a value in a select shape — a builder, `count()` or `aggregate()` of the relation's
|
|
206
|
-
// model (`posts: db.post.order("id", "desc").limit(5)`). Branded by model name so a builder of the wrong model
|
|
207
|
-
// is a type error; `[__sel]` is the shape it resolves to (see `Resolve`).
|
|
208
|
-
declare const __sub: unique symbol
|
|
209
|
-
declare const __sel: unique symbol
|
|
210
|
-
export type Sub<Name extends string, Shape = any> = { readonly [__sub]: Name, readonly [__sel]: Shape }
|
|
211
|
-
|
|
212
|
-
// A shape without field keys (only `$`-clauses, or nothing) selects id + every scalar — same rule as the engine.
|
|
213
|
-
export type Effective<T extends ModelTypes, S> = [Exclude<keyof S, ServiceKeys>] extends [never] ? T["scalars"] : S
|
|
214
|
-
// Sub-queries inside a shape resolve to the shape they carry, recursively; `$`-clauses are left alone.
|
|
215
|
-
export type Resolve<S> =
|
|
216
|
-
S extends { readonly [__sel]: infer X } ? Resolve<X>
|
|
217
|
-
: S extends object ? { [K in keyof S]: K extends `$${string}` ? S[K] : Resolve<S[K]> }
|
|
218
|
-
: S
|
|
219
|
-
export type Rows<T extends ModelTypes, Sel> = GetResult<T["model"], Resolve<Effective<T, Sel>>>
|
|
220
|
-
// The bare key value, accepted wherever an id object is (`after(42)` = `after({ id: 42 })`, `delete(42)`).
|
|
221
|
-
export type BareId<I> = I extends { id: infer V } ? V : never
|
|
222
|
-
export type IdArg<I> = I | BareId<I>
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* A lazy, immutable query over one model — `db.user` itself is one. Every clause returns a new query, so
|
|
226
|
-
* queries compose (`const active = db.user.where({ active: true })`). `await` runs it as `findMany`; passing
|
|
227
|
-
* it to `$transaction` batches it; placing it in another query's select makes it a sub-select. `Sel` is the
|
|
228
|
-
* projection: id + scalars until `select(...)` sets a shape.
|
|
229
|
-
*/
|
|
230
|
-
export interface Query<T extends ModelTypes, Sel = T["scalars"]> extends PromiseLike<Rows<T, Sel>[]> {
|
|
231
|
-
readonly [__op]: Rows<T, Sel>[]
|
|
232
|
-
readonly [__sub]: T["name"]
|
|
233
|
-
readonly [__sel]: Effective<T, Sel>
|
|
234
|
-
/** Filter (marcidb `$where`). Repeated calls are ANDed. */
|
|
235
|
-
where(where: T["where"]): Query<T, Sel>
|
|
236
|
-
/** Sort by one field: `order("age", "desc")` or `order({ age: "desc" })`. */
|
|
237
|
-
order(field: keyof T["order"] & string, direction?: "asc" | "desc"): Query<T, Sel>
|
|
238
|
-
order(order: T["order"]): Query<T, Sel>
|
|
239
|
-
limit(n: number): Query<T, Sel>
|
|
240
|
-
skip(n: number): Query<T, Sel>
|
|
241
|
-
/** Keyset cursor: rows strictly after this id in the current order (`$cursor`). */
|
|
242
|
-
after(id: IdArg<T["id"]>): Query<T, Sel>
|
|
243
|
-
/**
|
|
244
|
-
* The projection. Values are `true`, a nested shape, or a sub-query of the relation's model
|
|
245
|
-
* (`posts: db.post.limit(5)`, `posts: db.post.where({ published: true }).count()`). No argument, or no
|
|
246
|
-
* field keys, selects id + every scalar. `$`-clauses are accepted here too (the object form).
|
|
247
|
-
*/
|
|
248
|
-
select<S extends T["query"] = T["scalars"]>(shape?: S): Query<T, S>
|
|
249
|
-
/** The first matching row or `null`. */
|
|
250
|
-
first(): Op<Rows<T, Sel> | null>
|
|
251
|
-
/** Row count; inside a select it becomes `{ count }` for the relation. */
|
|
252
|
-
count(): Op<number> & Sub<T["name"], { $count: true }>
|
|
253
|
-
/** @deprecated pass the filter through the chain: `db.user.where(w).count()` (removed in the next minor). */
|
|
254
|
-
count(query: { $where?: T["where"] }): Op<number> & Sub<T["name"], { $count: true }>
|
|
255
|
-
// `NoInfer`: as a select value the contextual type is `Sub<Name, any>`, which would otherwise win the inference of `A`
|
|
256
|
-
aggregate<A extends T["aggregate"]>(query: A): Op<AggregateResult<T["model"], A>> & Sub<T["name"], NoInfer<A>>
|
|
257
|
-
|
|
258
|
-
insert(data: T["insert"]): Op<T["id"]>
|
|
259
|
-
update(id: IdArg<T["id"]>, data: T["update"]): Op<void>
|
|
260
|
-
/** Applies `data` to every row the chain's `where` matches (all rows without one); resolves to the number of rows. */
|
|
261
|
-
updateMany(data: T["update"]): Op<number>
|
|
262
|
-
/** @deprecated pass the filter through the chain: `db.user.where(w).updateMany(data)` (removed in the next minor). */
|
|
263
|
-
updateMany(query: { $where?: T["where"] }, data: T["update"]): Op<number>
|
|
264
|
-
delete(id: IdArg<T["id"]>): Op<void>
|
|
265
|
-
/**
|
|
266
|
-
* Deletes every row the chain's `where` matches (cascades apply, as for `delete`); resolves to the number
|
|
267
|
-
* deleted. Refuses to run without a `where` — write `.where({})` to mean "every row".
|
|
268
|
-
*/
|
|
269
|
-
deleteMany(): Op<number>
|
|
270
|
-
|
|
271
|
-
// ── object form (deprecated): one query object (select shape + $where/$order/$limit/$skip/$cursor)
|
|
272
|
-
/** @deprecated use `.select(query)` — it takes the same object, merged with the chain (removed in the next minor). */
|
|
273
|
-
findMany<Q extends T["query"] = {}>(query?: Q): Op<Rows<T, Q>[]>
|
|
274
|
-
/** @deprecated use `.select(query).first()` (removed in the next minor). */
|
|
275
|
-
findFirst<Q extends T["query"] = {}>(query?: Q): Op<Rows<T, Q> | null>
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/** `db.<model>`: the root query, plus `reindex()` for models with a `@custom` (vector / full-text) index. */
|
|
279
|
-
export type Collection<T extends ModelTypes> = Query<T> & (T["reindex"] extends true ? { reindex(): Op<{ ok: boolean, indexed: number }> } : {})
|
|
280
|
-
|
|
281
|
-
// ───────────────────────────── builder runtime ─────────────────────────────
|
|
282
|
-
|
|
283
|
-
/** One field of a model, in slot order: `n` name, `k` key | body | one | many, `m` the relation's target model. */
|
|
284
|
-
export type FieldDesc = { n: string; k: "key" | "body" | "one" | "many"; t?: string | null; m?: string };
|
|
285
|
-
/** Model name → its field descriptors (structs included, as relation targets). */
|
|
286
|
-
export type ModelsMeta = Record<string, readonly FieldDesc[]>;
|
|
287
|
-
|
|
288
|
-
export type QueryLayerOptions = {
|
|
289
|
-
models: ModelsMeta;
|
|
290
|
-
/** Runs one operation (a query, or a write) and resolves its result. */
|
|
291
|
-
run(op: MarciOp): Promise<any>;
|
|
292
|
-
/** Hook for `insert` payloads (the lecodes SDK generates uuid ids here). */
|
|
293
|
-
prepareInsert?(model: string, data: any): any;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const AGGREGATE_KEYS = ["$count", "$sum", "$avg", "$min", "$max"];
|
|
297
|
-
const and = (a: any, b: any): any => (a ? (b ? { $and: [a, b] } : a) : b);
|
|
298
|
-
|
|
299
|
-
type QueryState = { shape?: Record<string, any>; where?: any; order?: any; limit?: number; skip?: number; cursor?: any };
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* The query builder over a set of models and a `run` function. Returns `op(descriptor)` — a lazy operation
|
|
303
|
-
* (`await` runs it, `$transaction` takes its `__op`) — and `collection(model)`, the immutable `db.<model>`
|
|
304
|
-
* root query. Transport-agnostic: the generated client and the embedded/HTTP transports supply `run`.
|
|
305
|
-
*/
|
|
306
|
-
export function createQueryLayer(options: QueryLayerOptions): { op: (descriptor: MarciOp) => any; collection: (model: string) => any } {
|
|
307
|
-
const { models, run } = options;
|
|
308
|
-
|
|
309
|
-
// Lazily-executed operation: `await` runs it through the transport as a single op,
|
|
310
|
-
// while `$transaction` takes only the `__op` descriptor and sends them as one batch.
|
|
311
|
-
const op = (descriptor: MarciOp): any => ({
|
|
312
|
-
__op: descriptor,
|
|
313
|
-
then: (onFulfilled?: any, onRejected?: any) => run(descriptor).then(onFulfilled, onRejected),
|
|
314
|
-
catch: (onRejected?: any) => run(descriptor).catch(onRejected),
|
|
315
|
-
finally: (onFinally?: any) => run(descriptor).finally(onFinally),
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
// A field key is anything that isn't a `$`-clause. A shape without field keys selects id + every scalar
|
|
319
|
-
// (the engine's rule too — the client applies it so the binary decoder and older servers see explicit fields).
|
|
320
|
-
const scalarSelect = (model: string): Record<string, true> => {
|
|
321
|
-
const out: Record<string, true> = {};
|
|
322
|
-
for (const f of models[model] ?? []) if (f.k === "key" || f.k === "body") out[f.n] = true;
|
|
323
|
-
return out;
|
|
324
|
-
};
|
|
325
|
-
const keyField = (model: string): string => (models[model] ?? []).find((f) => f.k === "key")?.n ?? "id";
|
|
326
|
-
// `42` → `{ id: 42 }` (the bare value of a single-field key), an object passes through
|
|
327
|
-
const idObject = (model: string, id: any): any => (id !== null && typeof id === "object" ? id : { [keyField(model)]: id });
|
|
328
|
-
// Resolves sub-queries (values carrying `__select`) and fills empty projections, recursively along relations.
|
|
329
|
-
const resolveShape = (model: string, shape: Record<string, any>): Record<string, any> => {
|
|
330
|
-
const out: Record<string, any> = {};
|
|
331
|
-
let fields = 0;
|
|
332
|
-
for (const k in shape) {
|
|
333
|
-
const v = shape[k];
|
|
334
|
-
if (k.charCodeAt(0) === 36 /* $ */) { out[k] = v; continue; }
|
|
335
|
-
if (v !== undefined && v !== false) fields++;
|
|
336
|
-
if (v !== null && typeof v === "object") {
|
|
337
|
-
if ("__select" in v) { out[k] = v.__select; continue; }
|
|
338
|
-
const desc = (models[model] ?? []).find((f) => f.n === k);
|
|
339
|
-
out[k] = desc && desc.m && !AGGREGATE_KEYS.some((a) => a in v) ? resolveShape(desc.m, v) : v;
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
out[k] = v;
|
|
343
|
-
}
|
|
344
|
-
if (fields === 0) Object.assign(out, scalarSelect(model));
|
|
345
|
-
return out;
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
// `db.<model>` — an immutable builder; each clause returns a new one over the same `run`.
|
|
349
|
-
const collection = (model: string): any => {
|
|
350
|
-
const make = (st: QueryState): any => {
|
|
351
|
-
// The wire query: the (object-form) `query` merged over the chain's state.
|
|
352
|
-
const build = (query?: Record<string, any>): Record<string, any> => {
|
|
353
|
-
const q = resolveShape(model, { ...(st.shape ?? {}), ...(query ?? {}) });
|
|
354
|
-
const where = and(st.where, q.$where);
|
|
355
|
-
if (where) q.$where = where; else delete q.$where;
|
|
356
|
-
if (st.order && !q.$order) q.$order = st.order;
|
|
357
|
-
if (st.limit !== undefined && q.$limit === undefined) q.$limit = st.limit;
|
|
358
|
-
if (st.skip !== undefined && q.$skip === undefined) q.$skip = st.skip;
|
|
359
|
-
if (st.cursor !== undefined && q.$cursor === undefined) q.$cursor = st.cursor;
|
|
360
|
-
return q;
|
|
361
|
-
};
|
|
362
|
-
const whereOnly = (query?: Record<string, any>): Record<string, any> => {
|
|
363
|
-
const w = and(st.where, query && query.$where);
|
|
364
|
-
return w ? { $where: w } : {};
|
|
365
|
-
};
|
|
366
|
-
const findMany = (): MarciOp => ({ model, action: "findMany", query: build() });
|
|
367
|
-
return {
|
|
368
|
-
get __op() { return findMany(); },
|
|
369
|
-
get __select() { return build(); },
|
|
370
|
-
then: (onFulfilled?: any, onRejected?: any) => run(findMany()).then(onFulfilled, onRejected),
|
|
371
|
-
catch: (onRejected?: any) => run(findMany()).catch(onRejected),
|
|
372
|
-
finally: (onFinally?: any) => run(findMany()).finally(onFinally),
|
|
373
|
-
|
|
374
|
-
where: (where: any) => make({ ...st, where: and(st.where, where) }),
|
|
375
|
-
order: (field: any, direction?: "asc" | "desc") => make({ ...st, order: typeof field === "string" ? { [field]: direction ?? "asc" } : field }),
|
|
376
|
-
limit: (n: number) => make({ ...st, limit: n }),
|
|
377
|
-
skip: (n: number) => make({ ...st, skip: n }),
|
|
378
|
-
after: (id: any) => make({ ...st, cursor: idObject(model, id) }),
|
|
379
|
-
select: (shape?: Record<string, any>) => make({ ...st, shape: shape ?? {} }),
|
|
380
|
-
first: () => op({ model, action: "findFirst", query: build() }),
|
|
381
|
-
count: (query?: Record<string, any>) => {
|
|
382
|
-
const q = whereOnly(query);
|
|
383
|
-
return Object.assign(op({ model, action: "count", query: q }), { __select: { $count: true, ...q } });
|
|
384
|
-
},
|
|
385
|
-
aggregate: (query: Record<string, any>) => {
|
|
386
|
-
const q = { ...(query ?? {}), ...whereOnly(query) };
|
|
387
|
-
if (!q.$where) delete q.$where;
|
|
388
|
-
return Object.assign(op({ model, action: "aggregate", query: q }), { __select: q });
|
|
389
|
-
},
|
|
390
|
-
|
|
391
|
-
insert: (data: any) => op({ model, action: "insert", data: options.prepareInsert ? options.prepareInsert(model, data) : data }),
|
|
392
|
-
update: (id: any, data: any) => op({ model, action: "update", id: idObject(model, id), data }),
|
|
393
|
-
// `updateMany(data)`; the deprecated `updateMany(query, data)` form is told apart by arity
|
|
394
|
-
updateMany: (a: any, b?: any) => (b === undefined
|
|
395
|
-
? op({ model, action: "updateMany", query: whereOnly(), data: a })
|
|
396
|
-
: op({ model, action: "updateMany", query: whereOnly(a), data: b })),
|
|
397
|
-
delete: (id: any) => op({ model, action: "delete", id: idObject(model, id) }),
|
|
398
|
-
deleteMany: () => {
|
|
399
|
-
if (st.where === undefined) throw new Error(`marcidb: ${model}.deleteMany() needs a where — use .where({}) to delete every row`);
|
|
400
|
-
return op({ model, action: "deleteMany", query: whereOnly() });
|
|
401
|
-
},
|
|
402
|
-
reindex: () => op({ model, action: "$reindex" }),
|
|
403
|
-
|
|
404
|
-
findMany: (query?: Record<string, any>) => op({ model, action: "findMany", query: build(query) }),
|
|
405
|
-
findFirst: (query?: Record<string, any>) => op({ model, action: "findFirst", query: build(query) }),
|
|
406
|
-
};
|
|
407
|
-
};
|
|
408
|
-
return make({});
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
return { op, collection };
|
|
412
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type layer: projects a `defineDb({ User: model({...}), … })` literal into marcidb's generic query
|
|
3
|
-
* types (./marci/query.ts — vendored from marcidb, see scripts/sync-marcidb.ts): each model becomes the
|
|
4
|
-
* `ModelTypes` bag marcidb's codegen would have emitted, and `db.<model>` is marcidb's own `Query<T>`.
|
|
5
|
-
* Everything here is type-only; the runtime lives in ./defineDb.ts.
|
|
6
|
-
*
|
|
7
|
-
* Naming: `S` = the schema record (model name → Model), `N` = a model name, `F` = a fields record.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { Field, FieldMeta } from "./fields"
|
|
11
|
-
import type {
|
|
12
|
-
CompareNumValue, CompareRefListValue, CompareRefValue, CompareStrValue, CompareValue, CustomSearchValue,
|
|
13
|
-
FullTextSearch, JsonCondition, JsonPathWhere, Op, PrimitiveListUpdate, Query as MarciQuery, RefListUpdate,
|
|
14
|
-
RefListUpdateOrdered, RefUpdate, RefUpdateStruct, Rows, Sub, UpdateNumValue, VectorSearch, WhereValue,
|
|
15
|
-
} from "./marci/query"
|
|
16
|
-
|
|
17
|
-
// ───────────────────────────── schema shapes ─────────────────────────────
|
|
18
|
-
|
|
19
|
-
export type Fields = Record<string, Field<any, any>>
|
|
20
|
-
export type Model<F extends Fields = Fields> = { readonly fields: F, readonly __model: true }
|
|
21
|
-
export type Schema = Record<string, Model<any>>
|
|
22
|
-
|
|
23
|
-
export type FieldsOf<M> = M extends Model<infer F> ? F : never
|
|
24
|
-
type TsOf<Fld> = Fld extends Field<infer T, any> ? T : never
|
|
25
|
-
type StructFieldsOf<Fld> = TsOf<Fld> extends Fields ? TsOf<Fld> : never
|
|
26
|
-
type MetaOf<Fld> = Fld extends Field<any, infer M> ? M : never
|
|
27
|
-
type ModelName<S, Fld> = MetaOf<Fld>["model"] & keyof S & string
|
|
28
|
-
|
|
29
|
-
type Nullable<M extends FieldMeta, T> = M["optional"] extends true ? T | null : T
|
|
30
|
-
type Arr<M extends FieldMeta, T> = M["array"] extends true ? T[] : T
|
|
31
|
-
type IsNum<M extends FieldMeta> = M["scalar"] extends "int" | "float" | "date" ? true : false
|
|
32
|
-
|
|
33
|
-
// ───────────────────────────── key ─────────────────────────────
|
|
34
|
-
|
|
35
|
-
/** Explicit `.id()` fields, or a field literally named `id`. */
|
|
36
|
-
type IdKeys<F extends Fields> = { [K in keyof F]: MetaOf<F[K]>["isId"] extends true ? K : K extends "id" ? K : never }[keyof F]
|
|
37
|
-
type IdValue<S, Fld> = MetaOf<Fld>["kind"] extends "one" ? Id<S, ModelName<S, Fld>> : TsOf<Fld>
|
|
38
|
-
|
|
39
|
-
/** The id object of a model: `{ id: number }` implicitly, or the declared key fields. */
|
|
40
|
-
export type Id<S, N extends keyof S> =
|
|
41
|
-
[IdKeys<FieldsOf<S[N]>>] extends [never] ? { id: number } : { [K in IdKeys<FieldsOf<S[N]>>]: IdValue<S, FieldsOf<S[N]>[K]> }
|
|
42
|
-
/** What `update`/`delete` accept: the id object, or the bare value when the key is a single scalar. */
|
|
43
|
-
export type IdArg<S, N extends keyof S> = Id<S, N> | (Id<S, N> extends { id: infer V } ? V : never)
|
|
44
|
-
|
|
45
|
-
// ───────────────────────────── row ─────────────────────────────
|
|
46
|
-
|
|
47
|
-
type FieldRow<S, Fld, M extends FieldMeta = MetaOf<Fld>> =
|
|
48
|
-
M["kind"] extends "one" ? Nullable<M, Row<S, ModelName<S, Fld>>>
|
|
49
|
-
: M["kind"] extends "many" | "list" ? Row<S, ModelName<S, Fld>>[]
|
|
50
|
-
: M["kind"] extends "struct" ? Nullable<M, StructRow<S, StructFieldsOf<Fld>>>
|
|
51
|
-
: Nullable<M, Arr<M, TsOf<Fld>>>
|
|
52
|
-
|
|
53
|
-
/** Full row type of a model (relations included) — the `TModel` marcidb's `GetResult` selects from. */
|
|
54
|
-
export type Row<S, N extends keyof S> = Id<S, N> & { [K in Exclude<keyof FieldsOf<S[N]>, IdKeys<FieldsOf<S[N]>>>]: FieldRow<S, FieldsOf<S[N]>[K]> }
|
|
55
|
-
type StructRow<S, F extends Fields> = { [K in keyof F]: FieldRow<S, F[K]> }
|
|
56
|
-
|
|
57
|
-
type ScalarKeys<F extends Fields> = { [K in keyof F]: MetaOf<F[K]>["kind"] extends "scalar" | "enum" | "json" ? K : never }[keyof F]
|
|
58
|
-
type NumKeys<F extends Fields> = { [K in keyof F]: IsNum<MetaOf<F[K]>> extends true ? (MetaOf<F[K]>["array"] extends true ? never : K) : never }[keyof F]
|
|
59
|
-
/** What an empty select returns: id + every scalar field. */
|
|
60
|
-
export type Scalars<S, N extends keyof S> = Pick<Row<S, N>, (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>>
|
|
61
|
-
/** The same, as the `{ field: true }` select shape a query starts with. */
|
|
62
|
-
export type ScalarSelect<S, N extends keyof S> = { [K in (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>]: true }
|
|
63
|
-
|
|
64
|
-
// ───────────────────────────── insert ─────────────────────────────
|
|
65
|
-
|
|
66
|
-
type FieldInsert<S, Fld, M extends FieldMeta = MetaOf<Fld>> =
|
|
67
|
-
M["kind"] extends "one" ? Nullable<M, Id<S, ModelName<S, Fld>>>
|
|
68
|
-
: M["kind"] extends "many" | "list" ? Id<S, ModelName<S, Fld>>[]
|
|
69
|
-
: M["kind"] extends "struct" ? Nullable<M, StructInsert<S, StructFieldsOf<Fld>>>
|
|
70
|
-
: Nullable<M, Arr<M, TsOf<Fld>>>
|
|
71
|
-
|
|
72
|
-
type RequiredKeys<F extends Fields> = {
|
|
73
|
-
[K in keyof F]: K extends IdKeys<F> ? never
|
|
74
|
-
: MetaOf<F[K]>["optional"] extends true ? never
|
|
75
|
-
: MetaOf<F[K]>["hasDefault"] extends true ? never
|
|
76
|
-
: MetaOf<F[K]>["kind"] extends "many" | "list" ? never
|
|
77
|
-
: K
|
|
78
|
-
}[keyof F]
|
|
79
|
-
type Simplify<T> = { [K in keyof T]: T[K] } & {}
|
|
80
|
-
type InsertOf<S, F extends Fields> = Simplify<
|
|
81
|
-
{ [K in RequiredKeys<F>]: FieldInsert<S, F[K]> } &
|
|
82
|
-
{ [K in Exclude<keyof F, RequiredKeys<F>>]?: FieldInsert<S, F[K]> }
|
|
83
|
-
>
|
|
84
|
-
export type Insert<S, N extends keyof S> = InsertOf<S, FieldsOf<S[N]>>
|
|
85
|
-
type StructInsert<S, F extends Fields> = InsertOf<S, F>
|
|
86
|
-
|
|
87
|
-
// ───────────────────────────── update ─────────────────────────────
|
|
88
|
-
|
|
89
|
-
type FieldUpdate<S, Fld, M extends FieldMeta = MetaOf<Fld>> =
|
|
90
|
-
M["kind"] extends "one" ? Nullable<M, RefUpdate<Id<S, ModelName<S, Fld>>>> // `{ $connect: { id } }` / null — marcidb's update grammar (bare ids are for insert)
|
|
91
|
-
: M["kind"] extends "many" ? RefListUpdate<Id<S, ModelName<S, Fld>>>
|
|
92
|
-
: M["kind"] extends "list" ? RefListUpdateOrdered<Id<S, ModelName<S, Fld>>>
|
|
93
|
-
: M["kind"] extends "struct" ? RefUpdateStruct<StructInsert<S, StructFieldsOf<Fld>>, UpdateOf<S, StructFieldsOf<Fld>>> | null
|
|
94
|
-
: M["array"] extends true ? TsOf<Fld>[] | PrimitiveListUpdate<TsOf<Fld>>
|
|
95
|
-
: Nullable<M, TsOf<Fld> | (IsNum<M> extends true ? UpdateNumValue : never)>
|
|
96
|
-
|
|
97
|
-
type UpdateOf<S, F extends Fields> = { [K in Exclude<keyof F, IdKeys<F>>]?: FieldUpdate<S, F[K]> }
|
|
98
|
-
export type Update<S, N extends keyof S> = UpdateOf<S, FieldsOf<S[N]>>
|
|
99
|
-
|
|
100
|
-
// ───────────────────────────── select / where / order / query ─────────────────────────────
|
|
101
|
-
|
|
102
|
-
// A relation also accepts a sub-query built from the related model's collection (`posts: db.post.limit(5)`,
|
|
103
|
-
// `db.post.count()`), branded `Sub<"Post">` so a builder of the wrong model is a type error.
|
|
104
|
-
type FieldSelect<S, Fld, M extends FieldMeta = MetaOf<Fld>> =
|
|
105
|
-
M["kind"] extends "one" ? Select<S, ModelName<S, Fld>> | boolean | Sub<ModelName<S, Fld>>
|
|
106
|
-
: M["kind"] extends "many" | "list" ? QueryObject<S, ModelName<S, Fld>> | AggregateQuery<S, ModelName<S, Fld>> | boolean | Sub<ModelName<S, Fld>>
|
|
107
|
-
: M["kind"] extends "struct" ? StructSelect<S, StructFieldsOf<Fld>> | boolean
|
|
108
|
-
: boolean
|
|
109
|
-
|
|
110
|
-
export type Select<S, N extends keyof S> = { [K in keyof Row<S, N>]?: K extends keyof FieldsOf<S[N]> ? FieldSelect<S, FieldsOf<S[N]>[K]> : boolean }
|
|
111
|
-
type StructSelect<S, F extends Fields> = { [K in keyof F]?: FieldSelect<S, F[K]> }
|
|
112
|
-
|
|
113
|
-
type ScalarWhere<T, M extends FieldMeta> =
|
|
114
|
-
| Nullable<M, CompareValue<T>>
|
|
115
|
-
| (IsNum<M> extends true ? CompareNumValue<T> : M["scalar"] extends "string" ? CompareStrValue<T> : never)
|
|
116
|
-
|
|
117
|
-
type FieldWhere<S, Fld, M extends FieldMeta = MetaOf<Fld>> =
|
|
118
|
-
M["kind"] extends "one" ? CompareRefValue<Where<S, ModelName<S, Fld>> | null>
|
|
119
|
-
: M["kind"] extends "many" | "list" ? CompareRefListValue<Where<S, ModelName<S, Fld>>>
|
|
120
|
-
: M["kind"] extends "struct" ? CompareRefValue<WhereValue<StructWhereFields<S, StructFieldsOf<Fld>>> | null>
|
|
121
|
-
: M["kind"] extends "json" ? JsonPathWhere | JsonCondition
|
|
122
|
-
: M["array"] extends true ? CompareValue<TsOf<Fld>>
|
|
123
|
-
: ScalarWhere<TsOf<Fld>, M> | CustomSearchValue<FullTextSearch> | CustomSearchValue<VectorSearch>
|
|
124
|
-
|
|
125
|
-
type WhereFieldsOf<S, F extends Fields> = { [K in keyof F]?: FieldWhere<S, F[K]> }
|
|
126
|
-
type IdWhere<S, N extends keyof S> = { [K in keyof Id<S, N> as K extends keyof FieldsOf<S[N]> ? never : K]?: CompareValue<Id<S, N>[K]> | CompareNumValue<number> }
|
|
127
|
-
export type Where<S, N extends keyof S> = WhereValue<WhereFieldsOf<S, FieldsOf<S[N]>> & IdWhere<S, N>>
|
|
128
|
-
type StructWhereFields<S, F extends Fields> = WhereFieldsOf<S, F>
|
|
129
|
-
|
|
130
|
-
export type Order<S, N extends keyof S> = { [K in (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>]?: "asc" | "desc" }
|
|
131
|
-
|
|
132
|
-
/** The query object — marcidb's wire form: a select shape plus the `$`-clauses. */
|
|
133
|
-
export type QueryObject<S, N extends keyof S> = Select<S, N> & {
|
|
134
|
-
$where?: Where<S, N>
|
|
135
|
-
$order?: Order<S, N>
|
|
136
|
-
$limit?: number
|
|
137
|
-
$skip?: number
|
|
138
|
-
$cursor?: Id<S, N>
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export type AggregateQuery<S, N extends keyof S> = {
|
|
142
|
-
$where?: Where<S, N>
|
|
143
|
-
$count?: true
|
|
144
|
-
$sum?: NumKeys<FieldsOf<S[N]>> & string
|
|
145
|
-
$avg?: NumKeys<FieldsOf<S[N]>> & string
|
|
146
|
-
$min?: (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & string
|
|
147
|
-
$max?: (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & string
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// ───────────────────────────── query / db ─────────────────────────────
|
|
151
|
-
|
|
152
|
-
/** The per-model type bag marcidb's generic `Query<T>` is parametrised by (what its codegen emits as `UserTypes`). */
|
|
153
|
-
export type Types<S, N extends keyof S> = {
|
|
154
|
-
name: N & string
|
|
155
|
-
model: Row<S, N>
|
|
156
|
-
id: Id<S, N>
|
|
157
|
-
scalars: ScalarSelect<S, N>
|
|
158
|
-
select: Select<S, N>
|
|
159
|
-
query: QueryObject<S, N>
|
|
160
|
-
where: Where<S, N>
|
|
161
|
-
order: Order<S, N>
|
|
162
|
-
insert: Insert<S, N>
|
|
163
|
-
update: Update<S, N>
|
|
164
|
-
aggregate: AggregateQuery<S, N>
|
|
165
|
-
reindex: false
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* `db.<model>` — marcidb's lazy, immutable query over one model: clauses (`where/order/limit/skip/after`)
|
|
170
|
-
* return a new query, `select(shape)` sets the projection, `await` runs it, `first/count/aggregate` terminate,
|
|
171
|
-
* `updateMany(data)`/`deleteMany()` write through the chain's `where`; a query placed in another query's
|
|
172
|
-
* select is a sub-query. `Sel` is the projection: id + scalars until `select(...)` sets a shape.
|
|
173
|
-
*/
|
|
174
|
-
export type Query<S, N extends keyof S, Sel = ScalarSelect<S, N>> = MarciQuery<Types<S, N>, Sel>
|
|
175
|
-
/** The rows a query with projection `Q` resolves to (no field keys = id + scalars; sub-queries resolved). */
|
|
176
|
-
export type Result<S, N extends keyof S, Q> = Rows<Types<S, N>, Q>
|
|
177
|
-
/** `db.<model>` — the root query of a model. */
|
|
178
|
-
export type Collection<S, N extends keyof S> = Query<S, N>
|
|
179
|
-
|
|
180
|
-
export type Db<S extends Schema> = {
|
|
181
|
-
[N in keyof S & string as Uncapitalize<N>]: Query<S, N>
|
|
182
|
-
} & {
|
|
183
|
-
/** Atomic batch: all ops commit or none. `ref("0.id")` feeds a generated id into a later op. */
|
|
184
|
-
$transaction<P extends readonly Op<any>[]>(ops: [...P]): Promise<{ [K in keyof P]: P[K] extends Op<infer T> ? T : never }>
|
|
185
|
-
/** The `.marci` schema text this db syncs with. */
|
|
186
|
-
readonly $schema: string
|
|
187
|
-
/** @internal */ readonly $models: Record<string, Model>
|
|
188
|
-
/** @internal which models the auth runtime binds to (`Session` always exists; `User` when declared). */
|
|
189
|
-
readonly $auth: AuthBinding
|
|
190
|
-
}
|
|
191
|
-
/** @internal */
|
|
192
|
-
export type AuthBinding = { user: string | null, session: string }
|
|
193
|
-
|
|
194
|
-
// ───────────────────────────── relation-name validation ─────────────────────────────
|
|
195
|
-
|
|
196
|
-
type RelKinds = "one" | "many" | "list"
|
|
197
|
-
type CheckField<S, Fld> =
|
|
198
|
-
MetaOf<Fld>["kind"] extends RelKinds
|
|
199
|
-
? MetaOf<Fld>["model"] extends keyof S ? Fld : `Unknown model "${MetaOf<Fld>["model"]}" — not a key of defineDb({...})`
|
|
200
|
-
: Fld
|
|
201
|
-
/** Intersected with `S` in `defineDb`'s parameter: an unknown relation target fails to type-check on that field. */
|
|
202
|
-
export type ValidateRefs<S extends Schema> = { [N in keyof S]: { readonly fields: { [K in keyof FieldsOf<S[N]>]: CheckField<S, FieldsOf<S[N]>[K]> } } }
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `throw new ApiError(404, "Not found")` inside an endpoint → the client's promise rejects with the
|
|
3
|
-
* same status + message. Any other throw is a 500 (message hidden, logged to the server console).
|
|
4
|
-
*/
|
|
5
|
-
export class ApiError extends Error {
|
|
6
|
-
readonly status: number
|
|
7
|
-
constructor(status: number, message = "") {
|
|
8
|
-
super(message)
|
|
9
|
-
this.name = "ApiError"
|
|
10
|
-
this.status = status
|
|
11
|
-
}
|
|
12
|
-
}
|