@conduitplatform/module-tools 0.17.0-alpha.3 → 0.17.0-alpha.7

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.cts CHANGED
@@ -163,6 +163,7 @@ declare abstract class ManagedModule<T> extends ConduitServiceModule {
163
163
  private _pendingConfigUpdates;
164
164
  private _processingConfig;
165
165
  protected constructor(moduleName: string, peerManifestRoot?: string);
166
+ protected get configInitialized(): boolean;
166
167
  get name(): string;
167
168
  get address(): string;
168
169
  start(): Promise<void>;
@@ -342,7 +343,7 @@ declare function wrapGrpcFunctions(functions: {
342
343
  [name: string]: Function;
343
344
  };
344
345
 
345
- declare function createParsedRouterRequest(params: Params, urlParams?: Params, queryParams?: Params, bodyParams?: Params, path?: string, headers?: Headers, context?: Context, cookies?: Cookies): ParsedRouterRequest;
346
+ declare function createParsedRouterRequest(params: Params, urlParams?: Params, queryParams?: Params, bodyParams?: Params, path?: string, headers?: Headers, context?: Context, cookies?: Cookies, rawHeaders?: string[], rawBody?: Buffer): ParsedRouterRequest;
346
347
 
347
348
  type RouterRequestHandler = (call: ParsedRouterRequest) => Promise<UnparsedRouterResponse>;
348
349
  type RouterRequestHandlerCallback = (call: ParsedRouterRequest, callback: (response: UnparsedRouterResponse) => void) => Promise<UnparsedRouterResponse | undefined | void>;
@@ -406,6 +407,8 @@ declare class RouteBuilder {
406
407
  bodyParams(params: ConduitModel): RouteBuilder;
407
408
  strictParams(strict: boolean): RouteBuilder;
408
409
  rateLimit(maxRequests: number, resetInterval: number): RouteBuilder;
410
+ captureRawBody(capture: boolean): RouteBuilder;
411
+ captureRawHeaders(capture: boolean): RouteBuilder;
409
412
  return(name: string, fields: ConduitReturn): RouteBuilder;
410
413
  handler(fn: RequestHandlers): RouteBuilder;
411
414
  add(): void;
@@ -482,9 +485,26 @@ interface ImportModelAdapter {
482
485
  */
483
486
  declare function importModel(adapter: ImportModelAdapter, records: Record<string, unknown>[], options?: SanitizeForExportOptions): Promise<ImportResultEntry>;
484
487
 
488
+ declare const convictConfigParser: (config: Indexable) => Indexable;
489
+
490
+ declare function containsRedactedMarker(value: unknown): boolean;
491
+ declare function redactSensitiveConfig<T>(config: T, schema?: unknown): T;
492
+ declare function restoreRedactedSecrets<T>(incoming: T, current: T, schema?: unknown): T;
493
+
494
+ declare function stableConfigJson(value: unknown): string;
495
+ declare function storedConfigsEquivalent(left: unknown, right: unknown): boolean;
496
+ declare function reconcileStoredModuleConfig<T>(args: {
497
+ stored: T;
498
+ migrated: T;
499
+ configureOverride: (config: T) => Promise<T>;
500
+ }): Promise<{
501
+ config: T;
502
+ persisted: boolean;
503
+ }>;
504
+
485
505
  declare class ModuleError extends GrpcError {
486
506
  debugLogInfo?: string;
487
507
  constructor(errorDefinition: ModuleErrorDefinition, debugLogInfo?: string);
488
508
  }
489
509
 
490
- export { ConduitActiveSchema, ConduitBoolean, ConduitDate, ConduitJson, ConduitNumber, ConduitObjectId, type ConduitPackageJson, type ConduitPeerWatchEntry, type ConduitPeersManifest, ConduitRelation, type ConduitService, ConduitServiceModule, ConduitString, ConfigController, DEFAULT_STRIP_FIELDS, type ExportModelAdapter, type ExportResult, type ExportableResource, GrpcServer, type ImportModelAdapter, type ImportResult, type ImportResultEntry, ManagedModule, ModuleError, ModuleLifecycleStage, type RequestHandlers, RouteBuilder, type RouterRequestHandler, type RouterRequestHandlerCallback, RoutingManager, type SanitizeForExportOptions, type SocketEventHandler, type SocketRequestHandler, type SocketRequestHandlerCallback, type SocketRequestHandlers, addServiceToServer, createParsedRouterRequest, createServer, exportModel, importModel, initializeSdk, linearBackoffTimeout, linearBackoffTimeoutAsync, merge, readConduitPeersManifest, sanitizeDocumentsForExport, stripInternalFields, wrapFunctionsAsync, wrapGrpcFunctions, wrapRouterGrpcFunction };
510
+ export { ConduitActiveSchema, ConduitBoolean, ConduitDate, ConduitJson, ConduitNumber, ConduitObjectId, type ConduitPackageJson, type ConduitPeerWatchEntry, type ConduitPeersManifest, ConduitRelation, type ConduitService, ConduitServiceModule, ConduitString, ConfigController, DEFAULT_STRIP_FIELDS, type ExportModelAdapter, type ExportResult, type ExportableResource, GrpcServer, type ImportModelAdapter, type ImportResult, type ImportResultEntry, ManagedModule, ModuleError, ModuleLifecycleStage, type RequestHandlers, RouteBuilder, type RouterRequestHandler, type RouterRequestHandlerCallback, RoutingManager, type SanitizeForExportOptions, type SocketEventHandler, type SocketRequestHandler, type SocketRequestHandlerCallback, type SocketRequestHandlers, addServiceToServer, containsRedactedMarker, convictConfigParser, createParsedRouterRequest, createServer, exportModel, importModel, initializeSdk, linearBackoffTimeout, linearBackoffTimeoutAsync, merge, readConduitPeersManifest, reconcileStoredModuleConfig, redactSensitiveConfig, restoreRedactedSecrets, sanitizeDocumentsForExport, stableConfigJson, storedConfigsEquivalent, stripInternalFields, wrapFunctionsAsync, wrapGrpcFunctions, wrapRouterGrpcFunction };
package/dist/index.d.ts CHANGED
@@ -163,6 +163,7 @@ declare abstract class ManagedModule<T> extends ConduitServiceModule {
163
163
  private _pendingConfigUpdates;
164
164
  private _processingConfig;
165
165
  protected constructor(moduleName: string, peerManifestRoot?: string);
166
+ protected get configInitialized(): boolean;
166
167
  get name(): string;
167
168
  get address(): string;
168
169
  start(): Promise<void>;
@@ -342,7 +343,7 @@ declare function wrapGrpcFunctions(functions: {
342
343
  [name: string]: Function;
343
344
  };
344
345
 
345
- declare function createParsedRouterRequest(params: Params, urlParams?: Params, queryParams?: Params, bodyParams?: Params, path?: string, headers?: Headers, context?: Context, cookies?: Cookies): ParsedRouterRequest;
346
+ declare function createParsedRouterRequest(params: Params, urlParams?: Params, queryParams?: Params, bodyParams?: Params, path?: string, headers?: Headers, context?: Context, cookies?: Cookies, rawHeaders?: string[], rawBody?: Buffer): ParsedRouterRequest;
346
347
 
347
348
  type RouterRequestHandler = (call: ParsedRouterRequest) => Promise<UnparsedRouterResponse>;
348
349
  type RouterRequestHandlerCallback = (call: ParsedRouterRequest, callback: (response: UnparsedRouterResponse) => void) => Promise<UnparsedRouterResponse | undefined | void>;
@@ -406,6 +407,8 @@ declare class RouteBuilder {
406
407
  bodyParams(params: ConduitModel): RouteBuilder;
407
408
  strictParams(strict: boolean): RouteBuilder;
408
409
  rateLimit(maxRequests: number, resetInterval: number): RouteBuilder;
410
+ captureRawBody(capture: boolean): RouteBuilder;
411
+ captureRawHeaders(capture: boolean): RouteBuilder;
409
412
  return(name: string, fields: ConduitReturn): RouteBuilder;
410
413
  handler(fn: RequestHandlers): RouteBuilder;
411
414
  add(): void;
@@ -482,9 +485,26 @@ interface ImportModelAdapter {
482
485
  */
483
486
  declare function importModel(adapter: ImportModelAdapter, records: Record<string, unknown>[], options?: SanitizeForExportOptions): Promise<ImportResultEntry>;
484
487
 
488
+ declare const convictConfigParser: (config: Indexable) => Indexable;
489
+
490
+ declare function containsRedactedMarker(value: unknown): boolean;
491
+ declare function redactSensitiveConfig<T>(config: T, schema?: unknown): T;
492
+ declare function restoreRedactedSecrets<T>(incoming: T, current: T, schema?: unknown): T;
493
+
494
+ declare function stableConfigJson(value: unknown): string;
495
+ declare function storedConfigsEquivalent(left: unknown, right: unknown): boolean;
496
+ declare function reconcileStoredModuleConfig<T>(args: {
497
+ stored: T;
498
+ migrated: T;
499
+ configureOverride: (config: T) => Promise<T>;
500
+ }): Promise<{
501
+ config: T;
502
+ persisted: boolean;
503
+ }>;
504
+
485
505
  declare class ModuleError extends GrpcError {
486
506
  debugLogInfo?: string;
487
507
  constructor(errorDefinition: ModuleErrorDefinition, debugLogInfo?: string);
488
508
  }
489
509
 
490
- export { ConduitActiveSchema, ConduitBoolean, ConduitDate, ConduitJson, ConduitNumber, ConduitObjectId, type ConduitPackageJson, type ConduitPeerWatchEntry, type ConduitPeersManifest, ConduitRelation, type ConduitService, ConduitServiceModule, ConduitString, ConfigController, DEFAULT_STRIP_FIELDS, type ExportModelAdapter, type ExportResult, type ExportableResource, GrpcServer, type ImportModelAdapter, type ImportResult, type ImportResultEntry, ManagedModule, ModuleError, ModuleLifecycleStage, type RequestHandlers, RouteBuilder, type RouterRequestHandler, type RouterRequestHandlerCallback, RoutingManager, type SanitizeForExportOptions, type SocketEventHandler, type SocketRequestHandler, type SocketRequestHandlerCallback, type SocketRequestHandlers, addServiceToServer, createParsedRouterRequest, createServer, exportModel, importModel, initializeSdk, linearBackoffTimeout, linearBackoffTimeoutAsync, merge, readConduitPeersManifest, sanitizeDocumentsForExport, stripInternalFields, wrapFunctionsAsync, wrapGrpcFunctions, wrapRouterGrpcFunction };
510
+ export { ConduitActiveSchema, ConduitBoolean, ConduitDate, ConduitJson, ConduitNumber, ConduitObjectId, type ConduitPackageJson, type ConduitPeerWatchEntry, type ConduitPeersManifest, ConduitRelation, type ConduitService, ConduitServiceModule, ConduitString, ConfigController, DEFAULT_STRIP_FIELDS, type ExportModelAdapter, type ExportResult, type ExportableResource, GrpcServer, type ImportModelAdapter, type ImportResult, type ImportResultEntry, ManagedModule, ModuleError, ModuleLifecycleStage, type RequestHandlers, RouteBuilder, type RouterRequestHandler, type RouterRequestHandlerCallback, RoutingManager, type SanitizeForExportOptions, type SocketEventHandler, type SocketRequestHandler, type SocketRequestHandlerCallback, type SocketRequestHandlers, addServiceToServer, containsRedactedMarker, convictConfigParser, createParsedRouterRequest, createServer, exportModel, importModel, initializeSdk, linearBackoffTimeout, linearBackoffTimeoutAsync, merge, readConduitPeersManifest, reconcileStoredModuleConfig, redactSensitiveConfig, restoreRedactedSecrets, sanitizeDocumentsForExport, stableConfigJson, storedConfigsEquivalent, stripInternalFields, wrapFunctionsAsync, wrapGrpcFunctions, wrapRouterGrpcFunction };
package/dist/index.esm.js CHANGED
@@ -199,7 +199,7 @@ function addServiceToServer(server, protoPath, descriptorObject, functions) {
199
199
  // src/helpers/wrapGrpcFunctions.ts
200
200
  import { createVerifier } from "fast-jwt";
201
201
  import { status } from "@grpc/grpc-js";
202
- import { ConduitGrpcSdk } from "@conduitplatform/grpc-sdk";
202
+ import { ConduitGrpcSdk, GrpcError } from "@conduitplatform/grpc-sdk";
203
203
  function wrapGrpcFunctions(functions, postponeRestart, noAuth = false) {
204
204
  const grpcKey = process.env.GRPC_KEY;
205
205
  const wrappedFunctions = {};
@@ -232,11 +232,19 @@ function wrapGrpcFunctions(functions, postponeRestart, noAuth = false) {
232
232
  try {
233
233
  invoked = functions[name](call, callback);
234
234
  } catch (error) {
235
- return throwError(callback, error.message);
235
+ return throwError(
236
+ callback,
237
+ error.message,
238
+ error instanceof GrpcError ? error.code : status.INTERNAL
239
+ );
236
240
  }
237
241
  if (typeof invoked?.then === "function") {
238
242
  invoked.then().catch((error) => {
239
- return throwError(callback, error.message);
243
+ return throwError(
244
+ callback,
245
+ error.message,
246
+ error instanceof GrpcError ? error.code : status.INTERNAL
247
+ );
240
248
  });
241
249
  }
242
250
  };
@@ -250,7 +258,7 @@ function throwError(callback, message, code = status.INTERNAL) {
250
258
  }
251
259
 
252
260
  // src/helpers/GrpcToParsedRouterRequest.ts
253
- function createParsedRouterRequest(params, urlParams, queryParams, bodyParams, path5, headers, context, cookies) {
261
+ function createParsedRouterRequest(params, urlParams, queryParams, bodyParams, path5, headers, context, cookies, rawHeaders, rawBody) {
254
262
  return {
255
263
  request: {
256
264
  params,
@@ -259,6 +267,8 @@ function createParsedRouterRequest(params, urlParams, queryParams, bodyParams, p
259
267
  bodyParams: bodyParams ?? {},
260
268
  path: path5 ?? "",
261
269
  headers,
270
+ rawHeaders: rawHeaders ?? [],
271
+ rawBody: rawBody ?? Buffer.alloc(0),
262
272
  context: context ?? {},
263
273
  cookies: cookies ?? {}
264
274
  }
@@ -469,6 +479,14 @@ var RouteBuilder = class {
469
479
  this._options.rateLimit = { maxRequests, resetInterval };
470
480
  return this;
471
481
  }
482
+ captureRawBody(capture) {
483
+ this._options.captureRawBody = capture;
484
+ return this;
485
+ }
486
+ captureRawHeaders(capture) {
487
+ this._options.captureRawHeaders = capture;
488
+ return this;
489
+ }
472
490
  return(name, fields) {
473
491
  this._returns = new ConduitRouteReturnDefinition(name, fields);
474
492
  return this;
@@ -620,6 +638,12 @@ function wrapRouterGrpcFunction(fun, routerType) {
620
638
  routerRequest = !call.request.hasOwnProperty("event");
621
639
  if (routerRequest) {
622
640
  call.request.headers = parseRequestData(call.request.headers);
641
+ call.request.rawHeaders = call.request.rawHeaders ? JSON.parse(call.request.rawHeaders) : [];
642
+ if (call.request.rawBody && !Buffer.isBuffer(call.request.rawBody)) {
643
+ call.request.rawBody = Buffer.from(call.request.rawBody);
644
+ } else if (!call.request.rawBody) {
645
+ call.request.rawBody = Buffer.alloc(0);
646
+ }
623
647
  }
624
648
  } catch (e) {
625
649
  ConduitGrpcSdk3.Metrics?.increment(`${routerType}_grpc_errors_total`);
@@ -1735,6 +1759,110 @@ var convictConfigParser = (config) => {
1735
1759
  return config;
1736
1760
  };
1737
1761
 
1762
+ // src/utilities/redactSensitiveConfig.ts
1763
+ var WELL_KNOWN_SECRET_KEYS = /^(apiKey|api_key|password|secret|privateKey|private_key)$/i;
1764
+ function isRecord(value) {
1765
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1766
+ }
1767
+ function isSchemaLeaf(value) {
1768
+ return isRecord(value) && ("default" in value || "format" in value || "type" in value) && !isRecord(value._cvtProperties);
1769
+ }
1770
+ function isSensitiveLeaf(value) {
1771
+ return isSchemaLeaf(value) && value.sensitive === true;
1772
+ }
1773
+ function unwrapSchema(schema) {
1774
+ if (isRecord(schema) && isRecord(schema._cvtProperties)) {
1775
+ return schema._cvtProperties;
1776
+ }
1777
+ return schema;
1778
+ }
1779
+ var REDACTED_MARKER = "[REDACTED]";
1780
+ function containsRedactedMarker(value) {
1781
+ if (value === REDACTED_MARKER) return true;
1782
+ if (Array.isArray(value)) {
1783
+ return value.some(containsRedactedMarker);
1784
+ }
1785
+ if (!isRecord(value)) return false;
1786
+ return Object.values(value).some(containsRedactedMarker);
1787
+ }
1788
+ function redactSensitiveConfig(config, schema) {
1789
+ if (!isRecord(config)) return config;
1790
+ const redacted = Array.isArray(config) ? [...config] : { ...config };
1791
+ const node = unwrapSchema(schema);
1792
+ for (const [key, value] of Object.entries(redacted)) {
1793
+ const childSchema = isRecord(node) ? node[key] : void 0;
1794
+ if (isSensitiveLeaf(childSchema) || WELL_KNOWN_SECRET_KEYS.test(key)) {
1795
+ if (typeof value === "string" && value.length > 0) {
1796
+ redacted[key] = REDACTED_MARKER;
1797
+ }
1798
+ continue;
1799
+ }
1800
+ if (isRecord(value) || Array.isArray(value)) {
1801
+ redacted[key] = redactSensitiveConfig(
1802
+ value,
1803
+ childSchema
1804
+ );
1805
+ }
1806
+ }
1807
+ return redacted;
1808
+ }
1809
+ function restoreRedactedSecrets(incoming, current, schema) {
1810
+ if (Array.isArray(incoming) && Array.isArray(current)) {
1811
+ return incoming.map(
1812
+ (item, index) => restoreRedactedSecrets(item, current[index], schema)
1813
+ );
1814
+ }
1815
+ if (!isRecord(incoming) || !isRecord(current)) return incoming;
1816
+ const restored = { ...incoming };
1817
+ const node = unwrapSchema(schema);
1818
+ for (const [key, value] of Object.entries(restored)) {
1819
+ const childSchema = isRecord(node) ? node[key] : void 0;
1820
+ const currentValue = current[key];
1821
+ if (isSensitiveLeaf(childSchema) || WELL_KNOWN_SECRET_KEYS.test(key)) {
1822
+ if (value === REDACTED_MARKER && typeof currentValue === "string" && currentValue.length > 0 && currentValue !== REDACTED_MARKER) {
1823
+ restored[key] = currentValue;
1824
+ }
1825
+ continue;
1826
+ }
1827
+ if ((isRecord(value) || Array.isArray(value)) && (isRecord(currentValue) || Array.isArray(currentValue))) {
1828
+ restored[key] = restoreRedactedSecrets(value, currentValue, childSchema);
1829
+ }
1830
+ }
1831
+ return restored;
1832
+ }
1833
+
1834
+ // src/utilities/reconcileModuleConfig.ts
1835
+ function isRecord2(value) {
1836
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1837
+ }
1838
+ function sortJson(value) {
1839
+ if (Array.isArray(value)) {
1840
+ return value.map(sortJson);
1841
+ }
1842
+ if (!isRecord2(value)) {
1843
+ return value;
1844
+ }
1845
+ return Object.fromEntries(
1846
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortJson(nested)])
1847
+ );
1848
+ }
1849
+ function stableConfigJson(value) {
1850
+ return JSON.stringify(sortJson(value));
1851
+ }
1852
+ function storedConfigsEquivalent(left, right) {
1853
+ return stableConfigJson(left) === stableConfigJson(right);
1854
+ }
1855
+ async function reconcileStoredModuleConfig(args) {
1856
+ if (storedConfigsEquivalent(args.stored, args.migrated)) {
1857
+ return { config: args.migrated, persisted: false };
1858
+ }
1859
+ if (containsRedactedMarker(args.migrated)) {
1860
+ return { config: args.migrated, persisted: false };
1861
+ }
1862
+ const persisted = await args.configureOverride(args.migrated);
1863
+ return { config: persisted, persisted: true };
1864
+ }
1865
+
1738
1866
  // src/routing/RoutingController.ts
1739
1867
  import { status as status4 } from "@grpc/grpc-js";
1740
1868
  var RoutingController = class {
@@ -1787,6 +1915,9 @@ var ManagedModule = class extends ConduitServiceModule {
1787
1915
  throw new Error("Failed to initialize grpcSdk");
1788
1916
  }
1789
1917
  }
1918
+ get configInitialized() {
1919
+ return this._configInitialized;
1920
+ }
1790
1921
  get name() {
1791
1922
  return this._moduleName;
1792
1923
  }
@@ -1978,9 +2109,10 @@ var ManagedModule = class extends ConduitServiceModule {
1978
2109
  });
1979
2110
  }
1980
2111
  let config = JSON.parse(call.request.newConfig);
1981
- config = merge(this.config.getProperties(), config);
1982
- config = await this.preConfig(config);
1983
2112
  const previousConfig = this.config.getProperties();
2113
+ config = merge(previousConfig, config);
2114
+ config = restoreRedactedSecrets(config, previousConfig, this.configSchema);
2115
+ config = await this.preConfig(config);
1984
2116
  try {
1985
2117
  this.config.load(config).validate({
1986
2118
  allowed: "warn"
@@ -2056,7 +2188,21 @@ var ManagedModule = class extends ConduitServiceModule {
2056
2188
  this.configOverride
2057
2189
  );
2058
2190
  ConfigController.getInstance();
2059
- if (config) ConfigController.getInstance().config = config;
2191
+ if (config) {
2192
+ const migrated = await this.preConfig(config);
2193
+ this.config.load(migrated).validate({
2194
+ allowed: "warn"
2195
+ });
2196
+ const persistable = this.config.getProperties();
2197
+ const reconciled = await reconcileStoredModuleConfig({
2198
+ stored: config,
2199
+ migrated: persistable,
2200
+ configureOverride: (next) => this.grpcSdk.config.configure(next, convictConfigParser(configSchema), true)
2201
+ });
2202
+ config = reconciled.config;
2203
+ this.config.load(config);
2204
+ ConfigController.getInstance().config = this.config.getProperties();
2205
+ }
2060
2206
  if (!config || config.active || !config.hasOwnProperty("active"))
2061
2207
  await this.onConfig();
2062
2208
  }
@@ -2066,8 +2212,8 @@ var ManagedModule = class extends ConduitServiceModule {
2066
2212
  };
2067
2213
 
2068
2214
  // src/classes/ModuleError.ts
2069
- import { GrpcError } from "@conduitplatform/grpc-sdk";
2070
- var ModuleError = class extends GrpcError {
2215
+ import { GrpcError as GrpcError2 } from "@conduitplatform/grpc-sdk";
2216
+ var ModuleError = class extends GrpcError2 {
2071
2217
  debugLogInfo;
2072
2218
  constructor(errorDefinition, debugLogInfo) {
2073
2219
  const { grpcCode, conduitCode, message } = errorDefinition;
@@ -2100,6 +2246,8 @@ export {
2100
2246
  RouteBuilder,
2101
2247
  RoutingManager,
2102
2248
  addServiceToServer,
2249
+ containsRedactedMarker,
2250
+ convictConfigParser,
2103
2251
  createParsedRouterRequest,
2104
2252
  createServer,
2105
2253
  exportModel,
@@ -2109,7 +2257,12 @@ export {
2109
2257
  linearBackoffTimeoutAsync,
2110
2258
  merge,
2111
2259
  readConduitPeersManifest,
2260
+ reconcileStoredModuleConfig,
2261
+ redactSensitiveConfig,
2262
+ restoreRedactedSecrets,
2112
2263
  sanitizeDocumentsForExport,
2264
+ stableConfigJson,
2265
+ storedConfigsEquivalent,
2113
2266
  stripInternalFields,
2114
2267
  wrapFunctionsAsync,
2115
2268
  wrapGrpcFunctions,