@bayoudhi/moose-lib-serverless 0.7.2 → 0.7.4

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.mjs CHANGED
@@ -4,7 +4,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require3() {
8
14
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
15
  };
10
16
  var __copyProps = (to, from, except, desc) => {
@@ -180,9 +186,10 @@ var require_confluent_schema_registry = __commonJS({
180
186
  }
181
187
  });
182
188
 
183
- // ../ts-moose-lib/dist/serverless.mjs
189
+ // ../../node_modules/.pnpm/@514labs+moose-lib@0.6.417_@swc+helpers@0.5.17_esbuild@0.25.12_ts-patch@3.3.0_tsconfig-paths@_suczegg7f7vmuhhhtfsuwrbhmu/node_modules/@514labs/moose-lib/dist/index.mjs
184
190
  var import_kafka_javascript = __toESM(require_kafka_javascript(), 1);
185
191
  var import_client2 = __toESM(require_client(), 1);
192
+ var import_redis = __toESM(require_redis(), 1);
186
193
  import {
187
194
  existsSync,
188
195
  readdirSync,
@@ -191,16 +198,27 @@ import {
191
198
  } from "fs";
192
199
  import nodePath from "path";
193
200
  import { createClient } from "@clickhouse/client";
194
- import path from "path";
201
+ import path3 from "path";
195
202
  import * as toml from "toml";
196
203
  import process2 from "process";
197
- var import_redis = __toESM(require_redis(), 1);
198
- import { parse as parse2 } from "csv-parse";
204
+ import * as path2 from "path";
205
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
206
+ import path from "path";
199
207
  import { Readable } from "stream";
208
+ import { createHash } from "crypto";
200
209
  import { createHash as createHash2 } from "crypto";
201
- import { createHash as createHash3 } from "crypto";
210
+ import { createHash as createHash3, randomUUID } from "crypto";
211
+ import { performance } from "perf_hooks";
212
+ import * as fs from "fs";
213
+ import { parse as parse2 } from "csv-parse";
202
214
  var __defProp2 = Object.defineProperty;
203
215
  var __getOwnPropNames2 = Object.getOwnPropertyNames;
216
+ var __require2 = /* @__PURE__ */ ((x) => typeof __require !== "undefined" ? __require : typeof Proxy !== "undefined" ? new Proxy(x, {
217
+ get: (a, b) => (typeof __require !== "undefined" ? __require : a)[b]
218
+ }) : x)(function(x) {
219
+ if (typeof __require !== "undefined") return __require.apply(this, arguments);
220
+ throw Error('Dynamic require of "' + x + '" is not supported');
221
+ });
204
222
  var __esm = (fn, res) => function __init() {
205
223
  return fn && (res = (0, fn[__getOwnPropNames2(fn)[0]])(fn = 0)), res;
206
224
  };
@@ -268,11 +286,11 @@ function walkDirectory(dir, extensions) {
268
286
  }
269
287
  return results;
270
288
  }
