@openfn/language-mssql 5.0.14 → 5.1.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/ast.json +37 -1
- package/dist/index.cjs +38 -25
- package/dist/index.js +36 -24
- package/package.json +7 -6
- package/types/Adaptor.d.ts +10 -1
- package/types/index.d.ts +1 -0
- package/types/util.d.ts +13 -0
package/ast.json
CHANGED
|
@@ -74,6 +74,42 @@
|
|
|
74
74
|
},
|
|
75
75
|
"name": "filter"
|
|
76
76
|
},
|
|
77
|
+
{
|
|
78
|
+
"title": "param",
|
|
79
|
+
"description": "The uuid column to determine a matching/existing record",
|
|
80
|
+
"type": {
|
|
81
|
+
"type": "NameExpression",
|
|
82
|
+
"name": "string"
|
|
83
|
+
},
|
|
84
|
+
"name": "filter.uuid"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"title": "param",
|
|
88
|
+
"description": "The table to lookup the value in",
|
|
89
|
+
"type": {
|
|
90
|
+
"type": "NameExpression",
|
|
91
|
+
"name": "string"
|
|
92
|
+
},
|
|
93
|
+
"name": "filter.relation"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"title": "param",
|
|
97
|
+
"description": "The condition to use for the lookup. Values are automatically escaped for security.",
|
|
98
|
+
"type": {
|
|
99
|
+
"type": "NameExpression",
|
|
100
|
+
"name": "object"
|
|
101
|
+
},
|
|
102
|
+
"name": "filter.where"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"title": "param",
|
|
106
|
+
"description": "The operator to use for the lookup",
|
|
107
|
+
"type": {
|
|
108
|
+
"type": "NameExpression",
|
|
109
|
+
"name": "object"
|
|
110
|
+
},
|
|
111
|
+
"name": "filter.operator"
|
|
112
|
+
},
|
|
77
113
|
{
|
|
78
114
|
"title": "returns",
|
|
79
115
|
"description": null,
|
|
@@ -84,7 +120,7 @@
|
|
|
84
120
|
}
|
|
85
121
|
]
|
|
86
122
|
},
|
|
87
|
-
"valid":
|
|
123
|
+
"valid": false
|
|
88
124
|
},
|
|
89
125
|
{
|
|
90
126
|
"name": "insert",
|
package/dist/index.cjs
CHANGED
|
@@ -45,7 +45,8 @@ __export(src_exports, {
|
|
|
45
45
|
sql: () => sql,
|
|
46
46
|
upsert: () => upsert,
|
|
47
47
|
upsertIf: () => upsertIf,
|
|
48
|
-
upsertMany: () => upsertMany
|
|
48
|
+
upsertMany: () => upsertMany,
|
|
49
|
+
util: () => util_exports
|
|
49
50
|
});
|
|
50
51
|
module.exports = __toCommonJS(src_exports);
|
|
51
52
|
|
|
@@ -80,6 +81,22 @@ __export(Adaptor_exports, {
|
|
|
80
81
|
upsertMany: () => upsertMany
|
|
81
82
|
});
|
|
82
83
|
var import_language_common = require("@openfn/language-common");
|
|
84
|
+
|
|
85
|
+
// src/util.js
|
|
86
|
+
var util_exports = {};
|
|
87
|
+
__export(util_exports, {
|
|
88
|
+
escape: () => escape
|
|
89
|
+
});
|
|
90
|
+
function escape(stringExp) {
|
|
91
|
+
if (typeof stringExp === "object" && stringExp !== null) {
|
|
92
|
+
return Object.values(stringExp).map((x) => escape(x));
|
|
93
|
+
} else if (typeof stringExp !== "string") {
|
|
94
|
+
return stringExp;
|
|
95
|
+
}
|
|
96
|
+
return stringExp.replace(/\'/g, "''");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/Adaptor.js
|
|
83
100
|
var import_tedious = require("tedious");
|
|
84
101
|
var import_language_common2 = require("@openfn/language-common");
|
|
85
102
|
function createConnection(state) {
|
|
@@ -138,10 +155,9 @@ function execute(...operations) {
|
|
|
138
155
|
};
|
|
139
156
|
}
|
|
140
157
|
function cleanupState(state) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
delete state.connection;
|
|
158
|
+
var _a;
|
|
159
|
+
(_a = state == null ? void 0 : state.connection) == null ? void 0 : _a.close();
|
|
160
|
+
state == null ? true : delete state.connection;
|
|
145
161
|
return state;
|
|
146
162
|
}
|
|
147
163
|
function addRowsToRefs(state, rows) {
|
|
@@ -232,14 +248,6 @@ function handleOptions(options) {
|
|
|
232
248
|
}
|
|
233
249
|
return options && options.setNull || "'undefined'";
|
|
234
250
|
}
|
|
235
|
-
function escapeQuote(stringExp) {
|
|
236
|
-
if (typeof stringExp === "object" && stringExp !== null) {
|
|
237
|
-
return Object.values(stringExp).map((x) => escapeQuote(x));
|
|
238
|
-
} else if (typeof stringExp !== "string") {
|
|
239
|
-
return stringExp;
|
|
240
|
-
}
|
|
241
|
-
return stringExp.replace(/\'/g, "''");
|
|
242
|
-
}
|
|
243
251
|
function findValue(filter) {
|
|
244
252
|
return (state) => {
|
|
245
253
|
const { connection } = state;
|
|
@@ -247,10 +255,12 @@ function findValue(filter) {
|
|
|
247
255
|
const whereData = (0, import_language_common.expandReferences)(where)(state);
|
|
248
256
|
const operatorData = (0, import_language_common.expandReferences)(operator)(state);
|
|
249
257
|
let conditionsArray = [];
|
|
250
|
-
for (let key in whereData)
|
|
258
|
+
for (let key in whereData) {
|
|
259
|
+
const escapedValue = escape(whereData[key]);
|
|
251
260
|
conditionsArray.push(
|
|
252
|
-
`${key} ${operatorData ? operatorData[key] : "="} '${
|
|
261
|
+
`${key} ${operatorData ? operatorData[key] : "="} '${escapedValue}'`
|
|
253
262
|
);
|
|
263
|
+
}
|
|
254
264
|
const condition = conditionsArray.length > 0 ? `where ${conditionsArray.join(" and ")}` : "";
|
|
255
265
|
try {
|
|
256
266
|
const body = `select ${uuid} from ${relation} ${condition}`;
|
|
@@ -261,13 +271,15 @@ function findValue(filter) {
|
|
|
261
271
|
const request = new import_tedious.Request(body, (err, rowCount, rows) => {
|
|
262
272
|
if (err) {
|
|
263
273
|
console.error(err.message);
|
|
264
|
-
|
|
274
|
+
reject(err);
|
|
265
275
|
} else {
|
|
266
276
|
if (rows.length > 0) {
|
|
267
277
|
returnValue = rows[0][0].value;
|
|
268
278
|
}
|
|
269
|
-
if (returnValue === null)
|
|
279
|
+
if (returnValue === null) {
|
|
280
|
+
console.log("No value found");
|
|
270
281
|
resolve(void 0);
|
|
282
|
+
}
|
|
271
283
|
resolve(returnValue);
|
|
272
284
|
}
|
|
273
285
|
});
|
|
@@ -285,7 +297,7 @@ function insert(table, record, options) {
|
|
|
285
297
|
try {
|
|
286
298
|
const recordData = (0, import_language_common.expandReferences)(record)(state);
|
|
287
299
|
const columns = Object.keys(recordData).sort();
|
|
288
|
-
const values = columns.map((key) =>
|
|
300
|
+
const values = columns.map((key) => escape(recordData[key])).join("', '");
|
|
289
301
|
const query = handleValues(
|
|
290
302
|
`INSERT INTO ${table} (${columns.join(", ")}) VALUES ('${values}');`,
|
|
291
303
|
handleOptions(options)
|
|
@@ -311,7 +323,7 @@ function insertMany(table, records, options) {
|
|
|
311
323
|
const recordData = (0, import_language_common.expandReferences)(records)(state);
|
|
312
324
|
const columns = Object.keys(recordData[0]);
|
|
313
325
|
const valueSets = recordData.map(
|
|
314
|
-
(x) => `('${
|
|
326
|
+
(x) => `('${escape(Object.values(x)).join("', '")}')`
|
|
315
327
|
);
|
|
316
328
|
const query = handleValues(
|
|
317
329
|
`INSERT INTO ${table} (${columns.join(", ")}) VALUES ${valueSets.join(
|
|
@@ -339,8 +351,8 @@ function upsert(table, uuid, record, options) {
|
|
|
339
351
|
try {
|
|
340
352
|
const recordData = (0, import_language_common.expandReferences)(record)(state);
|
|
341
353
|
const columns = Object.keys(recordData).sort();
|
|
342
|
-
const selectValues = columns.map((key) => `'${
|
|
343
|
-
const updateValues = columns.map((key) => `[Target].${key}='${
|
|
354
|
+
const selectValues = columns.map((key) => `'${escape(recordData[key])}' AS ${key}`).join(", ");
|
|
355
|
+
const updateValues = columns.map((key) => `[Target].${key}='${escape(recordData[key])}'`).join(", ");
|
|
344
356
|
const insertColumns = columns.join(", ");
|
|
345
357
|
const insertValues = columns.map((key) => `[Source].${key}`).join(", ");
|
|
346
358
|
const constraint = [];
|
|
@@ -392,8 +404,8 @@ function upsertIf(logical, table, uuid, record, options) {
|
|
|
392
404
|
resolve(state);
|
|
393
405
|
return state;
|
|
394
406
|
}
|
|
395
|
-
const selectValues = columns.map((key) => `'${
|
|
396
|
-
const updateValues = columns.map((key) => `[Target].${key}='${
|
|
407
|
+
const selectValues = columns.map((key) => `'${escape(recordData[key])}' AS ${key}`).join(", ");
|
|
408
|
+
const updateValues = columns.map((key) => `[Target].${key}='${escape(recordData[key])}'`).join(", ");
|
|
397
409
|
const insertColumns = columns.join(", ");
|
|
398
410
|
const insertValues = columns.map((key) => `[Source].${key}`).join(", ");
|
|
399
411
|
const constraint = [];
|
|
@@ -443,7 +455,7 @@ function upsertMany(table, uuid, records, options) {
|
|
|
443
455
|
}
|
|
444
456
|
const columns = Object.keys(recordData[0]);
|
|
445
457
|
const valueSets = recordData.map(
|
|
446
|
-
(x) => `('${
|
|
458
|
+
(x) => `('${escape(Object.values(x)).join("', '")}')`
|
|
447
459
|
);
|
|
448
460
|
const insertColumns = columns.join(", ");
|
|
449
461
|
const insertValues = columns.map((key) => `[Source].${key}`).join(", ");
|
|
@@ -580,5 +592,6 @@ var src_default = Adaptor_exports;
|
|
|
580
592
|
sql,
|
|
581
593
|
upsert,
|
|
582
594
|
upsertIf,
|
|
583
|
-
upsertMany
|
|
595
|
+
upsertMany,
|
|
596
|
+
util
|
|
584
597
|
});
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,22 @@ import {
|
|
|
38
38
|
execute as commonExecute,
|
|
39
39
|
expandReferences
|
|
40
40
|
} from "@openfn/language-common";
|
|
41
|
+
|
|
42
|
+
// src/util.js
|
|
43
|
+
var util_exports = {};
|
|
44
|
+
__export(util_exports, {
|
|
45
|
+
escape: () => escape
|
|
46
|
+
});
|
|
47
|
+
function escape(stringExp) {
|
|
48
|
+
if (typeof stringExp === "object" && stringExp !== null) {
|
|
49
|
+
return Object.values(stringExp).map((x) => escape(x));
|
|
50
|
+
} else if (typeof stringExp !== "string") {
|
|
51
|
+
return stringExp;
|
|
52
|
+
}
|
|
53
|
+
return stringExp.replace(/\'/g, "''");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/Adaptor.js
|
|
41
57
|
import { Connection, Request } from "tedious";
|
|
42
58
|
import {
|
|
43
59
|
alterState,
|
|
@@ -112,10 +128,9 @@ function execute(...operations) {
|
|
|
112
128
|
};
|
|
113
129
|
}
|
|
114
130
|
function cleanupState(state) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
delete state.connection;
|
|
131
|
+
var _a;
|
|
132
|
+
(_a = state == null ? void 0 : state.connection) == null ? void 0 : _a.close();
|
|
133
|
+
state == null ? true : delete state.connection;
|
|
119
134
|
return state;
|
|
120
135
|
}
|
|
121
136
|
function addRowsToRefs(state, rows) {
|
|
@@ -206,14 +221,6 @@ function handleOptions(options) {
|
|
|
206
221
|
}
|
|
207
222
|
return options && options.setNull || "'undefined'";
|
|
208
223
|
}
|
|
209
|
-
function escapeQuote(stringExp) {
|
|
210
|
-
if (typeof stringExp === "object" && stringExp !== null) {
|
|
211
|
-
return Object.values(stringExp).map((x) => escapeQuote(x));
|
|
212
|
-
} else if (typeof stringExp !== "string") {
|
|
213
|
-
return stringExp;
|
|
214
|
-
}
|
|
215
|
-
return stringExp.replace(/\'/g, "''");
|
|
216
|
-
}
|
|
217
224
|
function findValue(filter) {
|
|
218
225
|
return (state) => {
|
|
219
226
|
const { connection } = state;
|
|
@@ -221,10 +228,12 @@ function findValue(filter) {
|
|
|
221
228
|
const whereData = expandReferences(where)(state);
|
|
222
229
|
const operatorData = expandReferences(operator)(state);
|
|
223
230
|
let conditionsArray = [];
|
|
224
|
-
for (let key in whereData)
|
|
231
|
+
for (let key in whereData) {
|
|
232
|
+
const escapedValue = escape(whereData[key]);
|
|
225
233
|
conditionsArray.push(
|
|
226
|
-
`${key} ${operatorData ? operatorData[key] : "="} '${
|
|
234
|
+
`${key} ${operatorData ? operatorData[key] : "="} '${escapedValue}'`
|
|
227
235
|
);
|
|
236
|
+
}
|
|
228
237
|
const condition = conditionsArray.length > 0 ? `where ${conditionsArray.join(" and ")}` : "";
|
|
229
238
|
try {
|
|
230
239
|
const body = `select ${uuid} from ${relation} ${condition}`;
|
|
@@ -235,13 +244,15 @@ function findValue(filter) {
|
|
|
235
244
|
const request = new Request(body, (err, rowCount, rows) => {
|
|
236
245
|
if (err) {
|
|
237
246
|
console.error(err.message);
|
|
238
|
-
|
|
247
|
+
reject(err);
|
|
239
248
|
} else {
|
|
240
249
|
if (rows.length > 0) {
|
|
241
250
|
returnValue = rows[0][0].value;
|
|
242
251
|
}
|
|
243
|
-
if (returnValue === null)
|
|
252
|
+
if (returnValue === null) {
|
|
253
|
+
console.log("No value found");
|
|
244
254
|
resolve(void 0);
|
|
255
|
+
}
|
|
245
256
|
resolve(returnValue);
|
|
246
257
|
}
|
|
247
258
|
});
|
|
@@ -259,7 +270,7 @@ function insert(table, record, options) {
|
|
|
259
270
|
try {
|
|
260
271
|
const recordData = expandReferences(record)(state);
|
|
261
272
|
const columns = Object.keys(recordData).sort();
|
|
262
|
-
const values = columns.map((key) =>
|
|
273
|
+
const values = columns.map((key) => escape(recordData[key])).join("', '");
|
|
263
274
|
const query = handleValues(
|
|
264
275
|
`INSERT INTO ${table} (${columns.join(", ")}) VALUES ('${values}');`,
|
|
265
276
|
handleOptions(options)
|
|
@@ -285,7 +296,7 @@ function insertMany(table, records, options) {
|
|
|
285
296
|
const recordData = expandReferences(records)(state);
|
|
286
297
|
const columns = Object.keys(recordData[0]);
|
|
287
298
|
const valueSets = recordData.map(
|
|
288
|
-
(x) => `('${
|
|
299
|
+
(x) => `('${escape(Object.values(x)).join("', '")}')`
|
|
289
300
|
);
|
|
290
301
|
const query = handleValues(
|
|
291
302
|
`INSERT INTO ${table} (${columns.join(", ")}) VALUES ${valueSets.join(
|
|
@@ -313,8 +324,8 @@ function upsert(table, uuid, record, options) {
|
|
|
313
324
|
try {
|
|
314
325
|
const recordData = expandReferences(record)(state);
|
|
315
326
|
const columns = Object.keys(recordData).sort();
|
|
316
|
-
const selectValues = columns.map((key) => `'${
|
|
317
|
-
const updateValues = columns.map((key) => `[Target].${key}='${
|
|
327
|
+
const selectValues = columns.map((key) => `'${escape(recordData[key])}' AS ${key}`).join(", ");
|
|
328
|
+
const updateValues = columns.map((key) => `[Target].${key}='${escape(recordData[key])}'`).join(", ");
|
|
318
329
|
const insertColumns = columns.join(", ");
|
|
319
330
|
const insertValues = columns.map((key) => `[Source].${key}`).join(", ");
|
|
320
331
|
const constraint = [];
|
|
@@ -366,8 +377,8 @@ function upsertIf(logical, table, uuid, record, options) {
|
|
|
366
377
|
resolve(state);
|
|
367
378
|
return state;
|
|
368
379
|
}
|
|
369
|
-
const selectValues = columns.map((key) => `'${
|
|
370
|
-
const updateValues = columns.map((key) => `[Target].${key}='${
|
|
380
|
+
const selectValues = columns.map((key) => `'${escape(recordData[key])}' AS ${key}`).join(", ");
|
|
381
|
+
const updateValues = columns.map((key) => `[Target].${key}='${escape(recordData[key])}'`).join(", ");
|
|
371
382
|
const insertColumns = columns.join(", ");
|
|
372
383
|
const insertValues = columns.map((key) => `[Source].${key}`).join(", ");
|
|
373
384
|
const constraint = [];
|
|
@@ -417,7 +428,7 @@ function upsertMany(table, uuid, records, options) {
|
|
|
417
428
|
}
|
|
418
429
|
const columns = Object.keys(recordData[0]);
|
|
419
430
|
const valueSets = recordData.map(
|
|
420
|
-
(x) => `('${
|
|
431
|
+
(x) => `('${escape(Object.values(x)).join("', '")}')`
|
|
421
432
|
);
|
|
422
433
|
const insertColumns = columns.join(", ");
|
|
423
434
|
const insertValues = columns.map((key) => `[Source].${key}`).join(", ");
|
|
@@ -554,5 +565,6 @@ export {
|
|
|
554
565
|
sql,
|
|
555
566
|
upsert,
|
|
556
567
|
upsertIf,
|
|
557
|
-
upsertMany
|
|
568
|
+
upsertMany,
|
|
569
|
+
util_exports as util
|
|
558
570
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfn/language-mssql",
|
|
3
|
-
"
|
|
3
|
+
"label": "MSSQL",
|
|
4
|
+
"version": "5.1.0",
|
|
4
5
|
"description": "A Microsoft SQL language pack for OpenFn",
|
|
5
6
|
"exports": {
|
|
6
7
|
".": {
|
|
@@ -25,13 +26,12 @@
|
|
|
25
26
|
],
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"tedious": "18.6.1",
|
|
28
|
-
"@openfn/language-common": "2.
|
|
29
|
+
"@openfn/language-common": "2.5.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"assertion-error": "2.0.0",
|
|
32
|
-
"chai": "
|
|
33
|
+
"chai": "^5.2.0",
|
|
33
34
|
"deep-eql": "4.1.1",
|
|
34
|
-
"esno": "^0.16.3",
|
|
35
35
|
"rimraf": "3.0.2"
|
|
36
36
|
},
|
|
37
37
|
"type": "module",
|
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
"main": "dist/index.cjs",
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "pnpm clean && build-adaptor mssql",
|
|
42
|
-
"test": "mocha --experimental-specifier-resolution=node --no-warnings",
|
|
43
|
-
"test:watch": "mocha -w --experimental-specifier-resolution=node --no-warnings",
|
|
42
|
+
"test": "mocha --experimental-specifier-resolution=node --no-warnings --exclude test/integration.js --recursive",
|
|
43
|
+
"test:watch": "mocha -w --experimental-specifier-resolution=node --no-warnings --exclude test/integration.js --recursive",
|
|
44
|
+
"test:integration": "mocha --experimental-specifier-resolution=node --no-warnings test/integration.js",
|
|
44
45
|
"clean": "rimraf dist types docs",
|
|
45
46
|
"pack": "pnpm pack --pack-destination ../../dist",
|
|
46
47
|
"lint": "eslint src"
|
package/types/Adaptor.d.ts
CHANGED
|
@@ -33,9 +33,18 @@ export function sql(params: object): Operation;
|
|
|
33
33
|
* })
|
|
34
34
|
* @function
|
|
35
35
|
* @param {object} filter - A filter object with the lookup table, a uuid and the condition
|
|
36
|
+
* @param {string} filter.uuid - The uuid column to determine a matching/existing record
|
|
37
|
+
* @param {string} filter.relation - The table to lookup the value in
|
|
38
|
+
* @param {object} filter.where - The condition to use for the lookup. Values are automatically escaped for security.
|
|
39
|
+
* @param {object} filter.operator - The operator to use for the lookup
|
|
36
40
|
* @returns {Operation}
|
|
37
41
|
*/
|
|
38
|
-
export function findValue(filter:
|
|
42
|
+
export function findValue(filter: {
|
|
43
|
+
uuid: string;
|
|
44
|
+
relation: string;
|
|
45
|
+
where: object;
|
|
46
|
+
operator: object;
|
|
47
|
+
}): Operation;
|
|
39
48
|
/**
|
|
40
49
|
* Insert a record
|
|
41
50
|
* @public
|
package/types/index.d.ts
CHANGED
package/types/util.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes a string for use in an SQL query.
|
|
3
|
+
* @example <caption>Examples</caption>
|
|
4
|
+
* util.escape('test string') // 'test string'
|
|
5
|
+
* util.escape("O'Connor") // "O''Connor"
|
|
6
|
+
* util.escape('string with "quotes"') // 'string with "quotes"'
|
|
7
|
+
* util.escape('') // ''
|
|
8
|
+
* util.escape(null) // null
|
|
9
|
+
* util.escape("'; DROP TABLE users; --") // "''; DROP TABLE users; --"
|
|
10
|
+
* @param {string} stringExp - The string to escape.
|
|
11
|
+
* @returns {string} The escaped string.
|
|
12
|
+
*/
|
|
13
|
+
export function escape(stringExp: string): string;
|