@noormdev/sdk 1.0.0-alpha.25 → 1.0.0-alpha.27
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/dist/index.d.ts +51 -0
- package/dist/index.js +190 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3920,6 +3920,57 @@ export declare class Context<DB = unknown, Procs = object, Funcs = object, Tvfs
|
|
|
3920
3920
|
impersonate<T>(username: string, fn: (scope: ImpersonatedScope<DB, Procs, Funcs, Tvfs>) => Promise<T>): Promise<T>;
|
|
3921
3921
|
impersonate(username: string): Promise<ImpersonatedScope<DB, Procs, Funcs, Tvfs>>;
|
|
3922
3922
|
}
|
|
3923
|
+
/**
|
|
3924
|
+
* A TVP marker that wraps row data with the required table type name.
|
|
3925
|
+
*
|
|
3926
|
+
* Use the `tvp()` helper to create instances. Column names are
|
|
3927
|
+
* inferred from the object keys of the first row.
|
|
3928
|
+
*
|
|
3929
|
+
* @example
|
|
3930
|
+
* ```typescript
|
|
3931
|
+
* interface CheckoutItem { Type: string; ReferenceNo: number; Qty: number }
|
|
3932
|
+
*
|
|
3933
|
+
* interface MyProcs {
|
|
3934
|
+
* 'Checkout_trx': [{ Party: number; Items: TvpValue<CheckoutItem> }, void];
|
|
3935
|
+
* }
|
|
3936
|
+
* ```
|
|
3937
|
+
*/
|
|
3938
|
+
export interface TvpValue<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
3939
|
+
readonly __noorm_tvp: true;
|
|
3940
|
+
readonly typeName: string;
|
|
3941
|
+
readonly rows: ReadonlyArray<T>;
|
|
3942
|
+
}
|
|
3943
|
+
/**
|
|
3944
|
+
* Create a Table-Valued Parameter for MSSQL stored procedure calls.
|
|
3945
|
+
*
|
|
3946
|
+
* Wraps an array of row objects as a TVP with the specified SQL Server
|
|
3947
|
+
* table type name. Column names are inferred from the first row's keys.
|
|
3948
|
+
*
|
|
3949
|
+
* @param typeName - SQL Server table type (e.g., 'CheckoutItems' or 'dbo.CheckoutItems')
|
|
3950
|
+
* @param rows - Array of row objects with consistent keys
|
|
3951
|
+
*
|
|
3952
|
+
* @example
|
|
3953
|
+
* ```typescript
|
|
3954
|
+
* interface CheckoutItem { Type: number; ReferenceNo: number; Qty: number }
|
|
3955
|
+
*
|
|
3956
|
+
* // Row type is inferred — returns TvpValue<CheckoutItem>
|
|
3957
|
+
* const items: CheckoutItem[] = [
|
|
3958
|
+
* { Type: 1, ReferenceNo: 100, Qty: 5 },
|
|
3959
|
+
* { Type: 2, ReferenceNo: 200, Qty: 3 },
|
|
3960
|
+
* ];
|
|
3961
|
+
*
|
|
3962
|
+
* // Named params — type-checked against TvpValue<CheckoutItem>
|
|
3963
|
+
* await ctx.proc('Checkout_trx', {
|
|
3964
|
+
* Party: 1,
|
|
3965
|
+
* PaymentMethod: 2,
|
|
3966
|
+
* Items: tvp('CheckoutItems', items),
|
|
3967
|
+
* });
|
|
3968
|
+
*
|
|
3969
|
+
* // Positional params
|
|
3970
|
+
* await ctx.proc('Checkout_trx', [1, 2, tvp('CheckoutItems', items)]);
|
|
3971
|
+
* ```
|
|
3972
|
+
*/
|
|
3973
|
+
export declare function tvp<T extends Record<string, unknown>>(typeName: string, rows: T[]): TvpValue<T>;
|
|
3923
3974
|
/**
|
|
3924
3975
|
* Error thrown when requireTest is enabled but config.isTest is false.
|
|
3925
3976
|
*
|
package/dist/index.js
CHANGED
|
@@ -16781,10 +16781,45 @@ async function waitForIdentityToLoad(db, dialect) {
|
|
|
16781
16781
|
context: { identity }
|
|
16782
16782
|
});
|
|
16783
16783
|
}
|
|
16784
|
+
|
|
16785
|
+
// src/sdk/tvp.ts
|
|
16786
|
+
var MSSQL_PARAM_LIMIT = 2100;
|
|
16787
|
+
function tvp(typeName, rows) {
|
|
16788
|
+
if (!typeName) {
|
|
16789
|
+
throw new Error("TVP type name is required.");
|
|
16790
|
+
}
|
|
16791
|
+
if (!Array.isArray(rows)) {
|
|
16792
|
+
throw new Error("TVP rows must be an array.");
|
|
16793
|
+
}
|
|
16794
|
+
if (rows.length > 1) {
|
|
16795
|
+
const expectedKeys = Object.keys(rows[0]).sort().join(",");
|
|
16796
|
+
for (let i = 1; i < rows.length; i++) {
|
|
16797
|
+
const rowKeys = Object.keys(rows[i]).sort().join(",");
|
|
16798
|
+
if (rowKeys !== expectedKeys) {
|
|
16799
|
+
throw new Error(
|
|
16800
|
+
`TVP row ${i} has mismatched keys. Expected [${Object.keys(rows[0]).join(", ")}] but got [${Object.keys(rows[i]).join(", ")}].`
|
|
16801
|
+
);
|
|
16802
|
+
}
|
|
16803
|
+
}
|
|
16804
|
+
}
|
|
16805
|
+
return {
|
|
16806
|
+
__noorm_tvp: true,
|
|
16807
|
+
typeName,
|
|
16808
|
+
rows
|
|
16809
|
+
};
|
|
16810
|
+
}
|
|
16811
|
+
function isTvp(value) {
|
|
16812
|
+
return typeof value === "object" && value !== null && "__noorm_tvp" in value && value["__noorm_tvp"] === true;
|
|
16813
|
+
}
|
|
16814
|
+
|
|
16815
|
+
// src/sdk/sql.ts
|
|
16784
16816
|
function buildProcCall(dialect, name, params) {
|
|
16785
16817
|
if (dialect === "sqlite") {
|
|
16786
16818
|
throw new Error("SQLite does not support stored procedures.");
|
|
16787
16819
|
}
|
|
16820
|
+
if (params && hasTvpParam(params) && dialect !== "mssql") {
|
|
16821
|
+
throw new Error("Table-valued parameters (TVP) are only supported on MSSQL.");
|
|
16822
|
+
}
|
|
16788
16823
|
const rawName = sql.raw(name);
|
|
16789
16824
|
if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
|
|
16790
16825
|
if (dialect === "mssql") {
|
|
@@ -16804,11 +16839,17 @@ function buildFuncCall(dialect, name, column, params) {
|
|
|
16804
16839
|
if (dialect === "sqlite") {
|
|
16805
16840
|
throw new Error("SQLite does not support database function calls.");
|
|
16806
16841
|
}
|
|
16842
|
+
if (params && hasTvpParam(params) && dialect !== "mssql") {
|
|
16843
|
+
throw new Error("Table-valued parameters (TVP) are only supported on MSSQL.");
|
|
16844
|
+
}
|
|
16807
16845
|
const rawName = sql.raw(name);
|
|
16808
16846
|
const rawCol = sql.raw(column);
|
|
16809
16847
|
if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
|
|
16810
16848
|
return sql`SELECT ${rawName}() AS ${rawCol}`;
|
|
16811
16849
|
}
|
|
16850
|
+
if (dialect === "mssql" && hasTvpParam(params)) {
|
|
16851
|
+
return buildMssqlFuncWithTvp(rawName, rawCol, params);
|
|
16852
|
+
}
|
|
16812
16853
|
if (dialect === "postgres" && !Array.isArray(params)) {
|
|
16813
16854
|
const parts = Object.entries(params).map(
|
|
16814
16855
|
([key, val]) => sql`${sql.raw(key)} => ${val}`
|
|
@@ -16835,10 +16876,16 @@ function buildTvfCall(dialect, name, params) {
|
|
|
16835
16876
|
if (dialect === "mysql") {
|
|
16836
16877
|
throw new Error("MySQL does not support table-valued functions.");
|
|
16837
16878
|
}
|
|
16879
|
+
if (params && hasTvpParam(params) && dialect !== "mssql") {
|
|
16880
|
+
throw new Error("Table-valued parameters (TVP) are only supported on MSSQL.");
|
|
16881
|
+
}
|
|
16838
16882
|
const rawName = sql.raw(name);
|
|
16839
16883
|
if (!params || Array.isArray(params) && params.length === 0 || !Array.isArray(params) && Object.keys(params).length === 0) {
|
|
16840
16884
|
return sql`SELECT * FROM ${rawName}()`;
|
|
16841
16885
|
}
|
|
16886
|
+
if (dialect === "mssql" && hasTvpParam(params)) {
|
|
16887
|
+
return buildMssqlTvfWithTvp(rawName, params);
|
|
16888
|
+
}
|
|
16842
16889
|
if (dialect === "postgres" && !Array.isArray(params)) {
|
|
16843
16890
|
const parts = Object.entries(params).map(
|
|
16844
16891
|
([key, val]) => sql`${sql.raw(key)} => ${val}`
|
|
@@ -16850,6 +16897,9 @@ function buildTvfCall(dialect, name, params) {
|
|
|
16850
16897
|
return sql`SELECT * FROM ${rawName}(${joined})`;
|
|
16851
16898
|
}
|
|
16852
16899
|
function buildMssqlProc(rawName, params) {
|
|
16900
|
+
if (hasTvpParam(params)) {
|
|
16901
|
+
return buildMssqlProcWithTvp(rawName, params);
|
|
16902
|
+
}
|
|
16853
16903
|
if (Array.isArray(params)) {
|
|
16854
16904
|
const joined = sql.join(params.map((v) => sql`${v}`));
|
|
16855
16905
|
return sql`EXEC ${rawName} ${joined}`;
|
|
@@ -16874,6 +16924,137 @@ function buildMysqlProc(rawName, params) {
|
|
|
16874
16924
|
const joined = sql.join(values.map((v) => sql`${v}`));
|
|
16875
16925
|
return sql`CALL ${rawName}(${joined})`;
|
|
16876
16926
|
}
|
|
16927
|
+
function hasTvpParam(params) {
|
|
16928
|
+
const values = Array.isArray(params) ? params : Object.values(params);
|
|
16929
|
+
return values.some(isTvp);
|
|
16930
|
+
}
|
|
16931
|
+
function validateTvpParamCount(params) {
|
|
16932
|
+
const values = Array.isArray(params) ? params : Object.values(params);
|
|
16933
|
+
let count = 0;
|
|
16934
|
+
for (const val of values) {
|
|
16935
|
+
if (isTvp(val)) {
|
|
16936
|
+
if (val.rows.length > 0) {
|
|
16937
|
+
count += val.rows.length * Object.keys(val.rows[0]).length;
|
|
16938
|
+
}
|
|
16939
|
+
} else {
|
|
16940
|
+
count += 1;
|
|
16941
|
+
}
|
|
16942
|
+
}
|
|
16943
|
+
if (count > MSSQL_PARAM_LIMIT) {
|
|
16944
|
+
throw new Error(
|
|
16945
|
+
"TVP parameter count (" + count + ") exceeds MSSQL limit of " + MSSQL_PARAM_LIMIT + ". Split your TVP rows into smaller batches and call the procedure multiple times."
|
|
16946
|
+
);
|
|
16947
|
+
}
|
|
16948
|
+
}
|
|
16949
|
+
function buildMssqlProcWithTvp(rawName, params) {
|
|
16950
|
+
validateTvpParamCount(params);
|
|
16951
|
+
const preamble = [];
|
|
16952
|
+
const execParts = [];
|
|
16953
|
+
if (Array.isArray(params)) {
|
|
16954
|
+
for (let i = 0; i < params.length; i++) {
|
|
16955
|
+
const val = params[i];
|
|
16956
|
+
if (isTvp(val)) {
|
|
16957
|
+
const varName = `@__tvp_${i}`;
|
|
16958
|
+
appendTvpStatements(preamble, varName, val);
|
|
16959
|
+
execParts.push(sql.raw(varName));
|
|
16960
|
+
} else {
|
|
16961
|
+
execParts.push(sql`${val}`);
|
|
16962
|
+
}
|
|
16963
|
+
}
|
|
16964
|
+
} else {
|
|
16965
|
+
for (const [key, val] of Object.entries(params)) {
|
|
16966
|
+
if (isTvp(val)) {
|
|
16967
|
+
const varName = `@__tvp_${key}`;
|
|
16968
|
+
appendTvpStatements(preamble, varName, val);
|
|
16969
|
+
execParts.push(sql`${sql.raw(`@${key}`)} = ${sql.raw(varName)}`);
|
|
16970
|
+
} else {
|
|
16971
|
+
execParts.push(sql`${sql.raw(`@${key}`)} = ${val}`);
|
|
16972
|
+
}
|
|
16973
|
+
}
|
|
16974
|
+
}
|
|
16975
|
+
const execStmt = sql`EXEC ${rawName} ${sql.join(execParts)}`;
|
|
16976
|
+
if (preamble.length === 0) {
|
|
16977
|
+
return execStmt;
|
|
16978
|
+
}
|
|
16979
|
+
return sql.join([...preamble, execStmt], sql.raw("; "));
|
|
16980
|
+
}
|
|
16981
|
+
function appendTvpStatements(statements, varName, tvpVal) {
|
|
16982
|
+
statements.push(sql.raw(`DECLARE ${varName} ${tvpVal.typeName}`));
|
|
16983
|
+
if (tvpVal.rows.length === 0) return;
|
|
16984
|
+
const cols = Object.keys(tvpVal.rows[0]);
|
|
16985
|
+
const colList = cols.map((c) => `[${c}]`).join(", ");
|
|
16986
|
+
const rowFragments = tvpVal.rows.map((row) => {
|
|
16987
|
+
const values = cols.map((c) => sql`${row[c]}`);
|
|
16988
|
+
return sql`(${sql.join(values)})`;
|
|
16989
|
+
});
|
|
16990
|
+
statements.push(
|
|
16991
|
+
sql`INSERT INTO ${sql.raw(varName)} (${sql.raw(colList)}) VALUES ${sql.join(rowFragments)}`
|
|
16992
|
+
);
|
|
16993
|
+
}
|
|
16994
|
+
function buildMssqlFuncWithTvp(rawName, rawCol, params) {
|
|
16995
|
+
validateTvpParamCount(params);
|
|
16996
|
+
const preamble = [];
|
|
16997
|
+
const execParts = [];
|
|
16998
|
+
if (Array.isArray(params)) {
|
|
16999
|
+
for (let i = 0; i < params.length; i++) {
|
|
17000
|
+
const val = params[i];
|
|
17001
|
+
if (isTvp(val)) {
|
|
17002
|
+
const varName = `@__tvp_${i}`;
|
|
17003
|
+
appendTvpStatements(preamble, varName, val);
|
|
17004
|
+
execParts.push(sql.raw(varName));
|
|
17005
|
+
} else {
|
|
17006
|
+
execParts.push(sql`${val}`);
|
|
17007
|
+
}
|
|
17008
|
+
}
|
|
17009
|
+
} else {
|
|
17010
|
+
for (const [key, val] of Object.entries(params)) {
|
|
17011
|
+
if (isTvp(val)) {
|
|
17012
|
+
const varName = `@__tvp_${key}`;
|
|
17013
|
+
appendTvpStatements(preamble, varName, val);
|
|
17014
|
+
execParts.push(sql`${sql.raw(`@${key}`)} = ${sql.raw(varName)}`);
|
|
17015
|
+
} else {
|
|
17016
|
+
execParts.push(sql`${sql.raw(`@${key}`)} = ${val}`);
|
|
17017
|
+
}
|
|
17018
|
+
}
|
|
17019
|
+
}
|
|
17020
|
+
const funcStmt = sql`DECLARE @__result sql_variant; EXEC @__result = ${rawName} ${sql.join(execParts)}; SELECT @__result AS ${rawCol}`;
|
|
17021
|
+
if (preamble.length === 0) {
|
|
17022
|
+
return funcStmt;
|
|
17023
|
+
}
|
|
17024
|
+
return sql.join([...preamble, funcStmt], sql.raw("; "));
|
|
17025
|
+
}
|
|
17026
|
+
function buildMssqlTvfWithTvp(rawName, params) {
|
|
17027
|
+
validateTvpParamCount(params);
|
|
17028
|
+
const preamble = [];
|
|
17029
|
+
const callParts = [];
|
|
17030
|
+
if (Array.isArray(params)) {
|
|
17031
|
+
for (let i = 0; i < params.length; i++) {
|
|
17032
|
+
const val = params[i];
|
|
17033
|
+
if (isTvp(val)) {
|
|
17034
|
+
const varName = `@__tvp_${i}`;
|
|
17035
|
+
appendTvpStatements(preamble, varName, val);
|
|
17036
|
+
callParts.push(sql.raw(varName));
|
|
17037
|
+
} else {
|
|
17038
|
+
callParts.push(sql`${val}`);
|
|
17039
|
+
}
|
|
17040
|
+
}
|
|
17041
|
+
} else {
|
|
17042
|
+
for (const [key, val] of Object.entries(params)) {
|
|
17043
|
+
if (isTvp(val)) {
|
|
17044
|
+
const varName = `@__tvp_${key}`;
|
|
17045
|
+
appendTvpStatements(preamble, varName, val);
|
|
17046
|
+
callParts.push(sql.raw(varName));
|
|
17047
|
+
} else {
|
|
17048
|
+
callParts.push(sql`${val}`);
|
|
17049
|
+
}
|
|
17050
|
+
}
|
|
17051
|
+
}
|
|
17052
|
+
const selectStmt = sql`SELECT * FROM ${rawName}(${sql.join(callParts)})`;
|
|
17053
|
+
if (preamble.length === 0) {
|
|
17054
|
+
return selectStmt;
|
|
17055
|
+
}
|
|
17056
|
+
return sql.join([...preamble, selectStmt], sql.raw("; "));
|
|
17057
|
+
}
|
|
16877
17058
|
var ChangeValidationError = class extends Error {
|
|
16878
17059
|
constructor(changeName, issue2) {
|
|
16879
17060
|
super(`Invalid change '${changeName}': ${issue2}`);
|
|
@@ -23351,8 +23532,14 @@ async function teardownSchema(db, dialect, options = {}) {
|
|
|
23351
23532
|
statements.push(ops.dropProcedure(proc.name, proc.schema));
|
|
23352
23533
|
}
|
|
23353
23534
|
}
|
|
23354
|
-
|
|
23355
|
-
|
|
23535
|
+
const skipTypesDueToKeptRoutines = dialect === "mssql" && (options.keepFunctions || options.keepProcedures);
|
|
23536
|
+
if (!options.keepTypes && !skipTypesDueToKeptRoutines) {
|
|
23537
|
+
const sortedTypes = [...types].sort((a, b) => {
|
|
23538
|
+
if (a.kind === "composite" && b.kind !== "composite") return -1;
|
|
23539
|
+
if (a.kind !== "composite" && b.kind === "composite") return 1;
|
|
23540
|
+
return 0;
|
|
23541
|
+
});
|
|
23542
|
+
for (const type of sortedTypes) {
|
|
23356
23543
|
dropped.types.push(type.name);
|
|
23357
23544
|
statements.push(ops.dropType(type.name, type.schema));
|
|
23358
23545
|
}
|
|
@@ -27528,6 +27715,6 @@ async function createContext(options = {}) {
|
|
|
27528
27715
|
return new Context(config2, settings, identity, options, projectRoot);
|
|
27529
27716
|
}
|
|
27530
27717
|
|
|
27531
|
-
export { ChangeAlreadyAppliedError, ChangeNotAppliedError, ChangeNotFoundError, ChangeOrphanedError, ChangeValidationError, ChangesNamespace, Context, DbNamespace, DtNamespace, ImpersonationError, LockAcquireError, LockExpiredError, LockNamespace, ManifestReferenceError, NoormOps, ProtectedConfigError, RequireTestError, RunNamespace, SecretsNamespace, TemplatesNamespace, TransferNamespace, UtilsNamespace, VaultNamespace, createContext };
|
|
27718
|
+
export { ChangeAlreadyAppliedError, ChangeNotAppliedError, ChangeNotFoundError, ChangeOrphanedError, ChangeValidationError, ChangesNamespace, Context, DbNamespace, DtNamespace, ImpersonationError, LockAcquireError, LockExpiredError, LockNamespace, ManifestReferenceError, NoormOps, ProtectedConfigError, RequireTestError, RunNamespace, SecretsNamespace, TemplatesNamespace, TransferNamespace, UtilsNamespace, VaultNamespace, createContext, tvp };
|
|
27532
27719
|
//# sourceMappingURL=index.js.map
|
|
27533
27720
|
//# sourceMappingURL=index.js.map
|