@temporalio/envconfig 1.13.2

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/src/types.ts ADDED
@@ -0,0 +1,116 @@
1
+ import type { NativeConnectionOptions } from '@temporalio/worker';
2
+
3
+ /**
4
+ * A data source for configuration, which can be a path to a file,
5
+ * the string contents of a file, or raw bytes.
6
+ *
7
+ * @experimental Environment configuration is new feature and subject to change.
8
+ */
9
+ export type ConfigDataSource = { path: string } | { data: string | Uint8Array };
10
+
11
+ /**
12
+ * TLS configuration as specified as part of client configuration.
13
+ *
14
+ * @experimental Environment configuration is new feature and subject to change.
15
+ */
16
+ export interface ClientConfigTLS {
17
+ disabled?: boolean;
18
+ serverName?: string;
19
+ clientCert?: ConfigDataSource;
20
+ clientKey?: ConfigDataSource;
21
+ serverCACert?: ConfigDataSource;
22
+ }
23
+
24
+ /**
25
+ * Configuration for connecting to a Temporal client, including connection options and namespace.
26
+ *
27
+ * @experimental Environment configuration is new feature and subject to change.
28
+ */
29
+ export interface ClientConnectConfig {
30
+ connectionOptions: NativeConnectionOptions;
31
+ namespace?: string;
32
+ }
33
+
34
+ /**
35
+ * Options for loading a client configuration profile.
36
+ *
37
+ * @experimental Environment configuration is new feature and subject to change.
38
+ */
39
+ export interface LoadClientProfileOptions {
40
+ /** The name of the profile to load from the config. Defaults to "default". */
41
+ profile?: string;
42
+ /**
43
+ * If present, this is used as the configuration source instead of default
44
+ * file locations. This can be a path to the file or the string/byte
45
+ * contents of the file.
46
+ */
47
+ configSource?: ConfigDataSource;
48
+ /**
49
+ * If true, file loading is disabled. This is only used when `configSource`
50
+ * is not present.
51
+ */
52
+ disableFile?: boolean;
53
+ /** If true, environment variable loading and overriding is disabled. */
54
+ disableEnv?: boolean;
55
+ /** If true, will error on unrecognized keys in the TOML file. */
56
+ configFileStrict?: boolean;
57
+ /**
58
+ * A dictionary of environment variables to use for loading and overrides.
59
+ * If not provided, the current process's environment is used.
60
+ */
61
+ overrideEnvVars?: Record<string, string>;
62
+ }
63
+
64
+ /**
65
+ * A client configuration profile with connection settings for a Temporal client.
66
+ *
67
+ * @experimental Environment configuration is new feature and subject to change.
68
+ */
69
+ export interface ClientConfigProfile {
70
+ address?: string;
71
+ namespace?: string;
72
+ apiKey?: string;
73
+ tls?: ClientConfigTLS;
74
+ grpcMeta?: Record<string, string>;
75
+ }
76
+
77
+ /**
78
+ * Options for loading client configuration.
79
+ * @experimental Environment configuration is new feature and subject to change.
80
+ */
81
+ export interface LoadClientConfigOptions {
82
+ /**
83
+ * If present, this is used as the configuration source instead of default
84
+ * file locations. This can be a path or the string/byte contents of the
85
+ * configuration file.
86
+ */
87
+ configSource?: ConfigDataSource;
88
+ /** If true, will error on unrecognized keys in the TOML file. */
89
+ configFileStrict?: boolean;
90
+ /**
91
+ * The environment variables to use for locating the
92
+ * default config file. If not provided, the current process's
93
+ * environment is used to check for `TEMPORAL_CONFIG_FILE`.
94
+ */
95
+ overrideEnvVars?: Record<string, string>;
96
+ }
97
+
98
+ /**
99
+ * Client configuration represents a client config file.
100
+ *
101
+ * @experimental Environment configuration is new feature and subject to change.
102
+ */
103
+ export interface ClientConfig {
104
+ /** Map of profile name to its corresponding ClientConfigProfile. */
105
+ profiles: Record<string, ClientConfigProfile>;
106
+ }
107
+
108
+ /**
109
+ * Options for parsing client configuration from TOML format.
110
+ *
111
+ * @experimental Environment configuration is new feature and subject to change.
112
+ */
113
+ export interface ClientConfigFromTomlOptions {
114
+ // If true, will error if there are unrecognized keys.
115
+ strict: boolean;
116
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,172 @@
1
+ import { readFileSync } from 'fs';
2
+ import { filterNullAndUndefined } from '@temporalio/common/lib/internal-workflow';
3
+ import { encode, decode } from '@temporalio/common/lib/encoding';
4
+ import { ClientConfigProfile, ClientConfigTLS, ClientConfig, ConfigDataSource } from './types';
5
+ import { normalizeGrpcMetaKey, TomlClientConfig, TomlClientConfigProfile, TomlClientConfigTLS } from './envconfig-toml';
6
+
7
+ /**
8
+ * Loads configuration data from a {@link ConfigDataSource} and returns it as a Uint8Array.
9
+ *
10
+ * @experimental Environment configuration is new feature and subject to change.
11
+ */
12
+ export function loadConfigData(source?: ConfigDataSource): Uint8Array | undefined {
13
+ if (!source) return undefined;
14
+
15
+ if ('path' in source) {
16
+ return Uint8Array.from(readFileSync(source.path));
17
+ }
18
+
19
+ return typeof source.data === 'string' ? encode(source.data) : source.data;
20
+ }
21
+
22
+ /**
23
+ * Converts a TOML profile structure to a {@link ClientConfigProfile}.
24
+ *
25
+ * @experimental Environment configuration is new feature and subject to change.
26
+ */
27
+ export function fromTomlProfile(tomlProfile: TomlClientConfigProfile): ClientConfigProfile {
28
+ let grpcMeta: Record<string, string> | undefined = undefined;
29
+ if (tomlProfile.grpc_meta !== undefined) {
30
+ grpcMeta = {};
31
+ // Normalize GRPC meta keys.
32
+ for (const [key, value] of Object.entries(tomlProfile.grpc_meta)) {
33
+ grpcMeta[normalizeGrpcMetaKey(key)] = value;
34
+ }
35
+ }
36
+ const profile: ClientConfigProfile = {
37
+ address: tomlProfile.address,
38
+ namespace: tomlProfile.namespace,
39
+ apiKey: tomlProfile.api_key,
40
+ tls: fromTomlTLS(tomlProfile.tls),
41
+ grpcMeta,
42
+ };
43
+ return filterNullAndUndefined(profile);
44
+ }
45
+
46
+ /**
47
+ * Converts a {@link ClientConfigProfile} to a TOML profile structure.
48
+ *
49
+ * @experimental Environment configuration is new feature and subject to change.
50
+ */
51
+ export function toTomlProfile(profile: ClientConfigProfile): TomlClientConfigProfile {
52
+ let grpc_meta: Record<string, string> | undefined = undefined;
53
+ if (profile.grpcMeta !== undefined) {
54
+ grpc_meta = {};
55
+ // Normalize GRPC meta keys.
56
+ for (const [key, value] of Object.entries(profile.grpcMeta)) {
57
+ grpc_meta[normalizeGrpcMetaKey(key)] = value;
58
+ }
59
+ }
60
+ const tomlProfile = {
61
+ address: profile.address,
62
+ namespace: profile.namespace,
63
+ api_key: profile.apiKey,
64
+ tls: toTomlTLS(profile.tls),
65
+ grpc_meta,
66
+ };
67
+ return filterNullAndUndefined(tomlProfile);
68
+ }
69
+
70
+ /**
71
+ * Converts a TOML TLS configuration structure to a {@link ClientConfigTLS}.
72
+ *
73
+ * @experimental Environment configuration is new feature and subject to change.
74
+ */
75
+ export function fromTomlTLS(tomlTLS?: TomlClientConfigTLS): ClientConfigTLS | undefined {
76
+ if (tomlTLS === undefined) {
77
+ return undefined;
78
+ }
79
+ const clientConfigTLS: ClientConfigTLS = {
80
+ disabled: tomlTLS.disabled,
81
+ serverName: tomlTLS.server_name,
82
+ clientCert: toConfigDataSource(tomlTLS.client_cert_path, tomlTLS.client_cert_data, 'client_cert'),
83
+ clientKey: toConfigDataSource(tomlTLS.client_key_path, tomlTLS.client_key_data, 'client_key'),
84
+ serverCACert: toConfigDataSource(tomlTLS.server_ca_cert_path, tomlTLS.server_ca_cert_data, 'server_ca_cert'),
85
+ };
86
+ return filterNullAndUndefined(clientConfigTLS);
87
+ }
88
+
89
+ /**
90
+ * Converts a {@link ClientConfigTLS} to a TOML TLS configuration structure.
91
+ *
92
+ * @experimental Environment configuration is new feature and subject to change.
93
+ */
94
+ export function toTomlTLS(tlsConfig?: ClientConfigTLS): TomlClientConfigTLS | undefined {
95
+ if (tlsConfig === undefined) {
96
+ return undefined;
97
+ }
98
+ const clientCert = toPathAndData(tlsConfig.clientCert);
99
+ const clientKey = toPathAndData(tlsConfig.clientKey);
100
+ const serverCACert = toPathAndData(tlsConfig.serverCACert);
101
+ const tomlConfigTLS = {
102
+ disabled: tlsConfig.disabled,
103
+ server_name: tlsConfig.serverName,
104
+ client_cert_path: clientCert?.path,
105
+ client_cert_data: clientCert?.data && decode(clientCert?.data),
106
+ client_key_path: clientKey?.path,
107
+ client_key_data: clientKey?.data && decode(clientKey?.data),
108
+ server_ca_cert_path: serverCACert?.path,
109
+ server_ca_cert_data: serverCACert?.data && decode(serverCACert?.data),
110
+ };
111
+ return filterNullAndUndefined(tomlConfigTLS);
112
+ }
113
+
114
+ /**
115
+ * Converts a TOML client configuration structure to a {@link ClientConfig}.
116
+ *
117
+ * @experimental Environment configuration is new feature and subject to change.
118
+ */
119
+ export function fromTomlConfig(tomlConfig: TomlClientConfig): ClientConfig {
120
+ const profiles: Record<string, ClientConfigProfile> = {};
121
+
122
+ for (const [profileName, profile] of Object.entries(tomlConfig.profile)) {
123
+ profiles[profileName] = fromTomlProfile(profile);
124
+ }
125
+
126
+ return { profiles };
127
+ }
128
+
129
+ /**
130
+ * Converts a {@link ClientConfig} to a TOML client configuration structure.
131
+ *
132
+ * @experimental Environment configuration is new feature and subject to change.
133
+ */
134
+ export function toTomlConfig(config: ClientConfig): TomlClientConfig {
135
+ const profile: Record<string, TomlClientConfigProfile> = {};
136
+
137
+ for (const [profileName, configProfile] of Object.entries(config.profiles)) {
138
+ profile[profileName] = toTomlProfile(configProfile);
139
+ }
140
+
141
+ return { profile };
142
+ }
143
+
144
+ export function toPathAndData(source?: ConfigDataSource): { path?: string; data?: Uint8Array } | undefined {
145
+ if (source === undefined) {
146
+ return undefined;
147
+ }
148
+ if ('path' in source) {
149
+ return { path: source.path };
150
+ }
151
+ if (typeof source.data === 'string') {
152
+ return { data: encode(source.data) };
153
+ }
154
+ return { data: source.data };
155
+ }
156
+
157
+ function toConfigDataSource(
158
+ path: string | undefined,
159
+ data: string | undefined,
160
+ fieldName: string
161
+ ): ConfigDataSource | undefined {
162
+ if (path !== undefined && data !== undefined) {
163
+ throw new Error(`Cannot specify both ${fieldName}_path and ${fieldName}_data`);
164
+ }
165
+ if (data !== undefined) {
166
+ return { data: encode(data) };
167
+ }
168
+ if (path !== undefined) {
169
+ return { path };
170
+ }
171
+ return undefined;
172
+ }