@outputai/core 0.14.1-next.bd031f8.0 → 0.14.1-next.e9dfa49.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 (103) hide show
  1. package/dist/credentials/credentials.d.ts +6 -0
  2. package/dist/credentials/credentials.js +87 -0
  3. package/dist/credentials/encrypted_yaml_provider.d.ts +2 -0
  4. package/dist/credentials/encrypted_yaml_provider.js +77 -0
  5. package/dist/credentials/encryption.d.ts +3 -0
  6. package/dist/credentials/encryption.js +6 -0
  7. package/dist/credentials/errors.d.ts +13 -0
  8. package/dist/credentials/errors.js +39 -0
  9. package/dist/credentials/index.d.ts +6 -0
  10. package/dist/credentials/index.js +5 -0
  11. package/dist/credentials/init.d.ts +1 -0
  12. package/dist/credentials/init.js +7 -0
  13. package/dist/credentials/paths.d.ts +7 -0
  14. package/dist/credentials/paths.js +14 -0
  15. package/dist/credentials/provider_registry.d.ts +3 -0
  16. package/dist/credentials/provider_registry.js +6 -0
  17. package/dist/credentials/types.d.ts +12 -0
  18. package/dist/credentials/types.js +1 -0
  19. package/package.json +25 -14
  20. package/src/async_storage.d.ts +4 -0
  21. package/src/consts.js +0 -2
  22. package/src/helpers/object.d.ts +2 -0
  23. package/src/helpers/search_attributes.js +25 -0
  24. package/src/helpers/temporal_context.js +4 -1
  25. package/src/hooks/index.d.ts +6 -8
  26. package/src/hooks/index.js +0 -3
  27. package/src/interface/workflow.js +10 -2
  28. package/src/logger/index.d.ts +4 -0
  29. package/src/worker/index.js +3 -1
  30. package/bin/healthcheck.spec.js +0 -90
  31. package/src/bus.spec.js +0 -196
  32. package/src/errors.spec.js +0 -19
  33. package/src/helpers/activity_options.spec.js +0 -55
  34. package/src/helpers/component.spec.js +0 -54
  35. package/src/helpers/error_serializer.spec.js +0 -479
  36. package/src/helpers/errors.spec.js +0 -189
  37. package/src/helpers/fetch.spec.js +0 -292
  38. package/src/helpers/function.spec.js +0 -24
  39. package/src/helpers/object.spec.js +0 -425
  40. package/src/helpers/promise.spec.js +0 -62
  41. package/src/helpers/redact.spec.js +0 -66
  42. package/src/helpers/string.spec.js +0 -99
  43. package/src/helpers/temporal_context.spec.ts +0 -83
  44. package/src/helpers/trace_info.spec.js +0 -45
  45. package/src/helpers/workflow_context.spec.js +0 -46
  46. package/src/hooks/index.spec.js +0 -265
  47. package/src/hooks/pending_hooks.spec.js +0 -62
  48. package/src/interface/evaluator.spec.js +0 -685
  49. package/src/interface/logger.spec.js +0 -172
  50. package/src/interface/step.spec.js +0 -128
  51. package/src/interface/validations/index.spec.js +0 -197
  52. package/src/interface/validations/schemas.spec.js +0 -229
  53. package/src/interface/webhook.spec.js +0 -170
  54. package/src/interface/workflow.spec.js +0 -710
  55. package/src/interface/workflow_utils.spec.js +0 -271
  56. package/src/interface/zod_integration.spec.js +0 -646
  57. package/src/internal_activities/index.spec.js +0 -186
  58. package/src/logger/development.spec.js +0 -87
  59. package/src/logger/index.spec.js +0 -27
  60. package/src/logger/production.spec.js +0 -71
  61. package/src/sdk/helpers/component_metadata.spec.js +0 -30
  62. package/src/sdk/helpers/objects.spec.js +0 -16
  63. package/src/sdk/helpers/path.spec.js +0 -102
  64. package/src/sdk/runtime/context.spec.js +0 -37
  65. package/src/sdk/runtime/events.spec.js +0 -40
  66. package/src/temporal/client.spec.js +0 -124
  67. package/src/tracing/processors/local/index.spec.js +0 -204
  68. package/src/tracing/processors/s3/configs.spec.js +0 -64
  69. package/src/tracing/processors/s3/index.spec.js +0 -185
  70. package/src/tracing/processors/s3/redis_client.spec.js +0 -179
  71. package/src/tracing/processors/s3/s3_client.spec.js +0 -68
  72. package/src/tracing/tools/build_trace_tree.spec.js +0 -216
  73. package/src/tracing/trace_engine.spec.js +0 -299
  74. package/src/worker/bundle.spec.js +0 -53
  75. package/src/worker/bundler_options.spec.js +0 -62
  76. package/src/worker/catalog_workflow/catalog_publisher.spec.js +0 -317
  77. package/src/worker/catalog_workflow/index.spec.js +0 -222
  78. package/src/worker/configs.spec.js +0 -213
  79. package/src/worker/configs_tuner_schema.spec.js +0 -127
  80. package/src/worker/connection_monitor.spec.js +0 -328
  81. package/src/worker/global_functions.spec.js +0 -55
  82. package/src/worker/index.spec.js +0 -526
  83. package/src/worker/interceptors/activity.spec.js +0 -369
  84. package/src/worker/interceptors/headers.spec.js +0 -73
  85. package/src/worker/interceptors/workflow.spec.js +0 -357
  86. package/src/worker/interruption.spec.js +0 -177
  87. package/src/worker/loader/activities.spec.js +0 -212
  88. package/src/worker/loader/hooks.spec.js +0 -64
  89. package/src/worker/loader/matchers.spec.js +0 -140
  90. package/src/worker/loader/tools.spec.js +0 -595
  91. package/src/worker/loader/workflows.spec.js +0 -287
  92. package/src/worker/log_hooks.spec.js +0 -303
  93. package/src/worker/shutdown.spec.js +0 -197
  94. package/src/worker/sinks.spec.js +0 -220
  95. package/src/worker/telemetry.spec.js +0 -80
  96. package/src/worker/temporal_logger.spec.js +0 -90
  97. package/src/worker/webpack_loaders/tools.spec.js +0 -314
  98. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +0 -134
  99. package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +0 -154
  100. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.spec.js +0 -165
  101. package/src/worker/webpack_loaders/workflow_validator/index.spec.js +0 -202
  102. package/src/worker/webpack_loaders/workflow_validator/npm_workflow_export_resolve.spec.js +0 -374
  103. package/src/worker/worker_runner.spec.js +0 -220
