@an5/orm 1.0.6 → 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.
Files changed (52) hide show
  1. package/README.md +175 -147
  2. package/dist/an5Metadata.d.ts +10 -0
  3. package/dist/an5Metadata.js +29 -0
  4. package/dist/an5Orm.d.ts +4 -1
  5. package/dist/an5Orm.js +214 -409
  6. package/dist/config.d.ts +2 -0
  7. package/dist/config.js +24 -0
  8. package/dist/errors.d.ts +14 -0
  9. package/dist/errors.js +16 -0
  10. package/dist/generator/src/code-generator.d.ts +13 -13
  11. package/dist/generator/src/code-generator.js +225 -225
  12. package/dist/generator/src/dotnet-generator.d.ts +11 -11
  13. package/dist/generator/src/dotnet-generator.js +546 -546
  14. package/dist/generator/src/index.d.ts +1 -1
  15. package/dist/generator/src/index.js +88 -88
  16. package/dist/generator/src/metadata-generator.d.ts +8 -8
  17. package/dist/generator/src/metadata-generator.js +90 -90
  18. package/dist/generator/src/parser.d.ts +11 -11
  19. package/dist/generator/src/parser.js +206 -206
  20. package/dist/generator/src/python-generator.d.ts +9 -9
  21. package/dist/generator/src/python-generator.js +105 -105
  22. package/dist/generator/src/types.d.ts +27 -27
  23. package/dist/generator/src/types.js +2 -2
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.js +5 -1
  26. package/dist/logger.d.ts +53 -0
  27. package/dist/logger.js +117 -0
  28. package/dist/metadata.d.ts +24 -0
  29. package/dist/metadata.js +15 -0
  30. package/dist/scripts/release-cli.d.ts +2 -2
  31. package/dist/scripts/release-cli.js +115 -115
  32. package/dist/sql-utils.d.ts +29 -0
  33. package/dist/sql-utils.js +220 -0
  34. package/generator/src/code-generator.ts +230 -234
  35. package/generator/src/dotnet-generator.ts +544 -544
  36. package/generator/src/index.ts +116 -95
  37. package/generator/src/metadata-generator.ts +101 -99
  38. package/generator/src/parser.ts +202 -202
  39. package/generator/src/python-generator.ts +114 -114
  40. package/generator/src/types.ts +29 -29
  41. package/package.json +5 -7
  42. package/dist/cleanup.d.ts +0 -2
  43. package/dist/cleanup.js +0 -120
  44. package/dist/cli.js +0 -64
  45. package/dist/migrate.d.ts +0 -11
  46. package/dist/migrate.js +0 -301
  47. package/dist/pull.d.ts +0 -2
  48. package/dist/pull.js +0 -339
  49. package/dist/push.d.ts +0 -2
  50. package/dist/push.js +0 -281
  51. package/dist/seed.d.ts +0 -2
  52. 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