@openstax/ts-utils 1.1.27 → 1.1.29
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/{assertions.d.ts → cjs/assertions.d.ts} +0 -0
- package/dist/{assertions.js → cjs/assertions.js} +0 -0
- package/dist/{aws → cjs/aws}/securityTokenService.d.ts +0 -0
- package/dist/{aws → cjs/aws}/securityTokenService.js +0 -0
- package/dist/{aws → cjs/aws}/ssmService.d.ts +0 -0
- package/dist/{aws → cjs/aws}/ssmService.js +0 -0
- package/dist/cjs/config/awsAccountConfig.d.ts +5 -0
- package/dist/cjs/config/awsAccountConfig.js +35 -0
- package/dist/cjs/config/awsParameterConfig.d.ts +2 -0
- package/dist/cjs/config/awsParameterConfig.js +18 -0
- package/dist/cjs/config/envConfig.d.ts +3 -0
- package/dist/cjs/config/envConfig.js +35 -0
- package/dist/cjs/config/index.d.ts +21 -0
- package/dist/cjs/config/index.js +39 -0
- package/dist/cjs/config/lambdaParameterConfig.d.ts +2 -0
- package/dist/cjs/config/lambdaParameterConfig.js +36 -0
- package/dist/cjs/config/replaceConfig.d.ts +4 -0
- package/dist/cjs/config/replaceConfig.js +12 -0
- package/dist/cjs/config/resolveConfigValue.d.ts +2 -0
- package/dist/cjs/config/resolveConfigValue.js +12 -0
- package/dist/{config.d.ts → cjs/config.d.ts} +0 -0
- package/dist/{config.js → cjs/config.js} +0 -0
- package/dist/{errors.d.ts → cjs/errors.d.ts} +0 -0
- package/dist/{errors.js → cjs/errors.js} +0 -0
- package/dist/{fetch.d.ts → cjs/fetch.d.ts} +0 -0
- package/dist/{fetch.js → cjs/fetch.js} +0 -0
- package/dist/{guards.d.ts → cjs/guards.d.ts} +0 -0
- package/dist/{guards.js → cjs/guards.js} +0 -0
- package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
- package/dist/{index.js → cjs/index.js} +0 -0
- package/dist/{middleware.d.ts → cjs/middleware.d.ts} +0 -0
- package/dist/{middleware.js → cjs/middleware.js} +0 -0
- package/dist/{pagination.d.ts → cjs/pagination.d.ts} +0 -0
- package/dist/{pagination.js → cjs/pagination.js} +0 -0
- package/dist/{profile.d.ts → cjs/profile.d.ts} +0 -0
- package/dist/{profile.js → cjs/profile.js} +0 -0
- package/dist/{routing.d.ts → cjs/routing.d.ts} +0 -0
- package/dist/{routing.js → cjs/routing.js} +0 -0
- package/dist/{services → cjs/services}/apiGateway/index.d.ts +0 -0
- package/dist/{services → cjs/services}/apiGateway/index.js +0 -0
- package/dist/{services → cjs/services}/authProvider/browser.d.ts +0 -0
- package/dist/{services → cjs/services}/authProvider/browser.js +0 -0
- package/dist/{services → cjs/services}/authProvider/decryption.d.ts +0 -0
- package/dist/{services → cjs/services}/authProvider/decryption.js +0 -0
- package/dist/{services → cjs/services}/authProvider/index.d.ts +0 -0
- package/dist/{services → cjs/services}/authProvider/index.js +0 -0
- package/dist/{services → cjs/services}/authProvider/subrequest.d.ts +0 -0
- package/dist/{services → cjs/services}/authProvider/subrequest.js +0 -0
- package/dist/{services → cjs/services}/authProvider/utils/embeddedAuthProvider.d.ts +0 -0
- package/dist/{services → cjs/services}/authProvider/utils/embeddedAuthProvider.js +0 -0
- package/dist/{services → cjs/services}/exercisesGateway/index.d.ts +0 -0
- package/dist/{services → cjs/services}/exercisesGateway/index.js +0 -0
- package/dist/{services → cjs/services}/lrsGateway/attempt-utils.d.ts +0 -0
- package/dist/{services → cjs/services}/lrsGateway/attempt-utils.js +0 -0
- package/dist/{services → cjs/services}/lrsGateway/file-system.d.ts +0 -0
- package/dist/{services → cjs/services}/lrsGateway/file-system.js +0 -0
- package/dist/{services → cjs/services}/lrsGateway/index.d.ts +0 -0
- package/dist/{services → cjs/services}/lrsGateway/index.js +0 -0
- package/dist/{services → cjs/services}/searchProvider/index.d.ts +0 -0
- package/dist/{services → cjs/services}/searchProvider/index.js +0 -0
- package/dist/{services → cjs/services}/searchProvider/memorySearchTheBadWay.d.ts +0 -0
- package/dist/{services → cjs/services}/searchProvider/memorySearchTheBadWay.js +0 -0
- package/dist/{services → cjs/services}/versionedDocumentStore/dynamodb.d.ts +0 -0
- package/dist/{services → cjs/services}/versionedDocumentStore/dynamodb.js +0 -0
- package/dist/{services → cjs/services}/versionedDocumentStore/file-system.d.ts +0 -0
- package/dist/{services → cjs/services}/versionedDocumentStore/file-system.js +0 -0
- package/dist/{services → cjs/services}/versionedDocumentStore/index.d.ts +0 -0
- package/dist/{services → cjs/services}/versionedDocumentStore/index.js +0 -0
- package/dist/cjs/tsconfig.withoutspecs.cjs.tsbuildinfo +1 -0
- package/dist/{types.d.ts → cjs/types.d.ts} +0 -0
- package/dist/{types.js → cjs/types.js} +0 -0
- package/dist/esm/assertions.d.ts +9 -0
- package/dist/esm/assertions.js +90 -0
- package/dist/esm/aws/securityTokenService.d.ts +2 -0
- package/dist/esm/aws/securityTokenService.js +3 -0
- package/dist/esm/aws/ssmService.d.ts +2 -0
- package/dist/esm/aws/ssmService.js +3 -0
- package/dist/esm/config/awsAccountConfig.d.ts +5 -0
- package/dist/esm/config/awsAccountConfig.js +31 -0
- package/dist/esm/config/awsParameterConfig.d.ts +2 -0
- package/dist/esm/config/awsParameterConfig.js +14 -0
- package/dist/esm/config/envConfig.d.ts +3 -0
- package/dist/esm/config/envConfig.js +31 -0
- package/dist/esm/config/index.d.ts +21 -0
- package/dist/esm/config/index.js +21 -0
- package/dist/esm/config/lambdaParameterConfig.d.ts +2 -0
- package/dist/esm/config/lambdaParameterConfig.js +29 -0
- package/dist/esm/config/replaceConfig.d.ts +4 -0
- package/dist/esm/config/replaceConfig.js +8 -0
- package/dist/esm/config/resolveConfigValue.d.ts +2 -0
- package/dist/esm/config/resolveConfigValue.js +8 -0
- package/dist/esm/config.d.ts +27 -0
- package/dist/esm/config.js +127 -0
- package/dist/esm/errors.d.ts +12 -0
- package/dist/esm/errors.js +26 -0
- package/dist/esm/fetch.d.ts +64 -0
- package/dist/esm/fetch.js +46 -0
- package/dist/esm/guards.d.ts +6 -0
- package/dist/esm/guards.js +29 -0
- package/dist/esm/index.d.ts +29 -0
- package/dist/esm/index.js +210 -0
- package/dist/esm/middleware.d.ts +9 -0
- package/dist/esm/middleware.js +34 -0
- package/dist/esm/pagination.d.ts +63 -0
- package/dist/esm/pagination.js +77 -0
- package/dist/esm/profile.d.ts +59 -0
- package/dist/esm/profile.js +191 -0
- package/dist/esm/routing.d.ts +107 -0
- package/dist/esm/routing.js +208 -0
- package/dist/esm/services/apiGateway/index.d.ts +55 -0
- package/dist/esm/services/apiGateway/index.js +51 -0
- package/dist/esm/services/authProvider/browser.d.ts +61 -0
- package/dist/esm/services/authProvider/browser.js +119 -0
- package/dist/esm/services/authProvider/decryption.d.ts +16 -0
- package/dist/esm/services/authProvider/decryption.js +61 -0
- package/dist/esm/services/authProvider/index.d.ts +42 -0
- package/dist/esm/services/authProvider/index.js +15 -0
- package/dist/esm/services/authProvider/subrequest.d.ts +16 -0
- package/dist/esm/services/authProvider/subrequest.js +36 -0
- package/dist/esm/services/authProvider/utils/embeddedAuthProvider.d.ts +20 -0
- package/dist/esm/services/authProvider/utils/embeddedAuthProvider.js +30 -0
- package/dist/esm/services/exercisesGateway/index.d.ts +74 -0
- package/dist/esm/services/exercisesGateway/index.js +69 -0
- package/dist/esm/services/lrsGateway/attempt-utils.d.ts +62 -0
- package/dist/esm/services/lrsGateway/attempt-utils.js +251 -0
- package/dist/esm/services/lrsGateway/file-system.d.ts +15 -0
- package/dist/esm/services/lrsGateway/file-system.js +96 -0
- package/dist/esm/services/lrsGateway/index.d.ts +110 -0
- package/dist/esm/services/lrsGateway/index.js +87 -0
- package/dist/esm/services/searchProvider/index.d.ts +19 -0
- package/dist/esm/services/searchProvider/index.js +1 -0
- package/dist/esm/services/searchProvider/memorySearchTheBadWay.d.ts +12 -0
- package/dist/esm/services/searchProvider/memorySearchTheBadWay.js +53 -0
- package/dist/esm/services/versionedDocumentStore/dynamodb.d.ts +23 -0
- package/dist/esm/services/versionedDocumentStore/dynamodb.js +147 -0
- package/dist/esm/services/versionedDocumentStore/file-system.d.ts +25 -0
- package/dist/esm/services/versionedDocumentStore/file-system.js +81 -0
- package/dist/esm/services/versionedDocumentStore/index.d.ts +23 -0
- package/dist/esm/services/versionedDocumentStore/index.js +1 -0
- package/dist/esm/tsconfig.withoutspecs.esm.tsbuildinfo +1 -0
- package/dist/esm/types.d.ts +6 -0
- package/dist/esm/types.js +1 -0
- package/package.json +24 -8
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/tsconfig.withoutspecs.tsbuildinfo +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare type ConfigValue = string;
|
|
2
|
+
export declare type Config = {
|
|
3
|
+
[key: string]: Config | ConfigValue;
|
|
4
|
+
};
|
|
5
|
+
export declare type ConfigValueProvider<V extends ConfigValue = ConfigValue> = (() => Promise<V> | V) | V;
|
|
6
|
+
export declare type ConfigProvider = {
|
|
7
|
+
[key: string]: ConfigProvider | ConfigValueProvider;
|
|
8
|
+
};
|
|
9
|
+
export declare type ConfigForConfigProvider<T> = T extends ConfigValue ? T : T extends ConfigProvider ? {
|
|
10
|
+
[key in keyof T]: ConfigForConfigProvider<T[key]>;
|
|
11
|
+
} : T extends ConfigValueProvider<infer R> ? R : never;
|
|
12
|
+
export declare type ConfigProviderForConfig<T> = T extends ConfigValue ? ConfigValueProvider<T> : T extends Config ? {
|
|
13
|
+
[key in keyof T]: ConfigProviderForConfig<T[key]>;
|
|
14
|
+
} : never;
|
|
15
|
+
export * from './resolveConfigValue';
|
|
16
|
+
export declare const stubConfig: <V extends string>(configValue: V) => ConfigValueProvider<V>;
|
|
17
|
+
export * from './envConfig';
|
|
18
|
+
export * from './replaceConfig';
|
|
19
|
+
export * from './awsAccountConfig';
|
|
20
|
+
export * from './awsParameterConfig';
|
|
21
|
+
export * from './lambdaParameterConfig';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './resolveConfigValue';
|
|
2
|
+
/*
|
|
3
|
+
* ===========
|
|
4
|
+
* re-usable config providers
|
|
5
|
+
* ===========
|
|
6
|
+
* */
|
|
7
|
+
/*
|
|
8
|
+
* stub, mostly for testing. sometimes it helps please typescript to use this if you have
|
|
9
|
+
* two configs you want to have the same type but one is a fixed string and one is a complicated provider
|
|
10
|
+
*
|
|
11
|
+
* eg:
|
|
12
|
+
* const config = {
|
|
13
|
+
* configValue: stubConfig('just-a-string'),
|
|
14
|
+
* };
|
|
15
|
+
* */
|
|
16
|
+
export const stubConfig = (configValue) => configValue;
|
|
17
|
+
export * from './envConfig';
|
|
18
|
+
export * from './replaceConfig';
|
|
19
|
+
export * from './awsAccountConfig';
|
|
20
|
+
export * from './awsParameterConfig';
|
|
21
|
+
export * from './lambdaParameterConfig';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
import { assertDefined } from '../assertions';
|
|
3
|
+
import { envConfig } from './envConfig';
|
|
4
|
+
import { resolveConfigValue } from '.';
|
|
5
|
+
const lambdaExtensionUrl = 'http://localhost:2773';
|
|
6
|
+
let lambdaExtensionReadyPromise;
|
|
7
|
+
// NOTE: Can only be used during in AWS Lambda
|
|
8
|
+
// The AWS Parameters and Secrets Lambda Extension Layer must be included in the Lambda function
|
|
9
|
+
export const lambdaParameterConfig = (parameterName) => async () => {
|
|
10
|
+
const token = await resolveConfigValue(envConfig('AWS_SESSION_TOKEN', 'runtime'));
|
|
11
|
+
const name = await resolveConfigValue(parameterName);
|
|
12
|
+
if (!lambdaExtensionReadyPromise) {
|
|
13
|
+
// This request will return 400 Bad Request,
|
|
14
|
+
// but we only care that it'll block until the extension is ready
|
|
15
|
+
lambdaExtensionReadyPromise = fetch(lambdaExtensionUrl);
|
|
16
|
+
}
|
|
17
|
+
await lambdaExtensionReadyPromise;
|
|
18
|
+
const resp = await fetch(
|
|
19
|
+
// Port 2773 is the default port for the extension
|
|
20
|
+
`${lambdaExtensionUrl}/systemsmanager/parameters/get?name=${name}&withDecryption=true`, { headers: { 'X-Aws-Parameters-Secrets-Token': token } });
|
|
21
|
+
if (resp.ok) {
|
|
22
|
+
const response = await resp.json();
|
|
23
|
+
const parameter = assertDefined(response.Parameter, `aws GetParameter response missing Parameter key for ${name}"`);
|
|
24
|
+
return assertDefined(parameter.Value, `aws GetParameter response missing Parameter.Value key for ${name}"`);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
throw new Error(`HTTP Error Response ${resp.status} ${resp.statusText} while fetching parameter ${name}`);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { resolveConfigValue } from './resolveConfigValue';
|
|
2
|
+
export const replaceConfig = (base, replacements) => {
|
|
3
|
+
return async () => {
|
|
4
|
+
const resolved = await Promise.all(Object.entries(replacements)
|
|
5
|
+
.map(async ([token, replacement]) => [token, await resolveConfigValue(replacement)]));
|
|
6
|
+
return resolved.reduce((result, [token, replacement]) => result.replace(token, replacement), await resolveConfigValue(base));
|
|
7
|
+
};
|
|
8
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare type ConfigValue = string;
|
|
2
|
+
export declare type Config = {
|
|
3
|
+
[key: string]: Config | ConfigValue;
|
|
4
|
+
};
|
|
5
|
+
export declare type ConfigValueProvider<V extends ConfigValue = ConfigValue> = (() => Promise<V> | V) | V;
|
|
6
|
+
export declare type ConfigProvider = {
|
|
7
|
+
[key: string]: ConfigProvider | ConfigValueProvider;
|
|
8
|
+
};
|
|
9
|
+
export declare type ConfigForConfigProvider<T> = T extends ConfigValue ? T : T extends ConfigProvider ? {
|
|
10
|
+
[key in keyof T]: ConfigForConfigProvider<T[key]>;
|
|
11
|
+
} : T extends ConfigValueProvider<infer R> ? R : never;
|
|
12
|
+
export declare type ConfigProviderForConfig<T> = T extends ConfigValue ? ConfigValueProvider<T> : T extends Config ? {
|
|
13
|
+
[key in keyof T]: ConfigProviderForConfig<T[key]>;
|
|
14
|
+
} : never;
|
|
15
|
+
export declare const resolveConfigValue: <V extends string>(provider: ConfigValueProvider<V>) => Promise<V>;
|
|
16
|
+
export declare const ENV_BUILD_CONFIGS: string[];
|
|
17
|
+
export declare const envConfig: (name: string, type?: 'build' | 'runtime', defaultValue?: string | undefined) => ConfigValueProvider<string>;
|
|
18
|
+
export declare const stubConfig: <V extends string>(configValue: V) => ConfigValueProvider<V>;
|
|
19
|
+
export declare const replaceConfig: (base: ConfigValueProvider<string>, replacements: {
|
|
20
|
+
[token: string]: ConfigValueProvider<string>;
|
|
21
|
+
}) => ConfigValueProvider<string>;
|
|
22
|
+
export declare const awsAccountConfig: <C extends string>(config: {
|
|
23
|
+
sandbox: ConfigValueProvider<C>;
|
|
24
|
+
production: ConfigValueProvider<C>;
|
|
25
|
+
}) => ConfigValueProvider<C>;
|
|
26
|
+
export declare const awsParameterConfig: (parameterName: ConfigValueProvider<string>) => ConfigValueProvider<string>;
|
|
27
|
+
export declare const lambdaParameterConfig: (parameterName: ConfigValueProvider<string>) => ConfigValueProvider<string>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { GetParameterCommand } from '@aws-sdk/client-ssm';
|
|
2
|
+
import { GetCallerIdentityCommand } from '@aws-sdk/client-sts';
|
|
3
|
+
import fetch from 'node-fetch';
|
|
4
|
+
import { assertDefined } from './assertions';
|
|
5
|
+
import { securityTokenService } from './aws/securityTokenService';
|
|
6
|
+
import { ssmService } from './aws/ssmService';
|
|
7
|
+
import { ifDefined } from './guards';
|
|
8
|
+
/*
|
|
9
|
+
* resolves a config value into a string, to be used inside of things that are provided configurations
|
|
10
|
+
* */
|
|
11
|
+
export const resolveConfigValue = async (provider) => {
|
|
12
|
+
return typeof provider === 'function'
|
|
13
|
+
? await provider()
|
|
14
|
+
: provider;
|
|
15
|
+
};
|
|
16
|
+
/*
|
|
17
|
+
* ===========
|
|
18
|
+
* re-usable config providers
|
|
19
|
+
* ===========
|
|
20
|
+
* */
|
|
21
|
+
/*
|
|
22
|
+
* uses a config from the process environment.
|
|
23
|
+
*
|
|
24
|
+
* there are two modes for this, by default it expects the value to be provided at build time,
|
|
25
|
+
* and there is access built in here for webpack to provide the configs. if you pass `runtime`
|
|
26
|
+
* as the second argument it skips the build logic and will try to literally pull it from
|
|
27
|
+
* `process.env` when the config is used at runtime
|
|
28
|
+
*
|
|
29
|
+
* the value is read from the environment when something tries to use it, not when `envConfig` is called.
|
|
30
|
+
*
|
|
31
|
+
* eg:
|
|
32
|
+
* const config = {
|
|
33
|
+
* configValue: envConfig('environment_variable_name'),
|
|
34
|
+
* };
|
|
35
|
+
* */
|
|
36
|
+
export const ENV_BUILD_CONFIGS = [];
|
|
37
|
+
export const envConfig = (name, type = 'build', defaultValue) => {
|
|
38
|
+
if (type === 'build') {
|
|
39
|
+
ENV_BUILD_CONFIGS.push(name);
|
|
40
|
+
}
|
|
41
|
+
return () => {
|
|
42
|
+
/*global __PROCESS_ENV*/
|
|
43
|
+
// @ts-ignore - hack to get around the way webpack/define works
|
|
44
|
+
// - https://github.com/webpack/webpack/issues/14800
|
|
45
|
+
// - https://github.com/webpack/webpack/issues/5392
|
|
46
|
+
const envs = { ...process.env, ...(typeof __PROCESS_ENV !== 'undefined' ? __PROCESS_ENV : {}) };
|
|
47
|
+
return assertDefined(ifDefined(envs[name], defaultValue), `expected to find environment variable with name: ${name}`);
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/*
|
|
51
|
+
* stub, mostly for testing. sometimes it helps please typescript to use this if you have
|
|
52
|
+
* two configs you want to have the same type but one is a fixed string and one is a complicated provider
|
|
53
|
+
*
|
|
54
|
+
* eg:
|
|
55
|
+
* const config = {
|
|
56
|
+
* configValue: stubConfig('just-a-string'),
|
|
57
|
+
* };
|
|
58
|
+
* */
|
|
59
|
+
export const stubConfig = (configValue) => configValue;
|
|
60
|
+
export const replaceConfig = (base, replacements) => {
|
|
61
|
+
return async () => {
|
|
62
|
+
const resolved = await Promise.all(Object.entries(replacements)
|
|
63
|
+
.map(async ([token, replacement]) => [token, await resolveConfigValue(replacement)]));
|
|
64
|
+
return resolved.reduce((result, [token, replacement]) => result.replace(token, replacement), await resolveConfigValue(base));
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
/*
|
|
68
|
+
* uses a different given value depending on which aws account the code is deployed in.
|
|
69
|
+
* this resolves the given value recursively, so its composable with more configProviders in the
|
|
70
|
+
* conditional cases.
|
|
71
|
+
*
|
|
72
|
+
* eg:
|
|
73
|
+
* const config = {
|
|
74
|
+
* configValue: awsAccountConfig({sandbox: 'inTheSandboxConfig', production: 'inProductionConfig'}),
|
|
75
|
+
* configValue: awsAccountConfig({sandbox: envConfig('an_environment_variable'), production: 'inProductionConfig'}),
|
|
76
|
+
* };
|
|
77
|
+
* */
|
|
78
|
+
export const awsAccountConfig = (config) => {
|
|
79
|
+
const production = envConfig('PRODUCTION_AWS');
|
|
80
|
+
const sandbox = envConfig('SANDBOX_AWS');
|
|
81
|
+
return async () => {
|
|
82
|
+
const identity = await securityTokenService().send(new GetCallerIdentityCommand({}));
|
|
83
|
+
switch (identity.Account) {
|
|
84
|
+
case await resolveConfigValue(sandbox):
|
|
85
|
+
return await resolveConfigValue(assertDefined(config.sandbox, 'a sandbox config was not provided'));
|
|
86
|
+
case await resolveConfigValue(production):
|
|
87
|
+
return await resolveConfigValue(assertDefined(config.production, 'a production config was not provided'));
|
|
88
|
+
default:
|
|
89
|
+
throw new Error('unknown aws account');
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
export const awsParameterConfig = (parameterName) => {
|
|
94
|
+
return async () => {
|
|
95
|
+
const command = new GetParameterCommand({ Name: await resolveConfigValue(parameterName), WithDecryption: true });
|
|
96
|
+
// send() throws ParameterNotFound if the parameter is missing,
|
|
97
|
+
// so it's not clear what missing Parameter or Value mean
|
|
98
|
+
const response = await ssmService().send(command);
|
|
99
|
+
const parameter = assertDefined(response.Parameter, `aws GetParameter response missing Parameter key for ${parameterName}"`);
|
|
100
|
+
return assertDefined(parameter.Value, `aws GetParameter response missing Parameter.Value key for ${parameterName}"`);
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const lambdaExtensionUrl = 'http://localhost:2773';
|
|
104
|
+
let lambdaExtensionReadyPromise;
|
|
105
|
+
// NOTE: Can only be used during in AWS Lambda
|
|
106
|
+
// The AWS Parameters and Secrets Lambda Extension Layer must be included in the Lambda function
|
|
107
|
+
export const lambdaParameterConfig = (parameterName) => async () => {
|
|
108
|
+
const token = await resolveConfigValue(envConfig('AWS_SESSION_TOKEN', 'runtime'));
|
|
109
|
+
const name = await resolveConfigValue(parameterName);
|
|
110
|
+
if (!lambdaExtensionReadyPromise) {
|
|
111
|
+
// This request will return 400 Bad Request,
|
|
112
|
+
// but we only care that it'll block until the extension is ready
|
|
113
|
+
lambdaExtensionReadyPromise = fetch(lambdaExtensionUrl);
|
|
114
|
+
}
|
|
115
|
+
await lambdaExtensionReadyPromise;
|
|
116
|
+
const resp = await fetch(
|
|
117
|
+
// Port 2773 is the default port for the extension
|
|
118
|
+
`${lambdaExtensionUrl}/systemsmanager/parameters/get?name=${name}&withDecryption=true`, { headers: { 'X-Aws-Parameters-Secrets-Token': token } });
|
|
119
|
+
if (resp.ok) {
|
|
120
|
+
const response = await resp.json();
|
|
121
|
+
const parameter = assertDefined(response.Parameter, `aws GetParameter response missing Parameter key for ${name}"`);
|
|
122
|
+
return assertDefined(parameter.Value, `aws GetParameter response missing Parameter.Value key for ${name}"`);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
throw new Error(`HTTP Error Response ${resp.status} ${resp.statusText} while fetching parameter ${name}`);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class InvalidRequestError extends Error {
|
|
2
|
+
static readonly TYPE = "InvalidRequestError";
|
|
3
|
+
static matches: (e: any) => e is typeof InvalidRequestError;
|
|
4
|
+
}
|
|
5
|
+
export declare class UnauthorizedError extends Error {
|
|
6
|
+
static readonly TYPE = "UnauthorizedError";
|
|
7
|
+
static matches: (e: any) => e is typeof UnauthorizedError;
|
|
8
|
+
}
|
|
9
|
+
export declare class NotFoundError extends Error {
|
|
10
|
+
static readonly TYPE = "NotFoundError";
|
|
11
|
+
static matches: (e: any) => e is typeof NotFoundError;
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* if code is split into multiple bundles, sometimes each bundle
|
|
3
|
+
* will get its own definition of this module and then instanceof checks
|
|
4
|
+
* are unreliable, this provides a way to reliably check the error types
|
|
5
|
+
*
|
|
6
|
+
* eg this will always work:
|
|
7
|
+
* InvalidRequestError.matches(error);
|
|
8
|
+
*
|
|
9
|
+
* eg this might not work if you have code splitting:
|
|
10
|
+
* error instanceof InvalidRequestError
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
13
|
+
const errorIsType = ({ TYPE }) => (e) => e instanceof Error
|
|
14
|
+
&& e.constructor.TYPE === TYPE;
|
|
15
|
+
export class InvalidRequestError extends Error {
|
|
16
|
+
}
|
|
17
|
+
InvalidRequestError.TYPE = 'InvalidRequestError';
|
|
18
|
+
InvalidRequestError.matches = errorIsType(InvalidRequestError);
|
|
19
|
+
export class UnauthorizedError extends Error {
|
|
20
|
+
}
|
|
21
|
+
UnauthorizedError.TYPE = 'UnauthorizedError';
|
|
22
|
+
UnauthorizedError.matches = errorIsType(UnauthorizedError);
|
|
23
|
+
export class NotFoundError extends Error {
|
|
24
|
+
}
|
|
25
|
+
NotFoundError.TYPE = 'NotFoundError';
|
|
26
|
+
NotFoundError.matches = errorIsType(NotFoundError);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { METHOD } from './routing';
|
|
2
|
+
export declare enum FetchStateType {
|
|
3
|
+
SUCCESS = "success",
|
|
4
|
+
ERROR = "error",
|
|
5
|
+
LOADING = "loading",
|
|
6
|
+
IDLE = "idle"
|
|
7
|
+
}
|
|
8
|
+
export declare type FetchState<D, E> = FetchStateLoading<D> | FetchStateError<D, E> | FetchStateSuccess<D> | FetchStateIdle;
|
|
9
|
+
declare type FetchStateLoading<D> = {
|
|
10
|
+
type: FetchStateType.LOADING;
|
|
11
|
+
data?: D;
|
|
12
|
+
};
|
|
13
|
+
declare type FetchStateError<D, E> = {
|
|
14
|
+
type: FetchStateType.ERROR;
|
|
15
|
+
data?: D;
|
|
16
|
+
error: E;
|
|
17
|
+
};
|
|
18
|
+
declare type FetchStateSuccess<D> = {
|
|
19
|
+
type: FetchStateType.SUCCESS;
|
|
20
|
+
data: D;
|
|
21
|
+
};
|
|
22
|
+
declare type FetchStateIdle = {
|
|
23
|
+
type: FetchStateType.IDLE;
|
|
24
|
+
};
|
|
25
|
+
export declare const fetchLoading: <D, E>(previous?: FetchState<D, E> | undefined) => FetchStateLoading<D>;
|
|
26
|
+
export declare const fetchError: <D, E>(error: E, previous?: FetchState<D, E> | undefined) => FetchStateError<D, E>;
|
|
27
|
+
export declare const fetchSuccess: <D>(data: D) => FetchStateSuccess<D>;
|
|
28
|
+
export declare const fetchIdle: () => FetchStateIdle;
|
|
29
|
+
export declare const stateHasData: <D, E>(state: {
|
|
30
|
+
type: FetchStateType;
|
|
31
|
+
data?: D | undefined;
|
|
32
|
+
error?: E | undefined;
|
|
33
|
+
}) => state is {
|
|
34
|
+
type: FetchStateType;
|
|
35
|
+
data: D;
|
|
36
|
+
};
|
|
37
|
+
export declare const stateHasError: <D, E>(state: {
|
|
38
|
+
type: FetchStateType;
|
|
39
|
+
data?: D | undefined;
|
|
40
|
+
error?: E | undefined;
|
|
41
|
+
}) => state is {
|
|
42
|
+
type: FetchStateType;
|
|
43
|
+
error: E;
|
|
44
|
+
};
|
|
45
|
+
export declare type FetchConfig = {
|
|
46
|
+
credentials?: 'include' | 'omit' | 'same-origin';
|
|
47
|
+
method?: METHOD;
|
|
48
|
+
body?: string;
|
|
49
|
+
headers?: {
|
|
50
|
+
[key: string]: string;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
declare type Headers = {
|
|
54
|
+
get: (name: string) => string | null;
|
|
55
|
+
};
|
|
56
|
+
export declare type Response = {
|
|
57
|
+
status: number;
|
|
58
|
+
headers: Headers;
|
|
59
|
+
json: () => Promise<any>;
|
|
60
|
+
text: () => Promise<string>;
|
|
61
|
+
};
|
|
62
|
+
export declare type GenericFetch<C extends FetchConfig = FetchConfig, R extends Response = Response> = (url: string, fetchConfig?: C) => Promise<R>;
|
|
63
|
+
export declare type ConfigForFetch<F> = F extends GenericFetch<infer C, any> ? C : never;
|
|
64
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* these are just helpers for formatting responses, they don't actually do any loading. especially in UI development they
|
|
3
|
+
* help with continuity over loading, reloading, saving, and errors. this is pretty nice in typescript because you have to deal
|
|
4
|
+
* with the possibility that the result state is in a loading or error state. if you avoid dealing with those states you need
|
|
5
|
+
* to write very clear code to ignore them, which easily presents missing functionality like errors that are not being messaged
|
|
6
|
+
* to the user.
|
|
7
|
+
* */
|
|
8
|
+
export var FetchStateType;
|
|
9
|
+
(function (FetchStateType) {
|
|
10
|
+
FetchStateType["SUCCESS"] = "success";
|
|
11
|
+
FetchStateType["ERROR"] = "error";
|
|
12
|
+
FetchStateType["LOADING"] = "loading";
|
|
13
|
+
FetchStateType["IDLE"] = "idle";
|
|
14
|
+
})(FetchStateType || (FetchStateType = {}));
|
|
15
|
+
/*
|
|
16
|
+
* keeps existing data but sets the new status
|
|
17
|
+
*
|
|
18
|
+
* const state = fetchLoading(previousState)
|
|
19
|
+
* */
|
|
20
|
+
export const fetchLoading = (previous) => ({ type: FetchStateType.LOADING, ...(previous && 'data' in previous ? { data: previous.data } : {}) });
|
|
21
|
+
/*
|
|
22
|
+
* keeps existing data but sets the new status and error value
|
|
23
|
+
*
|
|
24
|
+
* const state = fetchError(error, previousState)
|
|
25
|
+
* */
|
|
26
|
+
export const fetchError = (error, previous) => ({ ...previous, type: FetchStateType.ERROR, error });
|
|
27
|
+
/*
|
|
28
|
+
* formats data with success type
|
|
29
|
+
*
|
|
30
|
+
* const state = fetchSuccess(newData)
|
|
31
|
+
* */
|
|
32
|
+
export const fetchSuccess = (data) => ({ type: FetchStateType.SUCCESS, data });
|
|
33
|
+
/*
|
|
34
|
+
* formats data with idle type
|
|
35
|
+
*
|
|
36
|
+
* const state = fetchIdle(newData)
|
|
37
|
+
* */
|
|
38
|
+
export const fetchIdle = () => ({ type: FetchStateType.IDLE });
|
|
39
|
+
/*
|
|
40
|
+
* guard for checking if the state has result data, it might be true for any state type.
|
|
41
|
+
* */
|
|
42
|
+
export const stateHasData = (state) => 'data' in state;
|
|
43
|
+
/*
|
|
44
|
+
* guard for checking if the state has an error, it might be true for error or loading states.
|
|
45
|
+
* */
|
|
46
|
+
export const stateHasError = (state) => 'error' in state;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const isDefined: <X>(x: X) => x is Exclude<X, undefined>;
|
|
2
|
+
export declare const isNumber: (x: any) => x is number;
|
|
3
|
+
export declare const isPlainObject: (thing: any) => thing is {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
};
|
|
6
|
+
export declare const ifDefined: <X, D>(x: X, d: D) => D | Exclude<X, undefined>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* checks if a thing is defined. this is often easy to do with a simple if statement, but in certain
|
|
3
|
+
* situations the guard is required and its nice to have one pre-defined.
|
|
4
|
+
*
|
|
5
|
+
* eg this filters the array but doesn't fix the array type:
|
|
6
|
+
* const result = (array as Array<string | undefined>).filter(thing => !!thing);
|
|
7
|
+
*
|
|
8
|
+
* eg this does the right thing:
|
|
9
|
+
* const result = (array as Array<string | undefined>).filter(isDefined);
|
|
10
|
+
*
|
|
11
|
+
* eg because writing this is annoying:
|
|
12
|
+
* const result = (array as Array<string | undefined>).filter(<X>(x: X): x is Exclude<X, undefined> => x !== undefined);
|
|
13
|
+
*/
|
|
14
|
+
export const isDefined = (x) => x !== undefined;
|
|
15
|
+
export const isNumber = (x) => typeof x === 'number';
|
|
16
|
+
/*
|
|
17
|
+
* a guard for plain old javascript objects that are not based on some other prototype,
|
|
18
|
+
* for example making them safe to JSON stringify and stuff
|
|
19
|
+
* */
|
|
20
|
+
export const isPlainObject = (thing) => thing instanceof Object && thing.__proto__.constructor.name === 'Object';
|
|
21
|
+
/*
|
|
22
|
+
* this isn't really a guard its just a way to provide a default value without creating a coverage branch.
|
|
23
|
+
*
|
|
24
|
+
* if the first thing is defined it uses it, otherwise it returns the second thing.
|
|
25
|
+
*
|
|
26
|
+
* eg:
|
|
27
|
+
* const valueWithDefault = ifDefined(thing, 'default value')
|
|
28
|
+
*/
|
|
29
|
+
export const ifDefined = (x, d) => isDefined(x) ? x : d;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { UnionToIntersection } from './types';
|
|
2
|
+
export declare const getKeyValue: <K extends string>(key: K) => <O extends { [key in K]?: any; }>(obj: O) => O[K];
|
|
3
|
+
export declare const getKeyValueOr: <K extends string, V, Od extends { [key in K]?: any; } = { [key_1 in K]?: any; }>(key: K, defaultValue: V) => <O extends Od extends undefined ? { [key_2 in K]?: any; } : Od>(obj: O) => V | NonNullable<O[K]>;
|
|
4
|
+
export declare const putKeyValue: <K extends string>(key: K) => <O extends { [key in K]?: any; }>(obj: O, value: O[K]) => O;
|
|
5
|
+
export declare const coerceArray: <T>(thing: T | T[] | undefined) => T[];
|
|
6
|
+
declare type FlowFn<A, R> = (...args: [A]) => R;
|
|
7
|
+
declare type AnyFlowFn = FlowFn<any, any>;
|
|
8
|
+
declare type FlowFnResult<F, A> = F extends FlowFn<A, infer R> ? R : never;
|
|
9
|
+
declare type FlowResult<C, A> = C extends [infer F1, ...infer Cr] ? F1 extends AnyFlowFn ? Cr extends never[] ? FlowFnResult<F1, A> : FlowResult<Cr, FlowFnResult<F1, A>> : never : never;
|
|
10
|
+
declare type FlowChainArg<C> = C extends [infer F1, ...infer _] ? F1 extends FlowFn<infer A, any> ? A : never : never;
|
|
11
|
+
export declare const flow: <C extends AnyFlowFn[]>(...chain: C) => (param: FlowChainArg<C>) => FlowResult<C, FlowChainArg<C>>;
|
|
12
|
+
export declare const fnIf: <T1, T2>(condition: boolean, trueValue: T1, falseValue: T2) => T1 | T2;
|
|
13
|
+
export declare const mapFind: <I, R>(array: I[], mapper: (item: I) => R, predicate?: (result: R) => boolean) => R | undefined;
|
|
14
|
+
declare type HashValue = string | number | boolean | null | HashCompoundValue;
|
|
15
|
+
declare type HashCompoundValue = Array<HashValue> | {
|
|
16
|
+
[key: string]: HashValue;
|
|
17
|
+
};
|
|
18
|
+
export declare const hashValue: (value: HashValue) => string;
|
|
19
|
+
export declare const once: <F extends (...args: any[]) => any>(fn: F) => F;
|
|
20
|
+
export declare const partitionSequence: <T, P>(getPartition: (thing: T, previous?: P | undefined) => {
|
|
21
|
+
matches?: boolean | undefined;
|
|
22
|
+
value: P;
|
|
23
|
+
}, sequence: T[]) => [P, T[]][];
|
|
24
|
+
export declare const memoize: <F extends (...args: any[]) => any>(fn: F) => F;
|
|
25
|
+
export declare const roundToPrecision: (num: number, places: number) => number;
|
|
26
|
+
export declare const getCommonProperties: <T1 extends {}, T2 extends {}>(thing1: T1, thing2: T2) => (keyof T1 & keyof T2)[];
|
|
27
|
+
export declare const merge: <T extends {}[]>(...[thing1, ...tail]: T) => UnionToIntersection<T[number]>;
|
|
28
|
+
export declare const tuple: <A extends any[]>(...args: A) => A;
|
|
29
|
+
export {};
|