peta-orm 0.4.0 → 0.5.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 +51 -10
- package/dist/index.d.mts +576 -5
- package/dist/index.mjs +147 -6
- package/package.json +4 -11
- package/bin/peta +0 -3
- package/dist/index-BdJnSMYi.d.mts +0 -480
- package/dist/migrations/cli.d.mts +0 -4
- package/dist/migrations/cli.mjs +0 -74
- package/dist/migrations/index.d.mts +0 -53
- package/dist/migrations/index.mjs +0 -2
- package/dist/runner-DQ7uT6LC.mjs +0 -180
package/dist/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { a as getRawRelations, d as setExists, o as getState } from "./state-Ltl
|
|
|
7
7
|
import { a as setConfig$1, n as reloadModel, r as saveModel, t as getConfig$1 } from "./save-D5UKXvqC.mjs";
|
|
8
8
|
import { type } from "arktype";
|
|
9
9
|
import { Kysely, sql } from "kysely";
|
|
10
|
+
import { pathToFileURL } from "url";
|
|
10
11
|
import { ulid as ulid$1 } from "ulid";
|
|
11
12
|
//#region src/columns/arktype.ts
|
|
12
13
|
function createArkTypeSchemaConfig() {
|
|
@@ -189,7 +190,27 @@ function createColumn(schema, dataType, args = [], constraints = []) {
|
|
|
189
190
|
}
|
|
190
191
|
//#endregion
|
|
191
192
|
//#region src/columns/types.ts
|
|
192
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Pre-configured column type factory backed by ArkType validation.
|
|
195
|
+
*
|
|
196
|
+
* The most common usage — just import and use:
|
|
197
|
+
* ```ts
|
|
198
|
+
* import { t } from "peta-orm"
|
|
199
|
+
* const id = t.integer().primaryKey()
|
|
200
|
+
* ```
|
|
201
|
+
*
|
|
202
|
+
* For a custom validation backend, use `createColumnTypes({ schema })` instead.
|
|
203
|
+
*/
|
|
204
|
+
const t = createColumnTypes({ schema: createArkTypeSchemaConfig() });
|
|
205
|
+
/**
|
|
206
|
+
* Create a column type factory with a custom validation schema backend.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* const t = createColumnTypes({ schema: myCustomSchemaConfig })
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
function createColumnTypes(config) {
|
|
193
214
|
const schema = config.schema;
|
|
194
215
|
function col(dataType, args) {
|
|
195
216
|
return createColumn(schema, dataType, args);
|
|
@@ -217,6 +238,43 @@ function t(config) {
|
|
|
217
238
|
};
|
|
218
239
|
}
|
|
219
240
|
//#endregion
|
|
241
|
+
//#region src/init.ts
|
|
242
|
+
/**
|
|
243
|
+
* Create a lazy-initialized singleton factory.
|
|
244
|
+
*
|
|
245
|
+
* The factory function is called only once — on the first call to the returned
|
|
246
|
+
* function. Subsequent calls return the same resolved promise. This avoids
|
|
247
|
+
* module-level side effects: importing a model file won't trigger database
|
|
248
|
+
* connection or schema initialization until the first explicit `await db()`.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* import { createClient } from "@libsql/client"
|
|
253
|
+
* import { LibsqlDialect } from "@libsql/kysely-libsql"
|
|
254
|
+
* import { createDb, createORM, defineModel, t } from "peta-orm"
|
|
255
|
+
*
|
|
256
|
+
* const User = defineModel("users", { columns: { ... } })
|
|
257
|
+
*
|
|
258
|
+
* async function setup() {
|
|
259
|
+
* const client = createClient({ url: "file:my-app.db" })
|
|
260
|
+
* await client.execute("CREATE TABLE IF NOT EXISTS users (...)") // schema init
|
|
261
|
+
* const orm = createORM({ dialect: new LibsqlDialect({ client }) })
|
|
262
|
+
* orm.registerAll(User)
|
|
263
|
+
* return orm
|
|
264
|
+
* }
|
|
265
|
+
*
|
|
266
|
+
* export const db = createDb(setup)
|
|
267
|
+
* // Usage: const orm = await db()
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
function createDb(factory) {
|
|
271
|
+
let promise = null;
|
|
272
|
+
return () => {
|
|
273
|
+
if (!promise) promise = factory();
|
|
274
|
+
return promise;
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
//#endregion
|
|
220
278
|
//#region src/hooks/static.ts
|
|
221
279
|
var static_exports = /* @__PURE__ */ __exportAll({
|
|
222
280
|
addStaticHook: () => addStaticHook,
|
|
@@ -1483,9 +1541,6 @@ function defineModel(table, config) {
|
|
|
1483
1541
|
def.registerSoftDeletes = (deletedAtCol) => {
|
|
1484
1542
|
registerSoftDeletesFor(def, deletedAtCol);
|
|
1485
1543
|
};
|
|
1486
|
-
def.discover = async () => {
|
|
1487
|
-
throw new Error("discover() not yet implemented in v2");
|
|
1488
|
-
};
|
|
1489
1544
|
return def;
|
|
1490
1545
|
}
|
|
1491
1546
|
//#endregion
|
|
@@ -1895,9 +1950,14 @@ initRuntime({
|
|
|
1895
1950
|
/**
|
|
1896
1951
|
* Create an ORM instance — the central registry that wires Kysely to model definitions.
|
|
1897
1952
|
* Replaces createPeta() from v0.x.
|
|
1953
|
+
*
|
|
1954
|
+
* Pass either `dialect` (to auto-create a Kysely instance) or `kysely` (to reuse one).
|
|
1955
|
+
* Passing a pre-existing Kysely instance avoids creating a second connection for
|
|
1956
|
+
* migration runners or other tools that already have their own Kysely.
|
|
1898
1957
|
*/
|
|
1899
1958
|
function createORM(config) {
|
|
1900
|
-
|
|
1959
|
+
if (!config.dialect && !config.kysely) throw new Error("createORM: provide either `dialect` (to create a Kysely instance) or `kysely` (to reuse one)");
|
|
1960
|
+
const kysely = config.kysely ?? new Kysely({ dialect: config.dialect });
|
|
1901
1961
|
const modelMap = /* @__PURE__ */ new Map();
|
|
1902
1962
|
const orm = {
|
|
1903
1963
|
kysely,
|
|
@@ -1923,6 +1983,26 @@ function createORM(config) {
|
|
|
1923
1983
|
},
|
|
1924
1984
|
getModel(name) {
|
|
1925
1985
|
return modelMap.get(name);
|
|
1986
|
+
},
|
|
1987
|
+
async discover(pattern) {
|
|
1988
|
+
const entries = await (await import("fast-glob")).glob(pattern, {
|
|
1989
|
+
absolute: true,
|
|
1990
|
+
onlyFiles: true
|
|
1991
|
+
});
|
|
1992
|
+
if (entries.length === 0) throw new Error(`discover: no files matched pattern "${pattern}"`);
|
|
1993
|
+
const models = [];
|
|
1994
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1995
|
+
for (const fp of entries) {
|
|
1996
|
+
const mod = await import(pathToFileURL(fp).href);
|
|
1997
|
+
for (const val of Object.values(mod)) if (val && typeof val === "object" && "columns" in val && "table" in val && typeof val.table === "string" && val.table.length > 0) {
|
|
1998
|
+
const def = val;
|
|
1999
|
+
if (!seen.has(def.table)) {
|
|
2000
|
+
seen.add(def.table);
|
|
2001
|
+
models.push(def);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
return models;
|
|
1926
2006
|
}
|
|
1927
2007
|
};
|
|
1928
2008
|
if (config.models) for (const [_name, model] of Object.entries(config.models)) orm.register(model);
|
|
@@ -2601,4 +2681,65 @@ function defName(instance) {
|
|
|
2601
2681
|
return instance.constructor?.name ?? "model";
|
|
2602
2682
|
}
|
|
2603
2683
|
//#endregion
|
|
2604
|
-
|
|
2684
|
+
//#region src/repo/index.ts
|
|
2685
|
+
/**
|
|
2686
|
+
* Create a repository — a composable set of chainable query methods.
|
|
2687
|
+
*
|
|
2688
|
+
* ```ts
|
|
2689
|
+
* const userRepo = createRepo(User, {
|
|
2690
|
+
* queryMethods: {
|
|
2691
|
+
* search(q, query: string) {
|
|
2692
|
+
* return q.where('name', 'like', `%${query}%`)
|
|
2693
|
+
* },
|
|
2694
|
+
* },
|
|
2695
|
+
* })
|
|
2696
|
+
* const users = await userRepo.search('john').paginate(1, 20)
|
|
2697
|
+
* ```
|
|
2698
|
+
*/
|
|
2699
|
+
function createRepo(model, methods) {
|
|
2700
|
+
const customMethods = /* @__PURE__ */ new Map();
|
|
2701
|
+
if (methods.queryMethods) for (const [name, fn] of Object.entries(methods.queryMethods)) customMethods.set(name, fn);
|
|
2702
|
+
/**
|
|
2703
|
+
* Wrap a QueryBuilder so custom methods are available for chaining.
|
|
2704
|
+
* Custom methods operate on the CURRENT QB (not a fresh one), so
|
|
2705
|
+
* chaining carries forward previous conditions.
|
|
2706
|
+
*/
|
|
2707
|
+
function wrapQB(qb) {
|
|
2708
|
+
return new Proxy(qb, { get(target, prop) {
|
|
2709
|
+
if (typeof prop === "string") {
|
|
2710
|
+
if (customMethods.has(prop)) {
|
|
2711
|
+
const fn = customMethods.get(prop);
|
|
2712
|
+
return (...args) => {
|
|
2713
|
+
return wrapQB(fn(target, ...args));
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
if (methods.methods?.[prop]) return (...args) => methods.methods[prop](...args);
|
|
2717
|
+
}
|
|
2718
|
+
const val = target[prop];
|
|
2719
|
+
if (typeof val === "function") return function(...args) {
|
|
2720
|
+
const result = val.apply(target, args);
|
|
2721
|
+
return result === target ? wrapQB(result) : result;
|
|
2722
|
+
};
|
|
2723
|
+
return val;
|
|
2724
|
+
} });
|
|
2725
|
+
}
|
|
2726
|
+
return new Proxy({}, { get(_target, prop) {
|
|
2727
|
+
if (typeof prop === "string") {
|
|
2728
|
+
if (customMethods.has(prop)) {
|
|
2729
|
+
const fn = customMethods.get(prop);
|
|
2730
|
+
return (...args) => {
|
|
2731
|
+
return wrapQB(fn(model.query(), ...args));
|
|
2732
|
+
};
|
|
2733
|
+
}
|
|
2734
|
+
if (methods.methods?.[prop]) return (...args) => methods.methods[prop](...args);
|
|
2735
|
+
}
|
|
2736
|
+
const qb = model.query();
|
|
2737
|
+
const val = qb[prop];
|
|
2738
|
+
if (typeof val === "function") return (...args) => {
|
|
2739
|
+
return wrapQB(val.apply(qb, args));
|
|
2740
|
+
};
|
|
2741
|
+
return val;
|
|
2742
|
+
} });
|
|
2743
|
+
}
|
|
2744
|
+
//#endregion
|
|
2745
|
+
export { Attribute, DatabaseError, ModelNotFoundError, ModelNotRegisteredError, RelationNotAllowedError, RelationNotFoundError, ValidationError, belongsTo, createArkTypeSchemaConfig, createCollection, createColumn, createColumnTypes, createDb, createHookManager, createORM, createORM as createPeta, createPaginator, createQueryBuilder, createRepo, defineModel, defineMorphMany, defineMorphOne, defineMorphTo, hasMany, hasManyThrough, hasOne, eager_exports as i, manyToMany, relation_exports as n, normalizeError, delete_exports as r, resolveMorphRelation, softDeletes, t, timestamps, ulid };
|
package/package.json
CHANGED
|
@@ -2,31 +2,23 @@
|
|
|
2
2
|
"name": "peta-orm",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.5.0",
|
|
6
6
|
"description": "ORM for Bun, built on Kysely",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/zfadhli/peta-stack.git"
|
|
11
11
|
},
|
|
12
|
-
"module": "
|
|
12
|
+
"module": "./dist/index.mjs",
|
|
13
13
|
"main": "./dist/index.mjs",
|
|
14
14
|
"types": "./dist/index.d.mts",
|
|
15
15
|
"exports": {
|
|
16
16
|
".": {
|
|
17
17
|
"import": "./dist/index.mjs",
|
|
18
18
|
"types": "./dist/index.d.mts"
|
|
19
|
-
},
|
|
20
|
-
"./migrator": {
|
|
21
|
-
"import": "./dist/migrations/index.mjs",
|
|
22
|
-
"types": "./dist/migrations/index.d.mts"
|
|
23
19
|
}
|
|
24
20
|
},
|
|
25
|
-
"bin": {
|
|
26
|
-
"peta": "./bin/peta"
|
|
27
|
-
},
|
|
28
21
|
"files": [
|
|
29
|
-
"bin/",
|
|
30
22
|
"dist/",
|
|
31
23
|
"README.md",
|
|
32
24
|
"LICENSE"
|
|
@@ -34,6 +26,7 @@
|
|
|
34
26
|
"dependencies": {
|
|
35
27
|
"arktype": "^2.2.0",
|
|
36
28
|
"cac": "^7.0.0",
|
|
29
|
+
"fast-glob": "^3.3.3",
|
|
37
30
|
"ora": "^9.4.0",
|
|
38
31
|
"ulid": "^3.0.2"
|
|
39
32
|
},
|
|
@@ -63,6 +56,6 @@
|
|
|
63
56
|
"build": "tsdown",
|
|
64
57
|
"lint": "bunx biome check src test examples",
|
|
65
58
|
"lint:fix": "bunx biome check --write --unsafe src test examples",
|
|
66
|
-
"
|
|
59
|
+
"prepublishOnly": "bun run build"
|
|
67
60
|
}
|
|
68
61
|
}
|
package/bin/peta
DELETED