callman-core 1.10.0 → 1.11.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.
Files changed (109) hide show
  1. package/dist/host/connections.d.ts +67 -0
  2. package/dist/host/connections.d.ts.map +1 -0
  3. package/dist/host/connections.js +156 -0
  4. package/dist/host/connections.js.map +1 -0
  5. package/dist/host/db/mongoAdapter.d.ts +7 -0
  6. package/dist/host/db/mongoAdapter.d.ts.map +1 -0
  7. package/dist/host/db/mongoAdapter.js +426 -0
  8. package/dist/host/db/mongoAdapter.js.map +1 -0
  9. package/dist/host/db/mysqlAdapter.d.ts +7 -0
  10. package/dist/host/db/mysqlAdapter.d.ts.map +1 -0
  11. package/dist/host/db/mysqlAdapter.js +68 -0
  12. package/dist/host/db/mysqlAdapter.js.map +1 -0
  13. package/dist/host/db/oracleAdapter.d.ts +7 -0
  14. package/dist/host/db/oracleAdapter.d.ts.map +1 -0
  15. package/dist/host/db/oracleAdapter.js +142 -0
  16. package/dist/host/db/oracleAdapter.js.map +1 -0
  17. package/dist/host/db/oracleConnectString.d.ts +10 -0
  18. package/dist/host/db/oracleConnectString.d.ts.map +1 -0
  19. package/dist/host/db/oracleConnectString.js +58 -0
  20. package/dist/host/db/oracleConnectString.js.map +1 -0
  21. package/dist/host/db/postgresAdapter.d.ts +7 -0
  22. package/dist/host/db/postgresAdapter.d.ts.map +1 -0
  23. package/dist/host/db/postgresAdapter.js +67 -0
  24. package/dist/host/db/postgresAdapter.js.map +1 -0
  25. package/dist/host/db/queryExecutor.d.ts +3 -0
  26. package/dist/host/db/queryExecutor.d.ts.map +1 -0
  27. package/dist/host/db/queryExecutor.js +97 -0
  28. package/dist/host/db/queryExecutor.js.map +1 -0
  29. package/dist/host/db/sqlNormalize.d.ts +3 -0
  30. package/dist/host/db/sqlNormalize.d.ts.map +1 -0
  31. package/dist/host/db/sqlNormalize.js +29 -0
  32. package/dist/host/db/sqlNormalize.js.map +1 -0
  33. package/dist/host/db/templateResolver.d.ts +3 -0
  34. package/dist/host/db/templateResolver.d.ts.map +1 -0
  35. package/dist/host/db/templateResolver.js +77 -0
  36. package/dist/host/db/templateResolver.js.map +1 -0
  37. package/dist/host/db/types.d.ts +59 -0
  38. package/dist/host/db/types.d.ts.map +1 -0
  39. package/dist/host/db/types.js +6 -0
  40. package/dist/host/db/types.js.map +1 -0
  41. package/dist/host/index.d.ts +6 -0
  42. package/dist/host/index.d.ts.map +1 -0
  43. package/dist/host/index.js +7 -0
  44. package/dist/host/index.js.map +1 -0
  45. package/dist/host/lazy.d.ts +3 -0
  46. package/dist/host/lazy.d.ts.map +1 -0
  47. package/dist/host/lazy.js +31 -0
  48. package/dist/host/lazy.js.map +1 -0
  49. package/dist/host/redis/redisService.d.ts +9 -0
  50. package/dist/host/redis/redisService.d.ts.map +1 -0
  51. package/dist/host/redis/redisService.js +264 -0
  52. package/dist/host/redis/redisService.js.map +1 -0
  53. package/dist/host/redis/types.d.ts +44 -0
  54. package/dist/host/redis/types.d.ts.map +1 -0
  55. package/dist/host/redis/types.js +4 -0
  56. package/dist/host/redis/types.js.map +1 -0
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +1 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/runner/requestRunner.d.ts.map +1 -1
  62. package/dist/runner/requestRunner.js +120 -0
  63. package/dist/runner/requestRunner.js.map +1 -1
  64. package/dist/runner/runCollection.d.ts +1 -1
  65. package/dist/runner/runCollection.d.ts.map +1 -1
  66. package/dist/runner/runCollection.js +3 -1
  67. package/dist/runner/runCollection.js.map +1 -1
  68. package/dist/script/legacy.d.ts.map +1 -1
  69. package/dist/script/legacy.js +8 -0
  70. package/dist/script/legacy.js.map +1 -1
  71. package/dist/types/index.d.ts +11 -0
  72. package/dist/types/index.d.ts.map +1 -1
  73. package/dist-cjs/host/connections.js +164 -0
  74. package/dist-cjs/host/connections.js.map +1 -0
  75. package/dist-cjs/host/db/mongoAdapter.js +431 -0
  76. package/dist-cjs/host/db/mongoAdapter.js.map +1 -0
  77. package/dist-cjs/host/db/mysqlAdapter.js +73 -0
  78. package/dist-cjs/host/db/mysqlAdapter.js.map +1 -0
  79. package/dist-cjs/host/db/oracleAdapter.js +147 -0
  80. package/dist-cjs/host/db/oracleAdapter.js.map +1 -0
  81. package/dist-cjs/host/db/oracleConnectString.js +63 -0
  82. package/dist-cjs/host/db/oracleConnectString.js.map +1 -0
  83. package/dist-cjs/host/db/postgresAdapter.js +72 -0
  84. package/dist-cjs/host/db/postgresAdapter.js.map +1 -0
  85. package/dist-cjs/host/db/queryExecutor.js +101 -0
  86. package/dist-cjs/host/db/queryExecutor.js.map +1 -0
  87. package/dist-cjs/host/db/sqlNormalize.js +33 -0
  88. package/dist-cjs/host/db/sqlNormalize.js.map +1 -0
  89. package/dist-cjs/host/db/templateResolver.js +81 -0
  90. package/dist-cjs/host/db/templateResolver.js.map +1 -0
  91. package/dist-cjs/host/db/types.js +7 -0
  92. package/dist-cjs/host/db/types.js.map +1 -0
  93. package/dist-cjs/host/index.js +17 -0
  94. package/dist-cjs/host/index.js.map +1 -0
  95. package/dist-cjs/host/lazy.js +69 -0
  96. package/dist-cjs/host/lazy.js.map +1 -0
  97. package/dist-cjs/host/redis/redisService.js +268 -0
  98. package/dist-cjs/host/redis/redisService.js.map +1 -0
  99. package/dist-cjs/host/redis/types.js +5 -0
  100. package/dist-cjs/host/redis/types.js.map +1 -0
  101. package/dist-cjs/index.js +1 -0
  102. package/dist-cjs/index.js.map +1 -1
  103. package/dist-cjs/runner/requestRunner.js +120 -0
  104. package/dist-cjs/runner/requestRunner.js.map +1 -1
  105. package/dist-cjs/runner/runCollection.js +3 -1
  106. package/dist-cjs/runner/runCollection.js.map +1 -1
  107. package/dist-cjs/script/legacy.js +8 -0
  108. package/dist-cjs/script/legacy.js.map +1 -1
  109. package/package.json +8 -1
