@bunyad/orm 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/casts.d.ts +50 -0
- package/dist/casts.js +309 -0
- package/dist/concerns.d.ts +64 -0
- package/dist/concerns.js +216 -0
- package/dist/decorators.d.ts +7 -0
- package/dist/decorators.js +12 -0
- package/dist/eager-fetch.d.ts +7 -0
- package/dist/eager-fetch.js +38 -0
- package/dist/eager.d.ts +24 -0
- package/dist/eager.js +854 -0
- package/dist/factory.d.ts +68 -0
- package/dist/factory.js +265 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -0
- package/dist/model-events.d.ts +43 -0
- package/dist/model-events.js +138 -0
- package/dist/model-helpers.d.ts +32 -0
- package/dist/model-helpers.js +99 -0
- package/dist/model-query.d.ts +312 -0
- package/dist/model-query.js +3170 -0
- package/dist/model-strictness.d.ts +35 -0
- package/dist/model-strictness.js +114 -0
- package/dist/model.d.ts +490 -0
- package/dist/model.js +1931 -0
- package/dist/orm-collection.d.ts +37 -0
- package/dist/orm-collection.js +150 -0
- package/dist/pivot.d.ts +9 -0
- package/dist/pivot.js +9 -0
- package/dist/relations.d.ts +335 -0
- package/dist/relations.js +1164 -0
- package/dist/scopes.d.ts +36 -0
- package/dist/scopes.js +128 -0
- package/package.json +49 -0
package/dist/scopes.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ModelQuery } from "./model.js";
|
|
2
|
+
export type GlobalScopeCallback = (query: ModelQuery) => void;
|
|
3
|
+
type ModelClassLike = abstract new (...args: never[]) => unknown;
|
|
4
|
+
/** Register a named global scope on a model class. */
|
|
5
|
+
export declare function addGlobalScope(model: ModelClassLike, name: string, scope: GlobalScopeCallback): void;
|
|
6
|
+
/** Remove a named global scope from a model class. */
|
|
7
|
+
export declare function removeGlobalScope(model: ModelClassLike, name: string): void;
|
|
8
|
+
/** All registered global scopes for a model class. */
|
|
9
|
+
export declare function getGlobalScopes(model: ModelClassLike): Map<string, GlobalScopeCallback>;
|
|
10
|
+
export declare function hasGlobalScopes(model: ModelClassLike): boolean;
|
|
11
|
+
/** Clear scopes (tests). */
|
|
12
|
+
export declare function clearGlobalScopes(model?: ModelClassLike): void;
|
|
13
|
+
type CallStaticModel = {
|
|
14
|
+
newQuery(): ModelQuery;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Safe ModelQuery terminals forwarded by Model `__callStatic`
|
|
18
|
+
* (`Model.get()` → `Model.query().get()`).
|
|
19
|
+
*
|
|
20
|
+
* Allowlist only — avoid constructors, `then`, starters already owned as
|
|
21
|
+
* Model statics, and arbitrary junk. Own Model / subclass statics always win
|
|
22
|
+
* over this Proxy. Local `scopeFoo` still wins when present.
|
|
23
|
+
*
|
|
24
|
+
* @see https://laravel.com/docs/eloquent#retrieving-models
|
|
25
|
+
*/
|
|
26
|
+
export declare const MODEL_STATIC_BUILDER_TERMINALS: ReadonlySet<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Laravel `__callStatic`:
|
|
29
|
+
* - Local scopes: `Model.foo()` → `Model.query().foo()` when `scopeFoo` exists
|
|
30
|
+
* - Builder terminals: `Model.get()` / `pluck` / `count` / … → `Model.query()[method](…)`
|
|
31
|
+
*
|
|
32
|
+
* Installed as Model's [[Prototype]] so missing static lookups on subclasses
|
|
33
|
+
* (e.g. `Shop.active`, `User.get`) reach this trap before `Function.prototype`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function installLocalScopeCallStatic(ModelCtor: CallStaticModel): void;
|
|
36
|
+
export {};
|
package/dist/scopes.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const registry = new WeakMap();
|
|
2
|
+
function scopesFor(model) {
|
|
3
|
+
let map = registry.get(model);
|
|
4
|
+
if (!map) {
|
|
5
|
+
map = new Map();
|
|
6
|
+
registry.set(model, map);
|
|
7
|
+
}
|
|
8
|
+
return map;
|
|
9
|
+
}
|
|
10
|
+
/** Register a named global scope on a model class. */
|
|
11
|
+
export function addGlobalScope(model, name, scope) {
|
|
12
|
+
scopesFor(model).set(name, scope);
|
|
13
|
+
}
|
|
14
|
+
/** Remove a named global scope from a model class. */
|
|
15
|
+
export function removeGlobalScope(model, name) {
|
|
16
|
+
scopesFor(model).delete(name);
|
|
17
|
+
}
|
|
18
|
+
const EMPTY_SCOPES = new Map();
|
|
19
|
+
/** All registered global scopes for a model class. */
|
|
20
|
+
export function getGlobalScopes(model) {
|
|
21
|
+
return registry.get(model) ?? EMPTY_SCOPES;
|
|
22
|
+
}
|
|
23
|
+
export function hasGlobalScopes(model) {
|
|
24
|
+
const map = registry.get(model);
|
|
25
|
+
return map != null && map.size > 0;
|
|
26
|
+
}
|
|
27
|
+
/** Clear scopes (tests). */
|
|
28
|
+
export function clearGlobalScopes(model) {
|
|
29
|
+
if (model) {
|
|
30
|
+
registry.delete(model);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Safe ModelQuery terminals forwarded by Model `__callStatic`
|
|
36
|
+
* (`Model.get()` → `Model.query().get()`).
|
|
37
|
+
*
|
|
38
|
+
* Allowlist only — avoid constructors, `then`, starters already owned as
|
|
39
|
+
* Model statics, and arbitrary junk. Own Model / subclass statics always win
|
|
40
|
+
* over this Proxy. Local `scopeFoo` still wins when present.
|
|
41
|
+
*
|
|
42
|
+
* @see https://laravel.com/docs/eloquent#retrieving-models
|
|
43
|
+
*/
|
|
44
|
+
export const MODEL_STATIC_BUILDER_TERMINALS = new Set([
|
|
45
|
+
"get",
|
|
46
|
+
"pluck",
|
|
47
|
+
"value",
|
|
48
|
+
"count",
|
|
49
|
+
"sum",
|
|
50
|
+
"avg",
|
|
51
|
+
"min",
|
|
52
|
+
"max",
|
|
53
|
+
"exists",
|
|
54
|
+
"doesntExist",
|
|
55
|
+
"first",
|
|
56
|
+
"firstOrFail",
|
|
57
|
+
"sole",
|
|
58
|
+
"valueOrFail",
|
|
59
|
+
"soleValue",
|
|
60
|
+
"paginate",
|
|
61
|
+
"simplePaginate",
|
|
62
|
+
"cursorPaginate",
|
|
63
|
+
"getSync",
|
|
64
|
+
"firstSync",
|
|
65
|
+
"toSql",
|
|
66
|
+
"toRawSql",
|
|
67
|
+
"getBindings",
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* Laravel `__callStatic`:
|
|
71
|
+
* - Local scopes: `Model.foo()` → `Model.query().foo()` when `scopeFoo` exists
|
|
72
|
+
* - Builder terminals: `Model.get()` / `pluck` / `count` / … → `Model.query()[method](…)`
|
|
73
|
+
*
|
|
74
|
+
* Installed as Model's [[Prototype]] so missing static lookups on subclasses
|
|
75
|
+
* (e.g. `Shop.active`, `User.get`) reach this trap before `Function.prototype`.
|
|
76
|
+
*/
|
|
77
|
+
export function installLocalScopeCallStatic(ModelCtor) {
|
|
78
|
+
const parent = Object.getPrototypeOf(ModelCtor);
|
|
79
|
+
if (parent &&
|
|
80
|
+
parent
|
|
81
|
+
.__bunyadLocalScopeCallStatic) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const trap = new Proxy(parent, {
|
|
85
|
+
get(target, prop, receiver) {
|
|
86
|
+
if (typeof prop === "symbol") {
|
|
87
|
+
return Reflect.get(target, prop, receiver);
|
|
88
|
+
}
|
|
89
|
+
if (typeof prop === "string" &&
|
|
90
|
+
prop.length > 0 &&
|
|
91
|
+
!prop.startsWith("scope") &&
|
|
92
|
+
prop !== "prototype" &&
|
|
93
|
+
prop !== "name" &&
|
|
94
|
+
prop !== "length") {
|
|
95
|
+
const scopeName = `scope${prop.charAt(0).toUpperCase()}${prop.slice(1)}`;
|
|
96
|
+
const scopeFn = receiver[scopeName];
|
|
97
|
+
if (typeof scopeFn === "function") {
|
|
98
|
+
return (...args) => {
|
|
99
|
+
const q = receiver.newQuery();
|
|
100
|
+
const onQuery = q[prop];
|
|
101
|
+
if (typeof onQuery === "function") {
|
|
102
|
+
return onQuery.apply(q, args);
|
|
103
|
+
}
|
|
104
|
+
scopeFn.call(receiver, q, ...args);
|
|
105
|
+
return q;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (MODEL_STATIC_BUILDER_TERMINALS.has(prop)) {
|
|
109
|
+
return (...args) => {
|
|
110
|
+
const q = receiver.newQuery();
|
|
111
|
+
const fn = q[prop];
|
|
112
|
+
if (typeof fn !== "function") {
|
|
113
|
+
throw new TypeError(`${receiver.name ?? "Model"}.${prop} is not available on the query builder.`);
|
|
114
|
+
}
|
|
115
|
+
return fn.apply(q, args);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return Reflect.get(target, prop, receiver);
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
Object.defineProperty(trap, "__bunyadLocalScopeCallStatic", {
|
|
123
|
+
value: true,
|
|
124
|
+
enumerable: false,
|
|
125
|
+
configurable: false,
|
|
126
|
+
});
|
|
127
|
+
Object.setPrototypeOf(ModelCtor, trap);
|
|
128
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bunyad/orm",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Active-record ORM for Bunyad: models, relations, casts, scopes, events, factories.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Shah Khalid",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/bunyadjs/framework.git",
|
|
11
|
+
"directory": "packages/orm"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/bunyadjs/framework#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/bunyadjs/framework/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"bunyad",
|
|
19
|
+
"bun",
|
|
20
|
+
"typescript",
|
|
21
|
+
"orm",
|
|
22
|
+
"active-record"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@bunyad/common": "^0.1.0-alpha.0",
|
|
40
|
+
"@bunyad/database": "^0.1.0-alpha.0"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"test": "bun test",
|
|
47
|
+
"build": "bun ../../scripts/build-package.ts ."
|
|
48
|
+
}
|
|
49
|
+
}
|