271
- function addJsExtensionToImports(content, fileDir) {
289
+ function addJsExtensionToImports(content2, fileDir) {
272
290
  const fromPattern = /(from\s+['"])(\.\.?\/[^'"]*?)(['"])/g;
273
291
  const bareImportPattern = /(import\s+['"])(\.\.?\/[^'"]*?)(['"])/g;
274
292
  const dynamicPattern = /(import\s*\(\s*['"])(\.\.?\/[^'"]*?)(['"])/g;
275
- let result = content;
293
+ let result = content2;
276
294
  result = result.replace(fromPattern, (match, prefix, importPath, quote) => {
277
295
  return rewriteImportPath(match, prefix, importPath, quote, fileDir);
278
296
  });
@@ -323,10 +341,10 @@ function rewriteImportPath(match, prefix, importPath, quote, fileDir) {
323
341
  function rewriteImportExtensions(outDir) {
324
342
  const files = walkDirectory(outDir, [".js", ".mjs"]);
325
343
  for (const filePath of files) {
326
- const content = readFileSync(filePath, "utf-8");
344
+ const content2 = readFileSync(filePath, "utf-8");
327
345
  const fileDir = nodePath.dirname(filePath);
328
- const rewritten = addJsExtensionToImports(content, fileDir);
329
- if (content !== rewritten) {
346
+ const rewritten = addJsExtensionToImports(content2, fileDir);
347
+ if (content2 !== rewritten) {
330
348
  writeFileSync(filePath, rewritten, "utf-8");
331
349
  }
332
350
  }
@@ -378,7 +396,7 @@ var init_commons = __esm({
378
396
  console.log(message);
379
397
  }
380
398
  };
381
- antiCachePath = (path2) => `${path2}?num=${Math.random().toString()}&time=${Date.now()}`;
399
+ antiCachePath = (path4) => `${path4}?num=${Math.random().toString()}&time=${Date.now()}`;
382
400
  getFileName = (filePath) => {
383
401
  const regex = /\/([^\/]+)\.ts/;
384
402
  const matches = filePath.match(regex);
@@ -476,14 +494,14 @@ var init_commons = __esm({
476
494
  }
477
495
  });
478
496
  async function findConfigFile(startDir = process.cwd()) {
479
- const fs = await import("fs");
480
- let currentDir = path.resolve(startDir);
497
+ const fs2 = await import("fs");
498
+ let currentDir = path3.resolve(startDir);
481
499
  while (true) {
482
- const configPath = path.join(currentDir, "moose.config.toml");
483
- if (fs.existsSync(configPath)) {
500
+ const configPath = path3.join(currentDir, "moose.config.toml");
501
+ if (fs2.existsSync(configPath)) {
484
502
  return configPath;
485
503
  }
486
- const parentDir = path.dirname(currentDir);
504
+ const parentDir = path3.dirname(currentDir);
487
505
  if (parentDir === currentDir) {
488
506
  break;
489
507
  }
@@ -492,7 +510,7 @@ async function findConfigFile(startDir = process.cwd()) {
492
510
  return null;
493
511
  }
494
512
  async function readProjectConfig() {
495
- const fs = await import("fs");
513
+ const fs2 = await import("fs");
496
514
  const configPath = await findConfigFile();
497
515
  if (!configPath) {
498
516
  throw new ConfigError(
@@ -500,7 +518,7 @@ async function readProjectConfig() {
500
518
  );
501
519
  }
502
520
  try {
503
- const configContent = fs.readFileSync(configPath, "utf-8");
521
+ const configContent = fs2.readFileSync(configPath, "utf-8");
504
522
  const config = toml.parse(configContent);
505
523
  return config;
506
524
  } catch (error) {
@@ -791,6 +809,7 @@ var ClickHouseEngines = /* @__PURE__ */ ((ClickHouseEngines2) => {
791
809
  ClickHouseEngines2["Distributed"] = "Distributed";
792
810
  ClickHouseEngines2["IcebergS3"] = "IcebergS3";
793
811
  ClickHouseEngines2["Kafka"] = "Kafka";
812
+ ClickHouseEngines2["Merge"] = "Merge";
794
813
  ClickHouseEngines2["ReplicatedMergeTree"] = "ReplicatedMergeTree";
795
814
  ClickHouseEngines2["ReplicatedReplacingMergeTree"] = "ReplicatedReplacingMergeTree";
796
815
  ClickHouseEngines2["ReplicatedAggregatingMergeTree"] = "ReplicatedAggregatingMergeTree";
@@ -800,50 +819,292 @@ var ClickHouseEngines = /* @__PURE__ */ ((ClickHouseEngines2) => {
800
819
  return ClickHouseEngines2;
801
820
  })(ClickHouseEngines || {});
802
821
  init_commons();
803
- var MOOSE_RUNTIME_ENV_PREFIX = "__MOOSE_RUNTIME_ENV__:";
804
- var mooseRuntimeEnv = {
805
- /**
806
- * Gets a value from an environment variable, with behavior depending on context.
807
- *
808
- * When IS_LOADING_INFRA_MAP=true (infrastructure loading):
809
- * Returns a marker string that Moose CLI will resolve later
810
- *
811
- * When IS_LOADING_INFRA_MAP is unset (function/workflow runtime):
812
- * Returns the actual value from the environment variable
813
- *
814
- * @param envVarName - Name of the environment variable to resolve
815
- * @returns Either a marker string or the actual environment variable value
816
- * @throws {Error} If the environment variable name is empty
817
- * @throws {Error} If the environment variable is not set (runtime mode only)
818
- *
819
- * @example
820
- * ```typescript
821
- * // Instead of this (evaluated at build time):
822
- * awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID
823
- *
824
- * // Use this (evaluated at runtime):
825
- * awsAccessKeyId: mooseRuntimeEnv.get("AWS_ACCESS_KEY_ID")
826
- * ```
827
- */
828
- get(envVarName) {
829
- if (!envVarName || envVarName.trim() === "") {
830
- throw new Error("Environment variable name cannot be empty");
822
+ var MOOSE_COMPILER_PLUGINS = [
823
+ {
824
+ transform: "./node_modules/@514labs/moose-lib/dist/compilerPlugin.js"
825
+ // No longer using transformProgram - direct typia integration eliminates
826
+ // the need for program replacement and the associated incremental compilation issues
827
+ },
828
+ {
829
+ // Keep typia plugin for users who use typia directly (not through Moose resources)
830
+ transform: "typia/lib/transform"
831
+ }
832
+ ];
833
+ var MOOSE_COMPILER_OPTIONS = {
834
+ experimentalDecorators: true,
835
+ esModuleInterop: true,
836
+ // Disable strict module syntax checking to avoid dual-package type conflicts
837
+ // This prevents errors where the same type imported with different resolution
838
+ // modes (CJS vs ESM) is treated as incompatible
839
+ verbatimModuleSyntax: false
840
+ };
841
+ var MOOSE_MODULE_OPTIONS = {
842
+ module: "NodeNext",
843
+ moduleResolution: "NodeNext"
844
+ };
845
+ function getSourceDir() {
846
+ return process.env.MOOSE_SOURCE_DIR || "app";
847
+ }
848
+ var DEFAULT_OUT_DIR = ".moose/compiled";
849
+ function readUserOutDir(projectRoot = process.cwd()) {
850
+ try {
851
+ let content = readFileSync2(
852
+ path.join(projectRoot, "tsconfig.json"),
853
+ "utf-8"
854
+ );
855
+ if (content.charCodeAt(0) === 65279) {
856
+ content = content.slice(1);
831
857
  }
832
- const isLoadingInfraMap = process.env.IS_LOADING_INFRA_MAP === "true";
833
- if (isLoadingInfraMap) {
834
- return `${MOOSE_RUNTIME_ENV_PREFIX}${envVarName}`;
858
+ const tsconfig = eval(`(${content})`);
859
+ return tsconfig.compilerOptions?.outDir || null;
860
+ } catch {
861
+ return null;
862
+ }
863
+ }
864
+ function getOutDir(projectRoot2 = process.cwd()) {
865
+ const userOutDir = readUserOutDir(projectRoot2);
866
+ return userOutDir || DEFAULT_OUT_DIR;
867
+ }
868
+ function getCompiledIndexPath(projectRoot2 = process.cwd()) {
869
+ const outDir = getOutDir(projectRoot2);
870
+ const sourceDir = getSourceDir();
871
+ return path.resolve(projectRoot2, outDir, sourceDir, "index.js");
872
+ }
873
+ function hasCompiledArtifacts(projectRoot2 = process.cwd()) {
874
+ return existsSync2(getCompiledIndexPath(projectRoot2));
875
+ }
876
+ function detectModuleSystem(projectRoot2 = process.cwd()) {
877
+ const pkgPath = path.join(projectRoot2, "package.json");
878
+ if (existsSync2(pkgPath)) {
879
+ try {
880
+ const pkgContent = readFileSync2(pkgPath, "utf-8");
881
+ const pkg = JSON.parse(pkgContent);
882
+ if (pkg.type === "module") {
883
+ return "esm";
884
+ }
885
+ } catch (e) {
886
+ console.debug(
887
+ `[moose] Failed to parse package.json at ${pkgPath}, defaulting to CJS:`,
888
+ e
889
+ );
890
+ }
891
+ }
892
+ return "cjs";
893
+ }
894
+ function getModuleOptions(moduleSystem) {
895
+ if (moduleSystem === "esm") {
896
+ return {
897
+ module: "ES2022",
898
+ moduleResolution: "bundler"
899
+ };
900
+ }
901
+ return {
902
+ module: "CommonJS",
903
+ moduleResolution: "Node"
904
+ };
905
+ }
906
+ async function loadModule(modulePath, projectRoot2 = process.cwd()) {
907
+ const moduleSystem = detectModuleSystem(projectRoot2);
908
+ if (moduleSystem === "esm") {
909
+ const { pathToFileURL } = await import("url");
910
+ const fileUrl = pathToFileURL(modulePath).href;
911
+ return await import(fileUrl);
912
+ }
913
+ return __require2(modulePath);
914
+ }
915
+ var isClientOnlyMode = () => process2.env.MOOSE_CLIENT_ONLY === "true";
916
+ var moose_internal = {
917
+ tables: /* @__PURE__ */ new Map(),
918
+ streams: /* @__PURE__ */ new Map(),
919
+ ingestApis: /* @__PURE__ */ new Map(),
920
+ apis: /* @__PURE__ */ new Map(),
921
+ sqlResources: /* @__PURE__ */ new Map(),
922
+ workflows: /* @__PURE__ */ new Map(),
923
+ webApps: /* @__PURE__ */ new Map(),
924
+ materializedViews: /* @__PURE__ */ new Map(),
925
+ views: /* @__PURE__ */ new Map()
926
+ };
927
+ var defaultRetentionPeriod = 60 * 60 * 24 * 7;
928
+ var getMooseInternal = () => globalThis.moose_internal;
929
+ if (getMooseInternal() === void 0) {
930
+ globalThis.moose_internal = moose_internal;
931
+ }
932
+ var loadIndex = async () => {
933
+ if (!hasCompiledArtifacts()) {
934
+ const outDir2 = getOutDir();
935
+ const sourceDir = getSourceDir();
936
+ throw new Error(
937
+ `Compiled artifacts not found at ${outDir2}/${sourceDir}/index.js. Run 'npx moose-tspc' to compile your TypeScript first.`
938
+ );
939
+ }
940
+ const registry = getMooseInternal();
941
+ registry.tables.clear();
942
+ registry.streams.clear();
943
+ registry.ingestApis.clear();
944
+ registry.apis.clear();
945
+ registry.sqlResources.clear();
946
+ registry.workflows.clear();
947
+ registry.webApps.clear();
948
+ registry.materializedViews.clear();
949
+ registry.views.clear();
950
+ const outDir = getOutDir();
951
+ const compiledDir = path2.isAbsolute(outDir) ? outDir : path2.join(process2.cwd(), outDir);
952
+ Object.keys(__require2.cache).forEach((key) => {
953
+ if (key.startsWith(compiledDir)) {
954
+ delete __require2.cache[key];
955
+ }
956
+ });
957
+ try {
958
+ const indexPath = getCompiledIndexPath();
959
+ await loadModule(indexPath);
960
+ } catch (error) {
961
+ let hint;
962
+ let includeDetails = true;
963
+ const details = error instanceof Error ? error.message : String(error);
964
+ if (details.includes("no transform has been configured") || details.includes("NoTransformConfigurationError")) {
965
+ hint = "\u{1F534} Typia Transformation Error\n\nThis is likely a bug in Moose. The Typia type transformer failed to process your code.\n\nPlease report this issue:\n \u2022 Moose Slack: https://join.slack.com/t/moose-community/shared_invite/zt-2fjh5n3wz-cnOmM9Xe9DYAgQrNu8xKxg\n \u2022 Include the stack trace below and the file being processed\n\n";
966
+ includeDetails = false;
967
+ } else if (details.includes("ERR_REQUIRE_ESM") || details.includes("ES Module")) {
968
+ hint = "The file or its dependencies are ESM-only. Switch to packages that dual-support CJS & ESM, or upgrade to Node 22.12+. If you must use Node 20, you may try Node 20.19\n\n";
969
+ }
970
+ if (hint === void 0) {
971
+ throw error;
835
972
  } else {
836
- const value = process.env[envVarName];
837
- if (value === void 0) {
838
- throw new Error(
839
- `Environment variable '${envVarName}' is not set. This is required for runtime execution of functions/workflows.`
840
- );
973
+ const errorMsg = includeDetails ? `${hint}${details}` : hint;
974
+ const cause = error instanceof Error ? error : void 0;
975
+ throw new Error(errorMsg, { cause });
976
+ }
977
+ }
978
+ };
979
+ var dlqSchema = {
980
+ version: "3.1",
981
+ components: {
982
+ schemas: {
983
+ DeadLetterModel: {
984
+ type: "object",
985
+ properties: {
986
+ originalRecord: {
987
+ $ref: "#/components/schemas/Recordstringany"
988
+ },
989
+ errorMessage: {
990
+ type: "string"
991
+ },
992
+ errorType: {
993
+ type: "string"
994
+ },
995
+ failedAt: {
996
+ type: "string",
997
+ format: "date-time"
998
+ },
999
+ source: {
1000
+ oneOf: [
1001
+ {
1002
+ const: "api"
1003
+ },
1004
+ {
1005
+ const: "transform"
1006
+ },
1007
+ {
1008
+ const: "table"
1009
+ }
1010
+ ]
1011
+ }
1012
+ },
1013
+ required: [
1014
+ "originalRecord",
1015
+ "errorMessage",
1016
+ "errorType",
1017
+ "failedAt",
1018
+ "source"
1019
+ ]
1020
+ },
1021
+ Recordstringany: {
1022
+ type: "object",
1023
+ properties: {},
1024
+ required: [],
1025
+ description: "Construct a type with a set of properties K of type T",
1026
+ additionalProperties: {}
841
1027
  }
842
- return value;
843
1028
  }
1029
+ },
1030
+ schemas: [
1031
+ {
1032
+ $ref: "#/components/schemas/DeadLetterModel"
1033
+ }
1034
+ ]
1035
+ };
1036
+ var dlqColumns = [
1037
+ {
1038
+ name: "originalRecord",
1039
+ data_type: "Json",
1040
+ primary_key: false,
1041
+ required: true,
1042
+ unique: false,
1043
+ default: null,
1044
+ annotations: [],
1045
+ ttl: null,
1046
+ codec: null,
1047
+ materialized: null,
1048
+ comment: null
1049
+ },
1050
+ {
1051
+ name: "errorMessage",
1052
+ data_type: "String",
1053
+ primary_key: false,
1054
+ required: true,
1055
+ unique: false,
1056
+ default: null,
1057
+ annotations: [],
1058
+ ttl: null,
1059
+ codec: null,
1060
+ materialized: null,
1061
+ comment: null
1062
+ },
1063
+ {
1064
+ name: "errorType",
1065
+ data_type: "String",
1066
+ primary_key: false,
1067
+ required: true,
1068
+ unique: false,
1069
+ default: null,
1070
+ annotations: [],
1071
+ ttl: null,
1072
+ codec: null,
1073
+ materialized: null,
1074
+ comment: null
1075
+ },
1076
+ {
1077
+ name: "failedAt",
1078
+ data_type: "DateTime",
1079
+ primary_key: false,
1080
+ required: true,
1081
+ unique: false,
1082
+ default: null,
1083
+ annotations: [],
1084
+ ttl: null,
1085
+ codec: null,
1086
+ materialized: null,
1087
+ comment: null
1088
+ },
1089
+ {
1090
+ name: "source",
1091
+ data_type: "String",
1092
+ primary_key: false,
1093
+ required: true,
1094
+ unique: false,
1095
+ default: null,
1096
+ annotations: [],
1097
+ ttl: null,
1098
+ codec: null,
1099
+ materialized: null,
1100
+ comment: null
844
1101
  }
1102
+ ];
1103
+ var getWorkflows = async () => {
1104
+ await loadIndex();
1105
+ const registry = getMooseInternal();
1106
+ return registry.workflows;
845
1107
  };
846
- var mooseEnvSecrets = mooseRuntimeEnv;
847
1108
  var quoteIdentifier = (name) => {
848
1109
  return name.startsWith("`") && name.endsWith("`") ? name : `\`${name}\``;
849
1110
  };
@@ -1014,216 +1275,6 @@ var mapToClickHouseType = (value) => {
1014
1275
  function emptyIfUndefined(value) {
1015
1276
  return value === void 0 ? "" : value;
1016
1277
  }
1017
- init_commons();
1018
- function jsonDateReviver(key, value) {
1019
- const iso8601Format = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)$/;
1020
- if (typeof value === "string" && iso8601Format.test(value)) {
1021
- return new Date(value);
1022
- }
1023
- return value;
1024
- }
1025
- function parseCSV(content, config) {
1026
- return new Promise((resolve, reject) => {
1027
- const results = [];
1028
- parse2(content, {
1029
- delimiter: config.delimiter,
1030
- columns: config.columns ?? true,
1031
- skip_empty_lines: config.skipEmptyLines ?? true,
1032
- trim: config.trim ?? true
1033
- }).on("data", (row) => {
1034
- results.push(row);
1035
- }).on("end", () => {
1036
- resolve(results);
1037
- }).on("error", (error) => {
1038
- reject(error);
1039
- });
1040
- });
1041
- }
1042
- function parseJSON(content, config = {}) {
1043
- try {
1044
- const parsed = JSON.parse(content, config.reviver);
1045
- if (Array.isArray(parsed)) {
1046
- return parsed;
1047
- } else {
1048
- return [parsed];
1049
- }
1050
- } catch (error) {
1051
- throw new Error(
1052
- `Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`
1053
- );
1054
- }
1055
- }
1056
- function parseJSONWithDates(content) {
1057
- return parseJSON(content, { reviver: jsonDateReviver });
1058
- }
1059
- function isValidCSVDelimiter(delimiter) {
1060
- return delimiter.length === 1 && !/\s/.test(delimiter);
1061
- }
1062
- var CSV_DELIMITERS = {
1063
- COMMA: ",",
1064
- TAB: " ",
1065
- SEMICOLON: ";",
1066
- PIPE: "|"
1067
- };
1068
- var DEFAULT_CSV_CONFIG = {
1069
- delimiter: CSV_DELIMITERS.COMMA,
1070
- columns: true,
1071
- skipEmptyLines: true,
1072
- trim: true
1073
- };
1074
- var DEFAULT_JSON_CONFIG = {
1075
- reviver: jsonDateReviver
1076
- };
1077
- var DataSource = class {
1078
- name;
1079
- supportsIncremental;
1080
- constructor(config) {
1081
- this.name = config.name;
1082
- this.supportsIncremental = config.supportsIncremental ?? false;
1083
- }
1084
- };
1085
- init_commons();
1086
- var isClientOnlyMode = () => process2.env.MOOSE_CLIENT_ONLY === "true";
1087
- var moose_internal = {
1088
- tables: /* @__PURE__ */ new Map(),
1089
- streams: /* @__PURE__ */ new Map(),
1090
- ingestApis: /* @__PURE__ */ new Map(),
1091
- apis: /* @__PURE__ */ new Map(),
1092
- sqlResources: /* @__PURE__ */ new Map(),
1093
- workflows: /* @__PURE__ */ new Map(),
1094
- webApps: /* @__PURE__ */ new Map(),
1095
- materializedViews: /* @__PURE__ */ new Map(),
1096
- views: /* @__PURE__ */ new Map()
1097
- };
1098
- var defaultRetentionPeriod = 60 * 60 * 24 * 7;
1099
- var getMooseInternal = () => globalThis.moose_internal;
1100
- if (getMooseInternal() === void 0) {
1101
- globalThis.moose_internal = moose_internal;
1102
- }
1103
- var dlqSchema = {
1104
- version: "3.1",
1105
- components: {
1106
- schemas: {
1107
- DeadLetterModel: {
1108
- type: "object",
1109
- properties: {
1110
- originalRecord: {
1111
- $ref: "#/components/schemas/Recordstringany"
1112
- },
1113
- errorMessage: {
1114
- type: "string"
1115
- },
1116
- errorType: {
1117
- type: "string"
1118
- },
1119
- failedAt: {
1120
- type: "string",
1121
- format: "date-time"
1122
- },
1123
- source: {
1124
- oneOf: [
1125
- {
1126
- const: "api"
1127
- },
1128
- {
1129
- const: "transform"
1130
- },
1131
- {
1132
- const: "table"
1133
- }
1134
- ]
1135
- }
1136
- },
1137
- required: [
1138
- "originalRecord",
1139
- "errorMessage",
1140
- "errorType",
1141
- "failedAt",
1142
- "source"
1143
- ]
1144
- },
1145
- Recordstringany: {
1146
- type: "object",
1147
- properties: {},
1148
- required: [],
1149
- description: "Construct a type with a set of properties K of type T",
1150
- additionalProperties: {}
1151
- }
1152
- }
1153
- },
1154
- schemas: [
1155
- {
1156
- $ref: "#/components/schemas/DeadLetterModel"
1157
- }
1158
- ]
1159
- };
1160
- var dlqColumns = [
1161
- {
1162
- name: "originalRecord",
1163
- data_type: "Json",
1164
- primary_key: false,
1165
- required: true,
1166
- unique: false,
1167
- default: null,
1168
- annotations: [],
1169
- ttl: null,
1170
- codec: null,
1171
- materialized: null,
1172
- comment: null
1173
- },
1174
- {
1175
- name: "errorMessage",
1176
- data_type: "String",
1177
- primary_key: false,
1178
- required: true,
1179
- unique: false,
1180
- default: null,
1181
- annotations: [],
1182
- ttl: null,
1183
- codec: null,
1184
- materialized: null,
1185
- comment: null
1186
- },
1187
- {
1188
- name: "errorType",
1189
- data_type: "String",
1190
- primary_key: false,
1191
- required: true,
1192
- unique: false,
1193
- default: null,
1194
- annotations: [],
1195
- ttl: null,
1196
- codec: null,
1197
- materialized: null,
1198
- comment: null
1199
- },
1200
- {
1201
- name: "failedAt",
1202
- data_type: "DateTime",
1203
- primary_key: false,
1204
- required: true,
1205
- unique: false,
1206
- default: null,
1207
- annotations: [],
1208
- ttl: null,
1209
- codec: null,
1210
- materialized: null,
1211
- comment: null
1212
- },
1213
- {
1214
- name: "source",
1215
- data_type: "String",
1216
- primary_key: false,
1217
- required: true,
1218
- unique: false,
1219
- default: null,
1220
- annotations: [],
1221
- ttl: null,
1222
- codec: null,
1223
- materialized: null,
1224
- comment: null
1225
- }
1226
- ];
1227
1278
  var OlapTable = class extends TypedBase {
1228
1279
  name;
1229
1280
  /** @internal */
@@ -1295,7 +1346,7 @@ var OlapTable = class extends TypedBase {
1295
1346
  createConfigHash(clickhouseConfig) {
1296
1347
  const effectiveDatabase = this.config.database ?? clickhouseConfig.database;
1297
1348
  const configString = `${clickhouseConfig.host}:${clickhouseConfig.port}:${clickhouseConfig.username}:${clickhouseConfig.password}:${effectiveDatabase}:${clickhouseConfig.useSSL}`;
1298
- return createHash2("sha256").update(configString).digest("hex").substring(0, 16);
1349
+ return createHash("sha256").update(configString).digest("hex").substring(0, 16);
1299
1350
  }
1300
1351
  /**
1301
1352
  * Gets or creates a memoized ClickHouse client.
@@ -1985,7 +2036,7 @@ var Stream = class extends TypedBase {
1985
2036
  kafkaConfig.securityProtocol,
1986
2037
  kafkaConfig.namespace
1987
2038
  ].join(":");
1988
- return createHash3("sha256").update(configString).digest("hex").substring(0, 16);
2039
+ return createHash2("sha256").update(configString).digest("hex").substring(0, 16);
1989
2040
  }
1990
2041
  /**
1991
2042
  * Gets or creates a memoized KafkaJS producer using runtime configuration.
@@ -2426,22 +2477,22 @@ var Api = class extends TypedBase {
2426
2477
  return this._handler;
2427
2478
  };
2428
2479
  async call(baseUrl, queryParams) {
2429
- let path2;
2480
+ let path4;
2430
2481
  if (this.config?.path) {
2431
2482
  if (this.config.version) {
2432
2483
  const pathEndsWithVersion = this.config.path.endsWith(`/${this.config.version}`) || this.config.path === this.config.version || this.config.path.endsWith(this.config.version) && this.config.path.length > this.config.version.length && this.config.path[this.config.path.length - this.config.version.length - 1] === "/";
2433
2484
  if (pathEndsWithVersion) {
2434
- path2 = this.config.path;
2485
+ path4 = this.config.path;
2435
2486
  } else {
2436
- path2 = `${this.config.path.replace(/\/$/, "")}/${this.config.version}`;
2487
+ path4 = `${this.config.path.replace(/\/$/, "")}/${this.config.version}`;
2437
2488
  }
2438
2489
  } else {
2439
- path2 = this.config.path;
2490
+ path4 = this.config.path;
2440
2491
  }
2441
2492
  } else {
2442
- path2 = this.config?.version ? `${this.name}/${this.config.version}` : this.name;
2493
+ path4 = this.config?.version ? `${this.name}/${this.config.version}` : this.name;
2443
2494
  }
2444
- const url = new URL(`${baseUrl.replace(/\/$/, "")}/api/${path2}`);
2495
+ const url = new URL(`${baseUrl.replace(/\/$/, "")}/api/${path4}`);
2445
2496
  const searchParams = url.searchParams;
2446
2497
  for (const [key, value] of Object.entries(queryParams)) {
2447
2498
  if (Array.isArray(value)) {
@@ -2500,6 +2551,11 @@ var IngestPipeline = class extends TypedBase {
2500
2551
  }
2501
2552
  }
2502
2553
  if (config.table) {
2554
+ if (typeof config.table === "object" && "engine" in config.table && config.table.engine === "Merge") {
2555
+ throw new Error(
2556
+ `IngestPipeline "${name}": Merge engine is read-only and cannot be used as a table destination.`
2557
+ );
2558
+ }
2503
2559
  const tableConfig = typeof config.table === "object" ? {
2504
2560
  ...config.table,
2505
2561
  lifeCycle: config.table.lifeCycle ?? config.lifeCycle,
@@ -2743,6 +2799,8 @@ var MaterializedView = class {
2743
2799
  sourceTables;
2744
2800
  /** Optional metadata for the materialized view */
2745
2801
  metadata;
2802
+ /** Optional lifecycle management policy for the materialized view */
2803
+ lifeCycle;
2746
2804
  constructor(options, targetSchema, targetColumns) {
2747
2805
  let selectStatement = options.selectStatement;
2748
2806
  if (typeof selectStatement !== "string") {
@@ -2776,6 +2834,7 @@ var MaterializedView = class {
2776
2834
  this.sourceTables = options.selectTables.map(
2777
2835
  (t) => formatTableReference(t)
2778
2836
  );
2837
+ this.lifeCycle = options.lifeCycle;
2779
2838
  this.metadata = options.metadata ? { ...options.metadata } : {};
2780
2839
  if (!this.metadata.source) {
2781
2840
  const stack = new Error().stack;
@@ -3084,6 +3143,675 @@ function getView(name) {
3084
3143
  return getMooseInternal().views.get(name);
3085
3144
  }
3086
3145
  init_commons();
3146
+ var MOOSE_RUNTIME_ENV_PREFIX = "__MOOSE_RUNTIME_ENV__:";
3147
+ var mooseRuntimeEnv = {
3148
+ /**
3149
+ * Gets a value from an environment variable, with behavior depending on context.
3150
+ *
3151
+ * When IS_LOADING_INFRA_MAP=true (infrastructure loading):
3152
+ * Returns a marker string that Moose CLI will resolve later
3153
+ *
3154
+ * When IS_LOADING_INFRA_MAP is unset (function/workflow runtime):
3155
+ * Returns the actual value from the environment variable
3156
+ *
3157
+ * @param envVarName - Name of the environment variable to resolve
3158
+ * @returns Either a marker string or the actual environment variable value
3159
+ * @throws {Error} If the environment variable name is empty
3160
+ * @throws {Error} If the environment variable is not set (runtime mode only)
3161
+ *
3162
+ * @example
3163
+ * ```typescript
3164
+ * // Instead of this (evaluated at build time):
3165
+ * awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID
3166
+ *
3167
+ * // Use this (evaluated at runtime):
3168
+ * awsAccessKeyId: mooseRuntimeEnv.get("AWS_ACCESS_KEY_ID")
3169
+ * ```
3170
+ */
3171
+ get(envVarName) {
3172
+ if (!envVarName || envVarName.trim() === "") {
3173
+ throw new Error("Environment variable name cannot be empty");
3174
+ }
3175
+ const isLoadingInfraMap = process.env.IS_LOADING_INFRA_MAP === "true";
3176
+ if (isLoadingInfraMap) {
3177
+ return `${MOOSE_RUNTIME_ENV_PREFIX}${envVarName}`;
3178
+ } else {
3179
+ const value = process.env[envVarName];
3180
+ if (value === void 0) {
3181
+ throw new Error(
3182
+ `Environment variable '${envVarName}' is not set. This is required for runtime execution of functions/workflows.`
3183
+ );
3184
+ }
3185
+ return value;
3186
+ }
3187
+ }
3188
+ };
3189
+ var mooseEnvSecrets = mooseRuntimeEnv;
3190
+ function formatElapsedTime(ms) {
3191
+ if (ms < 1e3) {
3192
+ return `${Math.round(ms)} ms`;
3193
+ }
3194
+ const seconds = ms / 1e3;
3195
+ if (seconds < 60) {
3196
+ return `${seconds.toFixed(2)} seconds`;
3197
+ }
3198
+ const minutes = Math.floor(seconds / 60);
3199
+ const remainingSeconds = seconds % 60;
3200
+ return `${minutes} minutes and ${remainingSeconds.toFixed(2)} seconds`;
3201
+ }
3202
+ var MooseClient = class {
3203
+ query;
3204
+ workflow;
3205
+ constructor(queryClient, temporalClient) {
3206
+ this.query = queryClient;
3207
+ this.workflow = new WorkflowClient(temporalClient);
3208
+ }
3209
+ };
3210
+ var QueryClient = class {
3211
+ client;
3212
+ query_id_prefix;
3213
+ constructor(client, query_id_prefix) {
3214
+ this.client = client;
3215
+ this.query_id_prefix = query_id_prefix;
3216
+ }
3217
+ async execute(sql3) {
3218
+ const [query, query_params] = toQuery(sql3);
3219
+ console.log(`[QueryClient] | Query: ${toQueryPreview(sql3)}`);
3220
+ const start = performance.now();
3221
+ const result = await this.client.query({
3222
+ query,
3223
+ query_params,
3224
+ format: "JSONEachRow",
3225
+ query_id: this.query_id_prefix + randomUUID()
3226
+ // Note: wait_end_of_query deliberately NOT set here as this is used for SELECT queries
3227
+ // where response buffering would harm streaming performance and concurrency
3228
+ });
3229
+ const elapsedMs = performance.now() - start;
3230
+ console.log(
3231
+ `[QueryClient] | Query completed: ${formatElapsedTime(elapsedMs)}`
3232
+ );
3233
+ return result;
3234
+ }
3235
+ async command(sql3) {
3236
+ const [query, query_params] = toQuery(sql3);
3237
+ console.log(`[QueryClient] | Command: ${toQueryPreview(sql3)}`);
3238
+ const start = performance.now();
3239
+ const result = await this.client.command({
3240
+ query,
3241
+ query_params,
3242
+ query_id: this.query_id_prefix + randomUUID()
3243
+ });
3244
+ const elapsedMs = performance.now() - start;
3245
+ console.log(
3246
+ `[QueryClient] | Command completed: ${formatElapsedTime(elapsedMs)}`
3247
+ );
3248
+ return result;
3249
+ }
3250
+ };
3251
+ var WorkflowClient = class {
3252
+ client;
3253
+ constructor(temporalClient) {
3254
+ this.client = temporalClient;
3255
+ }
3256
+ async execute(name, input_data) {
3257
+ try {
3258
+ if (!this.client) {
3259
+ return {
3260
+ status: 404,
3261
+ body: `Temporal client not found. Is the feature flag enabled?`
3262
+ };
3263
+ }
3264
+ const config = await this.getWorkflowConfig(name);
3265
+ const [processedInput, workflowId] = this.processInputData(
3266
+ name,
3267
+ input_data
3268
+ );
3269
+ console.log(
3270
+ `WorkflowClient - starting workflow: ${name} with config ${JSON.stringify(config)} and input_data ${JSON.stringify(processedInput)}`
3271
+ );
3272
+ const handle = await this.client.workflow.start("ScriptWorkflow", {
3273
+ args: [
3274
+ { workflow_name: name, execution_mode: "start" },
3275
+ processedInput
3276
+ ],
3277
+ taskQueue: "typescript-script-queue",
3278
+ workflowId,
3279
+ workflowIdConflictPolicy: "FAIL",
3280
+ workflowIdReusePolicy: "ALLOW_DUPLICATE",
3281
+ retry: {
3282
+ // Temporal's maximumAttempts = total attempts (initial + retries)
3283
+ maximumAttempts: config.retries + 1
3284
+ },
3285
+ workflowRunTimeout: config.timeout
3286
+ });
3287
+ return {
3288
+ status: 200,
3289
+ body: `Workflow started: ${name}. View it in the Temporal dashboard: http://localhost:8080/namespaces/default/workflows/${workflowId}/${handle.firstExecutionRunId}/history`
3290
+ };
3291
+ } catch (error) {
3292
+ return {
3293
+ status: 400,
3294
+ body: `Error starting workflow: ${error}`
3295
+ };
3296
+ }
3297
+ }
3298
+ async terminate(workflowId) {
3299
+ try {
3300
+ if (!this.client) {
3301
+ return {
3302
+ status: 404,
3303
+ body: `Temporal client not found. Is the feature flag enabled?`
3304
+ };
3305
+ }
3306
+ const handle = this.client.workflow.getHandle(workflowId);
3307
+ await handle.terminate();
3308
+ return {
3309
+ status: 200,
3310
+ body: `Workflow terminated: ${workflowId}`
3311
+ };
3312
+ } catch (error) {
3313
+ return {
3314
+ status: 400,
3315
+ body: `Error terminating workflow: ${error}`
3316
+ };
3317
+ }
3318
+ }
3319
+ async getWorkflowConfig(name) {
3320
+ const workflows = await getWorkflows();
3321
+ const workflow = workflows.get(name);
3322
+ if (workflow) {
3323
+ return {
3324
+ retries: workflow.config.retries || 3,
3325
+ timeout: workflow.config.timeout || "1h"
3326
+ };
3327
+ }
3328
+ throw new Error(`Workflow config not found for ${name}`);
3329
+ }
3330
+ processInputData(name, input_data) {
3331
+ let workflowId = name;
3332
+ if (input_data) {
3333
+ const hash = createHash3("sha256").update(JSON.stringify(input_data)).digest("hex").slice(0, 16);
3334
+ workflowId = `${name}-${hash}`;
3335
+ }
3336
+ return [input_data, workflowId];
3337
+ }
3338
+ };
3339
+ async function getTemporalClient(temporalUrl, namespace, clientCert, clientKey, apiKey) {
3340
+ try {
3341
+ console.info(
3342
+ `<api> Using temporal_url: ${temporalUrl} and namespace: ${namespace}`
3343
+ );
3344
+ let connectionOptions = {
3345
+ address: temporalUrl,
3346
+ connectTimeout: "3s"
3347
+ };
3348
+ if (clientCert && clientKey) {
3349
+ console.log("Using TLS for secure Temporal");
3350
+ const cert = await fs.readFileSync(clientCert);
3351
+ const key = await fs.readFileSync(clientKey);
3352
+ connectionOptions.tls = {
3353
+ clientCertPair: { crt: cert, key }
3354
+ };
3355
+ } else if (apiKey) {
3356
+ console.log("Using API key for secure Temporal");
3357
+ connectionOptions.address = "us-west1.gcp.api.temporal.io:7233";
3358
+ connectionOptions.apiKey = apiKey;
3359
+ connectionOptions.tls = {};
3360
+ connectionOptions.metadata = {
3361
+ "temporal-namespace": namespace
3362
+ };
3363
+ }
3364
+ console.log(`<api> Connecting to Temporal at ${connectionOptions.address}`);
3365
+ const connection = await import_client2.Connection.connect(connectionOptions);
3366
+ const client = new import_client2.Client({ connection, namespace });
3367
+ console.log("<api> Connected to Temporal server");
3368
+ return client;
3369
+ } catch (error) {
3370
+ console.warn(`Failed to connect to Temporal. Is the feature flag enabled?`);
3371
+ console.warn(error);
3372
+ return void 0;
3373
+ }
3374
+ }
3375
+ var ApiHelpers = {
3376
+ column: (value) => ["Identifier", value],
3377
+ table: (value) => ["Identifier", value]
3378
+ };
3379
+ var ConsumptionHelpers = ApiHelpers;
3380
+ function joinQueries({
3381
+ values,
3382
+ separator = ",",
3383
+ prefix = "",
3384
+ suffix = ""
3385
+ }) {
3386
+ if (values.length === 0) {
3387
+ throw new TypeError(
3388
+ "Expected `join([])` to be called with an array of multiple elements, but got an empty array"
3389
+ );
3390
+ }
3391
+ return new Sql(
3392
+ [prefix, ...Array(values.length - 1).fill(separator), suffix],
3393
+ values
3394
+ );
3395
+ }
3396
+ function getMooseUtilsFromRequest(req) {
3397
+ console.warn(
3398
+ "[DEPRECATED] getMooseUtilsFromRequest() is deprecated. Import getMooseUtils from '@514labs/moose-lib' and call it without parameters: const { client, sql } = await getMooseUtils();"
3399
+ );
3400
+ return req.moose;
3401
+ }
3402
+ var getLegacyMooseUtils = getMooseUtilsFromRequest;
3403
+ function expressMiddleware() {
3404
+ console.warn(
3405
+ "[DEPRECATED] expressMiddleware() is deprecated. Use getMooseUtils() directly or rely on injectMooseUtils config."
3406
+ );
3407
+ return (req, res, next) => {
3408
+ if (!req.moose && req.raw && req.raw.moose) {
3409
+ req.moose = req.raw.moose;
3410
+ }
3411
+ next();
3412
+ };
3413
+ }
3414
+ var instance = null;
3415
+ var initPromise = null;
3416
+ var MooseCache = class _MooseCache {
3417
+ client;
3418
+ isConnected = false;
3419
+ keyPrefix;
3420
+ disconnectTimer = null;
3421
+ idleTimeout;
3422
+ connectPromise = null;
3423
+ constructor() {
3424
+ const redisUrl = process.env.MOOSE_REDIS_CONFIG__URL || "redis://127.0.0.1:6379";
3425
+ const prefix = process.env.MOOSE_REDIS_CONFIG__KEY_PREFIX || "MS";
3426
+ this.idleTimeout = parseInt(process.env.MOOSE_REDIS_CONFIG__IDLE_TIMEOUT || "30", 10) * 1e3;
3427
+ this.keyPrefix = `${prefix}::moosecache::`;
3428
+ this.client = (0, import_redis.createClient)({
3429
+ url: redisUrl
3430
+ });
3431
+ process.on("SIGTERM", this.gracefulShutdown);
3432
+ process.on("SIGINT", this.gracefulShutdown);
3433
+ this.client.on("error", async (err) => {
3434
+ console.error("TS Redis client error:", err);
3435
+ await this.disconnect();
3436
+ });
3437
+ this.client.on("connect", () => {
3438
+ this.isConnected = true;
3439
+ console.log("TS Redis client connected");
3440
+ });
3441
+ this.client.on("end", () => {
3442
+ this.isConnected = false;
3443
+ console.log("TS Redis client disconnected");
3444
+ this.clearDisconnectTimer();
3445
+ });
3446
+ }
3447
+ clearDisconnectTimer() {
3448
+ if (this.disconnectTimer) {
3449
+ clearTimeout(this.disconnectTimer);
3450
+ this.disconnectTimer = null;
3451
+ }
3452
+ }
3453
+ resetDisconnectTimer() {
3454
+ this.clearDisconnectTimer();
3455
+ this.disconnectTimer = setTimeout(async () => {
3456
+ if (this.isConnected) {
3457
+ console.log("TS Redis client disconnecting due to inactivity");
3458
+ await this.disconnect();
3459
+ }
3460
+ }, this.idleTimeout);
3461
+ }
3462
+ async ensureConnected() {
3463
+ if (!this.isConnected) {
3464
+ await this.connect();
3465
+ }
3466
+ this.resetDisconnectTimer();
3467
+ }
3468
+ async connect() {
3469
+ if (this.isConnected) {
3470
+ return;
3471
+ }
3472
+ if (this.connectPromise) {
3473
+ return this.connectPromise;
3474
+ }
3475
+ this.connectPromise = (async () => {
3476
+ try {
3477
+ await this.client.connect();
3478
+ this.resetDisconnectTimer();
3479
+ } catch (error) {
3480
+ this.connectPromise = null;
3481
+ throw error;
3482
+ }
3483
+ })();
3484
+ return this.connectPromise;
3485
+ }
3486
+ async gracefulShutdown() {
3487
+ if (this.isConnected) {
3488
+ await this.disconnect();
3489
+ }
3490
+ process.exit(0);
3491
+ }
3492
+ getPrefixedKey(key) {
3493
+ return `${this.keyPrefix}${key}`;
3494
+ }
3495
+ /**
3496
+ * Gets the singleton instance of MooseCache. Creates a new instance if one doesn't exist.
3497
+ * The client will automatically connect to Redis and handle reconnection if needed.
3498
+ *
3499
+ * @returns Promise<MooseCache> The singleton instance of MooseCache
3500
+ * @example
3501
+ * const cache = await MooseCache.get();
3502
+ */
3503
+ static async get() {
3504
+ if (instance) {
3505
+ return instance;
3506
+ }
3507
+ if (initPromise) {
3508
+ return initPromise;
3509
+ }
3510
+ initPromise = (async () => {
3511
+ try {
3512
+ const newInstance = new _MooseCache();
3513
+ await newInstance.connect();
3514
+ instance = newInstance;
3515
+ return newInstance;
3516
+ } catch (error) {
3517
+ initPromise = null;
3518
+ throw error;
3519
+ }
3520
+ })();
3521
+ return initPromise;
3522
+ }
3523
+ /**
3524
+ * Sets a value in the cache. Objects are automatically JSON stringified.
3525
+ *
3526
+ * @param key - The key to store the value under
3527
+ * @param value - The value to store. Can be a string or any object (will be JSON stringified)
3528
+ * @param ttlSeconds - Optional time-to-live in seconds. If not provided, defaults to 1 hour (3600 seconds).
3529
+ * Must be a non-negative number. If 0, the key will expire immediately.
3530
+ * @example
3531
+ * // Store a string
3532
+ * await cache.set("foo", "bar");
3533
+ *
3534
+ * // Store an object with custom TTL
3535
+ * await cache.set("foo:config", { baz: 123, qux: true }, 60); // expires in 1 minute
3536
+ *
3537
+ * // This is essentially a get-set, which returns the previous value if it exists.
3538
+ * // You can create logic to only do work for the first time.
3539
+ * const value = await cache.set("testSessionId", "true");
3540
+ * if (value) {
3541
+ * // Cache was set before, return
3542
+ * } else {
3543
+ * // Cache was set for first time, do work
3544
+ * }
3545
+ */
3546
+ async set(key, value, ttlSeconds) {
3547
+ try {
3548
+ if (ttlSeconds !== void 0 && ttlSeconds < 0) {
3549
+ throw new Error("ttlSeconds must be a non-negative number");
3550
+ }
3551
+ await this.ensureConnected();
3552
+ const prefixedKey = this.getPrefixedKey(key);
3553
+ const stringValue = typeof value === "object" ? JSON.stringify(value) : value;
3554
+ const ttl = ttlSeconds ?? 3600;
3555
+ return await this.client.set(prefixedKey, stringValue, {
3556
+ EX: ttl,
3557
+ GET: true
3558
+ });
3559
+ } catch (error) {
3560
+ console.error(`Error setting cache key ${key}:`, error);
3561
+ throw error;
3562
+ }
3563
+ }
3564
+ /**
3565
+ * Retrieves a value from the cache. Attempts to parse the value as JSON if possible.
3566
+ *
3567
+ * @param key - The key to retrieve
3568
+ * @returns Promise<T | null> The value, parsed as type T if it was JSON, or as string if not. Returns null if key doesn't exist
3569
+ * @example
3570
+ * // Get a string
3571
+ * const value = await cache.get("foo");
3572
+ *
3573
+ * // Get and parse an object with type safety
3574
+ * interface Config { baz: number; qux: boolean; }
3575
+ * const config = await cache.get<Config>("foo:config");
3576
+ */
3577
+ async get(key) {
3578
+ try {
3579
+ await this.ensureConnected();
3580
+ const prefixedKey = this.getPrefixedKey(key);
3581
+ const value = await this.client.get(prefixedKey);
3582
+ if (value === null) return null;
3583
+ try {
3584
+ const parsed = JSON.parse(value);
3585
+ if (typeof parsed === "object" && parsed !== null) {
3586
+ return parsed;
3587
+ }
3588
+ return value;
3589
+ } catch {
3590
+ return value;
3591
+ }
3592
+ } catch (error) {
3593
+ console.error(`Error getting cache key ${key}:`, error);
3594
+ throw error;
3595
+ }
3596
+ }
3597
+ /**
3598
+ * Deletes a specific key from the cache.
3599
+ *
3600
+ * @param key - The key to delete
3601
+ * @example
3602
+ * await cache.delete("foo");
3603
+ */
3604
+ async delete(key) {
3605
+ try {
3606
+ await this.ensureConnected();
3607
+ const prefixedKey = this.getPrefixedKey(key);
3608
+ await this.client.del(prefixedKey);
3609
+ } catch (error) {
3610
+ console.error(`Error deleting cache key ${key}:`, error);
3611
+ throw error;
3612
+ }
3613
+ }
3614
+ /**
3615
+ * Deletes all keys that start with the given prefix.
3616
+ *
3617
+ * @param keyPrefix - The prefix of keys to delete
3618
+ * @example
3619
+ * // Delete all keys starting with "foo"
3620
+ * await cache.clearKeys("foo");
3621
+ */
3622
+ async clearKeys(keyPrefix) {
3623
+ try {
3624
+ await this.ensureConnected();
3625
+ const prefixedKey = this.getPrefixedKey(keyPrefix);
3626
+ const keys = await this.client.keys(`${prefixedKey}*`);
3627
+ if (keys.length > 0) {
3628
+ await this.client.del(keys);
3629
+ }
3630
+ } catch (error) {
3631
+ console.error(
3632
+ `Error clearing cache keys with prefix ${keyPrefix}:`,
3633
+ error
3634
+ );
3635
+ throw error;
3636
+ }
3637
+ }
3638
+ /**
3639
+ * Deletes all keys in the cache
3640
+ *
3641
+ * @example
3642
+ * await cache.clear();
3643
+ */
3644
+ async clear() {
3645
+ try {
3646
+ await this.ensureConnected();
3647
+ const keys = await this.client.keys(`${this.keyPrefix}*`);
3648
+ if (keys.length > 0) {
3649
+ await this.client.del(keys);
3650
+ }
3651
+ } catch (error) {
3652
+ console.error("Error clearing cache:", error);
3653
+ throw error;
3654
+ }
3655
+ }
3656
+ /**
3657
+ * Manually disconnects the Redis client. The client will automatically reconnect
3658
+ * when the next operation is performed.
3659
+ *
3660
+ * @example
3661
+ * await cache.disconnect();
3662
+ */
3663
+ async disconnect() {
3664
+ this.clearDisconnectTimer();
3665
+ this.connectPromise = null;
3666
+ if (this.isConnected) {
3667
+ await this.client.quit();
3668
+ }
3669
+ }
3670
+ };
3671
+ init_commons();
3672
+ var standaloneUtils = null;
3673
+ var initPromise2 = null;
3674
+ var toClientConfig = (config) => ({
3675
+ ...config,
3676
+ useSSL: config.useSSL ? "true" : "false"
3677
+ });
3678
+ async function getMooseUtils(req) {
3679
+ if (req !== void 0) {
3680
+ console.warn(
3681
+ "[DEPRECATED] getMooseUtils(req) no longer requires a request parameter. Use getMooseUtils() instead."
3682
+ );
3683
+ }
3684
+ const runtimeContext = globalThis._mooseRuntimeContext;
3685
+ if (runtimeContext) {
3686
+ return {
3687
+ client: runtimeContext.client,
3688
+ sql,
3689
+ jwt: runtimeContext.jwt
3690
+ };
3691
+ }
3692
+ if (standaloneUtils) {
3693
+ return standaloneUtils;
3694
+ }
3695
+ if (initPromise2) {
3696
+ return initPromise2;
3697
+ }
3698
+ initPromise2 = (async () => {
3699
+ await Promise.resolve().then(() => (init_runtime(), runtime_exports));
3700
+ const configRegistry = globalThis._mooseConfigRegistry;
3701
+ if (!configRegistry) {
3702
+ throw new Error(
3703
+ "Moose not initialized. Ensure you're running within a Moose app or have proper configuration set up."
3704
+ );
3705
+ }
3706
+ const clickhouseConfig = await configRegistry.getStandaloneClickhouseConfig();
3707
+ const clickhouseClient = getClickhouseClient(
3708
+ toClientConfig(clickhouseConfig)
3709
+ );
3710
+ const queryClient = new QueryClient(clickhouseClient, "standalone");
3711
+ const mooseClient = new MooseClient(queryClient);
3712
+ standaloneUtils = {
3713
+ client: mooseClient,
3714
+ sql,
3715
+ jwt: void 0
3716
+ };
3717
+ return standaloneUtils;
3718
+ })();
3719
+ try {
3720
+ return await initPromise2;
3721
+ } finally {
3722
+ initPromise2 = null;
3723
+ }
3724
+ }
3725
+ async function getMooseClients(config) {
3726
+ console.warn(
3727
+ "[DEPRECATED] getMooseClients() is deprecated. Use getMooseUtils() instead."
3728
+ );
3729
+ if (config && Object.keys(config).length > 0) {
3730
+ await Promise.resolve().then(() => (init_runtime(), runtime_exports));
3731
+ const configRegistry = globalThis._mooseConfigRegistry;
3732
+ if (!configRegistry) {
3733
+ throw new Error(
3734
+ "Configuration registry not initialized. Ensure the Moose framework is properly set up."
3735
+ );
3736
+ }
3737
+ const clickhouseConfig = await configRegistry.getStandaloneClickhouseConfig(config);
3738
+ const clickhouseClient = getClickhouseClient(
3739
+ toClientConfig(clickhouseConfig)
3740
+ );
3741
+ const queryClient = new QueryClient(clickhouseClient, "standalone");
3742
+ const mooseClient = new MooseClient(queryClient);
3743
+ return { client: mooseClient };
3744
+ }
3745
+ const utils = await getMooseUtils();
3746
+ return { client: utils.client };
3747
+ }
3748
+ function jsonDateReviver(key, value) {
3749
+ const iso8601Format = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)$/;
3750
+ if (typeof value === "string" && iso8601Format.test(value)) {
3751
+ return new Date(value);
3752
+ }
3753
+ return value;
3754
+ }
3755
+ function parseCSV(content2, config) {
3756
+ return new Promise((resolve2, reject) => {
3757
+ const results = [];
3758
+ parse2(content2, {
3759
+ delimiter: config.delimiter,
3760
+ columns: config.columns ?? true,
3761
+ skip_empty_lines: config.skipEmptyLines ?? true,
3762
+ trim: config.trim ?? true
3763
+ }).on("data", (row) => {
3764
+ results.push(row);
3765
+ }).on("end", () => {
3766
+ resolve2(results);
3767
+ }).on("error", (error) => {
3768
+ reject(error);
3769
+ });
3770
+ });
3771
+ }
3772
+ function parseJSON(content2, config = {}) {
3773
+ try {
3774
+ const parsed = JSON.parse(content2, config.reviver);
3775
+ if (Array.isArray(parsed)) {
3776
+ return parsed;
3777
+ } else {
3778
+ return [parsed];
3779
+ }
3780
+ } catch (error) {
3781
+ throw new Error(
3782
+ `Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`
3783
+ );
3784
+ }
3785
+ }
3786
+ function parseJSONWithDates(content2) {
3787
+ return parseJSON(content2, { reviver: jsonDateReviver });
3788
+ }
3789
+ function isValidCSVDelimiter(delimiter) {
3790
+ return delimiter.length === 1 && !/\s/.test(delimiter);
3791
+ }
3792
+ var CSV_DELIMITERS = {
3793
+ COMMA: ",",
3794
+ TAB: " ",
3795
+ SEMICOLON: ";",
3796
+ PIPE: "|"
3797
+ };
3798
+ var DEFAULT_CSV_CONFIG = {
3799
+ delimiter: CSV_DELIMITERS.COMMA,
3800
+ columns: true,
3801
+ skipEmptyLines: true,
3802
+ trim: true
3803
+ };
3804
+ var DEFAULT_JSON_CONFIG = {
3805
+ reviver: jsonDateReviver
3806
+ };
3807
+ var DataSource = class {
3808
+ name;
3809
+ supportsIncremental;
3810
+ constructor(config) {
3811
+ this.name = config.name;
3812
+ this.supportsIncremental = config.supportsIncremental ?? false;
3813
+ }
3814
+ };
3087
3815
 
3088
3816
  // src/index.ts
3089
3817
  var _pendingClickHouseConfig = null;
@@ -3120,9 +3848,11 @@ function configureClickHouse(config) {
3120
3848
  export {
3121
3849
  ACKs,
3122
3850
  Api,
3851
+ ApiHelpers,
3123
3852
  CSV_DELIMITERS,
3124
3853
  ClickHouseEngines,
3125
3854
  ConsumptionApi,
3855
+ ConsumptionHelpers,
3126
3856
  DEFAULT_CSV_CONFIG,
3127
3857
  DEFAULT_JSON_CONFIG,
3128
3858
  DataSource,
@@ -3136,7 +3866,10 @@ export {
3136
3866
  MAX_RETRY_TIME_MS,
3137
3867
  MOOSE_RUNTIME_ENV_PREFIX,
3138
3868
  MaterializedView,
3869
+ MooseCache,
3870
+ MooseClient,
3139
3871
  OlapTable,
3872
+ QueryClient,
3140
3873
  RETRY_FACTOR_PRODUCER,
3141
3874
  RETRY_INITIAL_TIME_MS,
3142
3875
  Sql,
@@ -3146,24 +3879,35 @@ export {
3146
3879
  View,
3147
3880
  WebApp,
3148
3881
  Workflow,
3882
+ WorkflowClient,
3149
3883
  antiCachePath,
3150
3884
  cliLog,
3151
3885
  compilerLog,
3152
3886
  configureClickHouse,
3153
3887
  createClickhouseParameter,
3888
+ createProducerConfig,
3889
+ expressMiddleware,
3154
3890
  getApi,
3155
3891
  getApis,
3892
+ getClickhouseClient,
3156
3893
  getFileName,
3157
3894
  getIngestApi,
3158
3895
  getIngestApis,
3896
+ getKafkaClient,
3897
+ getKafkaProducer,
3898
+ getLegacyMooseUtils,
3159
3899
  getMaterializedView,
3160
3900
  getMaterializedViews,
3901
+ getMooseClients,
3902
+ getMooseUtils,
3903
+ getMooseUtilsFromRequest,
3161
3904
  getSqlResource,
3162
3905
  getSqlResources,
3163
3906
  getStream,
3164
3907
  getStreams,
3165
3908
  getTable,
3166
3909
  getTables,
3910
+ getTemporalClient,
3167
3911
  getValueFromParameter,
3168
3912
  getView,
3169
3913
  getViews,
@@ -3172,6 +3916,7 @@ export {
3172
3916
  getWorkflow,
3173
3917
  getWorkflows2 as getWorkflows,
3174
3918
  isValidCSVDelimiter,
3919
+ joinQueries,
3175
3920
  logError,
3176
3921
  mapToClickHouseType,
3177
3922
  mapTstoJs,
@@ -3181,6 +3926,7 @@ export {
3181
3926
  parseJSON,
3182
3927
  parseJSONWithDates,
3183
3928
  quoteIdentifier,
3929
+ rewriteImportExtensions,
3184
3930
  sql,
3185
3931
  toQuery,
3186
3932
  toQueryPreview,