@@ -0,0 +1,67 @@
1
+ import type { ScriptDbExecutionInput, ScriptDbExecutionResult, ScriptRedisCapability } from "../script/types.js";
2
+ import type { DbConnectionType, DbConnectionMode } from "./db/types.js";
3
+ import type { RedisCommandExecutionResult, RedisCommandPhase } from "./redis/types.js";
4
+ export interface DbConnectionRuntime {
5
+ kind: "db";
6
+ id: string;
7
+ name: string;
8
+ type: DbConnectionType;
9
+ connectionMode?: DbConnectionMode;
10
+ connectionString?: string;
11
+ host?: string;
12
+ port?: number;
13
+ database?: string;
14
+ serviceName?: string;
15
+ username?: string;
16
+ password?: string;
17
+ ssl?: boolean;
18
+ }
19
+ export interface RedisConnectionRuntime {
20
+ kind: "redis";
21
+ id: string;
22
+ name: string;
23
+ host: string;
24
+ port: number;
25
+ password?: string;
26
+ dbIndex?: number;
27
+ ssl?: boolean;
28
+ }
29
+ export type ConnectionRuntime = DbConnectionRuntime | RedisConnectionRuntime;
30
+ export type ConnectionRuntimeMap = Record<string, ConnectionRuntime>;
31
+ export interface DbNodeConfig {
32
+ enabled?: boolean;
33
+ connectionId?: string | null;
34
+ query?: string;
35
+ }
36
+ export interface RequestDatabaseRuntimeConfig {
37
+ preRequest?: DbNodeConfig;
38
+ postResponse?: DbNodeConfig;
39
+ }
40
+ export interface RequestRedisRuntimeConfig {
41
+ enabled?: boolean;
42
+ connectionId?: string | null;
43
+ preCommands?: string[];
44
+ postCommands?: string[];
45
+ }
46
+ export interface ScriptTemplateContext {
47
+ response?: unknown | null;
48
+ env?: Record<string, string>;
49
+ global?: Record<string, string>;
50
+ }
51
+ export declare const buildDbExecuteCapability: (connections: ConnectionRuntimeMap) => (input: ScriptDbExecutionInput) => Promise<ScriptDbExecutionResult>;
52
+ export declare const runConfiguredDbQuery: (input: {
53
+ connections: ConnectionRuntimeMap;
54
+ config: DbNodeConfig | undefined;
55
+ phase: "pre" | "post";
56
+ context: ScriptTemplateContext;
57
+ }) => Promise<ScriptDbExecutionResult | null>;
58
+ export declare const runRedisCommandsForPhase: (input: {
59
+ connections: ConnectionRuntimeMap;
60
+ connectionId: string | null | undefined;
61
+ commands: string[];
62
+ phase: RedisCommandPhase;
63
+ context: ScriptTemplateContext;
64
+ }) => Promise<RedisCommandExecutionResult[]>;
65
+ export declare const buildRedisValueCache: (results: RedisCommandExecutionResult[]) => Record<string, unknown>;
66
+ export declare const buildRedisCapability: (pre: RedisCommandExecutionResult[], post: RedisCommandExecutionResult[]) => ScriptRedisCapability;
67
+ //# sourceMappingURL=connections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/host/connections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ // Bridges resolved connection runtimes (from the pipeline bundle) into the
2
+ // script capabilities callman-core's executor understands. This is the glue
3
+ // that lets the collection runner execute `pm.db.query`, pre-/post-request DB
4
+ // nodes, and Redis commands locally — the same surface the Electron host wires
5
+ // up, but driven by connections the runner receives instead of an in-process
6
+ // store.
7
+ import { executeQuery } from "./db/queryExecutor.js";
8
+ import { executeRedisCommands } from "./redis/redisService.js";
9
+ const toDbConnectionInput = (runtime) => ({
10
+ id: runtime.id,
11
+ name: runtime.name,
12
+ type: runtime.type,
13
+ connectionMode: runtime.connectionMode ??
14
+ (runtime.connectionString?.trim() ? "connectionString" : "detailed"),
15
+ connectionString: runtime.connectionString,
16
+ host: runtime.host ?? "",
17
+ port: runtime.port ?? 0,
18
+ database: runtime.database,
19
+ serviceName: runtime.serviceName,
20
+ username: runtime.username ?? "",
21
+ password: runtime.password ?? "",
22
+ ssl: runtime.ssl,
23
+ });
24
+ const toRedisConnectionInput = (runtime) => ({
25
+ id: runtime.id,
26
+ name: runtime.name,
27
+ type: "redis",
28
+ host: runtime.host,
29
+ port: runtime.port,
30
+ password: runtime.password,
31
+ dbIndex: runtime.dbIndex,
32
+ });
33
+ const toScriptDbResult = (result) => ({
34
+ success: result.success,
35
+ error: result.error ?? null,
36
+ phase: result.phase,
37
+ connectionId: result.connectionId,
38
+ connectionName: result.connectionName,
39
+ connectionType: result.connectionType,
40
+ query: result.query,
41
+ resolvedQuery: result.resolvedQuery,
42
+ rows: result.rows,
43
+ rowCount: result.rowCount,
44
+ durationMs: result.durationMs,
45
+ executedAt: result.executedAt,
46
+ });
47
+ const buildMissingConnectionResult = (input) => ({
48
+ success: false,
49
+ error: `Database connection "${input.connectionId}" was not found in the run bundle`,
50
+ phase: input.phase,
51
+ connectionId: input.connectionId,
52
+ connectionName: "",
53
+ connectionType: "mongo",
54
+ query: input.query,
55
+ resolvedQuery: input.query,
56
+ rows: [],
57
+ rowCount: 0,
58
+ durationMs: 0,
59
+ executedAt: new Date().toISOString(),
60
+ });
61
+ // ── DB capability ───────────────────────────────────────────────────
62
+ // Builds the `execute` callback powering `pm.db.query(...)`. Resolves the
63
+ // connectionId against the bundle, runs the query against the right driver,
64
+ // and maps the result into the canonical `ScriptDbExecutionResult`.
65
+ export const buildDbExecuteCapability = (connections) => async (input) => {
66
+ const runtime = connections[input.connectionId];
67
+ if (!runtime || runtime.kind !== "db") {
68
+ return buildMissingConnectionResult({
69
+ connectionId: input.connectionId,
70
+ query: input.query,
71
+ phase: input.phase,
72
+ });
73
+ }
74
+ const result = await executeQuery({
75
+ connectionId: input.connectionId,
76
+ connection: toDbConnectionInput(runtime),
77
+ query: input.query,
78
+ phase: input.phase,
79
+ context: {
80
+ response: input.context?.response ?? null,
81
+ env: input.context?.env ?? {},
82
+ global: input.context?.global ?? {},
83
+ },
84
+ });
85
+ return toScriptDbResult(result);
86
+ };
87
+ // Runs a configured pre-request / post-response DB node, producing the result
88
+ // surfaced as `pm.db.pre` / `pm.db.post`. Returns null when the node is
89
+ // disabled or incomplete (so it's never wired into the capability).
90
+ export const runConfiguredDbQuery = async (input) => {
91
+ const { config } = input;
92
+ if (!config?.enabled || !config.connectionId || !config.query?.trim()) {
93
+ return null;
94
+ }
95
+ const execute = buildDbExecuteCapability(input.connections);
96
+ return execute({
97
+ connectionId: config.connectionId,
98
+ query: config.query,
99
+ phase: input.phase,
100
+ context: {
101
+ response: input.context.response ?? null,
102
+ env: input.context.env ?? {},
103
+ global: input.context.global ?? {},
104
+ },
105
+ });
106
+ };
107
+ // ── Redis capability ────────────────────────────────────────────────
108
+ export const runRedisCommandsForPhase = async (input) => {
109
+ const connectionId = input.connectionId?.trim() ?? "";
110
+ const commands = (input.commands ?? []).map((command) => command.trim()).filter(Boolean);
111
+ if (!connectionId || commands.length === 0) {
112
+ return [];
113
+ }
114
+ const runtime = input.connections[connectionId];
115
+ const connection = runtime && runtime.kind === "redis" ? toRedisConnectionInput(runtime) : undefined;
116
+ return executeRedisCommands({
117
+ connectionId,
118
+ connection,
119
+ commands,
120
+ phase: input.phase,
121
+ context: {
122
+ response: input.context.response ?? null,
123
+ env: input.context.env ?? {},
124
+ global: input.context.global ?? {},
125
+ },
126
+ });
127
+ };
128
+ // Mirror of the desktop `buildRedisValueCache`
129
+ // (`pmanfrontend/src/features/redis/lib/redisAssertions.ts`). Maps successful
130
+ // command results to a `key → value` map for `pm.redis.get(key)`.
131
+ export const buildRedisValueCache = (results) => {
132
+ const cache = {};
133
+ for (const result of results) {
134
+ if (!result.success || !result.key) {
135
+ continue;
136
+ }
137
+ if (result.commandName === "GET" || result.commandName === "SET") {
138
+ cache[result.key] = result.result;
139
+ continue;
140
+ }
141
+ if (result.commandName === "DEL") {
142
+ cache[result.key] = null;
143
+ continue;
144
+ }
145
+ if (result.commandName === "EXISTS" && result.result === false) {
146
+ cache[result.key] = null;
147
+ }
148
+ }
149
+ return cache;
150
+ };
151
+ // Assembles the read-only `pm.redis` capability from pre/post command results.
152
+ export const buildRedisCapability = (pre, post) => ({
153
+ values: buildRedisValueCache([...pre, ...post]),
154
+ results: { pre, post },
155
+ });
156
+ //# sourceMappingURL=connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/host/connections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { DbConnection } from "./types.js";
2
+ export declare const testMongoConnection: (connection: DbConnection) => Promise<void>;
3
+ export declare const executeMongoQuery: (connection: DbConnection, query: unknown) => Promise<{
4
+ rows: unknown[];
5
+ rowCount: number;
6
+ }>;
7
+ //# sourceMappingURL=mongoAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongoAdapter.d.ts","sourceRoot":"","sources":["../../../src/host/db/mongoAdapter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAid/C,eAAO,MAAM,mBAAmB,GAAU,YAAY,YAAY,KAAG,OAAO,CAAC,IAAI,CAWhF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,YAAY,YAAY,EACxB,OAAO,OAAO,KACb,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA6F/C,CAAC"}
@@ -0,0 +1,426 @@
1
+ // MongoDB adapter. Ported from `pmanfrontend/electron/db/mongoAdapter.ts`.
2
+ // The only change vs. the desktop original is driver loading: instead of
3
+ // `createRequire`, the `mongodb` / `bson` packages are loaded lazily via
4
+ // `loadOptionalModule` so callman-core stays driver-agnostic.
5
+ import { loadOptionalModule, loadOptionalModuleOrNull } from "../lazy.js";
6
+ const unwrap = (mod) => (mod && mod.default && !mod.MongoClient ? mod.default : mod);
7
+ const loadMongoDriver = async () => {
8
+ try {
9
+ return unwrap(await loadOptionalModule("mongodb"));
10
+ }
11
+ catch {
12
+ throw new Error("MongoDB driver (`mongodb`) is not installed. Install `mongodb` to use Mongo connections.");
13
+ }
14
+ };
15
+ // `bson` is a soft dependency (only needed to render Decimal128 from a plain
16
+ // object). It ships with `mongodb`, but we load it independently and cache it
17
+ // synchronously so the recursive value normaliser can stay sync.
18
+ let cachedBson = null;
19
+ let bsonLoaded = false;
20
+ const ensureBson = async () => {
21
+ if (!bsonLoaded) {
22
+ cachedBson = unwrap(await loadOptionalModuleOrNull("bson"));
23
+ bsonLoaded = true;
24
+ }
25
+ return cachedBson;
26
+ };
27
+ const buildMongoUri = (connection) => {
28
+ if (connection.connectionString?.trim()) {
29
+ return connection.connectionString.trim();
30
+ }
31
+ const username = encodeURIComponent(connection.username);
32
+ const password = encodeURIComponent(connection.password);
33
+ const database = connection.database?.trim() || "admin";
34
+ return `mongodb://${username}:${password}@${connection.host.trim()}:${connection.port}/${database}`;
35
+ };
36
+ const getMongoDatabaseName = (connection) => {
37
+ if (connection.database?.trim()) {
38
+ return connection.database.trim();
39
+ }
40
+ if (connection.connectionString?.trim()) {
41
+ try {
42
+ const uri = connection.connectionString.trim();
43
+ const normalizedUri = uri.startsWith("mongodb+srv://")
44
+ ? uri.replace("mongodb+srv://", "https://")
45
+ : uri.replace("mongodb://", "http://");
46
+ const parsedUrl = new URL(normalizedUri);
47
+ const pathname = parsedUrl.pathname.replace(/^\/+/, "").trim();
48
+ if (pathname) {
49
+ return pathname;
50
+ }
51
+ }
52
+ catch {
53
+ return "admin";
54
+ }
55
+ }
56
+ return "admin";
57
+ };
58
+ const ensureMongoCommand = (value) => {
59
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
60
+ throw new Error("Mongo query must be a JSON object. Example: {\"collection\":\"users\",\"operation\":\"find\",\"filter\":{}}");
61
+ }
62
+ const command = value;
63
+ if (!command.collection?.trim()) {
64
+ throw new Error("Mongo query must include a collection name");
65
+ }
66
+ if (!command.operation?.trim()) {
67
+ throw new Error("Mongo query must include an operation");
68
+ }
69
+ return command;
70
+ };
71
+ const formatUuidFromBytes = (bytes) => {
72
+ const hex = Buffer.from(bytes).toString("hex");
73
+ return [
74
+ hex.slice(0, 8),
75
+ hex.slice(8, 12),
76
+ hex.slice(12, 16),
77
+ hex.slice(16, 20),
78
+ hex.slice(20, 32),
79
+ ].join("-");
80
+ };
81
+ const normalizeBinaryBytes = (bytes, preferUuid = false) => {
82
+ if (preferUuid && bytes.byteLength === 16) {
83
+ return formatUuidFromBytes(bytes);
84
+ }
85
+ return Buffer.from(bytes).toString("hex");
86
+ };
87
+ const toUint8Array = (value) => {
88
+ if (Buffer.isBuffer(value)) {
89
+ return value;
90
+ }
91
+ if (value instanceof Uint8Array) {
92
+ return value;
93
+ }
94
+ if (ArrayBuffer.isView(value)) {
95
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
96
+ }
97
+ if (value instanceof ArrayBuffer) {
98
+ return new Uint8Array(value);
99
+ }
100
+ return null;
101
+ };
102
+ const toUint8ArrayFromIndexedObject = (value) => {
103
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
104
+ return null;
105
+ }
106
+ const entries = Object.entries(value);
107
+ if (entries.length === 0 ||
108
+ !entries.every(([key, entryValue]) => /^\d+$/.test(key) && typeof entryValue === "number" && Number.isInteger(entryValue))) {
109
+ return null;
110
+ }
111
+ return Uint8Array.from(entries
112
+ .sort(([leftKey], [rightKey]) => Number(leftKey) - Number(rightKey))
113
+ .map(([, byteValue]) => byteValue));
114
+ };
115
+ const isMongoObjectId = (value) => {
116
+ if (!value || typeof value !== "object") {
117
+ return false;
118
+ }
119
+ const candidate = value;
120
+ return (candidate._bsontype === "ObjectId" ||
121
+ typeof candidate.toHexString === "function");
122
+ };
123
+ const getMongoBsonType = (value) => {
124
+ if (!value || typeof value !== "object") {
125
+ return null;
126
+ }
127
+ return typeof value._bsontype === "string"
128
+ ? (value._bsontype)
129
+ : null;
130
+ };
131
+ const normalizeMongoNumericValue = (value) => {
132
+ const rawValue = typeof value.valueOf === "function" ? value.valueOf() : undefined;
133
+ if (typeof rawValue === "number") {
134
+ return rawValue;
135
+ }
136
+ if (typeof rawValue === "bigint") {
137
+ return rawValue <= BigInt(Number.MAX_SAFE_INTEGER) &&
138
+ rawValue >= BigInt(Number.MIN_SAFE_INTEGER)
139
+ ? Number(rawValue)
140
+ : rawValue.toString();
141
+ }
142
+ if (typeof rawValue === "string") {
143
+ const parsedNumber = Number(rawValue);
144
+ if (rawValue.trim() &&
145
+ Number.isFinite(parsedNumber) &&
146
+ Number.isSafeInteger(parsedNumber) &&
147
+ String(parsedNumber) === rawValue) {
148
+ return parsedNumber;
149
+ }
150
+ return rawValue;
151
+ }
152
+ return typeof value.toString === "function" ? value.toString() : String(value);
153
+ };
154
+ const normalizePlainDecimal128Object = (value) => {
155
+ if (!("bytes" in value)) {
156
+ return null;
157
+ }
158
+ const bytes = toUint8Array(value.bytes) ?? toUint8ArrayFromIndexedObject(value.bytes);
159
+ if (!bytes || bytes.byteLength !== 16) {
160
+ return null;
161
+ }
162
+ if (!cachedBson?.Decimal128) {
163
+ return null;
164
+ }
165
+ try {
166
+ return new cachedBson.Decimal128(bytes).toString();
167
+ }
168
+ catch {
169
+ return null;
170
+ }
171
+ };
172
+ const normalizeMongoSpecialObject = (value) => {
173
+ const bsonType = getMongoBsonType(value);
174
+ if (!bsonType) {
175
+ return normalizePlainDecimal128Object(value);
176
+ }
177
+ if (bsonType === "ObjectId") {
178
+ return isMongoObjectId(value) ? value.toHexString() : String(value);
179
+ }
180
+ if (bsonType === "Decimal128") {
181
+ return typeof value.toString === "function" ? value.toString() : String(value);
182
+ }
183
+ if (bsonType === "Long" || bsonType === "Int32" || bsonType === "Double") {
184
+ return normalizeMongoNumericValue(value);
185
+ }
186
+ if (bsonType === "Timestamp") {
187
+ const seconds = typeof value.getHighBits === "function"
188
+ ? value.getHighBits()
189
+ : null;
190
+ const increment = typeof value.getLowBits === "function"
191
+ ? value.getLowBits()
192
+ : null;
193
+ if (seconds !== null || increment !== null) {
194
+ return {
195
+ seconds,
196
+ increment,
197
+ };
198
+ }
199
+ return typeof value.toString === "function" ? value.toString() : String(value);
200
+ }
201
+ if (bsonType === "Binary" || bsonType === "UUID") {
202
+ const rawBytes = toUint8Array(value.buffer) ??
203
+ (typeof value.value === "function" ? toUint8Array(value.value()) : null);
204
+ const subtype = typeof value.sub_type === "number"
205
+ ? value.sub_type
206
+ : typeof value.subtype === "number"
207
+ ? value.subtype
208
+ : null;
209
+ if (rawBytes) {
210
+ return normalizeBinaryBytes(rawBytes, bsonType === "UUID" || subtype === 3 || subtype === 4);
211
+ }
212
+ return typeof value.toString === "function" ? value.toString() : String(value);
213
+ }
214
+ if (bsonType === "BSONRegExp") {
215
+ const pattern = typeof value.pattern === "string" ? value.pattern : "";
216
+ const options = typeof value.options === "string" ? value.options : "";
217
+ return `/${pattern}/${options}`;
218
+ }
219
+ if (bsonType === "DBRef") {
220
+ return {
221
+ $ref: typeof value.collection === "string" ? value.collection : "",
222
+ $id: normalizeMongoValue(value.oid ?? null),
223
+ ...(typeof value.db === "string" ? { $db: value.db } : {}),
224
+ };
225
+ }
226
+ if (bsonType === "Code") {
227
+ return {
228
+ code: typeof value.code === "string" ? value.code : String(value.code ?? ""),
229
+ ...(value.scope && typeof value.scope === "object"
230
+ ? { scope: normalizeMongoValue(value.scope) }
231
+ : {}),
232
+ };
233
+ }
234
+ if (bsonType === "MinKey" || bsonType === "MaxKey") {
235
+ return bsonType;
236
+ }
237
+ return null;
238
+ };
239
+ const normalizeMongoValue = (value) => {
240
+ if (value === null || value === undefined) {
241
+ return value;
242
+ }
243
+ if (typeof value === "string" ||
244
+ typeof value === "number" ||
245
+ typeof value === "boolean") {
246
+ return value;
247
+ }
248
+ if (value instanceof Date) {
249
+ return value.toISOString();
250
+ }
251
+ if (typeof value === "bigint") {
252
+ return value.toString();
253
+ }
254
+ if (isMongoObjectId(value)) {
255
+ return value.toHexString();
256
+ }
257
+ const binaryValue = toUint8Array(value);
258
+ if (binaryValue) {
259
+ return normalizeBinaryBytes(binaryValue);
260
+ }
261
+ if (Array.isArray(value)) {
262
+ return value.map(normalizeMongoValue);
263
+ }
264
+ if (typeof value === "object") {
265
+ const normalizedSpecialObject = normalizeMongoSpecialObject(value);
266
+ if (normalizedSpecialObject !== null) {
267
+ return normalizedSpecialObject;
268
+ }
269
+ return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [
270
+ key,
271
+ normalizeMongoValue(entryValue),
272
+ ]));
273
+ }
274
+ return String(value);
275
+ };
276
+ const normalizeMongoResult = (value) => {
277
+ if (Array.isArray(value)) {
278
+ const rows = value.map(normalizeMongoValue);
279
+ return {
280
+ rows,
281
+ rowCount: rows.length,
282
+ };
283
+ }
284
+ if (value === null || value === undefined) {
285
+ return {
286
+ rows: [],
287
+ rowCount: 0,
288
+ };
289
+ }
290
+ return {
291
+ rows: [normalizeMongoValue(value)],
292
+ rowCount: 1,
293
+ };
294
+ };
295
+ const OBJECTID_HEX_PATTERN = /^[a-f\d]{24}$/i;
296
+ const coerceMongoFilterValue = (value, ObjectId) => {
297
+ if (typeof value === "string" && OBJECTID_HEX_PATTERN.test(value)) {
298
+ try {
299
+ return new ObjectId(value);
300
+ }
301
+ catch {
302
+ return value;
303
+ }
304
+ }
305
+ if (Array.isArray(value)) {
306
+ return value.map((item) => coerceMongoFilterValue(item, ObjectId));
307
+ }
308
+ if (typeof value === "object" && value !== null) {
309
+ const obj = value;
310
+ // Support Extended JSON $oid syntax: { "$oid": "hexstring" }
311
+ if (typeof obj.$oid === "string") {
312
+ try {
313
+ return new ObjectId(obj.$oid);
314
+ }
315
+ catch {
316
+ return value;
317
+ }
318
+ }
319
+ return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, coerceMongoFilterValue(v, ObjectId)]));
320
+ }
321
+ return value;
322
+ };
323
+ const coerceMongoFilter = (filter, ObjectId) => {
324
+ if (!filter) {
325
+ return {};
326
+ }
327
+ return Object.fromEntries(Object.entries(filter).map(([key, value]) => [key, coerceMongoFilterValue(value, ObjectId)]));
328
+ };
329
+ export const testMongoConnection = async (connection) => {
330
+ const { MongoClient } = await loadMongoDriver();
331
+ const client = new MongoClient(buildMongoUri(connection));
332
+ await client.connect();
333
+ try {
334
+ await client.db(getMongoDatabaseName(connection)).command({ ping: 1 });
335
+ }
336
+ finally {
337
+ await client.close();
338
+ }
339
+ };
340
+ export const executeMongoQuery = async (connection, query) => {
341
+ const { MongoClient, ObjectId } = await loadMongoDriver();
342
+ await ensureBson();
343
+ const command = ensureMongoCommand(query);
344
+ const client = new MongoClient(buildMongoUri(connection));
345
+ await client.connect();
346
+ try {
347
+ const db = client.db(getMongoDatabaseName(connection));
348
+ const collection = db.collection(command.collection);
349
+ const options = command.options ?? {};
350
+ const filter = coerceMongoFilter(command.filter, ObjectId);
351
+ switch (command.operation) {
352
+ case "find": {
353
+ const cursor = collection.find(filter, {
354
+ ...options,
355
+ projection: command.projection,
356
+ sort: command.sort,
357
+ skip: command.skip,
358
+ limit: command.limit,
359
+ });
360
+ const rows = (await cursor.toArray()).map(normalizeMongoValue);
361
+ return {
362
+ rows,
363
+ rowCount: rows.length,
364
+ };
365
+ }
366
+ case "findOne": {
367
+ const row = await collection.findOne(filter, {
368
+ ...options,
369
+ projection: command.projection,
370
+ sort: command.sort,
371
+ skip: command.skip,
372
+ });
373
+ return normalizeMongoResult(row);
374
+ }
375
+ case "aggregate": {
376
+ const rows = (await collection.aggregate(command.pipeline ?? [], options).toArray()).map(normalizeMongoValue);
377
+ return {
378
+ rows,
379
+ rowCount: rows.length,
380
+ };
381
+ }
382
+ case "insertOne": {
383
+ const result = await collection.insertOne(command.document ?? {}, options);
384
+ return normalizeMongoResult({
385
+ acknowledged: result.acknowledged,
386
+ insertedId: result.insertedId,
387
+ });
388
+ }
389
+ case "updateOne": {
390
+ const result = await collection.updateOne(filter, command.update ?? {}, options);
391
+ return normalizeMongoResult({
392
+ acknowledged: result.acknowledged,
393
+ matchedCount: result.matchedCount,
394
+ modifiedCount: result.modifiedCount,
395
+ upsertedId: result.upsertedId ?? null,
396
+ });
397
+ }
398
+ case "deleteOne": {
399
+ const result = await collection.deleteOne(filter, options);
400
+ return normalizeMongoResult({
401
+ acknowledged: result.acknowledged,
402
+ deletedCount: result.deletedCount,
403
+ });
404
+ }
405
+ case "deleteMany": {
406
+ const result = await collection.deleteMany(filter, options);
407
+ return normalizeMongoResult({
408
+ acknowledged: result.acknowledged,
409
+ deletedCount: result.deletedCount,
410
+ });
411
+ }
412
+ case "countDocuments": {
413
+ const count = await collection.countDocuments(command.filter ?? {}, options);
414
+ return normalizeMongoResult({
415
+ count,
416
+ });
417
+ }
418
+ default:
419
+ throw new Error(`Unsupported Mongo operation: ${command.operation}`);
420
+ }
421
+ }
422
+ finally {
423
+ await client.close();
424
+ }
425
+ };
426
+ //# sourceMappingURL=mongoAdapter.js.map