@metaobjectsdev/runtime-ts 0.5.0-rc.1
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 +189 -0
- package/README.md +102 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -0
- package/dist/drivers/drizzle-driver.d.ts +25 -0
- package/dist/drivers/drizzle-driver.d.ts.map +1 -0
- package/dist/drivers/drizzle-driver.js +405 -0
- package/dist/drivers/drizzle-driver.js.map +1 -0
- package/dist/drivers/in-memory-driver.d.ts +11 -0
- package/dist/drivers/in-memory-driver.d.ts.map +1 -0
- package/dist/drivers/in-memory-driver.js +232 -0
- package/dist/drivers/in-memory-driver.js.map +1 -0
- package/dist/drivers/index.d.ts +4 -0
- package/dist/drivers/index.d.ts.map +1 -0
- package/dist/drivers/index.js +4 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/kysely-driver.d.ts +12 -0
- package/dist/drivers/kysely-driver.d.ts.map +1 -0
- package/dist/drivers/kysely-driver.js +203 -0
- package/dist/drivers/kysely-driver.js.map +1 -0
- package/dist/drizzle-fastify/filter-allowlist.d.ts +19 -0
- package/dist/drizzle-fastify/filter-allowlist.d.ts.map +1 -0
- package/dist/drizzle-fastify/filter-allowlist.js +10 -0
- package/dist/drizzle-fastify/filter-allowlist.js.map +1 -0
- package/dist/drizzle-fastify/filter-parser.d.ts +28 -0
- package/dist/drizzle-fastify/filter-parser.d.ts.map +1 -0
- package/dist/drizzle-fastify/filter-parser.js +185 -0
- package/dist/drizzle-fastify/filter-parser.js.map +1 -0
- package/dist/drizzle-fastify/index.d.ts +48 -0
- package/dist/drizzle-fastify/index.d.ts.map +1 -0
- package/dist/drizzle-fastify/index.js +181 -0
- package/dist/drizzle-fastify/index.js.map +1 -0
- package/dist/drizzle-fastify/mount-read-only.d.ts +17 -0
- package/dist/drizzle-fastify/mount-read-only.d.ts.map +1 -0
- package/dist/drizzle-fastify/mount-read-only.js +159 -0
- package/dist/drizzle-fastify/mount-read-only.js.map +1 -0
- package/dist/drizzle-fastify/util.d.ts +5 -0
- package/dist/drizzle-fastify/util.d.ts.map +1 -0
- package/dist/drizzle-fastify/util.js +12 -0
- package/dist/drizzle-fastify/util.js.map +1 -0
- package/dist/errors.d.ts +68 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +86 -0
- package/dist/errors.js.map +1 -0
- package/dist/fastify/index.d.ts +65 -0
- package/dist/fastify/index.d.ts.map +1 -0
- package/dist/fastify/index.js +118 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/identity-strategy.d.ts +10 -0
- package/dist/identity-strategy.d.ts.map +1 -0
- package/dist/identity-strategy.js +67 -0
- package/dist/identity-strategy.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/n2m-resolver.d.ts +27 -0
- package/dist/n2m-resolver.d.ts.map +1 -0
- package/dist/n2m-resolver.js +103 -0
- package/dist/n2m-resolver.js.map +1 -0
- package/dist/object-manager.d.ts +51 -0
- package/dist/object-manager.d.ts.map +1 -0
- package/dist/object-manager.js +355 -0
- package/dist/object-manager.js.map +1 -0
- package/dist/persistence-driver.d.ts +88 -0
- package/dist/persistence-driver.d.ts.map +1 -0
- package/dist/persistence-driver.js +5 -0
- package/dist/persistence-driver.js.map +1 -0
- package/dist/query-builder.d.ts +35 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/query-builder.js +178 -0
- package/dist/query-builder.js.map +1 -0
- package/dist/ref-codec.d.ts +8 -0
- package/dist/ref-codec.d.ts.map +1 -0
- package/dist/ref-codec.js +42 -0
- package/dist/ref-codec.js.map +1 -0
- package/dist/relation-resolver.d.ts +27 -0
- package/dist/relation-resolver.d.ts.map +1 -0
- package/dist/relation-resolver.js +136 -0
- package/dist/relation-resolver.js.map +1 -0
- package/dist/type-coercer.d.ts +5 -0
- package/dist/type-coercer.d.ts.map +1 -0
- package/dist/type-coercer.js +43 -0
- package/dist/type-coercer.js.map +1 -0
- package/dist/validator-runner.d.ts +14 -0
- package/dist/validator-runner.d.ts.map +1 -0
- package/dist/validator-runner.js +155 -0
- package/dist/validator-runner.js.map +1 -0
- package/dist/view.d.ts +19 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +60 -0
- package/dist/view.js.map +1 -0
- package/package.json +87 -0
- package/src/constants.ts +7 -0
- package/src/drivers/drizzle-driver.ts +474 -0
- package/src/drivers/in-memory-driver.ts +256 -0
- package/src/drivers/index.ts +3 -0
- package/src/drivers/kysely-driver.ts +240 -0
- package/src/drizzle-fastify/filter-allowlist.ts +31 -0
- package/src/drizzle-fastify/filter-parser.ts +229 -0
- package/src/drizzle-fastify/index.ts +225 -0
- package/src/drizzle-fastify/mount-read-only.ts +187 -0
- package/src/drizzle-fastify/util.ts +10 -0
- package/src/errors.ts +114 -0
- package/src/fastify/index.ts +181 -0
- package/src/identity-strategy.ts +92 -0
- package/src/index.ts +24 -0
- package/src/n2m-resolver.ts +152 -0
- package/src/object-manager.ts +444 -0
- package/src/persistence-driver.ts +92 -0
- package/src/query-builder.ts +224 -0
- package/src/ref-codec.ts +64 -0
- package/src/relation-resolver.ts +171 -0
- package/src/type-coercer.ts +39 -0
- package/src/validator-runner.ts +168 -0
- package/src/view.ts +82 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Pure function: NEVER throws. ObjectManager wraps a non-ok result in a ValidationError on writes;
|
|
2
|
+
// om.validate() returns the result directly.
|
|
3
|
+
import { TYPE_FIELD, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, VALIDATOR_SUBTYPE_LENGTH, VALIDATOR_SUBTYPE_REGEX, FIELD_SUBTYPE_STRING, FIELD_SUBTYPE_INT, FIELD_SUBTYPE_LONG, FIELD_SUBTYPE_SHORT, FIELD_SUBTYPE_BYTE, FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT, FIELD_SUBTYPE_BOOLEAN, FIELD_ATTR_REQUIRED, FIELD_ATTR_MAX_LENGTH, FIELD_ATTR_DEFAULT, VALIDATOR_ATTR_MIN, VALIDATOR_ATTR_MAX, VALIDATOR_ATTR_PATTERN, } from "@metaobjectsdev/metadata";
|
|
4
|
+
const NUMERIC_FIELD_SUBTYPES = new Set([
|
|
5
|
+
FIELD_SUBTYPE_INT, FIELD_SUBTYPE_LONG, FIELD_SUBTYPE_SHORT, FIELD_SUBTYPE_BYTE,
|
|
6
|
+
FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT,
|
|
7
|
+
]);
|
|
8
|
+
export function runValidators(entity, data, opts = {}) {
|
|
9
|
+
const errors = [];
|
|
10
|
+
for (const field of entity.ownChildren()) {
|
|
11
|
+
if (field.type !== TYPE_FIELD)
|
|
12
|
+
continue;
|
|
13
|
+
const present = Object.prototype.hasOwnProperty.call(data, field.name);
|
|
14
|
+
const value = data[field.name];
|
|
15
|
+
// In partial mode (update), absent keys are "untouched" — only validate fields the caller passed.
|
|
16
|
+
// Fields with a `@default` are also exempt from required-on-insert: the
|
|
17
|
+
// DB will fill them in (e.g. timestamps with `@default: CURRENT_TIMESTAMP`,
|
|
18
|
+
// booleans with `@default: false`).
|
|
19
|
+
const required = isRequired(field);
|
|
20
|
+
const hasDefault = field.ownAttr(FIELD_ATTR_DEFAULT) !== undefined;
|
|
21
|
+
if (required && (value === undefined || value === null)) {
|
|
22
|
+
if (opts.partial && !present)
|
|
23
|
+
continue;
|
|
24
|
+
if (hasDefault)
|
|
25
|
+
continue;
|
|
26
|
+
errors.push({
|
|
27
|
+
field: field.name,
|
|
28
|
+
rule: "required",
|
|
29
|
+
message: `'${field.name}' is required`,
|
|
30
|
+
});
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (value === undefined || value === null)
|
|
34
|
+
continue;
|
|
35
|
+
const typeError = checkType(field.subType, value);
|
|
36
|
+
if (typeError !== null) {
|
|
37
|
+
errors.push({
|
|
38
|
+
field: field.name,
|
|
39
|
+
rule: "type",
|
|
40
|
+
message: typeError,
|
|
41
|
+
expected: field.subType,
|
|
42
|
+
received: typeof value,
|
|
43
|
+
});
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const maxLen = resolveMaxLength(field);
|
|
47
|
+
const minLen = resolveMinLength(field);
|
|
48
|
+
if (typeof value === "string") {
|
|
49
|
+
if (maxLen !== undefined && value.length > maxLen) {
|
|
50
|
+
errors.push({
|
|
51
|
+
field: field.name,
|
|
52
|
+
rule: "length",
|
|
53
|
+
message: `'${field.name}' must be at most ${maxLen} chars (got ${value.length})`,
|
|
54
|
+
expected: { max: maxLen },
|
|
55
|
+
received: value.length,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (minLen !== undefined && value.length < minLen) {
|
|
59
|
+
errors.push({
|
|
60
|
+
field: field.name,
|
|
61
|
+
rule: "length",
|
|
62
|
+
message: `'${field.name}' must be at least ${minLen} chars (got ${value.length})`,
|
|
63
|
+
expected: { min: minLen },
|
|
64
|
+
received: value.length,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const child of field.ownChildren()) {
|
|
69
|
+
if (child.type !== TYPE_VALIDATOR)
|
|
70
|
+
continue;
|
|
71
|
+
if (child.subType !== VALIDATOR_SUBTYPE_REGEX)
|
|
72
|
+
continue;
|
|
73
|
+
const pattern = child.ownAttr(VALIDATOR_ATTR_PATTERN);
|
|
74
|
+
if (typeof pattern !== "string")
|
|
75
|
+
continue;
|
|
76
|
+
if (typeof value !== "string")
|
|
77
|
+
continue;
|
|
78
|
+
let regex;
|
|
79
|
+
try {
|
|
80
|
+
regex = new RegExp(pattern);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
errors.push({
|
|
84
|
+
field: field.name,
|
|
85
|
+
rule: "regex",
|
|
86
|
+
message: `'${field.name}' has an invalid validator pattern: ${pattern}`,
|
|
87
|
+
expected: pattern,
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (!regex.test(value)) {
|
|
92
|
+
errors.push({
|
|
93
|
+
field: field.name,
|
|
94
|
+
rule: "regex",
|
|
95
|
+
message: `'${field.name}' does not match required pattern`,
|
|
96
|
+
expected: pattern,
|
|
97
|
+
received: value,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
103
|
+
}
|
|
104
|
+
function isRequired(field) {
|
|
105
|
+
if (field.ownAttr(FIELD_ATTR_REQUIRED) === true)
|
|
106
|
+
return true;
|
|
107
|
+
for (const child of field.ownChildren()) {
|
|
108
|
+
if (child.type === TYPE_VALIDATOR && child.subType === VALIDATOR_SUBTYPE_REQUIRED)
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
function resolveMaxLength(field) {
|
|
114
|
+
const attr = field.ownAttr(FIELD_ATTR_MAX_LENGTH);
|
|
115
|
+
if (typeof attr === "number")
|
|
116
|
+
return attr;
|
|
117
|
+
for (const child of field.ownChildren()) {
|
|
118
|
+
if (child.type !== TYPE_VALIDATOR)
|
|
119
|
+
continue;
|
|
120
|
+
if (child.subType !== VALIDATOR_SUBTYPE_LENGTH)
|
|
121
|
+
continue;
|
|
122
|
+
const max = child.ownAttr(VALIDATOR_ATTR_MAX);
|
|
123
|
+
if (typeof max === "number")
|
|
124
|
+
return max;
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
function resolveMinLength(field) {
|
|
129
|
+
for (const child of field.ownChildren()) {
|
|
130
|
+
if (child.type !== TYPE_VALIDATOR)
|
|
131
|
+
continue;
|
|
132
|
+
if (child.subType !== VALIDATOR_SUBTYPE_LENGTH)
|
|
133
|
+
continue;
|
|
134
|
+
const min = child.ownAttr(VALIDATOR_ATTR_MIN);
|
|
135
|
+
if (typeof min === "number")
|
|
136
|
+
return min;
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
function checkType(subType, value) {
|
|
141
|
+
if (subType === FIELD_SUBTYPE_STRING) {
|
|
142
|
+
if (typeof value !== "string")
|
|
143
|
+
return `expected string`;
|
|
144
|
+
}
|
|
145
|
+
else if (NUMERIC_FIELD_SUBTYPES.has(subType)) {
|
|
146
|
+
if (typeof value !== "number")
|
|
147
|
+
return `expected number`;
|
|
148
|
+
}
|
|
149
|
+
else if (subType === FIELD_SUBTYPE_BOOLEAN) {
|
|
150
|
+
if (typeof value !== "boolean")
|
|
151
|
+
return `expected boolean`;
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=validator-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator-runner.js","sourceRoot":"","sources":["../src/validator-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/view.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MetaData } from "@metaobjectsdev/metadata";
|
|
2
|
+
export interface FieldViewSpec {
|
|
3
|
+
fieldName: string;
|
|
4
|
+
fieldSubType: string;
|
|
5
|
+
viewName: string;
|
|
6
|
+
/** The view node's subType (e.g., "text", "number", "select"). */
|
|
7
|
+
controlType: string;
|
|
8
|
+
attrs: Record<string, unknown>;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface EntityViewSpec {
|
|
12
|
+
entityName: string;
|
|
13
|
+
viewName: string;
|
|
14
|
+
fields: FieldViewSpec[];
|
|
15
|
+
}
|
|
16
|
+
export declare function viewFieldNames(entity: MetaData, viewName: string): string[];
|
|
17
|
+
export declare function fieldViewSpec(entity: MetaData, fieldName: string, viewName: string): FieldViewSpec | null;
|
|
18
|
+
export declare function entityViewSpec(entity: MetaData, viewName: string): EntityViewSpec;
|
|
19
|
+
//# sourceMappingURL=view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAQzD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAS3E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAsBzG;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAcjF"}
|
package/dist/view.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { TYPE_FIELD, TYPE_VIEW, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, FIELD_ATTR_REQUIRED, } from "@metaobjectsdev/metadata";
|
|
2
|
+
import { MetadataError } from "./errors.js";
|
|
3
|
+
export function viewFieldNames(entity, viewName) {
|
|
4
|
+
const names = [];
|
|
5
|
+
for (const field of entity.ownChildren()) {
|
|
6
|
+
if (field.type !== TYPE_FIELD)
|
|
7
|
+
continue;
|
|
8
|
+
if (field.ownChildren().some((c) => c.type === TYPE_VIEW && c.name === viewName)) {
|
|
9
|
+
names.push(field.name);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return names;
|
|
13
|
+
}
|
|
14
|
+
export function fieldViewSpec(entity, fieldName, viewName) {
|
|
15
|
+
const field = entity.ownChildren().find((c) => c.type === TYPE_FIELD && c.name === fieldName);
|
|
16
|
+
if (!field)
|
|
17
|
+
return null;
|
|
18
|
+
const view = field.ownChildren().find((c) => c.type === TYPE_VIEW && c.name === viewName);
|
|
19
|
+
if (!view)
|
|
20
|
+
return null;
|
|
21
|
+
const attrs = {};
|
|
22
|
+
for (const key of view.ownAttrs().keys()) {
|
|
23
|
+
attrs[key] = view.ownAttr(key);
|
|
24
|
+
}
|
|
25
|
+
const required = isFieldRequired(field);
|
|
26
|
+
const result = {
|
|
27
|
+
fieldName: field.name,
|
|
28
|
+
fieldSubType: field.subType,
|
|
29
|
+
viewName,
|
|
30
|
+
controlType: view.subType,
|
|
31
|
+
attrs,
|
|
32
|
+
};
|
|
33
|
+
if (required)
|
|
34
|
+
result.required = true;
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
export function entityViewSpec(entity, viewName) {
|
|
38
|
+
const fields = [];
|
|
39
|
+
for (const field of entity.ownChildren()) {
|
|
40
|
+
if (field.type !== TYPE_FIELD)
|
|
41
|
+
continue;
|
|
42
|
+
const spec = fieldViewSpec(entity, field.name, viewName);
|
|
43
|
+
if (spec !== null)
|
|
44
|
+
fields.push(spec);
|
|
45
|
+
}
|
|
46
|
+
if (fields.length === 0) {
|
|
47
|
+
throw new MetadataError(`No fields tagged with view '${viewName}' on entity '${entity.name}'`, { entity: entity.name });
|
|
48
|
+
}
|
|
49
|
+
return { entityName: entity.name, viewName, fields };
|
|
50
|
+
}
|
|
51
|
+
function isFieldRequired(field) {
|
|
52
|
+
if (field.ownAttr(FIELD_ATTR_REQUIRED) === true)
|
|
53
|
+
return true;
|
|
54
|
+
for (const child of field.ownChildren()) {
|
|
55
|
+
if (child.type === TYPE_VALIDATOR && child.subType === VALIDATOR_SUBTYPE_REQUIRED)
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=view.js.map
|
package/dist/view.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@metaobjectsdev/runtime-ts",
|
|
3
|
+
"version": "0.5.0-rc.1",
|
|
4
|
+
"description": "Node-side runtime helpers for MetaObjects: Fastify route builders, Drizzle filter/sort integration, Kysely drivers.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"bun": "./src/index.ts",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./drivers": {
|
|
15
|
+
"bun": "./src/drivers/index.ts",
|
|
16
|
+
"types": "./dist/drivers/index.d.ts",
|
|
17
|
+
"default": "./dist/drivers/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./fastify": {
|
|
20
|
+
"bun": "./src/fastify/index.ts",
|
|
21
|
+
"types": "./dist/fastify/index.d.ts",
|
|
22
|
+
"default": "./dist/fastify/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./drizzle-fastify": {
|
|
25
|
+
"bun": "./src/drizzle-fastify/index.ts",
|
|
26
|
+
"types": "./dist/drizzle-fastify/index.d.ts",
|
|
27
|
+
"default": "./dist/drizzle-fastify/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": ["dist", "src", "README.md", "LICENSE"],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p .",
|
|
33
|
+
"typecheck": "tsc -p tsconfig.typecheck.json"
|
|
34
|
+
},
|
|
35
|
+
"license": "Apache-2.0",
|
|
36
|
+
"author": "Doug Mealing <doug@dougmealing.com>",
|
|
37
|
+
"homepage": "https://metaobjects.dev",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/metaobjectsdev/metaobjects/issues"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/metaobjectsdev/metaobjects.git",
|
|
44
|
+
"directory": "server/typescript/packages/runtime-ts"
|
|
45
|
+
},
|
|
46
|
+
"keywords": ["metaobjects", "runtime", "fastify", "drizzle", "kysely"],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@metaobjectsdev/metadata": "0.5.0",
|
|
52
|
+
"qs": "^6.13.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"drizzle-orm": ">=0.36.0",
|
|
56
|
+
"fastify": ">=5.0.0",
|
|
57
|
+
"kysely": ">=0.27.0",
|
|
58
|
+
"zod": ">=3.23.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"drizzle-orm": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"fastify": {
|
|
65
|
+
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"kysely": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"zod": {
|
|
71
|
+
"optional": true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@libsql/client": "^0.15.0",
|
|
76
|
+
"@libsql/kysely-libsql": "^0.4.1",
|
|
77
|
+
"@types/qs": "^6.9.0",
|
|
78
|
+
"bun-types": "latest",
|
|
79
|
+
"drizzle-orm": "^0.45.1",
|
|
80
|
+
"fastify": "^5.6.2",
|
|
81
|
+
"jsdom": "^29.1.1",
|
|
82
|
+
"kysely": "^0.27.0",
|
|
83
|
+
"pg-mem": "^3.0.4",
|
|
84
|
+
"typescript": "^5.6.0",
|
|
85
|
+
"zod": "^4.4.3"
|
|
86
|
+
}
|
|
87
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const DEFAULT_IF_MISSING = "throw" as const;
|
|
2
|
+
|
|
3
|
+
// Mirrors SP2's path-traversal guard — entity names appear in filesystem paths.
|
|
4
|
+
export const VALID_ENTITY_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5
|
+
|
|
6
|
+
export const REF_SEPARATOR = ":";
|
|
7
|
+
export const REF_PK_SEPARATOR = ",";
|