@an5/orm 1.0.7 → 1.0.8
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 +175 -153
- package/dist/an5Metadata.d.ts +10 -0
- package/dist/an5Metadata.js +29 -0
- package/dist/an5Orm.d.ts +4 -1
- package/dist/an5Orm.js +214 -409
- package/dist/config.d.ts +2 -0
- package/dist/config.js +24 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +16 -0
- package/dist/generator/src/code-generator.d.ts +13 -13
- package/dist/generator/src/code-generator.js +225 -225
- package/dist/generator/src/dotnet-generator.d.ts +11 -11
- package/dist/generator/src/dotnet-generator.js +546 -546
- package/dist/generator/src/index.d.ts +1 -1
- package/dist/generator/src/index.js +88 -88
- package/dist/generator/src/metadata-generator.d.ts +8 -8
- package/dist/generator/src/metadata-generator.js +90 -90
- package/dist/generator/src/parser.d.ts +11 -11
- package/dist/generator/src/parser.js +206 -206
- package/dist/generator/src/python-generator.d.ts +9 -9
- package/dist/generator/src/python-generator.js +105 -105
- package/dist/generator/src/types.d.ts +27 -27
- package/dist/generator/src/types.js +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -1
- package/dist/logger.d.ts +53 -0
- package/dist/logger.js +117 -0
- package/dist/metadata.d.ts +24 -0
- package/dist/metadata.js +15 -0
- package/dist/scripts/release-cli.d.ts +2 -2
- package/dist/scripts/release-cli.js +115 -115
- package/dist/sql-utils.d.ts +29 -0
- package/dist/sql-utils.js +220 -0
- package/generator/src/code-generator.ts +230 -234
- package/generator/src/dotnet-generator.ts +544 -544
- package/generator/src/index.ts +116 -104
- package/generator/src/metadata-generator.ts +101 -99
- package/generator/src/parser.ts +202 -202
- package/generator/src/python-generator.ts +114 -114
- package/generator/src/types.ts +29 -29
- package/package.json +2 -6
- package/dist/cleanup.d.ts +0 -2
- package/dist/cleanup.js +0 -120
- package/dist/cli.js +0 -64
- package/dist/migrate.d.ts +0 -11
- package/dist/migrate.js +0 -301
- package/dist/pull.d.ts +0 -2
- package/dist/pull.js +0 -339
- package/dist/push.d.ts +0 -2
- package/dist/push.js +0 -281
- package/dist/seed.d.ts +0 -2
- package/dist/seed.js +0 -401
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.quoteIdentifier = quoteIdentifier;
|
|
4
|
+
exports.sanitizeParamName = sanitizeParamName;
|
|
5
|
+
exports.normalizeSortDirection = normalizeSortDirection;
|
|
6
|
+
exports.toNonNegativeInt = toNonNegativeInt;
|
|
7
|
+
exports.buildOrderBy = buildOrderBy;
|
|
8
|
+
exports.parseWhere = parseWhere;
|
|
9
|
+
/**
|
|
10
|
+
* SQL Server identifier quoting.
|
|
11
|
+
*
|
|
12
|
+
* Wraps a bare identifier in square brackets and escapes any embedded
|
|
13
|
+
* closing bracket (`]` → `]]`), which is the only character that can break
|
|
14
|
+
* out of a bracketed identifier in T-SQL. This blocks SQL injection through
|
|
15
|
+
* user-supplied column / alias names.
|
|
16
|
+
*/
|
|
17
|
+
function quoteIdentifier(name) {
|
|
18
|
+
const s = String(name);
|
|
19
|
+
return `[${s.replace(/\]/g, "]]")}]`;
|
|
20
|
+
}
|
|
21
|
+
/** Sanitizes a parameter name to a safe T-SQL identifier fragment. */
|
|
22
|
+
function sanitizeParamName(name) {
|
|
23
|
+
const s = String(name);
|
|
24
|
+
const cleaned = s.replace(/[^A-Za-z0-9_]/g, "_");
|
|
25
|
+
return /^[A-Za-z]/.test(cleaned) ? cleaned : `p_${cleaned}`;
|
|
26
|
+
}
|
|
27
|
+
/** Validates a direction token, defaulting to ASC. */
|
|
28
|
+
function normalizeSortDirection(dir) {
|
|
29
|
+
const upper = typeof dir === "string" ? dir.toUpperCase() : "";
|
|
30
|
+
return upper === "DESC" ? "DESC" : "ASC";
|
|
31
|
+
}
|
|
32
|
+
/** Coerces a value to a non-negative integer, or returns the fallback. */
|
|
33
|
+
function toNonNegativeInt(value, fallback = 0) {
|
|
34
|
+
const n = Number.parseInt(String(value), 10);
|
|
35
|
+
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
36
|
+
}
|
|
37
|
+
const OPERATOR_KEYS = ["in", "notIn", "contains", "startsWith", "endsWith", "not", "gte", "lte", "gt", "lt"];
|
|
38
|
+
function isOperatorValue(value) {
|
|
39
|
+
if (!value || typeof value !== "object" || value instanceof Date)
|
|
40
|
+
return false;
|
|
41
|
+
return OPERATOR_KEYS.some((op) => op in value);
|
|
42
|
+
}
|
|
43
|
+
function buildOrderBy(orderBy) {
|
|
44
|
+
if (!orderBy)
|
|
45
|
+
return "";
|
|
46
|
+
const orderClauses = [];
|
|
47
|
+
const orderByArr = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
48
|
+
for (const orderObj of orderByArr) {
|
|
49
|
+
if (orderObj && typeof orderObj === "object") {
|
|
50
|
+
for (const [k, dir] of Object.entries(orderObj)) {
|
|
51
|
+
orderClauses.push(`${quoteIdentifier(k)} ${normalizeSortDirection(dir)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return orderClauses.length > 0 ? ` ORDER BY ${orderClauses.join(", ")}` : "";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Recursively builds a WHERE clause from a Prisma-style filter object.
|
|
59
|
+
*
|
|
60
|
+
* Values are always bound as parameters (`@name`); only identifiers are
|
|
61
|
+
* interpolated directly, and they are run through {@link quoteIdentifier}.
|
|
62
|
+
*/
|
|
63
|
+
function parseWhere(modelName, where, params, prefix = "", ctx = {}) {
|
|
64
|
+
if (!where)
|
|
65
|
+
return "";
|
|
66
|
+
const conditions = [];
|
|
67
|
+
const relationMap = ctx.relationMap || {};
|
|
68
|
+
const modelToTable = ctx.modelToTable || {};
|
|
69
|
+
const cleanWhere = {};
|
|
70
|
+
for (const [key, value] of Object.entries(where)) {
|
|
71
|
+
if (key.includes("_") && value && typeof value === "object" && !(value instanceof Date) && !isOperatorValue(value)) {
|
|
72
|
+
Object.assign(cleanWhere, value);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
cleanWhere[key] = value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
for (const [key, value] of Object.entries(cleanWhere)) {
|
|
79
|
+
if (key === "OR" && Array.isArray(value)) {
|
|
80
|
+
const orConditions = value.map((subWhere, idx) => parseWhere(modelName, subWhere, params, `${prefix}or_${idx}_`, ctx));
|
|
81
|
+
const filtered = orConditions.filter(Boolean);
|
|
82
|
+
if (filtered.length > 0) {
|
|
83
|
+
conditions.push(`(${filtered.join(" OR ")})`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (key === "AND" && Array.isArray(value)) {
|
|
87
|
+
const andConditions = value.map((subWhere, idx) => parseWhere(modelName, subWhere, params, `${prefix}and_${idx}_`, ctx));
|
|
88
|
+
const filtered = andConditions.filter(Boolean);
|
|
89
|
+
if (filtered.length > 0) {
|
|
90
|
+
conditions.push(`(${filtered.join(" AND ")})`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const modelRelations = relationMap[modelName];
|
|
95
|
+
const relation = modelRelations?.[key];
|
|
96
|
+
if (relation) {
|
|
97
|
+
const relationTable = modelToTable[relation.modelName] || relation.modelName;
|
|
98
|
+
const subParams = {};
|
|
99
|
+
let subWhere = value;
|
|
100
|
+
let op = "some";
|
|
101
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
102
|
+
if (value.some) {
|
|
103
|
+
subWhere = value.some;
|
|
104
|
+
op = "some";
|
|
105
|
+
}
|
|
106
|
+
else if (value.none) {
|
|
107
|
+
subWhere = value.none;
|
|
108
|
+
op = "none";
|
|
109
|
+
}
|
|
110
|
+
else if (value.every) {
|
|
111
|
+
subWhere = value.every;
|
|
112
|
+
op = "every";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const subWhereSql = parseWhere(relation.modelName, subWhere, subParams, `${prefix}${key}_`, ctx);
|
|
116
|
+
Object.assign(params, subParams);
|
|
117
|
+
if (subWhereSql) {
|
|
118
|
+
const fk = quoteIdentifier(relation.foreignKey);
|
|
119
|
+
const lk = quoteIdentifier(relation.localKey);
|
|
120
|
+
if (relation.relationType === "one") {
|
|
121
|
+
if (op === "none") {
|
|
122
|
+
conditions.push(`${fk} NOT IN (SELECT ${lk} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
conditions.push(`${fk} IN (SELECT ${lk} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
if (op === "none") {
|
|
130
|
+
conditions.push(`${lk} NOT IN (SELECT ${fk} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
conditions.push(`${lk} IN (SELECT ${fk} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const col = quoteIdentifier(key);
|
|
140
|
+
const paramName = sanitizeParamName(`${prefix}${key}`);
|
|
141
|
+
if (value && typeof value === "object" && !(value instanceof Date)) {
|
|
142
|
+
const ops = Object.entries(value);
|
|
143
|
+
for (const [op, opVal] of ops) {
|
|
144
|
+
if (op === "in" && Array.isArray(opVal)) {
|
|
145
|
+
if (opVal.length === 0) {
|
|
146
|
+
conditions.push("1 = 0");
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const inParams = [];
|
|
150
|
+
opVal.forEach((item, idx) => {
|
|
151
|
+
const inParamName = `${paramName}_in_${idx}`;
|
|
152
|
+
inParams.push(`@${inParamName}`);
|
|
153
|
+
params[inParamName] = item;
|
|
154
|
+
});
|
|
155
|
+
conditions.push(`${col} IN (${inParams.join(", ")})`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else if (op === "notIn" && Array.isArray(opVal)) {
|
|
159
|
+
if (opVal.length === 0) {
|
|
160
|
+
conditions.push("1 = 1");
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const inParams = [];
|
|
164
|
+
opVal.forEach((item, idx) => {
|
|
165
|
+
const inParamName = `${paramName}_notin_${idx}`;
|
|
166
|
+
inParams.push(`@${inParamName}`);
|
|
167
|
+
params[inParamName] = item;
|
|
168
|
+
});
|
|
169
|
+
conditions.push(`${col} NOT IN (${inParams.join(", ")})`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (op === "contains") {
|
|
173
|
+
conditions.push(`${col} LIKE @${paramName}_contains`);
|
|
174
|
+
params[`${paramName}_contains`] = `%${opVal}%`;
|
|
175
|
+
}
|
|
176
|
+
else if (op === "startsWith") {
|
|
177
|
+
conditions.push(`${col} LIKE @${paramName}_startsWith`);
|
|
178
|
+
params[`${paramName}_startsWith`] = `${opVal}%`;
|
|
179
|
+
}
|
|
180
|
+
else if (op === "endsWith") {
|
|
181
|
+
conditions.push(`${col} LIKE @${paramName}_endsWith`);
|
|
182
|
+
params[`${paramName}_endsWith`] = `%${opVal}`;
|
|
183
|
+
}
|
|
184
|
+
else if (op === "not") {
|
|
185
|
+
conditions.push(`${col} <> @${paramName}_not`);
|
|
186
|
+
params[`${paramName}_not`] = opVal;
|
|
187
|
+
}
|
|
188
|
+
else if (op === "gte") {
|
|
189
|
+
conditions.push(`${col} >= @${paramName}_gte`);
|
|
190
|
+
params[`${paramName}_gte`] = opVal;
|
|
191
|
+
}
|
|
192
|
+
else if (op === "lte") {
|
|
193
|
+
conditions.push(`${col} <= @${paramName}_lte`);
|
|
194
|
+
params[`${paramName}_lte`] = opVal;
|
|
195
|
+
}
|
|
196
|
+
else if (op === "gt") {
|
|
197
|
+
conditions.push(`${col} > @${paramName}_gt`);
|
|
198
|
+
params[`${paramName}_gt`] = opVal;
|
|
199
|
+
}
|
|
200
|
+
else if (op === "lt") {
|
|
201
|
+
conditions.push(`${col} < @${paramName}_lt`);
|
|
202
|
+
params[`${paramName}_lt`] = opVal;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
if (value === null) {
|
|
208
|
+
conditions.push(`${col} IS NULL`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
conditions.push(`${col} = @${paramName}`);
|
|
212
|
+
params[paramName] = value;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return conditions.join(" AND ");
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=sql-utils.js.map
|