@openstax/ts-utils 1.7.0 → 1.9.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.
- package/dist/cjs/{fetch.d.ts → fetch/index.d.ts} +1 -1
- package/dist/{esm/middleware.d.ts → cjs/middleware/index.d.ts} +2 -2
- package/dist/cjs/misc/hashValue.d.ts +2 -3
- package/dist/cjs/{pagination.d.ts → pagination/index.d.ts} +1 -1
- package/dist/cjs/{pagination.js → pagination/index.js} +3 -3
- package/dist/cjs/routing/index.d.ts +0 -3
- package/dist/cjs/routing/index.js +7 -9
- package/dist/cjs/services/authProvider/decryption.js +5 -5
- package/dist/cjs/services/authProvider/index.d.ts +0 -2
- package/dist/cjs/services/authProvider/subrequest.js +6 -6
- package/dist/cjs/services/documentStore/dynamoEncoding.d.ts +10 -0
- package/dist/cjs/services/documentStore/dynamoEncoding.js +52 -0
- package/dist/cjs/services/documentStore/index.d.ts +14 -0
- package/dist/cjs/services/documentStore/unversioned/dynamodb.d.ts +13 -0
- package/dist/cjs/services/documentStore/unversioned/dynamodb.js +51 -0
- package/dist/cjs/services/documentStore/unversioned/file-system.d.ts +15 -0
- package/dist/cjs/services/documentStore/unversioned/file-system.js +81 -0
- package/dist/cjs/services/documentStore/unversioned/index.d.ts +2 -0
- package/dist/cjs/services/documentStore/unversioned/index.js +2 -0
- package/dist/{esm/services/versionedDocumentStore → cjs/services/documentStore/versioned}/dynamodb.d.ts +6 -11
- package/dist/cjs/services/{versionedDocumentStore → documentStore/versioned}/dynamodb.js +27 -70
- package/dist/cjs/services/{versionedDocumentStore → documentStore/versioned}/file-system.d.ts +6 -11
- package/dist/cjs/services/{versionedDocumentStore → documentStore/versioned}/file-system.js +16 -16
- package/dist/cjs/services/{versionedDocumentStore → documentStore/versioned}/index.d.ts +2 -8
- package/dist/cjs/services/documentStore/versioned/index.js +2 -0
- package/dist/cjs/services/exercisesGateway/index.d.ts +3 -6
- package/dist/cjs/services/exercisesGateway/index.js +7 -7
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +4 -0
- package/dist/esm/{fetch.d.ts → fetch/index.d.ts} +1 -1
- package/dist/{cjs/middleware.d.ts → esm/middleware/index.d.ts} +2 -2
- package/dist/esm/misc/hashValue.d.ts +2 -3
- package/dist/esm/{pagination.d.ts → pagination/index.d.ts} +1 -1
- package/dist/esm/{pagination.js → pagination/index.js} +3 -3
- package/dist/esm/routing/index.d.ts +0 -3
- package/dist/esm/routing/index.js +7 -9
- package/dist/esm/services/authProvider/decryption.js +5 -5
- package/dist/esm/services/authProvider/index.d.ts +0 -2
- package/dist/esm/services/authProvider/subrequest.js +6 -6
- package/dist/esm/services/documentStore/dynamoEncoding.d.ts +10 -0
- package/dist/esm/services/documentStore/dynamoEncoding.js +45 -0
- package/dist/esm/services/documentStore/index.d.ts +14 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.d.ts +13 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.js +47 -0
- package/dist/esm/services/documentStore/unversioned/file-system.d.ts +15 -0
- package/dist/esm/services/documentStore/unversioned/file-system.js +51 -0
- package/dist/esm/services/documentStore/unversioned/index.d.ts +2 -0
- package/dist/esm/services/documentStore/unversioned/index.js +1 -0
- package/dist/{cjs/services/versionedDocumentStore → esm/services/documentStore/versioned}/dynamodb.d.ts +6 -11
- package/dist/esm/services/{versionedDocumentStore → documentStore/versioned}/dynamodb.js +17 -60
- package/dist/esm/services/{versionedDocumentStore → documentStore/versioned}/file-system.d.ts +6 -11
- package/dist/esm/services/{versionedDocumentStore → documentStore/versioned}/file-system.js +16 -16
- package/dist/esm/services/{versionedDocumentStore → documentStore/versioned}/index.d.ts +2 -8
- package/dist/esm/services/documentStore/versioned/index.js +1 -0
- package/dist/esm/services/exercisesGateway/index.d.ts +3 -6
- package/dist/esm/services/exercisesGateway/index.js +7 -7
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +4 -0
- package/package.json +118 -13
- package/dist/cjs/profile.d.ts +0 -61
- package/dist/cjs/profile.js +0 -199
- package/dist/esm/profile.d.ts +0 -61
- package/dist/esm/profile.js +0 -191
- /package/dist/cjs/{assertions.d.ts → assertions/index.d.ts} +0 -0
- /package/dist/cjs/{assertions.js → assertions/index.js} +0 -0
- /package/dist/cjs/{errors.d.ts → errors/index.d.ts} +0 -0
- /package/dist/cjs/{errors.js → errors/index.js} +0 -0
- /package/dist/cjs/{fetch.js → fetch/index.js} +0 -0
- /package/dist/cjs/{guards.d.ts → guards/index.d.ts} +0 -0
- /package/dist/cjs/{guards.js → guards/index.js} +0 -0
- /package/dist/cjs/{middleware.js → middleware/index.js} +0 -0
- /package/dist/cjs/services/{versionedDocumentStore → documentStore}/index.js +0 -0
- /package/dist/esm/{assertions.d.ts → assertions/index.d.ts} +0 -0
- /package/dist/esm/{assertions.js → assertions/index.js} +0 -0
- /package/dist/esm/{errors.d.ts → errors/index.d.ts} +0 -0
- /package/dist/esm/{errors.js → errors/index.js} +0 -0
- /package/dist/esm/{fetch.js → fetch/index.js} +0 -0
- /package/dist/esm/{guards.d.ts → guards/index.d.ts} +0 -0
- /package/dist/esm/{guards.js → guards/index.js} +0 -0
- /package/dist/esm/{middleware.js → middleware/index.js} +0 -0
- /package/dist/esm/services/{versionedDocumentStore → documentStore}/index.js +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TupleZip } from '../types';
|
|
2
2
|
export declare type MiddlewareProvider<Sa, M, A extends any[], R> = (app: Sa, appBinder?: ((app: Sa, provider: MiddlewareProvider<Sa, M, A, R>) => (middleware: M, ...args: A) => R)) => (middleware: M, ...args: A) => R;
|
|
3
3
|
export declare type MiddlewareTransformProvider<Sa, M, A extends any[], R> = (app: Sa) => (middleware: M, ...args: A) => Omit<M, keyof R> & R;
|
|
4
4
|
export declare type MiddlewareInput<S> = S extends MiddlewareProvider<any, infer M, any, any> ? M : never;
|
|
5
5
|
export declare type ServiceMiddlewareProviderResult<M, S> = [M] extends [never] ? never : [M] extends [MiddlewareInput<S>] ? S extends MiddlewareTransformProvider<any, M, any, infer R> ? (Omit<R, keyof M> & M) extends R ? Omit<R, keyof M> & M : R extends M ? R : Omit<M, keyof R> & R : S extends MiddlewareProvider<any, M, any, infer R> ? R : never : never;
|
|
6
6
|
export declare type ServiceMiddlewareProviderArgs<S> = S extends MiddlewareProvider<any, any, infer A, any> ? A : never;
|
|
7
7
|
export declare type ServiceMiddlewareProviderChainResult<C, M> = C extends [infer S1, ...infer S] ? S extends never[] ? ServiceMiddlewareProviderResult<M, S1> : ServiceMiddlewareProviderChainResult<S, ServiceMiddlewareProviderResult<M, S1>> : C extends unknown ? M : never;
|
|
8
|
-
export declare type ServiceMiddlewareProviderChainArgs<C> = C extends [infer S1, ...infer S] ? S extends never[] ? ServiceMiddlewareProviderArgs<S1> :
|
|
8
|
+
export declare type ServiceMiddlewareProviderChainArgs<C> = C extends [infer S1, ...infer S] ? S extends never[] ? ServiceMiddlewareProviderArgs<S1> : TupleZip<ServiceMiddlewareProviderChainArgs<S>, ServiceMiddlewareProviderArgs<S1>> : C extends unknown ? [] : never;
|
|
9
9
|
/**
|
|
10
10
|
* Creates a middleware composer for given AppServices and input value types. The composer accepts a list of middleware
|
|
11
11
|
* that it assembles into a chain. The function returned by the composer takes a value of the given input value type,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
declare type HashValue = string | number | boolean | null | HashCompoundValue;
|
|
2
|
-
declare type HashCompoundValue = Array<HashValue> | {
|
|
1
|
+
export declare type HashValue = string | number | boolean | null | HashCompoundValue;
|
|
2
|
+
export declare type HashCompoundValue = Array<HashValue> | {
|
|
3
3
|
[key: string]: HashValue;
|
|
4
4
|
};
|
|
5
5
|
/**
|
|
@@ -8,4 +8,3 @@ declare type HashCompoundValue = Array<HashValue> | {
|
|
|
8
8
|
* @example hashValue({someKey: 'someValue'})
|
|
9
9
|
*/
|
|
10
10
|
export declare const hashValue: (value: HashValue) => string;
|
|
11
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { QueryParams, RouteMatchRecord } from '
|
|
1
|
+
import { QueryParams, RouteMatchRecord } from '../routing';
|
|
2
2
|
export declare type PaginationHandler<Pa, Q extends QueryParams> = <R>(queryParams: Q, match: RouteMatchRecord<R>) => Pa & {
|
|
3
3
|
getUnusedQueryParams: () => Q;
|
|
4
4
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pageNumberPagination = exports.loadMorePagination = exports.createPaginationMiddleware = void 0;
|
|
4
|
-
const assertions_1 = require("
|
|
5
|
-
const errors_1 = require("
|
|
6
|
-
const routing_1 = require("
|
|
4
|
+
const assertions_1 = require("../assertions");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const routing_1 = require("../routing");
|
|
7
7
|
/**
|
|
8
8
|
* helper to create middleware with the given paginator. aside from taking care of annoying to write pagination logic, these helpers also make
|
|
9
9
|
* sure that all item list responses have the same formatting.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Track } from '../profile';
|
|
2
1
|
import { Logger } from '../services/logger';
|
|
3
2
|
/** HTTP query parameters */
|
|
4
3
|
export declare type QueryParams = Record<string, string | undefined | string[] | null>;
|
|
@@ -35,7 +34,6 @@ export declare type PayloadForRoute<R> = RequestServicesForRoute<R> extends {
|
|
|
35
34
|
} ? RequestServicesForRoute<R>['payload'] : undefined;
|
|
36
35
|
declare type RequestServiceProvider<Sa, Sr, Ri> = (app: Sa) => <R>(middleware: {
|
|
37
36
|
request: Ri;
|
|
38
|
-
profile: Track;
|
|
39
37
|
logger: Logger;
|
|
40
38
|
}, match: RouteMatchRecord<R>) => Sr;
|
|
41
39
|
declare type RouteHandler<P, Sr, Ro> = (params: P, request: Sr) => Ro;
|
|
@@ -168,7 +166,6 @@ declare type RequestResponder<Sa, Ri, Ro> = {
|
|
|
168
166
|
(services: CompatibleServices<Sa>): (request: Ri) => Ro | undefined;
|
|
169
167
|
<RoF>(services: CompatibleServices<Sa>, responseMiddleware: (app: Sa) => (response: Ro | undefined, request: {
|
|
170
168
|
request: Ri;
|
|
171
|
-
profile: Track;
|
|
172
169
|
logger: Logger;
|
|
173
170
|
}) => RoF): (request: Ri) => RoF;
|
|
174
171
|
};
|
|
@@ -33,7 +33,6 @@ exports.METHOD = exports.apiHtmlResponse = exports.apiTextResponse = exports.api
|
|
|
33
33
|
const pathToRegexp = __importStar(require("path-to-regexp"));
|
|
34
34
|
const query_string_1 = __importDefault(require("query-string"));
|
|
35
35
|
const helpers_1 = require("../misc/helpers");
|
|
36
|
-
const profile_1 = require("../profile");
|
|
37
36
|
const console_1 = require("../services/logger/console");
|
|
38
37
|
/**
|
|
39
38
|
* Makes a createRoute function that can be used to create routes (this is a factory factory). The
|
|
@@ -136,11 +135,11 @@ exports.renderAnyRouteUrl = (0, exports.makeRenderRouteUrl)();
|
|
|
136
135
|
const bindRoute = (services, appBinder, pathExtractor, matcher) => (route) => {
|
|
137
136
|
const getParamsFromPath = pathToRegexp.match(route.path, { decode: decodeURIComponent });
|
|
138
137
|
const boundServiceProvider = route.requestServiceProvider && appBinder(services, route.requestServiceProvider);
|
|
139
|
-
return (request,
|
|
138
|
+
return (request, logger) => {
|
|
140
139
|
const path = pathExtractor(request);
|
|
141
140
|
const match = getParamsFromPath(path);
|
|
142
141
|
if ((!matcher || matcher(request, route)) && match) {
|
|
143
|
-
return
|
|
142
|
+
return () => route.handler(match.params, boundServiceProvider ? boundServiceProvider({ request, logger }, { route, params: match.params }) : undefined);
|
|
144
143
|
}
|
|
145
144
|
};
|
|
146
145
|
};
|
|
@@ -189,19 +188,18 @@ const makeGetRequestResponder = () => ({ routes, pathExtractor, routeMatcher, er
|
|
|
189
188
|
// types are getting complicated quickly here.
|
|
190
189
|
const isPromise = (thing) => thing instanceof Promise;
|
|
191
190
|
return (request) => {
|
|
192
|
-
const { end, ...profile } = (0, profile_1.createProfile)(new Date().toISOString()).start();
|
|
193
191
|
const logger = appLogger.createSubContext();
|
|
194
192
|
if (logExtractor) {
|
|
195
193
|
logger.setContext(logExtractor(request));
|
|
196
194
|
}
|
|
197
195
|
try {
|
|
198
|
-
const executor = (0, helpers_1.mapFind)(boundRoutes, (route) => route(request,
|
|
196
|
+
const executor = (0, helpers_1.mapFind)(boundRoutes, (route) => route(request, logger));
|
|
199
197
|
if (executor) {
|
|
200
198
|
const result = boundResponseMiddleware ?
|
|
201
|
-
boundResponseMiddleware(executor(), { request,
|
|
199
|
+
boundResponseMiddleware(executor(), { request, logger }) : executor();
|
|
202
200
|
if (isPromise(result) && errorHandler) {
|
|
203
201
|
const errorHandlerWithMiddleware = (e) => boundResponseMiddleware ?
|
|
204
|
-
boundResponseMiddleware(errorHandler(e, logger), { request,
|
|
202
|
+
boundResponseMiddleware(errorHandler(e, logger), { request, logger }) : errorHandler(e, logger);
|
|
205
203
|
return result.catch(errorHandlerWithMiddleware);
|
|
206
204
|
}
|
|
207
205
|
else {
|
|
@@ -209,13 +207,13 @@ const makeGetRequestResponder = () => ({ routes, pathExtractor, routeMatcher, er
|
|
|
209
207
|
}
|
|
210
208
|
}
|
|
211
209
|
else if (boundResponseMiddleware) {
|
|
212
|
-
return boundResponseMiddleware(undefined, { request,
|
|
210
|
+
return boundResponseMiddleware(undefined, { request, logger });
|
|
213
211
|
}
|
|
214
212
|
}
|
|
215
213
|
catch (e) {
|
|
216
214
|
if (errorHandler && e instanceof Error) {
|
|
217
215
|
return boundResponseMiddleware
|
|
218
|
-
? boundResponseMiddleware(errorHandler(e, logger), { request,
|
|
216
|
+
? boundResponseMiddleware(errorHandler(e, logger), { request, logger })
|
|
219
217
|
: errorHandler(e, logger);
|
|
220
218
|
}
|
|
221
219
|
throw e;
|
|
@@ -11,22 +11,22 @@ const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
|
11
11
|
const cookieName = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.cookieName));
|
|
12
12
|
const encryptionPrivateKey = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.encryptionPrivateKey));
|
|
13
13
|
const signaturePublicKey = (0, helpers_1.once)(() => (0, resolveConfigValue_1.resolveConfigValue)(config.signaturePublicKey));
|
|
14
|
-
return ({ request
|
|
14
|
+
return ({ request }) => {
|
|
15
15
|
let user;
|
|
16
|
-
const getAuthorizedFetchConfig =
|
|
16
|
+
const getAuthorizedFetchConfig = async () => {
|
|
17
17
|
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
18
18
|
if (!token) {
|
|
19
19
|
return {};
|
|
20
20
|
}
|
|
21
21
|
return { headers };
|
|
22
|
-
}
|
|
23
|
-
const loadUser =
|
|
22
|
+
};
|
|
23
|
+
const loadUser = async () => {
|
|
24
24
|
const [token] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
25
25
|
if (!token) {
|
|
26
26
|
return undefined;
|
|
27
27
|
}
|
|
28
28
|
return (0, decryptAndVerify_1.decryptAndVerify)(token, await encryptionPrivateKey(), await signaturePublicKey());
|
|
29
|
-
}
|
|
29
|
+
};
|
|
30
30
|
return {
|
|
31
31
|
getAuthorizedFetchConfig,
|
|
32
32
|
getUser: async () => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { FetchConfig } from '../../fetch';
|
|
2
|
-
import type { Track } from '../../profile';
|
|
3
2
|
import type { HttpHeaders } from '../../routing';
|
|
4
3
|
export interface TokenUser {
|
|
5
4
|
id: number;
|
|
@@ -41,7 +40,6 @@ export declare type CookieAuthProviderRequest = {
|
|
|
41
40
|
};
|
|
42
41
|
export declare type CookieAuthProvider = (inputs: {
|
|
43
42
|
request: CookieAuthProviderRequest;
|
|
44
|
-
profile: Track;
|
|
45
43
|
}) => AuthProvider;
|
|
46
44
|
export declare type StubAuthProvider = (user: User | undefined) => AuthProvider;
|
|
47
45
|
export declare const stubAuthProvider: (user?: User | undefined) => AuthProvider;
|
|
@@ -9,23 +9,23 @@ const subrequestAuthProvider = (initializer) => (configProvider) => {
|
|
|
9
9
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'subrequest')];
|
|
10
10
|
const cookieName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.cookieName));
|
|
11
11
|
const accountsBase = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.accountsBase));
|
|
12
|
-
return ({ request
|
|
12
|
+
return ({ request }) => {
|
|
13
13
|
let user;
|
|
14
|
-
const getAuthorizedFetchConfig =
|
|
14
|
+
const getAuthorizedFetchConfig = async () => {
|
|
15
15
|
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
16
16
|
if (!token) {
|
|
17
17
|
return {};
|
|
18
18
|
}
|
|
19
19
|
return { headers };
|
|
20
|
-
}
|
|
21
|
-
const loadUser =
|
|
20
|
+
};
|
|
21
|
+
const loadUser = async () => {
|
|
22
22
|
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
23
23
|
if (!token) {
|
|
24
24
|
return undefined;
|
|
25
25
|
}
|
|
26
|
-
return
|
|
26
|
+
return initializer.fetch((await accountsBase()).replace(/\/+$/, '') + '/api/user', { headers })
|
|
27
27
|
.then(response => response.json());
|
|
28
|
-
}
|
|
28
|
+
};
|
|
29
29
|
return {
|
|
30
30
|
getAuthorizedFetchConfig,
|
|
31
31
|
getUser: async () => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AttributeValue } from '@aws-sdk/client-dynamodb';
|
|
2
|
+
import { DocumentBaseType, DocumentBaseValueTypes } from '.';
|
|
3
|
+
export declare const encodeDynamoAttribute: (value: DocumentBaseValueTypes) => AttributeValue;
|
|
4
|
+
export declare const encodeDynamoDocument: (base: DocumentBaseType) => {
|
|
5
|
+
[k: string]: AttributeValue;
|
|
6
|
+
};
|
|
7
|
+
export declare const decodeDynamoAttribute: (value: AttributeValue) => DocumentBaseValueTypes;
|
|
8
|
+
export declare const decodeDynamoDocument: <T extends DocumentBaseType>(document: {
|
|
9
|
+
[key: string]: AttributeValue;
|
|
10
|
+
}) => T;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeDynamoDocument = exports.decodeDynamoAttribute = exports.encodeDynamoDocument = exports.encodeDynamoAttribute = void 0;
|
|
4
|
+
const guards_1 = require("../../guards");
|
|
5
|
+
const encodeDynamoAttribute = (value) => {
|
|
6
|
+
if (typeof value === 'string') {
|
|
7
|
+
return { S: value };
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === 'number') {
|
|
10
|
+
return { N: value.toString() };
|
|
11
|
+
}
|
|
12
|
+
if (typeof value === 'boolean') {
|
|
13
|
+
return { BOOL: value };
|
|
14
|
+
}
|
|
15
|
+
if (value === null) {
|
|
16
|
+
return { NULL: true };
|
|
17
|
+
}
|
|
18
|
+
if (value instanceof Array) {
|
|
19
|
+
return { L: value.map(exports.encodeDynamoAttribute) };
|
|
20
|
+
}
|
|
21
|
+
if ((0, guards_1.isPlainObject)(value)) {
|
|
22
|
+
return { M: (0, exports.encodeDynamoDocument)(value) };
|
|
23
|
+
}
|
|
24
|
+
throw new Error(`unknown attribute type ${typeof value} with value ${value}.`);
|
|
25
|
+
};
|
|
26
|
+
exports.encodeDynamoAttribute = encodeDynamoAttribute;
|
|
27
|
+
const encodeDynamoDocument = (base) => Object.fromEntries(Object.entries(base).map(([key, value]) => ([key, (0, exports.encodeDynamoAttribute)(value)])));
|
|
28
|
+
exports.encodeDynamoDocument = encodeDynamoDocument;
|
|
29
|
+
const decodeDynamoAttribute = (value) => {
|
|
30
|
+
if (value.S !== undefined) {
|
|
31
|
+
return value.S;
|
|
32
|
+
}
|
|
33
|
+
if (value.N !== undefined) {
|
|
34
|
+
return parseFloat(value.N);
|
|
35
|
+
}
|
|
36
|
+
if (value.BOOL !== undefined) {
|
|
37
|
+
return value.BOOL;
|
|
38
|
+
}
|
|
39
|
+
if (value.NULL !== undefined) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (value.L !== undefined) {
|
|
43
|
+
return value.L.map(exports.decodeDynamoAttribute);
|
|
44
|
+
}
|
|
45
|
+
if (value.M !== undefined) {
|
|
46
|
+
return (0, exports.decodeDynamoDocument)(value.M);
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`unknown attribute type: ${JSON.stringify(value)}.`);
|
|
49
|
+
};
|
|
50
|
+
exports.decodeDynamoAttribute = decodeDynamoAttribute;
|
|
51
|
+
const decodeDynamoDocument = (document) => Object.fromEntries(Object.entries(document).map(([key, value]) => ([key, (0, exports.decodeDynamoAttribute)(value)])));
|
|
52
|
+
exports.decodeDynamoDocument = decodeDynamoDocument;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare type Config = {
|
|
2
|
+
tableName: string;
|
|
3
|
+
};
|
|
4
|
+
export declare type DocumentBaseMapType = {
|
|
5
|
+
[key: string]: DocumentBaseValueTypes;
|
|
6
|
+
};
|
|
7
|
+
export declare type DocumentBaseListType = DocumentBaseValueTypes[];
|
|
8
|
+
export declare type DocumentBaseValueTypes = number | boolean | string | null | DocumentBaseMapType | DocumentBaseListType;
|
|
9
|
+
export declare type DocumentBaseType = {
|
|
10
|
+
[key: string]: DocumentBaseValueTypes;
|
|
11
|
+
};
|
|
12
|
+
export declare type TDocument<T> = {
|
|
13
|
+
[k in keyof T]: DocumentBaseValueTypes;
|
|
14
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Config, TDocument } from '..';
|
|
2
|
+
import { ConfigProviderForConfig } from '../../../config';
|
|
3
|
+
interface Initializer<C> {
|
|
4
|
+
configSpace?: C;
|
|
5
|
+
}
|
|
6
|
+
export declare const dynamoUnversionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends TDocument<T>>() => (configProvider: { [key in C]: {
|
|
7
|
+
tableName: import("../../../config").ConfigValueProvider<string>;
|
|
8
|
+
}; }) => <K extends keyof T>(_: {}, hashKey: K) => {
|
|
9
|
+
loadAllDocumentsTheBadWay: () => Promise<T[]>;
|
|
10
|
+
getItem: (id: T[K]) => Promise<T | undefined>;
|
|
11
|
+
putItem: (item: T) => Promise<T>;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dynamoUnversionedDocumentStore = void 0;
|
|
4
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
5
|
+
const __1 = require("../../..");
|
|
6
|
+
const config_1 = require("../../../config");
|
|
7
|
+
const guards_1 = require("../../../guards");
|
|
8
|
+
const dynamoEncoding_1 = require("../dynamoEncoding");
|
|
9
|
+
const dynamodb = (0, __1.once)(() => new client_dynamodb_1.DynamoDB({ apiVersion: '2012-08-10' }));
|
|
10
|
+
const dynamoUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey) => {
|
|
11
|
+
const options = (0, guards_1.ifDefined)(initializer, {});
|
|
12
|
+
const tableName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(configProvider[(0, guards_1.ifDefined)(options.configSpace, 'dynamodb')].tableName));
|
|
13
|
+
return {
|
|
14
|
+
loadAllDocumentsTheBadWay: async () => {
|
|
15
|
+
const loadAllResults = async (ExclusiveStartKey) => {
|
|
16
|
+
var _a;
|
|
17
|
+
const cmd = new client_dynamodb_1.ScanCommand({ TableName: await tableName(), ExclusiveStartKey });
|
|
18
|
+
const result = await dynamodb().send(cmd);
|
|
19
|
+
const resultItems = ((_a = result.Items) === null || _a === void 0 ? void 0 : _a.map(dynamoEncoding_1.decodeDynamoDocument)) || [];
|
|
20
|
+
if (result.LastEvaluatedKey) {
|
|
21
|
+
return [...resultItems, ...await loadAllResults(result.LastEvaluatedKey)];
|
|
22
|
+
}
|
|
23
|
+
return resultItems;
|
|
24
|
+
};
|
|
25
|
+
return loadAllResults();
|
|
26
|
+
},
|
|
27
|
+
getItem: async (id) => {
|
|
28
|
+
const cmd = new client_dynamodb_1.QueryCommand({
|
|
29
|
+
TableName: await tableName(),
|
|
30
|
+
KeyConditionExpression: '#hk = :hkv',
|
|
31
|
+
ExpressionAttributeNames: { '#hk': hashKey.toString() },
|
|
32
|
+
ExpressionAttributeValues: { ':hkv': (0, dynamoEncoding_1.encodeDynamoAttribute)(id) },
|
|
33
|
+
ScanIndexForward: false,
|
|
34
|
+
Limit: 1
|
|
35
|
+
});
|
|
36
|
+
return dynamodb().send(cmd).then(result => {
|
|
37
|
+
var _a;
|
|
38
|
+
return (_a = result.Items) === null || _a === void 0 ? void 0 : _a.map(dynamoEncoding_1.decodeDynamoDocument)[0];
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
/* saves a new version of a document with the given data */
|
|
42
|
+
putItem: async (item) => {
|
|
43
|
+
const cmd = new client_dynamodb_1.PutItemCommand({
|
|
44
|
+
TableName: await tableName(),
|
|
45
|
+
Item: (0, dynamoEncoding_1.encodeDynamoDocument)(item),
|
|
46
|
+
});
|
|
47
|
+
return dynamodb().send(cmd).then(() => item);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
exports.dynamoUnversionedDocumentStore = dynamoUnversionedDocumentStore;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Config, TDocument } from '..';
|
|
2
|
+
import { ConfigProviderForConfig } from '../../../config';
|
|
3
|
+
interface Initializer<C> {
|
|
4
|
+
dataDir: string;
|
|
5
|
+
fs?: Pick<typeof import('fs'), 'mkdir' | 'readdir' | 'readFile' | 'writeFile'>;
|
|
6
|
+
configSpace?: C;
|
|
7
|
+
}
|
|
8
|
+
export declare const fileSystemUnversionedDocumentStore: <C extends string = "fileSystem">(initializer: Initializer<C>) => <T extends TDocument<T>>() => (configProvider: { [key in C]: {
|
|
9
|
+
tableName: import("../../../config").ConfigValueProvider<string>;
|
|
10
|
+
}; }) => <K extends keyof T>(_: {}, hashKey: K) => {
|
|
11
|
+
loadAllDocumentsTheBadWay: () => Promise<T[]>;
|
|
12
|
+
getItem: (id: T[K]) => Promise<T | undefined>;
|
|
13
|
+
putItem: (item: T) => Promise<T>;
|
|
14
|
+
};
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.fileSystemUnversionedDocumentStore = void 0;
|
|
30
|
+
const fsModule = __importStar(require("fs"));
|
|
31
|
+
const path_1 = __importDefault(require("path"));
|
|
32
|
+
const __1 = require("../../..");
|
|
33
|
+
const config_1 = require("../../../config");
|
|
34
|
+
const guards_1 = require("../../../guards");
|
|
35
|
+
const fileSystemUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey) => {
|
|
36
|
+
const tableName = (0, config_1.resolveConfigValue)(configProvider[initializer.configSpace || 'fileSystem'].tableName);
|
|
37
|
+
const tablePath = tableName.then((table) => path_1.default.join(initializer.dataDir, table));
|
|
38
|
+
const { mkdir, readdir, readFile, writeFile } = (0, guards_1.ifDefined)(initializer.fs, fsModule);
|
|
39
|
+
const mkTableDir = new Promise((resolve, reject) => tablePath.then((path) => mkdir(path, { recursive: true }, (err) => err ? reject(err) : resolve())));
|
|
40
|
+
const hashFilename = (value) => `${(0, __1.hashValue)(value)}.json`;
|
|
41
|
+
const filePath = async (filename) => path_1.default.join(await tablePath, filename);
|
|
42
|
+
const load = async (filename) => {
|
|
43
|
+
const path = await filePath(filename);
|
|
44
|
+
await mkTableDir;
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
readFile(path, (err, readData) => {
|
|
47
|
+
if (err) {
|
|
48
|
+
err.code === 'ENOENT' ? resolve(undefined) : reject(err);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
try {
|
|
52
|
+
const data = JSON.parse(readData.toString());
|
|
53
|
+
typeof data === 'object' ? resolve(data) : reject(new Error('unexpected non-object JSON'));
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
reject(err);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
loadAllDocumentsTheBadWay: async () => {
|
|
64
|
+
const path = await tablePath;
|
|
65
|
+
await mkTableDir;
|
|
66
|
+
return new Promise((resolve, reject) => readdir(path, (err, files) => err ?
|
|
67
|
+
reject(err) :
|
|
68
|
+
Promise.all(files.map((file) => load(file)))
|
|
69
|
+
.then((allData) => resolve(allData.filter(guards_1.isDefined)), (err) => reject(err))));
|
|
70
|
+
},
|
|
71
|
+
getItem: (id) => load(hashFilename(id)),
|
|
72
|
+
putItem: async (item) => {
|
|
73
|
+
const path = await filePath(hashFilename(item[hashKey]));
|
|
74
|
+
await mkTableDir;
|
|
75
|
+
return new Promise((resolve, reject) => {
|
|
76
|
+
writeFile(path, JSON.stringify(item, null, 2), (err) => err ? reject(err) : resolve(item));
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
exports.fileSystemUnversionedDocumentStore = fileSystemUnversionedDocumentStore;
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
declare type DynamoConfig = {
|
|
5
|
-
tableName: string;
|
|
6
|
-
};
|
|
1
|
+
import { Config } from '..';
|
|
2
|
+
import { ConfigProviderForConfig } from '../../../config';
|
|
3
|
+
import { VersionedDocumentAuthor, VersionedTDocument } from '.';
|
|
7
4
|
interface Initializer<C> {
|
|
8
5
|
configSpace?: C;
|
|
9
6
|
}
|
|
10
|
-
export declare const dynamoVersionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends
|
|
11
|
-
tableName: import("
|
|
12
|
-
}; }) => <K extends keyof T, A extends ((...a: any[]) => Promise<VersionedDocumentAuthor>) | undefined>({
|
|
13
|
-
profile: Track;
|
|
14
|
-
}, hashKey: K, getAuthor: A) => {
|
|
7
|
+
export declare const dynamoVersionedDocumentStore: <C extends string = "dynamodb">(initializer?: Initializer<C> | undefined) => <T extends VersionedTDocument<T>>() => (configProvider: { [key in C]: {
|
|
8
|
+
tableName: import("../../../config").ConfigValueProvider<string>;
|
|
9
|
+
}; }) => <K extends keyof T, A extends ((...a: any[]) => Promise<VersionedDocumentAuthor>) | undefined>(_: {}, hashKey: K, getAuthor: A) => {
|
|
15
10
|
loadAllDocumentsTheBadWay: () => Promise<T[]>;
|
|
16
11
|
getVersions: (id: T[K], startVersion?: number | undefined) => Promise<{
|
|
17
12
|
items: T[];
|