@atscript/db 0.1.38 → 0.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -303
- package/dist/agg.cjs +8 -3
- package/dist/agg.d.cts +7 -0
- package/dist/agg.d.mts +7 -0
- package/dist/agg.mjs +7 -3
- package/dist/control-DRgryKeg.cjs +14 -0
- package/dist/{control_as-bjmwe24C.mjs → control-IANbnfjG.mjs} +6 -18
- package/dist/db-readable-BQQzfguJ.d.cts +1249 -0
- package/dist/db-readable-Bbr4CjMb.d.mts +1249 -0
- package/dist/db-space-BUrQ5BFm.d.mts +309 -0
- package/dist/db-space-Vxpcnyt5.d.cts +309 -0
- package/dist/db-validator-plugin-07kDiis2.d.cts +22 -0
- package/dist/db-validator-plugin-CiqsHTI_.d.mts +22 -0
- package/dist/db-view-BntnAmXO.cjs +3071 -0
- package/dist/db-view-ZsoN91-q.mjs +2970 -0
- package/dist/index.cjs +95 -2801
- package/dist/index.d.cts +137 -0
- package/dist/index.d.mts +137 -0
- package/dist/index.mjs +55 -2761
- package/dist/{nested-writer-BkqL7cp3.cjs → nested-writer-BDXsDMPP.cjs} +196 -150
- package/dist/{nested-writer-NEN51mnR.mjs → nested-writer-Dmm1gbZV.mjs} +118 -70
- package/dist/ops-BdRAFLKY.d.mts +67 -0
- package/dist/ops-DXJ4Zw0P.d.cts +67 -0
- package/dist/ops.cjs +123 -0
- package/dist/ops.d.cts +2 -0
- package/dist/ops.d.mts +2 -0
- package/dist/ops.mjs +112 -0
- package/dist/plugin.cjs +90 -109
- package/dist/plugin.d.cts +6 -0
- package/dist/plugin.d.mts +6 -0
- package/dist/plugin.mjs +29 -49
- package/dist/rel.cjs +20 -20
- package/dist/rel.d.cts +119 -0
- package/dist/rel.d.mts +119 -0
- package/dist/rel.mjs +4 -5
- package/dist/{relation-helpers-guFL_oRf.cjs → relation-helpers-BYvsE1tR.cjs} +26 -22
- package/dist/{relation-helpers-DyBIlQnB.mjs → relation-helpers-CLasawQq.mjs} +11 -6
- package/dist/{relation-loader-Dv7qXYq7.mjs → relation-loader-BEOTXNcq.mjs} +63 -43
- package/dist/{relation-loader-CpnDRf9k.cjs → relation-loader-CRC5LcqM.cjs} +74 -49
- package/dist/shared.cjs +13 -13
- package/dist/{shared.d.ts → shared.d.cts} +14 -13
- package/dist/shared.d.mts +71 -0
- package/dist/shared.mjs +2 -3
- package/dist/sync.cjs +300 -252
- package/dist/sync.d.cts +369 -0
- package/dist/sync.d.mts +369 -0
- package/dist/sync.mjs +284 -233
- package/dist/{validation-utils-DEoCMmEb.cjs → validation-utils-DVJDijnB.cjs} +141 -109
- package/dist/{validation-utils-DhR_mtKa.mjs → validation-utils-DhjIjP1-.mjs} +71 -37
- package/package.json +31 -30
- package/LICENSE +0 -21
- package/dist/agg-BJFJ3dFQ.mjs +0 -8
- package/dist/agg-DnUWAOK8.cjs +0 -14
- package/dist/agg.d.ts +0 -13
- package/dist/chunk-CrpGerW8.cjs +0 -31
- package/dist/control_as-BFPERAF_.cjs +0 -28
- package/dist/index.d.ts +0 -1706
- package/dist/logger-B7oxCfLQ.mjs +0 -12
- package/dist/logger-Dt2v_-wb.cjs +0 -18
- package/dist/plugin.d.ts +0 -5
- package/dist/rel.d.ts +0 -1305
- package/dist/relation-loader-D4mTw6yH.cjs +0 -4
- package/dist/relation-loader-Ggy1ujwR.mjs +0 -4
- package/dist/sync.d.ts +0 -1878
package/README.md
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://atscript.dev/logo.svg" alt="Atscript" width="120" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">@atscript/db</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Define your models once</strong> — get TypeScript types, runtime validation, and DB metadata from a single <code>.as</code> model.
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://db.atscript.dev">Documentation</a> · <a href="https://db.atscript.dev/guide/">Database Guide</a>
|
|
13
|
+
</p>
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
- **`BaseDbAdapter`** — an abstract class that adapter authors extend to connect any database (MongoDB, SQLite, MySQL, PostgreSQL, etc.).
|
|
15
|
+
---
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## Architecture
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
AtscriptDbTable ──delegates CRUD──▶ BaseDbAdapter
|
|
18
|
-
◀──reads metadata── (via this._table)
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
**One adapter per table.** The adapter gets a back-reference to the table instance via `registerTable()`, giving it full access to computed metadata (flatMap, indexes, primaryKeys, columnMap, etc.) for internal use in query rendering, index sync, and other adapter-specific logic.
|
|
17
|
+
Generic database abstraction layer for Atscript. Provides unified CRUD, relations, views, aggregations, and schema sync — all driven by `@db.*` annotations in your `.as` models. Pluggable adapters connect any database engine (SQLite, PostgreSQL, MongoDB, MySQL).
|
|
22
18
|
|
|
23
19
|
## Installation
|
|
24
20
|
|
|
@@ -26,318 +22,61 @@ AtscriptDbTable ──delegates CRUD──▶ BaseDbAdapter
|
|
|
26
22
|
pnpm add @atscript/db
|
|
27
23
|
```
|
|
28
24
|
|
|
29
|
-
Peer dependencies: `@atscript/core`, `@atscript/typescript`.
|
|
30
|
-
|
|
31
25
|
## Quick Start
|
|
32
26
|
|
|
33
|
-
### 1. Define your type in Atscript (`.as` file)
|
|
34
|
-
|
|
35
27
|
```atscript
|
|
36
28
|
@db.table "users"
|
|
37
|
-
@db.schema "auth"
|
|
38
29
|
interface User {
|
|
39
30
|
@meta.id
|
|
31
|
+
@db.default.increment
|
|
40
32
|
id: number
|
|
41
33
|
|
|
42
34
|
@db.index.unique "email_idx"
|
|
43
|
-
@db.column "email_address"
|
|
44
35
|
email: string
|
|
45
36
|
|
|
46
|
-
@db.index.plain "name_idx"
|
|
47
37
|
name: string
|
|
48
|
-
|
|
49
|
-
@db.default "active"
|
|
50
|
-
status: string
|
|
51
|
-
|
|
52
|
-
@db.ignore
|
|
53
|
-
displayName?: string
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### 2. Create an adapter and table
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
import { AtscriptDbTable } from '@atscript/db'
|
|
61
|
-
import { MyAdapter } from './my-adapter'
|
|
62
|
-
import { User } from './user.as'
|
|
63
|
-
|
|
64
|
-
const adapter = new MyAdapter(/* db connection */)
|
|
65
|
-
const users = new AtscriptDbTable(User, adapter)
|
|
66
|
-
|
|
67
|
-
// CRUD operations
|
|
68
|
-
await users.insertOne({ name: 'John', email: 'john@example.com' })
|
|
69
|
-
await users.findMany({ status: 'active' }, { limit: 10 })
|
|
70
|
-
await users.deleteOne(123)
|
|
71
|
-
await users.syncIndexes()
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Writing a Database Adapter
|
|
75
|
-
|
|
76
|
-
Extend `BaseDbAdapter` and implement the abstract methods. The adapter receives a back-reference to the `AtscriptDbTable` instance — use `this._table` to access all computed metadata.
|
|
77
|
-
|
|
78
|
-
### Minimal adapter
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
import {
|
|
82
|
-
BaseDbAdapter,
|
|
83
|
-
type TDbFilter,
|
|
84
|
-
type TDbFindOptions,
|
|
85
|
-
type TDbInsertResult,
|
|
86
|
-
type TDbInsertManyResult,
|
|
87
|
-
type TDbUpdateResult,
|
|
88
|
-
type TDbDeleteResult,
|
|
89
|
-
} from '@atscript/db'
|
|
90
|
-
|
|
91
|
-
class SqliteAdapter extends BaseDbAdapter {
|
|
92
|
-
constructor(private db: SqliteDatabase) {
|
|
93
|
-
super()
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Access table metadata via this._table:
|
|
97
|
-
// this._table.tableName — resolved table name
|
|
98
|
-
// this._table.schema — database schema/namespace
|
|
99
|
-
// this._table.flatMap — Map<string, TAtscriptAnnotatedType>
|
|
100
|
-
// this._table.indexes — Map<string, TDbIndex>
|
|
101
|
-
// this._table.primaryKeys — readonly string[]
|
|
102
|
-
// this._table.columnMap — Map<string, string> (logical → physical)
|
|
103
|
-
// this._table.defaults — Map<string, TDbDefaultValue>
|
|
104
|
-
// this._table.ignoredFields — Set<string>
|
|
105
|
-
// this._table.uniqueProps — Set<string>
|
|
106
|
-
|
|
107
|
-
async insertOne(data: Record<string, unknown>): Promise<TDbInsertResult> {
|
|
108
|
-
const table = this._table.tableName
|
|
109
|
-
const keys = Object.keys(data)
|
|
110
|
-
const placeholders = keys.map(() => '?').join(', ')
|
|
111
|
-
const sql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`
|
|
112
|
-
const result = this.db.run(sql, Object.values(data))
|
|
113
|
-
return { insertedId: result.lastInsertRowid }
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async insertMany(data: Record<string, unknown>[]): Promise<TDbInsertManyResult> {
|
|
117
|
-
const ids: unknown[] = []
|
|
118
|
-
for (const row of data) {
|
|
119
|
-
const result = await this.insertOne(row)
|
|
120
|
-
ids.push(result.insertedId)
|
|
121
|
-
}
|
|
122
|
-
return { insertedCount: ids.length, insertedIds: ids }
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async findOne(
|
|
126
|
-
filter: TDbFilter,
|
|
127
|
-
options?: TDbFindOptions
|
|
128
|
-
): Promise<Record<string, unknown> | null> {
|
|
129
|
-
const { sql, params } = this.buildSelect(filter, { ...options, limit: 1 })
|
|
130
|
-
return this.db.get(sql, params) ?? null
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async findMany(
|
|
134
|
-
filter: TDbFilter,
|
|
135
|
-
options?: TDbFindOptions
|
|
136
|
-
): Promise<Record<string, unknown>[]> {
|
|
137
|
-
const { sql, params } = this.buildSelect(filter, options)
|
|
138
|
-
return this.db.all(sql, params)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async updateOne(
|
|
142
|
-
filter: TDbFilter,
|
|
143
|
-
data: Record<string, unknown>
|
|
144
|
-
): Promise<TDbUpdateResult> {
|
|
145
|
-
// ... build UPDATE ... SET ... WHERE ...
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async replaceOne(
|
|
149
|
-
filter: TDbFilter,
|
|
150
|
-
data: Record<string, unknown>
|
|
151
|
-
): Promise<TDbUpdateResult> {
|
|
152
|
-
// ... INSERT OR REPLACE ...
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async deleteOne(filter: TDbFilter): Promise<TDbDeleteResult> {
|
|
156
|
-
// ... DELETE FROM ... WHERE ...
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async count(filter: TDbFilter): Promise<number> {
|
|
160
|
-
// ... SELECT COUNT(*) ...
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async updateMany(filter: TDbFilter, data: Record<string, unknown>): Promise<TDbUpdateResult> {
|
|
164
|
-
// ... UPDATE ... SET ... WHERE ...
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async replaceMany(filter: TDbFilter, data: Record<string, unknown>): Promise<TDbUpdateResult> {
|
|
168
|
-
// ... batch replace ...
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async deleteMany(filter: TDbFilter): Promise<TDbDeleteResult> {
|
|
172
|
-
// ... DELETE FROM ... WHERE ...
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async syncIndexes(): Promise<void> {
|
|
176
|
-
// Read this._table.indexes and CREATE INDEX / DROP INDEX as needed
|
|
177
|
-
for (const [key, index] of this._table.indexes) {
|
|
178
|
-
const cols = index.fields.map(f =>
|
|
179
|
-
`${f.name} ${f.sort === 'desc' ? 'DESC' : 'ASC'}`
|
|
180
|
-
).join(', ')
|
|
181
|
-
const unique = index.type === 'unique' ? 'UNIQUE' : ''
|
|
182
|
-
this.db.run(
|
|
183
|
-
`CREATE ${unique} INDEX IF NOT EXISTS ${index.name}
|
|
184
|
-
ON ${this._table.tableName} (${cols})`
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async ensureTable(): Promise<void> {
|
|
190
|
-
// Use this._table.flatMap, primaryKeys, etc. to build CREATE TABLE
|
|
191
|
-
}
|
|
192
38
|
}
|
|
193
39
|
```
|
|
194
40
|
|
|
195
|
-
### Adapter hooks
|
|
196
|
-
|
|
197
|
-
Override these optional methods to process adapter-specific annotations during field scanning:
|
|
198
|
-
|
|
199
|
-
| Hook | When it runs | Use case |
|
|
200
|
-
|---|---|---|
|
|
201
|
-
| `onBeforeFlatten(type)` | Before field scanning begins | Extract table-level adapter annotations |
|
|
202
|
-
| `onFieldScanned(field, type, metadata)` | For each field during scanning | Extract field-level adapter annotations |
|
|
203
|
-
| `onAfterFlatten()` | After all fields are scanned | Finalize adapter-specific computed state |
|
|
204
|
-
| `getAdapterTableName(type)` | During constructor | Return adapter-specific table name (e.g., from `@db.mongo.collection`) |
|
|
205
|
-
| `getTopLevelArrayTag()` | During flatten | Return custom tag for top-level array detection |
|
|
206
|
-
|
|
207
|
-
### Overridable behaviors
|
|
208
|
-
|
|
209
|
-
| Method | Default | Override to... |
|
|
210
|
-
|---|---|---|
|
|
211
|
-
| `prepareId(id, fieldType)` | passthrough | Convert string → ObjectId, parse UUIDs, etc. |
|
|
212
|
-
| `getValidatorPlugins()` | `[]` | Add adapter-specific validation (e.g., ObjectId format) |
|
|
213
|
-
| `supportsNativePatch()` | `false` | Enable native array patch operations |
|
|
214
|
-
| `nativePatch(filter, patch)` | throws | Implement native patch (e.g., MongoDB `$push`/`$pull`) |
|
|
215
|
-
|
|
216
|
-
## What `AtscriptDbTable` Does For You
|
|
217
|
-
|
|
218
|
-
When you call `insertOne(payload)`, the table automatically:
|
|
219
|
-
|
|
220
|
-
1. **Flattens** the annotated type (lazy, cached) — extracts all fields, indexes, metadata
|
|
221
|
-
2. **Applies defaults** — fills `@db.default` fields that are missing
|
|
222
|
-
3. **Validates** — runs Atscript validators + adapter plugins
|
|
223
|
-
4. **Prepares IDs** — calls `adapter.prepareId()` on primary key fields
|
|
224
|
-
5. **Strips ignored fields** — removes `@db.ignore` fields
|
|
225
|
-
6. **Maps columns** — renames `@db.column` logical names to physical names
|
|
226
|
-
7. **Delegates** — calls `adapter.insertOne()` with the cleaned data
|
|
227
|
-
|
|
228
|
-
For `updateOne()`, it additionally:
|
|
229
|
-
- Extracts a filter from primary key fields in the payload
|
|
230
|
-
- Routes to `adapter.nativePatch()` if supported, otherwise decomposes the patch generically
|
|
231
|
-
|
|
232
|
-
## Supported Annotations
|
|
233
|
-
|
|
234
|
-
These `@db.*` annotations are defined in `@atscript/core` and processed by `AtscriptDbTable`:
|
|
235
|
-
|
|
236
|
-
| Annotation | Level | Purpose |
|
|
237
|
-
|---|---|---|
|
|
238
|
-
| `@db.table "name"` | Interface | Table/collection name |
|
|
239
|
-
| `@db.schema "name"` | Interface | Database schema/namespace |
|
|
240
|
-
| `@meta.id` | Field | Marks primary key (no args; multiple = composite key) |
|
|
241
|
-
| `@db.column "name"` | Field | Physical column name override |
|
|
242
|
-
| `@db.default "val"` | Field | Default value on insert |
|
|
243
|
-
| `@db.default.increment` | Field | Auto-incrementing integer default |
|
|
244
|
-
| `@db.default.uuid` | Field | UUID generation default |
|
|
245
|
-
| `@db.default.now` | Field | Current timestamp default |
|
|
246
|
-
| `@db.ignore` | Field | Exclude from database operations |
|
|
247
|
-
| `@db.index.plain "name"` | Field | B-tree index (optional sort: `"name", "desc"`) |
|
|
248
|
-
| `@db.index.unique "name"` | Field | Unique index |
|
|
249
|
-
| `@db.index.fulltext "name"` | Field | Full-text search index |
|
|
250
|
-
| `@db.json` | Field | Store as a single JSON column (skip flattening) |
|
|
251
|
-
|
|
252
|
-
Multiple fields with the same index name form a **composite index**.
|
|
253
|
-
|
|
254
|
-
## Type-Safe Queries with `__flat`
|
|
255
|
-
|
|
256
|
-
Interfaces annotated with `@db.table` get a `__flat` static property in the generated `.d.ts` file, mapping all dot-notation paths to their value types. This enables autocomplete and type checking for filter expressions and `$select`/`$sort` operations.
|
|
257
|
-
|
|
258
|
-
Use `FlatOf<T>` to extract the flat type:
|
|
259
|
-
|
|
260
41
|
```typescript
|
|
261
|
-
import
|
|
42
|
+
import { DbSpace } from "@atscript/db";
|
|
43
|
+
import { createAdapter } from "@atscript/db-sqlite";
|
|
262
44
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
`AtscriptDbTable` uses `FlatOf<T>` as the type parameter for query methods (`findOne`, `findMany`, `count`, `updateMany`, `replaceMany`, `deleteMany`), giving you autocomplete on filter keys and select paths. When `__flat` is not present (no `@db.table`), `FlatOf<T>` falls back to the regular data shape — fully backward-compatible.
|
|
268
|
-
|
|
269
|
-
### `$select` Parent Path Expansion
|
|
270
|
-
|
|
271
|
-
Selecting a parent object path (e.g., `$select: ['contact']`) automatically expands to all its leaf physical columns for relational databases. Sorting by parent paths is silently ignored.
|
|
272
|
-
|
|
273
|
-
## Cross-Cutting Concerns
|
|
274
|
-
|
|
275
|
-
Since `AtscriptDbTable` is concrete, extend it for cross-cutting concerns that work with any adapter:
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
class SecureDbTable extends AtscriptDbTable {
|
|
279
|
-
constructor(type, adapter, private permissions: PermissionConfig) {
|
|
280
|
-
super(type, adapter)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
async insertOne(payload) {
|
|
284
|
-
this.checkPermission('write', payload)
|
|
285
|
-
return super.insertOne(payload)
|
|
286
|
-
}
|
|
45
|
+
const db = createAdapter("./myapp.db");
|
|
46
|
+
const users = db.getTable(User);
|
|
287
47
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
return result ? this.filterFields(result, 'read') : null
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Works with any adapter:
|
|
295
|
-
const secureUsers = new SecureDbTable(User, new MongoAdapter(db), perms)
|
|
296
|
-
const secureOrders = new SecureDbTable(Order, new SqliteAdapter(db), perms)
|
|
48
|
+
await users.insertOne({ name: "John", email: "john@example.com" });
|
|
49
|
+
const all = await users.findMany({ filter: { name: { $eq: "John" } } });
|
|
297
50
|
```
|
|
298
51
|
|
|
299
|
-
##
|
|
300
|
-
|
|
301
|
-
For fields that are arrays of objects, `updateOne()` supports structured patch operators:
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
await users.updateOne({
|
|
305
|
-
id: 123,
|
|
306
|
-
tags: {
|
|
307
|
-
$insert: [{ name: 'new-tag' }], // append items
|
|
308
|
-
$upsert: [{ name: 'existing', value: 1 }], // insert or replace by key
|
|
309
|
-
$update: [{ name: 'existing', value: 2 }], // partial update by key
|
|
310
|
-
$remove: [{ name: 'old-tag' }], // remove by key
|
|
311
|
-
$replace: [/* full replacement */], // replace entire array
|
|
312
|
-
}
|
|
313
|
-
})
|
|
314
|
-
```
|
|
52
|
+
## Sub-entries
|
|
315
53
|
|
|
316
|
-
|
|
54
|
+
| Entry | Purpose |
|
|
55
|
+
| --------------------- | -------------------------------------------------------- |
|
|
56
|
+
| `@atscript/db/plugin` | `dbPlugin()` — registers all `@db.*` annotations |
|
|
57
|
+
| `@atscript/db/rel` | Relation loading and nested writes |
|
|
58
|
+
| `@atscript/db/agg` | Aggregation query validation |
|
|
59
|
+
| `@atscript/db/sync` | Schema sync with drift detection and distributed locking |
|
|
60
|
+
| `@atscript/db/shared` | Annotation helpers for adapter plugins |
|
|
317
61
|
|
|
318
|
-
##
|
|
62
|
+
## Features
|
|
319
63
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
64
|
+
- Annotation-driven schema: table names, indexes, column mappings, defaults, primary keys
|
|
65
|
+
- Pluggable adapters via `BaseDbAdapter` — same code works with any database
|
|
66
|
+
- Automatic write pipeline: defaults, validation, ID preparation, column mapping
|
|
67
|
+
- Embedded object flattening (`__`-separated columns) and `@db.json` storage
|
|
68
|
+
- Relations: `@db.rel.to`, `@db.rel.from`, `@db.rel.via` with nested writes
|
|
69
|
+
- Views: `@db.view` with joins, filters, materialized views, aggregation
|
|
70
|
+
- Schema sync: FNV-1a hash drift detection, distributed locking, column/table renames
|
|
71
|
+
- Array patch operations: `$insert`, `$upsert`, `$update`, `$remove`, `$replace`
|
|
72
|
+
- Type-safe queries with `FlatOf<T>` for autocomplete on filters and projections
|
|
324
73
|
|
|
325
|
-
|
|
326
|
-
export { decomposePatch } from './patch-decomposer'
|
|
327
|
-
export { getKeyProps } from './patch-types'
|
|
74
|
+
## Documentation
|
|
328
75
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
TDbFilter, TDbFindOptions,
|
|
333
|
-
TDbInsertResult, TDbInsertManyResult, TDbUpdateResult, TDbDeleteResult,
|
|
334
|
-
TDbIndex, TDbIndexField, TDbDefaultValue, TIdDescriptor, TDbFieldMeta,
|
|
335
|
-
TArrayPatch, TDbPatch,
|
|
336
|
-
} from './types'
|
|
337
|
-
export type { TGenericLogger } from './logger'
|
|
338
|
-
export { NoopLogger } from './logger'
|
|
339
|
-
```
|
|
76
|
+
- [Database Guide](https://db.atscript.dev/guide/)
|
|
77
|
+
- [API & Annotations](https://db.atscript.dev/api/tables)
|
|
78
|
+
- [Full Documentation](https://db.atscript.dev)
|
|
340
79
|
|
|
341
80
|
## License
|
|
342
81
|
|
|
343
|
-
|
|
82
|
+
MIT
|
package/dist/agg.cjs
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/agg.ts
|
|
3
|
+
/** Resolves output alias: $as if provided, otherwise `{fn}_{field}`. */
|
|
4
|
+
function resolveAlias(expr) {
|
|
5
|
+
return expr.$as ?? `${expr.$fn}_${expr.$field}`;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
exports.resolveAlias = resolveAlias;
|
package/dist/agg.d.cts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AggregateControls, AggregateExpr, AggregateExpr as AggregateExpr$1, AggregateFn, AggregateQuery, AggregateResult } from "@uniqu/core";
|
|
2
|
+
|
|
3
|
+
//#region src/agg.d.ts
|
|
4
|
+
/** Resolves output alias: $as if provided, otherwise `{fn}_{field}`. */
|
|
5
|
+
declare function resolveAlias(expr: AggregateExpr$1): string;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, resolveAlias };
|
package/dist/agg.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AggregateControls, AggregateExpr, AggregateExpr as AggregateExpr$1, AggregateFn, AggregateQuery, AggregateResult } from "@uniqu/core";
|
|
2
|
+
|
|
3
|
+
//#region src/agg.d.ts
|
|
4
|
+
/** Resolves output alias: $as if provided, otherwise `{fn}_{field}`. */
|
|
5
|
+
declare function resolveAlias(expr: AggregateExpr$1): string;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, resolveAlias };
|
package/dist/agg.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
//#region src/agg.ts
|
|
2
|
+
/** Resolves output alias: $as if provided, otherwise `{fn}_{field}`. */
|
|
3
|
+
function resolveAlias(expr) {
|
|
4
|
+
return expr.$as ?? `${expr.$fn}_${expr.$field}`;
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { resolveAlias };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
let _atscript_typescript_utils = require("@atscript/typescript/utils");
|
|
2
|
+
//#region src/schema/control.as
|
|
3
|
+
var AtscriptControl = class {
|
|
4
|
+
static __is_atscript_annotated_type = true;
|
|
5
|
+
static type = {};
|
|
6
|
+
static metadata = /* @__PURE__ */ new Map();
|
|
7
|
+
static id = "AtscriptControl";
|
|
8
|
+
static toJsonSchema() {
|
|
9
|
+
(0, _atscript_typescript_utils.throwFeatureDisabled)("JSON Schema", "jsonSchema", "emit.jsonSchema");
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
(0, _atscript_typescript_utils.defineAnnotatedType)("object", AtscriptControl).prop("_id", (0, _atscript_typescript_utils.defineAnnotatedType)().designType("string").tags("string").annotate("meta.id", true).$type).prop("value", (0, _atscript_typescript_utils.defineAnnotatedType)().designType("string").tags("string").optional().$type).prop("lockedBy", (0, _atscript_typescript_utils.defineAnnotatedType)().designType("string").tags("string").optional().$type).prop("lockedAt", (0, _atscript_typescript_utils.defineAnnotatedType)().designType("number").tags("number").optional().$type).prop("expiresAt", (0, _atscript_typescript_utils.defineAnnotatedType)().designType("number").tags("number").optional().$type).annotate("db.table", "__atscript_control");
|
|
13
|
+
//#endregion
|
|
14
|
+
exports.AtscriptControl = AtscriptControl;
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
import { defineAnnotatedType, throwFeatureDisabled } from "@atscript/typescript/utils";
|
|
2
|
-
|
|
3
|
-
//#region packages/db/src/schema/control.as.js
|
|
4
|
-
function _define_property(obj, key, value) {
|
|
5
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
6
|
-
value,
|
|
7
|
-
enumerable: true,
|
|
8
|
-
configurable: true,
|
|
9
|
-
writable: true
|
|
10
|
-
});
|
|
11
|
-
else obj[key] = value;
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
2
|
+
//#region src/schema/control.as
|
|
14
3
|
var AtscriptControl = class {
|
|
4
|
+
static __is_atscript_annotated_type = true;
|
|
5
|
+
static type = {};
|
|
6
|
+
static metadata = /* @__PURE__ */ new Map();
|
|
7
|
+
static id = "AtscriptControl";
|
|
15
8
|
static toJsonSchema() {
|
|
16
9
|
throwFeatureDisabled("JSON Schema", "jsonSchema", "emit.jsonSchema");
|
|
17
10
|
}
|
|
18
11
|
};
|
|
19
|
-
_define_property(AtscriptControl, "__is_atscript_annotated_type", true);
|
|
20
|
-
_define_property(AtscriptControl, "type", {});
|
|
21
|
-
_define_property(AtscriptControl, "metadata", new Map());
|
|
22
|
-
_define_property(AtscriptControl, "id", "AtscriptControl");
|
|
23
12
|
defineAnnotatedType("object", AtscriptControl).prop("_id", defineAnnotatedType().designType("string").tags("string").annotate("meta.id", true).$type).prop("value", defineAnnotatedType().designType("string").tags("string").optional().$type).prop("lockedBy", defineAnnotatedType().designType("string").tags("string").optional().$type).prop("lockedAt", defineAnnotatedType().designType("number").tags("number").optional().$type).prop("expiresAt", defineAnnotatedType().designType("number").tags("number").optional().$type).annotate("db.table", "__atscript_control");
|
|
24
|
-
|
|
25
13
|
//#endregion
|
|
26
|
-
export { AtscriptControl };
|
|
14
|
+
export { AtscriptControl };
|