@@ -0,0 +1,6 @@
1
+ export declare const resolveCredentialRefs: () => string[];
2
+ export declare const credentials: {
3
+ get: (path: string, defaultValue?: unknown) => unknown;
4
+ require: (path: string) => unknown;
5
+ _reset: () => void;
6
+ };
@@ -0,0 +1,87 @@
1
+ import { dirname } from 'node:path';
2
+ import { MissingCredentialError } from './errors.js';
3
+ import { deepMerge } from '#helpers/object';
4
+ import { getProvider } from './provider_registry.js';
5
+ import { Storage } from '#async_storage';
6
+ const getNestedValue = (obj, dotPath) => dotPath.split('.').reduce((acc, part) => acc?.[part], obj);
7
+ const detectEnvironment = () => {
8
+ const env = process.env.NODE_ENV;
9
+ return (env === 'production' || env === 'development') ? env : undefined;
10
+ };
11
+ const GLOBAL_CACHE_KEY = Symbol('global');
12
+ const cache = new Map();
13
+ const loadGlobal = () => {
14
+ if (cache.has(GLOBAL_CACHE_KEY)) {
15
+ return cache.get(GLOBAL_CACHE_KEY);
16
+ }
17
+ const data = getProvider().loadGlobal({ environment: detectEnvironment() });
18
+ cache.set(GLOBAL_CACHE_KEY, data);
19
+ return data;
20
+ };
21
+ const loadForWorkflow = (workflowName, workflowDir) => {
22
+ if (cache.has(workflowName)) {
23
+ return cache.get(workflowName);
24
+ }
25
+ const globalData = loadGlobal();
26
+ const workflowData = getProvider().loadForWorkflow({
27
+ workflowName,
28
+ workflowDir,
29
+ environment: detectEnvironment()
30
+ });
31
+ const merged = workflowData ? deepMerge(globalData, workflowData) : globalData;
32
+ cache.set(workflowName, merged);
33
+ return merged;
34
+ };
35
+ const getWorkflowContext = () => {
36
+ const ctx = Storage.load();
37
+ if (!ctx) {
38
+ return { workflowName: undefined, workflowDir: undefined };
39
+ }
40
+ return {
41
+ workflowName: ctx.activityInfo.workflowType,
42
+ workflowDir: dirname(ctx.workflowFilename)
43
+ };
44
+ };
45
+ const load = () => {
46
+ const { workflowName, workflowDir } = getWorkflowContext();
47
+ if (!workflowName) {
48
+ return loadGlobal();
49
+ }
50
+ return loadForWorkflow(workflowName, workflowDir);
51
+ };
52
+ const CREDENTIAL_REF_PREFIX = 'credential:';
53
+ export const resolveCredentialRefs = () => {
54
+ const refs = Object.entries(process.env)
55
+ .filter(([, v]) => typeof v === 'string' && v.startsWith(CREDENTIAL_REF_PREFIX));
56
+ if (refs.length === 0) {
57
+ return [];
58
+ }
59
+ const data = loadGlobal();
60
+ const resolved = [];
61
+ for (const [envVar, value] of refs) {
62
+ const credPath = value.slice(CREDENTIAL_REF_PREFIX.length);
63
+ const credValue = getNestedValue(data, credPath);
64
+ if (typeof credValue === 'string' && credValue.length > 0) {
65
+ process.env[envVar] = credValue;
66
+ resolved.push(envVar);
67
+ }
68
+ }
69
+ return resolved;
70
+ };
71
+ export const credentials = {
72
+ get: (path, defaultValue = undefined) => {
73
+ const data = load();
74
+ const value = getNestedValue(data, path);
75
+ return value !== undefined ? value : defaultValue;
76
+ },
77
+ require: (path) => {
78
+ const value = credentials.get(path);
79
+ if (value === undefined || value === null) {
80
+ throw new MissingCredentialError(path);
81
+ }
82
+ return value;
83
+ },
84
+ _reset: () => {
85
+ cache.clear();
86
+ }
87
+ };
@@ -0,0 +1,2 @@
1
+ import type { CredentialsProvider } from './types.js';
2
+ export declare const encryptedYamlProvider: CredentialsProvider;
@@ -0,0 +1,77 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { load as parseYaml } from 'js-yaml';
3
+ import { decrypt } from './encryption.js';
4
+ import { InvalidCredentialsKeyError, MalformedCredentialsKeyError, MissingKeyError } from './errors.js';
5
+ import { resolveKeyEnvVar, resolveCredentialsPath, resolveKeyPath, resolveWorkflowCredentialsPath, resolveWorkflowKeyPath, resolveWorkflowKeyEnvVar } from './paths.js';
6
+ const resolveBaseDir = () => {
7
+ const arg = process.argv[2];
8
+ return (arg && arg.startsWith('/')) ? arg : process.cwd();
9
+ };
10
+ const resolveKey = (environment) => {
11
+ const envVarName = resolveKeyEnvVar(environment);
12
+ if (process.env[envVarName]) {
13
+ return process.env[envVarName];
14
+ }
15
+ const keyFilePath = resolveKeyPath(resolveBaseDir(), environment);
16
+ if (existsSync(keyFilePath)) {
17
+ return readFileSync(keyFilePath, 'utf8').trim();
18
+ }
19
+ throw new MissingKeyError(environment);
20
+ };
21
+ const resolveWorkflowKey = (workflowName, workflowDir) => {
22
+ const envVarName = resolveWorkflowKeyEnvVar(workflowName);
23
+ if (process.env[envVarName]) {
24
+ return process.env[envVarName];
25
+ }
26
+ const keyPath = resolveWorkflowKeyPath(workflowDir);
27
+ if (existsSync(keyPath)) {
28
+ return readFileSync(keyPath, 'utf8').trim();
29
+ }
30
+ return resolveKey(undefined);
31
+ };
32
+ const safeDecrypt = (ciphertext, key, credPath) => {
33
+ try {
34
+ return decrypt(ciphertext, key);
35
+ }
36
+ catch (error) {
37
+ if (error instanceof RangeError) {
38
+ throw new MalformedCredentialsKeyError(credPath, error.message);
39
+ }
40
+ if (error instanceof Error && error.message.includes('aes/gcm')) {
41
+ throw new InvalidCredentialsKeyError(credPath);
42
+ }
43
+ throw new InvalidCredentialsKeyError(credPath, error instanceof Error ? error.message : String(error));
44
+ }
45
+ };
46
+ const decryptYaml = (credPath, key) => {
47
+ const ciphertext = readFileSync(credPath, 'utf8').trim();
48
+ const plaintext = safeDecrypt(ciphertext, key, credPath);
49
+ return parseYaml(plaintext) || {};
50
+ };
51
+ export const encryptedYamlProvider = {
52
+ loadGlobal: ({ environment }) => {
53
+ const baseDir = resolveBaseDir();
54
+ const credPath = resolveCredentialsPath(baseDir, environment);
55
+ if (!existsSync(credPath)) {
56
+ if (environment) {
57
+ const defaultPath = resolveCredentialsPath(baseDir, undefined);
58
+ if (existsSync(defaultPath)) {
59
+ return decryptYaml(defaultPath, resolveKey(undefined));
60
+ }
61
+ }
62
+ return {};
63
+ }
64
+ return decryptYaml(credPath, resolveKey(environment));
65
+ },
66
+ loadForWorkflow: ({ workflowName, workflowDir }) => {
67
+ if (!workflowDir) {
68
+ return null;
69
+ }
70
+ const credPath = resolveWorkflowCredentialsPath(workflowDir);
71
+ if (!existsSync(credPath)) {
72
+ return null;
73
+ }
74
+ const key = resolveWorkflowKey(workflowName, workflowDir);
75
+ return decryptYaml(credPath, key);
76
+ }
77
+ };
@@ -0,0 +1,3 @@
1
+ export declare const generateKey: () => string;
2
+ export declare const encrypt: (plaintext: string, keyHex: string) => string;
3
+ export declare const decrypt: (ciphertext: string, keyHex: string) => string;
@@ -0,0 +1,6 @@
1
+ import { gcm } from '@noble/ciphers/aes.js';
2
+ import { managedNonce, randomBytes, hexToBytes, bytesToHex } from '@noble/ciphers/utils.js';
3
+ const aes = managedNonce(gcm);
4
+ export const generateKey = () => bytesToHex(randomBytes(32));
5
+ export const encrypt = (plaintext, keyHex) => Buffer.from(aes(hexToBytes(keyHex)).encrypt(new TextEncoder().encode(plaintext))).toString('base64');
6
+ export const decrypt = (ciphertext, keyHex) => new TextDecoder().decode(aes(hexToBytes(keyHex)).decrypt(Buffer.from(ciphertext, 'base64')));
@@ -0,0 +1,13 @@
1
+ import { FatalError } from '#errors';
2
+ export declare class MissingKeyError extends FatalError {
3
+ constructor(environment?: string | null);
4
+ }
5
+ export declare class MissingCredentialError extends FatalError {
6
+ constructor(path: string);
7
+ }
8
+ export declare class InvalidCredentialsKeyError extends FatalError {
9
+ constructor(credentialsPath: string, underlyingError?: string);
10
+ }
11
+ export declare class MalformedCredentialsKeyError extends FatalError {
12
+ constructor(credentialsPath: string, detail: string);
13
+ }
@@ -0,0 +1,39 @@
1
+ import { FatalError } from '#errors';
2
+ export class MissingKeyError extends FatalError {
3
+ constructor(environment) {
4
+ const envVar = environment ?
5
+ `OUTPUT_CREDENTIALS_KEY_${environment.toUpperCase()}` :
6
+ 'OUTPUT_CREDENTIALS_KEY';
7
+ const keyFile = environment ?
8
+ `config/credentials/${environment}.key` :
9
+ 'config/credentials.key';
10
+ super(`No credentials key found. Set ${envVar} env var or create ${keyFile}.`);
11
+ this.name = 'MissingKeyError';
12
+ }
13
+ }
14
+ export class MissingCredentialError extends FatalError {
15
+ constructor(path) {
16
+ super(`Required credential not found: "${path}".`);
17
+ this.name = 'MissingCredentialError';
18
+ }
19
+ }
20
+ export class InvalidCredentialsKeyError extends FatalError {
21
+ constructor(credentialsPath, underlyingError) {
22
+ const message = underlyingError ?
23
+ `Failed to decrypt ${credentialsPath}: ${underlyingError}. ` +
24
+ 'The credentials key may not match the one used to encrypt this file, or the credentials file may be corrupted. ' +
25
+ 'Check OUTPUT_CREDENTIALS_KEY env var or config/credentials.key.' :
26
+ `Failed to decrypt ${credentialsPath}. The credentials key does not match the one used to encrypt this file. ` +
27
+ 'Check OUTPUT_CREDENTIALS_KEY env var or config/credentials.key.';
28
+ super(message);
29
+ this.name = 'InvalidCredentialsKeyError';
30
+ }
31
+ }
32
+ export class MalformedCredentialsKeyError extends FatalError {
33
+ constructor(credentialsPath, detail) {
34
+ super(`Credentials key for ${credentialsPath} is malformed (${detail}). ` +
35
+ 'The key must be exactly 64 hex characters. ' +
36
+ 'Check OUTPUT_CREDENTIALS_KEY env var or config/credentials.key for typos, whitespace, or truncation.');
37
+ this.name = 'MalformedCredentialsKeyError';
38
+ }
39
+ }
@@ -0,0 +1,6 @@
1
+ export { credentials, resolveCredentialRefs } from './credentials.js';
2
+ export { setProvider } from './provider_registry.js';
3
+ export { encrypt, decrypt, generateKey } from './encryption.js';
4
+ export { InvalidCredentialsKeyError, MalformedCredentialsKeyError, MissingCredentialError, MissingKeyError } from './errors.js';
5
+ export { getNestedValue, resolveCredentialsPath, resolveKeyPath, resolveKeyEnvVar, resolveWorkflowCredentialsPath, resolveWorkflowKeyPath, resolveWorkflowKeyEnvVar } from './paths.js';
6
+ export type { CredentialsProvider } from './types.js';
@@ -0,0 +1,5 @@
1
+ export { credentials, resolveCredentialRefs } from './credentials.js';
2
+ export { setProvider } from './provider_registry.js';
3
+ export { encrypt, decrypt, generateKey } from './encryption.js';
4
+ export { InvalidCredentialsKeyError, MalformedCredentialsKeyError, MissingCredentialError, MissingKeyError } from './errors.js';
5
+ export { getNestedValue, resolveCredentialsPath, resolveKeyPath, resolveKeyEnvVar, resolveWorkflowCredentialsPath, resolveWorkflowKeyPath, resolveWorkflowKeyEnvVar } from './paths.js';
@@ -0,0 +1 @@
1
+ export declare const init: () => void;
@@ -0,0 +1,7 @@
1
+ import { createChildLogger } from '#logger';
2
+ import { resolveCredentialRefs } from './credentials.js';
3
+ const log = createChildLogger('Credentials');
4
+ export const init = () => {
5
+ const vars = resolveCredentialRefs();
6
+ log.info('Resolved credential env vars', { vars });
7
+ };
@@ -0,0 +1,7 @@
1
+ export declare const resolveKeyEnvVar: (environment?: string) => string;
2
+ export declare const resolveWorkflowKeyEnvVar: (workflowName: string) => string;
3
+ export declare const resolveCredentialsPath: (baseDir: string, environment?: string) => string;
4
+ export declare const resolveKeyPath: (baseDir: string, environment?: string) => string;
5
+ export declare const resolveWorkflowCredentialsPath: (workflowDir: string) => string;
6
+ export declare const resolveWorkflowKeyPath: (workflowDir: string) => string;
7
+ export declare const getNestedValue: (obj: unknown, dotPath: string) => unknown;
@@ -0,0 +1,14 @@
1
+ import { resolve } from 'node:path';
2
+ export const resolveKeyEnvVar = (environment) => environment ?
3
+ `OUTPUT_CREDENTIALS_KEY_${environment.toUpperCase()}` :
4
+ 'OUTPUT_CREDENTIALS_KEY';
5
+ export const resolveWorkflowKeyEnvVar = (workflowName) => `OUTPUT_CREDENTIALS_KEY_${workflowName.toUpperCase()}`;
6
+ export const resolveCredentialsPath = (baseDir, environment) => environment ?
7
+ resolve(baseDir, `config/credentials/${environment}.yml.enc`) :
8
+ resolve(baseDir, 'config/credentials.yml.enc');
9
+ export const resolveKeyPath = (baseDir, environment) => environment ?
10
+ resolve(baseDir, `config/credentials/${environment}.key`) :
11
+ resolve(baseDir, 'config/credentials.key');
12
+ export const resolveWorkflowCredentialsPath = (workflowDir) => resolve(workflowDir, 'credentials.yml.enc');
13
+ export const resolveWorkflowKeyPath = (workflowDir) => resolve(workflowDir, 'credentials.key');
14
+ export const getNestedValue = (obj, dotPath) => dotPath.split('.').reduce((acc, part) => acc && typeof acc === 'object' ? acc[part] : undefined, obj);
@@ -0,0 +1,3 @@
1
+ import type { CredentialsProvider } from './types.js';
2
+ export declare const getProvider: () => CredentialsProvider;
3
+ export declare const setProvider: (provider: CredentialsProvider) => void;
@@ -0,0 +1,6 @@
1
+ import { encryptedYamlProvider } from './encrypted_yaml_provider.js';
2
+ const registry = { provider: encryptedYamlProvider };
3
+ export const getProvider = () => registry.provider;
4
+ export const setProvider = (provider) => {
5
+ registry.provider = provider;
6
+ };
@@ -0,0 +1,12 @@
1
+ export interface GlobalContext {
2
+ environment: string | undefined;
3
+ }
4
+ export interface WorkflowContext {
5
+ workflowName: string;
6
+ workflowDir: string | undefined;
7
+ environment?: string | undefined;
8
+ }
9
+ export interface CredentialsProvider {
10
+ loadGlobal(context: GlobalContext): Record<string, unknown>;
11
+ loadForWorkflow(context: WorkflowContext): Record<string, unknown> | null;
12
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outputai/core",
3
- "version": "0.14.1-next.bd031f8.0",
3
+ "version": "0.14.1-next.e9dfa49.0",
4
4
  "description": "The core module of the output framework",
5
5
  "type": "module",
6
6
  "engines": {
@@ -26,11 +26,18 @@
26
26
  "./temporal": {
27
27
  "types": "./src/temporal/index.d.ts",
28
28
  "import": "./src/temporal/index.js"
29
+ },
30
+ "./credentials": {
31
+ "types": "./dist/credentials/index.d.ts",
32
+ "import": "./dist/credentials/index.js"
29
33
  }
30
34
  },
31
35
  "files": [
32
36
  "./src",
33
- "./bin"
37
+ "./dist",
38
+ "./bin",
39
+ "!**/*.spec.*",
40
+ "!src/credentials"
34
41
  ],
35
42
  "bin": {
36
43
  "output-worker": "./bin/worker.sh",
@@ -39,29 +46,32 @@
39
46
  "output-copy-assets": "./bin/copy_assets.js"
40
47
  },
41
48
  "dependencies": {
42
- "@aws-sdk/client-s3": "3.1038.0",
43
- "@aws-sdk/lib-storage": "3.1038.0",
49
+ "@aws-sdk/client-s3": "3.1138.0",
50
+ "@aws-sdk/lib-storage": "3.1138.0",
44
51
  "@babel/generator": "7.29.1",
45
- "@babel/parser": "7.29.2",
52
+ "@babel/parser": "7.29.9",
46
53
  "@babel/traverse": "7.29.0",
47
54
  "@babel/types": "7.29.0",
48
- "@temporalio/activity": "1.20.3",
49
- "@temporalio/client": "1.20.3",
50
- "@temporalio/common": "1.20.3",
51
- "@temporalio/worker": "1.20.3",
52
- "@temporalio/workflow": "1.20.3",
55
+ "@noble/ciphers": "2.4.0",
56
+ "@temporalio/activity": "1.24.0",
57
+ "@temporalio/client": "1.24.0",
58
+ "@temporalio/common": "1.24.0",
59
+ "@temporalio/worker": "1.24.0",
60
+ "@temporalio/workflow": "1.24.0",
53
61
  "folder-hash": "4.1.3",
54
- "json-stream-stringify": "3.1.6",
62
+ "js-yaml": "5.4.2",
63
+ "json-stream-stringify": "3.1.7",
55
64
  "redis": "5.12.1",
56
65
  "stacktrace-parser": "0.1.11",
57
- "undici": "8.9.0",
66
+ "undici": "8.11.0",
58
67
  "winston": "3.19.0"
59
68
  },
60
69
  "peerDependencies": {
61
70
  "zod": ">=4.3 <5"
62
71
  },
63
72
  "devDependencies": {
64
- "zod": "4.3.6"
73
+ "@types/js-yaml": "4.0.9",
74
+ "zod": "4.6.5"
65
75
  },
66
76
  "license": "Apache-2.0",
67
77
  "publishConfig": {
@@ -70,6 +80,7 @@
70
80
  "imports": {
71
81
  "#bus": "./src/bus.js",
72
82
  "#consts": "./src/consts.js",
83
+ "#credentials/*": "./dist/credentials/*.js",
73
84
  "#errors": "./src/errors.js",
74
85
  "#logger": "./src/logger/index.js",
75
86
  "#hooks/*": "./src/hooks/*.js",
@@ -82,6 +93,6 @@
82
93
  },
83
94
  "scripts": {
84
95
  "worker": "node ./src/worker/index.js",
85
- "build": "pnpm exec tsc -p ./tsconfig.typecheck.json"
96
+ "build": "rm -rf ./dist && tsc && pnpm exec tsc -p ./tsconfig.typecheck.json"
86
97
  }
87
98
  }
@@ -0,0 +1,4 @@
1
+ // Minimal types so TS modules (credentials) can import this JS file
2
+ export declare const Storage: {
3
+ load: () => { activityInfo: { workflowType: string }; workflowFilename: string } | undefined;
4
+ };
package/src/consts.js CHANGED
@@ -23,8 +23,6 @@ export const LifecycleEvent = {
23
23
  };
24
24
 
25
25
  export const BusEventType = {
26
- WORKER_BEFORE_START: 'worker:before_start',
27
-
28
26
  WORKFLOW_END: 'workflow:end',
29
27
  WORKFLOW_ERROR: 'workflow:error',
30
28
  WORKFLOW_LOG: 'workflow:log',
@@ -0,0 +1,2 @@
1
+ // Minimal types so TS modules (credentials) can import this JS file
2
+ export declare function deepMerge( base: Record<string, unknown>, overlay: Record<string, unknown> ): Record<string, unknown>;
@@ -0,0 +1,25 @@
1
+ const serializeValue = value => typeof value?.toISOString === 'function' ? value.toISOString() : value;
2
+
3
+ /**
4
+ * Converts Datetime (Date) search attribute values to ISO strings so the result survives JSON and structured-clone boundaries identically.
5
+ *
6
+ * @param {Record<string, unknown[]>} [searchAttributes] Temporal untyped search attributes
7
+ * @returns {Record<string, Array<string|number|boolean>>|undefined} Undefined when there are no attributes
8
+ */
9
+ export const serializeSearchAttributes = searchAttributes =>
10
+ Object.keys( searchAttributes ?? {} ).length ?
11
+ Object.fromEntries( Object.entries( searchAttributes ).map( ( [ k, values ] ) => [ k, values.map( serializeValue ) ] ) ) :
12
+ undefined;
13
+
14
+ const isSystemAttribute = name => name.startsWith( 'Temporal' ) || name === 'BuildIds';
15
+
16
+ /**
17
+ * Drops Temporal system search attributes so the rest can be forwarded to child workflows.
18
+ *
19
+ * @param {Record<string, unknown[]>} [searchAttributes] Temporal untyped search attributes
20
+ * @returns {Record<string, unknown[]>|undefined} Undefined when nothing remains
21
+ */
22
+ export const inheritableSearchAttributes = searchAttributes => {
23
+ const entries = Object.entries( searchAttributes ?? {} ).filter( ( [ k ] ) => !isSystemAttribute( k ) );
24
+ return entries.length ? Object.fromEntries( entries ) : undefined;
25
+ };
@@ -1,3 +1,5 @@
1
+ import { serializeSearchAttributes } from './search_attributes.js';
2
+
1
3
  export const createWorkflowDetails = info => ( {
2
4
  attempt: info.attempt,
3
5
  continuedFromExecutionRunId: info.continuedFromExecutionRunId,
@@ -8,5 +10,6 @@ export const createWorkflowDetails = info => ( {
8
10
  runStartTime: info.runStartTime.getTime(),
9
11
  startTime: info.startTime.getTime(),
10
12
  workflowId: info.workflowId,
11
- workflowType: info.workflowType
13
+ workflowType: info.workflowType,
14
+ searchAttributes: serializeSearchAttributes( info.searchAttributes )
12
15
  } );
@@ -77,6 +77,12 @@ export interface WorkflowDetails {
77
77
  * Starts at 1 and increments for every retry if there is a `retryPolicy`
78
78
  */
79
79
  attempt: number;
80
+ /**
81
+ * Temporal search attributes set on this workflow execution, if any. Datetime values are ISO strings.
82
+ * Uses the untyped form because `typedSearchAttributes` does not survive the sink/activity-header
83
+ * serialization boundary (https://github.com/temporalio/sdk-typescript/issues/1635).
84
+ */
85
+ searchAttributes?: Record<string, string[] | number[] | boolean[]>;
80
86
  }
81
87
 
82
88
  /**
@@ -185,14 +191,6 @@ export type ErrorHookPayload =
185
191
  */
186
192
  export declare function onError( handler: ( payload: ErrorHookPayload ) => void ): void;
187
193
 
188
- /**
189
- * Register a handler to be invoked once, before the worker starts processing tasks.
190
- * It is invoked before Worker.create().
191
- *
192
- * @param handler - Function called with no arguments.
193
- */
194
- export declare function onBeforeWorkerStart( handler: () => void ): void;
195
-
196
194
  /**
197
195
  * Register a handler to be invoked when a workflow run starts.
198
196
  *
@@ -33,8 +33,6 @@ const onError = cb => {
33
33
  callHookCb( cb, { source: 'runtime', ...payload }, 'onError' ) );
34
34
  };
35
35
 
36
- const onBeforeWorkerStart = cb => mainEventBus.on( BusEventType.WORKER_BEFORE_START, () => callHookCb( cb, undefined, 'onBeforeWorkerStart' ) );
37
-
38
36
  // Workflow Life-cycle
39
37
  // --------------------------------------
40
38
  const onWorkflowStart = cb => mainEventBus.on( BusEventType.WORKFLOW_START, payload => callHookCb( cb, payload, 'onWorkflowStart' ) );
@@ -68,7 +66,6 @@ export {
68
66
  onActivityEnd,
69
67
  onActivityError,
70
68
  onActivityStart,
71
- onBeforeWorkerStart,
72
69
  onError,
73
70
  onWorkflowEnd,
74
71
  onWorkflowError,
@@ -2,6 +2,7 @@
2
2
  import { proxyActivities, inWorkflowContext, executeChild, workflowInfo, uuid4, ParentClosePolicy, upsertMemo } from '@temporalio/workflow';
3
3
  import { WorkflowValidator } from './validations/index.js';
4
4
  import { toUrlSafeBase64 } from '#helpers/string';
5
+ import { inheritableSearchAttributes } from '#helpers/search_attributes';
5
6
  import { WorkflowContext } from '#helpers/workflow_context';
6
7
  import { deepMerge } from '#helpers/object';
7
8
  import { defaultOptions } from './workflow_activity_options.js';
@@ -48,7 +49,7 @@ export function workflow( { name, description, inputSchema, outputSchema, fn, op
48
49
  );
49
50
  }
50
51
 
51
- const { workflowId, runId, memo, root } = workflowInfo();
52
+ const { workflowId, runId, memo, root, searchAttributes } = workflowInfo();
52
53
  const isRoot = !root;
53
54
 
54
55
  checkGlobalContextContamination( runId );
@@ -59,7 +60,14 @@ export function workflow( { name, description, inputSchema, outputSchema, fn, op
59
60
  const parentClosePolicy = ParentClosePolicy[invocationOptions?.detached ? 'ABANDON' : 'TERMINATE'];
60
61
  const childWorkflowId = `${workflowId}-${toUrlSafeBase64( uuid4() )}`;
61
62
  const args = [ input, { activityOptions: invocationOptions?.activityOptions } ];
62
- return executeChild( name, { args, workflowId: childWorkflowId, parentClosePolicy, memo } );
63
+ const childSearchAttributes = inheritableSearchAttributes( searchAttributes );
64
+ return executeChild( name, {
65
+ args,
66
+ workflowId: childWorkflowId,
67
+ parentClosePolicy,
68
+ memo,
69
+ ...( childSearchAttributes && { searchAttributes: childSearchAttributes } )
70
+ } );
63
71
  }
64
72
 
65
73
  // Resolve the activity options: invocation options > definition options > parent options > default options, then enforce final SDK options
@@ -0,0 +1,4 @@
1
+ // Minimal types so TS modules (credentials) can import this JS file
2
+ export declare function createChildLogger( namespace: string ): {
3
+ info: ( message: string, meta?: Record<string, unknown> ) => void;
4
+ };
@@ -23,6 +23,7 @@ import { serializeError } from '#helpers/error_serializer';
23
23
  import { setupTemporalLogger } from './temporal_logger.js';
24
24
  import { WorkerRunner } from './worker_runner.js';
25
25
  import { shutdownServices } from './shutdown.js';
26
+ import { init as initCredentials } from '#credentials/init';
26
27
 
27
28
  import './log_hooks.js';
28
29
 
@@ -76,7 +77,8 @@ const execute = async () => {
76
77
  log.info( 'Loading activities...', { callerDir } );
77
78
  const { activities } = await run( () => loadActivities( callerDir, workflows ) );
78
79
 
79
- mainEventBus.emit( BusEventType.WORKER_BEFORE_START );
80
+ log.info( 'Initializing credentials...' );
81
+ run( initCredentials );
80
82
 
81
83
  log.info( 'Initializing tracing...' );
82
84
  await run( initTracing );