@react-router/architect 7.0.0-pre.2 → 7.0.0-pre.4
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/CHANGELOG.md +16 -0
- package/dist/index.d.mts +58 -0
- package/dist/index.d.ts +58 -3
- package/dist/index.js +241 -7
- package/dist/index.mjs +218 -0
- package/package.json +36 -9
- package/dist/__tests__/binaryTypes-test.d.ts +0 -1
- package/dist/__tests__/server-test.d.ts +0 -1
- package/dist/binaryTypes.d.ts +0 -1
- package/dist/binaryTypes.js +0 -38
- package/dist/server.d.ts +0 -23
- package/dist/server.js +0 -107
- package/dist/sessions/arcTableSessionStorage.d.ts +0 -36
- package/dist/sessions/arcTableSessionStorage.js +0 -102
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @react-router/architect
|
|
2
2
|
|
|
3
|
+
## 7.0.0-pre.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- `react-router@7.0.0-pre.4`
|
|
9
|
+
- `@react-router/node@7.0.0-pre.4`
|
|
10
|
+
|
|
11
|
+
## 7.0.0-pre.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies:
|
|
16
|
+
- `react-router@7.0.0-pre.3`
|
|
17
|
+
- `@react-router/node@7.0.0-pre.3`
|
|
18
|
+
|
|
3
19
|
## 7.0.0-pre.2
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SessionData, SessionStorage, SessionIdStorageStrategy, AppLoadContext, ServerBuild } from 'react-router';
|
|
2
|
+
import { ArcTable } from '@architect/functions/types/tables';
|
|
3
|
+
import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from 'aws-lambda';
|
|
4
|
+
|
|
5
|
+
interface ArcTableSessionStorageOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The Cookie used to store the session id on the client, or options used
|
|
8
|
+
* to automatically create one.
|
|
9
|
+
*/
|
|
10
|
+
cookie?: SessionIdStorageStrategy["cookie"];
|
|
11
|
+
/**
|
|
12
|
+
* The table used to store sessions, or its name as it appears in your
|
|
13
|
+
* project's app.arc file.
|
|
14
|
+
*/
|
|
15
|
+
table: ArcTable<SessionData> | string;
|
|
16
|
+
/**
|
|
17
|
+
* The name of the DynamoDB attribute used to store the session ID.
|
|
18
|
+
* This should be the table's partition key.
|
|
19
|
+
*/
|
|
20
|
+
idx: string;
|
|
21
|
+
/**
|
|
22
|
+
* The name of the DynamoDB attribute used to store the expiration time.
|
|
23
|
+
* If absent, then no TTL will be stored and session records will not expire.
|
|
24
|
+
*/
|
|
25
|
+
ttl?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Session storage using a DynamoDB table managed by Architect.
|
|
29
|
+
*
|
|
30
|
+
* Add the following lines to your project's `app.arc` file:
|
|
31
|
+
*
|
|
32
|
+
* @tables
|
|
33
|
+
* arc-sessions
|
|
34
|
+
* _idx *String
|
|
35
|
+
* _ttl TTL
|
|
36
|
+
*/
|
|
37
|
+
declare function createArcTableSessionStorage<Data = SessionData, FlashData = Data>({ cookie, ...props }: ArcTableSessionStorageOptions): SessionStorage<Data, FlashData>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A function that returns the value to use as `context` in route `loader` and
|
|
41
|
+
* `action` functions.
|
|
42
|
+
*
|
|
43
|
+
* You can think of this as an escape hatch that allows you to pass
|
|
44
|
+
* environment/platform-specific values through to your loader/action.
|
|
45
|
+
*/
|
|
46
|
+
type GetLoadContextFunction = (event: APIGatewayProxyEventV2) => Promise<AppLoadContext> | AppLoadContext;
|
|
47
|
+
type RequestHandler = APIGatewayProxyHandlerV2;
|
|
48
|
+
/**
|
|
49
|
+
* Returns a request handler for Architect that serves the response using
|
|
50
|
+
* React Router.
|
|
51
|
+
*/
|
|
52
|
+
declare function createRequestHandler({ build, getLoadContext, mode, }: {
|
|
53
|
+
build: ServerBuild;
|
|
54
|
+
getLoadContext?: GetLoadContextFunction;
|
|
55
|
+
mode?: string;
|
|
56
|
+
}): RequestHandler;
|
|
57
|
+
|
|
58
|
+
export { type GetLoadContextFunction, type RequestHandler, createArcTableSessionStorage, createRequestHandler };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { SessionData, SessionStorage, SessionIdStorageStrategy, AppLoadContext, ServerBuild } from 'react-router';
|
|
2
|
+
import { ArcTable } from '@architect/functions/types/tables';
|
|
3
|
+
import { APIGatewayProxyEventV2, APIGatewayProxyHandlerV2 } from 'aws-lambda';
|
|
4
|
+
|
|
5
|
+
interface ArcTableSessionStorageOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The Cookie used to store the session id on the client, or options used
|
|
8
|
+
* to automatically create one.
|
|
9
|
+
*/
|
|
10
|
+
cookie?: SessionIdStorageStrategy["cookie"];
|
|
11
|
+
/**
|
|
12
|
+
* The table used to store sessions, or its name as it appears in your
|
|
13
|
+
* project's app.arc file.
|
|
14
|
+
*/
|
|
15
|
+
table: ArcTable<SessionData> | string;
|
|
16
|
+
/**
|
|
17
|
+
* The name of the DynamoDB attribute used to store the session ID.
|
|
18
|
+
* This should be the table's partition key.
|
|
19
|
+
*/
|
|
20
|
+
idx: string;
|
|
21
|
+
/**
|
|
22
|
+
* The name of the DynamoDB attribute used to store the expiration time.
|
|
23
|
+
* If absent, then no TTL will be stored and session records will not expire.
|
|
24
|
+
*/
|
|
25
|
+
ttl?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Session storage using a DynamoDB table managed by Architect.
|
|
29
|
+
*
|
|
30
|
+
* Add the following lines to your project's `app.arc` file:
|
|
31
|
+
*
|
|
32
|
+
* @tables
|
|
33
|
+
* arc-sessions
|
|
34
|
+
* _idx *String
|
|
35
|
+
* _ttl TTL
|
|
36
|
+
*/
|
|
37
|
+
declare function createArcTableSessionStorage<Data = SessionData, FlashData = Data>({ cookie, ...props }: ArcTableSessionStorageOptions): SessionStorage<Data, FlashData>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A function that returns the value to use as `context` in route `loader` and
|
|
41
|
+
* `action` functions.
|
|
42
|
+
*
|
|
43
|
+
* You can think of this as an escape hatch that allows you to pass
|
|
44
|
+
* environment/platform-specific values through to your loader/action.
|
|
45
|
+
*/
|
|
46
|
+
type GetLoadContextFunction = (event: APIGatewayProxyEventV2) => Promise<AppLoadContext> | AppLoadContext;
|
|
47
|
+
type RequestHandler = APIGatewayProxyHandlerV2;
|
|
48
|
+
/**
|
|
49
|
+
* Returns a request handler for Architect that serves the response using
|
|
50
|
+
* React Router.
|
|
51
|
+
*/
|
|
52
|
+
declare function createRequestHandler({ build, getLoadContext, mode, }: {
|
|
53
|
+
build: ServerBuild;
|
|
54
|
+
getLoadContext?: GetLoadContextFunction;
|
|
55
|
+
mode?: string;
|
|
56
|
+
}): RequestHandler;
|
|
57
|
+
|
|
58
|
+
export { type GetLoadContextFunction, type RequestHandler, createArcTableSessionStorage, createRequestHandler };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/architect v7.0.0-pre.
|
|
2
|
+
* @react-router/architect v7.0.0-pre.4
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -8,14 +8,248 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
"use strict";
|
|
12
|
+
var __create = Object.create;
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
15
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
16
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
17
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
18
|
+
var __export = (target, all) => {
|
|
19
|
+
for (var name in all)
|
|
20
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
21
|
+
};
|
|
22
|
+
var __copyProps = (to, from, except, desc) => {
|
|
23
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
24
|
+
for (let key of __getOwnPropNames(from))
|
|
25
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
26
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
27
|
+
}
|
|
28
|
+
return to;
|
|
29
|
+
};
|
|
30
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
31
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
32
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
33
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
34
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
35
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
36
|
+
mod
|
|
37
|
+
));
|
|
38
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
12
39
|
|
|
13
|
-
|
|
40
|
+
// index.ts
|
|
41
|
+
var react_router_architect_exports = {};
|
|
42
|
+
__export(react_router_architect_exports, {
|
|
43
|
+
createArcTableSessionStorage: () => createArcTableSessionStorage,
|
|
44
|
+
createRequestHandler: () => createRequestHandler
|
|
45
|
+
});
|
|
46
|
+
module.exports = __toCommonJS(react_router_architect_exports);
|
|
14
47
|
|
|
15
|
-
|
|
16
|
-
var
|
|
48
|
+
// sessions/arcTableSessionStorage.ts
|
|
49
|
+
var import_react_router = require("react-router");
|
|
50
|
+
var import_functions = __toESM(require("@architect/functions"));
|
|
51
|
+
function createArcTableSessionStorage({
|
|
52
|
+
cookie,
|
|
53
|
+
...props
|
|
54
|
+
}) {
|
|
55
|
+
async function getTable() {
|
|
56
|
+
if (typeof props.table === "string") {
|
|
57
|
+
let tables = await import_functions.default.tables();
|
|
58
|
+
return tables[props.table];
|
|
59
|
+
} else {
|
|
60
|
+
return props.table;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return (0, import_react_router.createSessionStorage)({
|
|
64
|
+
cookie,
|
|
65
|
+
async createData(data, expires) {
|
|
66
|
+
let table = await getTable();
|
|
67
|
+
while (true) {
|
|
68
|
+
let randomBytes = crypto.getRandomValues(new Uint8Array(8));
|
|
69
|
+
let id = [...randomBytes].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
70
|
+
if (await table.get({ [props.idx]: id })) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
let params = {
|
|
74
|
+
[props.idx]: id,
|
|
75
|
+
...data
|
|
76
|
+
};
|
|
77
|
+
if (props.ttl) {
|
|
78
|
+
params[props.ttl] = expires ? Math.round(expires.getTime() / 1e3) : void 0;
|
|
79
|
+
}
|
|
80
|
+
await table.put(params);
|
|
81
|
+
return id;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
async readData(id) {
|
|
85
|
+
let table = await getTable();
|
|
86
|
+
let data = await table.get({ [props.idx]: id });
|
|
87
|
+
if (data) {
|
|
88
|
+
delete data[props.idx];
|
|
89
|
+
if (props.ttl) delete data[props.ttl];
|
|
90
|
+
}
|
|
91
|
+
return data;
|
|
92
|
+
},
|
|
93
|
+
async updateData(id, data, expires) {
|
|
94
|
+
let table = await getTable();
|
|
95
|
+
let params = {
|
|
96
|
+
[props.idx]: id,
|
|
97
|
+
...data
|
|
98
|
+
};
|
|
99
|
+
if (props.ttl) {
|
|
100
|
+
params[props.ttl] = expires ? Math.round(expires.getTime() / 1e3) : void 0;
|
|
101
|
+
}
|
|
102
|
+
await table.put(params);
|
|
103
|
+
},
|
|
104
|
+
async deleteData(id) {
|
|
105
|
+
let table = await getTable();
|
|
106
|
+
await table.delete({ [props.idx]: id });
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
17
110
|
|
|
111
|
+
// server.ts
|
|
112
|
+
var import_react_router2 = require("react-router");
|
|
113
|
+
var import_node = require("@react-router/node");
|
|
18
114
|
|
|
115
|
+
// binaryTypes.ts
|
|
116
|
+
var binaryTypes = [
|
|
117
|
+
"application/octet-stream",
|
|
118
|
+
// Docs
|
|
119
|
+
"application/epub+zip",
|
|
120
|
+
"application/msword",
|
|
121
|
+
"application/pdf",
|
|
122
|
+
"application/rtf",
|
|
123
|
+
"application/vnd.amazon.ebook",
|
|
124
|
+
"application/vnd.ms-excel",
|
|
125
|
+
"application/vnd.ms-powerpoint",
|
|
126
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
127
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
128
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
129
|
+
// Fonts
|
|
130
|
+
"font/otf",
|
|
131
|
+
"font/woff",
|
|
132
|
+
"font/woff2",
|
|
133
|
+
// Images
|
|
134
|
+
"image/avif",
|
|
135
|
+
"image/bmp",
|
|
136
|
+
"image/gif",
|
|
137
|
+
"image/jpeg",
|
|
138
|
+
"image/png",
|
|
139
|
+
"image/tiff",
|
|
140
|
+
"image/vnd.microsoft.icon",
|
|
141
|
+
"image/webp",
|
|
142
|
+
// Audio
|
|
143
|
+
"audio/3gpp",
|
|
144
|
+
"audio/aac",
|
|
145
|
+
"audio/basic",
|
|
146
|
+
"audio/mpeg",
|
|
147
|
+
"audio/ogg",
|
|
148
|
+
"audio/wav",
|
|
149
|
+
"audio/webm",
|
|
150
|
+
"audio/x-aiff",
|
|
151
|
+
"audio/x-midi",
|
|
152
|
+
"audio/x-wav",
|
|
153
|
+
// Video
|
|
154
|
+
"video/3gpp",
|
|
155
|
+
"video/mp2t",
|
|
156
|
+
"video/mpeg",
|
|
157
|
+
"video/ogg",
|
|
158
|
+
"video/quicktime",
|
|
159
|
+
"video/webm",
|
|
160
|
+
"video/x-msvideo",
|
|
161
|
+
// Archives
|
|
162
|
+
"application/java-archive",
|
|
163
|
+
"application/vnd.apple.installer+xml",
|
|
164
|
+
"application/x-7z-compressed",
|
|
165
|
+
"application/x-apple-diskimage",
|
|
166
|
+
"application/x-bzip",
|
|
167
|
+
"application/x-bzip2",
|
|
168
|
+
"application/x-gzip",
|
|
169
|
+
"application/x-java-archive",
|
|
170
|
+
"application/x-rar-compressed",
|
|
171
|
+
"application/x-tar",
|
|
172
|
+
"application/x-zip",
|
|
173
|
+
"application/zip"
|
|
174
|
+
];
|
|
175
|
+
function isBinaryType(contentType) {
|
|
176
|
+
if (!contentType) return false;
|
|
177
|
+
let [test] = contentType.split(";");
|
|
178
|
+
return binaryTypes.includes(test);
|
|
179
|
+
}
|
|
19
180
|
|
|
20
|
-
|
|
21
|
-
|
|
181
|
+
// server.ts
|
|
182
|
+
function createRequestHandler({
|
|
183
|
+
build,
|
|
184
|
+
getLoadContext,
|
|
185
|
+
mode = process.env.NODE_ENV
|
|
186
|
+
}) {
|
|
187
|
+
let handleRequest = (0, import_react_router2.createRequestHandler)(build, mode);
|
|
188
|
+
return async (event) => {
|
|
189
|
+
let request = createReactRouterRequest(event);
|
|
190
|
+
let loadContext = await getLoadContext?.(event);
|
|
191
|
+
let response = await handleRequest(request, loadContext);
|
|
192
|
+
return sendReactRouterResponse(response);
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function createReactRouterRequest(event) {
|
|
196
|
+
let host = event.headers["x-forwarded-host"] || event.headers.host;
|
|
197
|
+
let search = event.rawQueryString.length ? `?${event.rawQueryString}` : "";
|
|
198
|
+
let scheme = process.env.ARC_SANDBOX ? "http" : "https";
|
|
199
|
+
let url = new URL(`${scheme}://${host}${event.rawPath}${search}`);
|
|
200
|
+
let isFormData = event.headers["content-type"]?.includes(
|
|
201
|
+
"multipart/form-data"
|
|
202
|
+
);
|
|
203
|
+
let controller = new AbortController();
|
|
204
|
+
return new Request(url.href, {
|
|
205
|
+
method: event.requestContext.http.method,
|
|
206
|
+
headers: createReactRouterHeaders(event.headers, event.cookies),
|
|
207
|
+
signal: controller.signal,
|
|
208
|
+
body: event.body && event.isBase64Encoded ? isFormData ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "base64").toString() : event.body
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function createReactRouterHeaders(requestHeaders, requestCookies) {
|
|
212
|
+
let headers = new Headers();
|
|
213
|
+
for (let [header, value] of Object.entries(requestHeaders)) {
|
|
214
|
+
if (value) {
|
|
215
|
+
headers.append(header, value);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (requestCookies) {
|
|
219
|
+
headers.append("Cookie", requestCookies.join("; "));
|
|
220
|
+
}
|
|
221
|
+
return headers;
|
|
222
|
+
}
|
|
223
|
+
async function sendReactRouterResponse(nodeResponse) {
|
|
224
|
+
let cookies = [];
|
|
225
|
+
for (let [key, value] of nodeResponse.headers.entries()) {
|
|
226
|
+
if (key.toLowerCase() === "set-cookie") {
|
|
227
|
+
cookies.push(value);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (cookies.length) {
|
|
231
|
+
nodeResponse.headers.delete("Set-Cookie");
|
|
232
|
+
}
|
|
233
|
+
let contentType = nodeResponse.headers.get("Content-Type");
|
|
234
|
+
let isBase64Encoded = isBinaryType(contentType);
|
|
235
|
+
let body;
|
|
236
|
+
if (nodeResponse.body) {
|
|
237
|
+
if (isBase64Encoded) {
|
|
238
|
+
body = await (0, import_node.readableStreamToString)(nodeResponse.body, "base64");
|
|
239
|
+
} else {
|
|
240
|
+
body = await nodeResponse.text();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
statusCode: nodeResponse.status,
|
|
245
|
+
headers: Object.fromEntries(nodeResponse.headers.entries()),
|
|
246
|
+
cookies,
|
|
247
|
+
body,
|
|
248
|
+
isBase64Encoded
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
252
|
+
0 && (module.exports = {
|
|
253
|
+
createArcTableSessionStorage,
|
|
254
|
+
createRequestHandler
|
|
255
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @react-router/architect v7.0.0-pre.4
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// sessions/arcTableSessionStorage.ts
|
|
13
|
+
import { createSessionStorage } from "react-router";
|
|
14
|
+
import arc from "@architect/functions";
|
|
15
|
+
function createArcTableSessionStorage({
|
|
16
|
+
cookie,
|
|
17
|
+
...props
|
|
18
|
+
}) {
|
|
19
|
+
async function getTable() {
|
|
20
|
+
if (typeof props.table === "string") {
|
|
21
|
+
let tables = await arc.tables();
|
|
22
|
+
return tables[props.table];
|
|
23
|
+
} else {
|
|
24
|
+
return props.table;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return createSessionStorage({
|
|
28
|
+
cookie,
|
|
29
|
+
async createData(data, expires) {
|
|
30
|
+
let table = await getTable();
|
|
31
|
+
while (true) {
|
|
32
|
+
let randomBytes = crypto.getRandomValues(new Uint8Array(8));
|
|
33
|
+
let id = [...randomBytes].map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
34
|
+
if (await table.get({ [props.idx]: id })) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
let params = {
|
|
38
|
+
[props.idx]: id,
|
|
39
|
+
...data
|
|
40
|
+
};
|
|
41
|
+
if (props.ttl) {
|
|
42
|
+
params[props.ttl] = expires ? Math.round(expires.getTime() / 1e3) : void 0;
|
|
43
|
+
}
|
|
44
|
+
await table.put(params);
|
|
45
|
+
return id;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
async readData(id) {
|
|
49
|
+
let table = await getTable();
|
|
50
|
+
let data = await table.get({ [props.idx]: id });
|
|
51
|
+
if (data) {
|
|
52
|
+
delete data[props.idx];
|
|
53
|
+
if (props.ttl) delete data[props.ttl];
|
|
54
|
+
}
|
|
55
|
+
return data;
|
|
56
|
+
},
|
|
57
|
+
async updateData(id, data, expires) {
|
|
58
|
+
let table = await getTable();
|
|
59
|
+
let params = {
|
|
60
|
+
[props.idx]: id,
|
|
61
|
+
...data
|
|
62
|
+
};
|
|
63
|
+
if (props.ttl) {
|
|
64
|
+
params[props.ttl] = expires ? Math.round(expires.getTime() / 1e3) : void 0;
|
|
65
|
+
}
|
|
66
|
+
await table.put(params);
|
|
67
|
+
},
|
|
68
|
+
async deleteData(id) {
|
|
69
|
+
let table = await getTable();
|
|
70
|
+
await table.delete({ [props.idx]: id });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// server.ts
|
|
76
|
+
import { createRequestHandler as createReactRouterRequestHandler } from "react-router";
|
|
77
|
+
import { readableStreamToString } from "@react-router/node";
|
|
78
|
+
|
|
79
|
+
// binaryTypes.ts
|
|
80
|
+
var binaryTypes = [
|
|
81
|
+
"application/octet-stream",
|
|
82
|
+
// Docs
|
|
83
|
+
"application/epub+zip",
|
|
84
|
+
"application/msword",
|
|
85
|
+
"application/pdf",
|
|
86
|
+
"application/rtf",
|
|
87
|
+
"application/vnd.amazon.ebook",
|
|
88
|
+
"application/vnd.ms-excel",
|
|
89
|
+
"application/vnd.ms-powerpoint",
|
|
90
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
91
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
92
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
93
|
+
// Fonts
|
|
94
|
+
"font/otf",
|
|
95
|
+
"font/woff",
|
|
96
|
+
"font/woff2",
|
|
97
|
+
// Images
|
|
98
|
+
"image/avif",
|
|
99
|
+
"image/bmp",
|
|
100
|
+
"image/gif",
|
|
101
|
+
"image/jpeg",
|
|
102
|
+
"image/png",
|
|
103
|
+
"image/tiff",
|
|
104
|
+
"image/vnd.microsoft.icon",
|
|
105
|
+
"image/webp",
|
|
106
|
+
// Audio
|
|
107
|
+
"audio/3gpp",
|
|
108
|
+
"audio/aac",
|
|
109
|
+
"audio/basic",
|
|
110
|
+
"audio/mpeg",
|
|
111
|
+
"audio/ogg",
|
|
112
|
+
"audio/wav",
|
|
113
|
+
"audio/webm",
|
|
114
|
+
"audio/x-aiff",
|
|
115
|
+
"audio/x-midi",
|
|
116
|
+
"audio/x-wav",
|
|
117
|
+
// Video
|
|
118
|
+
"video/3gpp",
|
|
119
|
+
"video/mp2t",
|
|
120
|
+
"video/mpeg",
|
|
121
|
+
"video/ogg",
|
|
122
|
+
"video/quicktime",
|
|
123
|
+
"video/webm",
|
|
124
|
+
"video/x-msvideo",
|
|
125
|
+
// Archives
|
|
126
|
+
"application/java-archive",
|
|
127
|
+
"application/vnd.apple.installer+xml",
|
|
128
|
+
"application/x-7z-compressed",
|
|
129
|
+
"application/x-apple-diskimage",
|
|
130
|
+
"application/x-bzip",
|
|
131
|
+
"application/x-bzip2",
|
|
132
|
+
"application/x-gzip",
|
|
133
|
+
"application/x-java-archive",
|
|
134
|
+
"application/x-rar-compressed",
|
|
135
|
+
"application/x-tar",
|
|
136
|
+
"application/x-zip",
|
|
137
|
+
"application/zip"
|
|
138
|
+
];
|
|
139
|
+
function isBinaryType(contentType) {
|
|
140
|
+
if (!contentType) return false;
|
|
141
|
+
let [test] = contentType.split(";");
|
|
142
|
+
return binaryTypes.includes(test);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// server.ts
|
|
146
|
+
function createRequestHandler({
|
|
147
|
+
build,
|
|
148
|
+
getLoadContext,
|
|
149
|
+
mode = process.env.NODE_ENV
|
|
150
|
+
}) {
|
|
151
|
+
let handleRequest = createReactRouterRequestHandler(build, mode);
|
|
152
|
+
return async (event) => {
|
|
153
|
+
let request = createReactRouterRequest(event);
|
|
154
|
+
let loadContext = await getLoadContext?.(event);
|
|
155
|
+
let response = await handleRequest(request, loadContext);
|
|
156
|
+
return sendReactRouterResponse(response);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function createReactRouterRequest(event) {
|
|
160
|
+
let host = event.headers["x-forwarded-host"] || event.headers.host;
|
|
161
|
+
let search = event.rawQueryString.length ? `?${event.rawQueryString}` : "";
|
|
162
|
+
let scheme = process.env.ARC_SANDBOX ? "http" : "https";
|
|
163
|
+
let url = new URL(`${scheme}://${host}${event.rawPath}${search}`);
|
|
164
|
+
let isFormData = event.headers["content-type"]?.includes(
|
|
165
|
+
"multipart/form-data"
|
|
166
|
+
);
|
|
167
|
+
let controller = new AbortController();
|
|
168
|
+
return new Request(url.href, {
|
|
169
|
+
method: event.requestContext.http.method,
|
|
170
|
+
headers: createReactRouterHeaders(event.headers, event.cookies),
|
|
171
|
+
signal: controller.signal,
|
|
172
|
+
body: event.body && event.isBase64Encoded ? isFormData ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "base64").toString() : event.body
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function createReactRouterHeaders(requestHeaders, requestCookies) {
|
|
176
|
+
let headers = new Headers();
|
|
177
|
+
for (let [header, value] of Object.entries(requestHeaders)) {
|
|
178
|
+
if (value) {
|
|
179
|
+
headers.append(header, value);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (requestCookies) {
|
|
183
|
+
headers.append("Cookie", requestCookies.join("; "));
|
|
184
|
+
}
|
|
185
|
+
return headers;
|
|
186
|
+
}
|
|
187
|
+
async function sendReactRouterResponse(nodeResponse) {
|
|
188
|
+
let cookies = [];
|
|
189
|
+
for (let [key, value] of nodeResponse.headers.entries()) {
|
|
190
|
+
if (key.toLowerCase() === "set-cookie") {
|
|
191
|
+
cookies.push(value);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (cookies.length) {
|
|
195
|
+
nodeResponse.headers.delete("Set-Cookie");
|
|
196
|
+
}
|
|
197
|
+
let contentType = nodeResponse.headers.get("Content-Type");
|
|
198
|
+
let isBase64Encoded = isBinaryType(contentType);
|
|
199
|
+
let body;
|
|
200
|
+
if (nodeResponse.body) {
|
|
201
|
+
if (isBase64Encoded) {
|
|
202
|
+
body = await readableStreamToString(nodeResponse.body, "base64");
|
|
203
|
+
} else {
|
|
204
|
+
body = await nodeResponse.text();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
statusCode: nodeResponse.status,
|
|
209
|
+
headers: Object.fromEntries(nodeResponse.headers.entries()),
|
|
210
|
+
cookies,
|
|
211
|
+
body,
|
|
212
|
+
isBase64Encoded
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export {
|
|
216
|
+
createArcTableSessionStorage,
|
|
217
|
+
createRequestHandler
|
|
218
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/architect",
|
|
3
|
-
"version": "7.0.0-pre.
|
|
3
|
+
"version": "7.0.0-pre.4",
|
|
4
4
|
"description": "Architect server request handler for React Router",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/remix-run/react-router/issues"
|
|
@@ -15,11 +15,36 @@
|
|
|
15
15
|
"typings": "dist/index.d.ts",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
18
|
-
"
|
|
19
|
-
|
|
18
|
+
"node": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"module-sync": "./dist/index.mjs",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"import": {
|
|
24
|
+
"types": "./dist/index.d.mts",
|
|
25
|
+
"default": "./dist/index.mjs"
|
|
26
|
+
},
|
|
27
|
+
"default": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
}
|
|
20
31
|
},
|
|
21
32
|
"./package.json": "./package.json"
|
|
22
33
|
},
|
|
34
|
+
"wireit": {
|
|
35
|
+
"build": {
|
|
36
|
+
"command": "tsup",
|
|
37
|
+
"files": [
|
|
38
|
+
"sessions/**",
|
|
39
|
+
"*.ts",
|
|
40
|
+
"tsconfig.json",
|
|
41
|
+
"package.json"
|
|
42
|
+
],
|
|
43
|
+
"output": [
|
|
44
|
+
"dist/**"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
},
|
|
23
48
|
"dependencies": {
|
|
24
49
|
"@architect/functions": "^5.2.0",
|
|
25
50
|
"@types/aws-lambda": "^8.10.82"
|
|
@@ -30,14 +55,16 @@
|
|
|
30
55
|
"lambda-tester": "^4.0.1",
|
|
31
56
|
"react": "^18.2.0",
|
|
32
57
|
"react-dom": "^18.2.0",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
58
|
+
"tsup": "^8.3.0",
|
|
59
|
+
"typescript": "^5.1.6",
|
|
60
|
+
"wireit": "0.14.9",
|
|
61
|
+
"@react-router/node": "7.0.0-pre.4",
|
|
62
|
+
"react-router": "7.0.0-pre.4"
|
|
36
63
|
},
|
|
37
64
|
"peerDependencies": {
|
|
38
65
|
"typescript": "^5.1.0",
|
|
39
|
-
"@react-router/node": "^7.0.0-pre.
|
|
40
|
-
"react-router": "^7.0.0-pre.
|
|
66
|
+
"@react-router/node": "^7.0.0-pre.4",
|
|
67
|
+
"react-router": "^7.0.0-pre.4"
|
|
41
68
|
},
|
|
42
69
|
"peerDependenciesMeta": {
|
|
43
70
|
"typescript": {
|
|
@@ -54,6 +81,6 @@
|
|
|
54
81
|
"README.md"
|
|
55
82
|
],
|
|
56
83
|
"scripts": {
|
|
57
|
-
"
|
|
84
|
+
"build": "wireit"
|
|
58
85
|
}
|
|
59
86
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/binaryTypes.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function isBinaryType(contentType: string | null | undefined): boolean;
|
package/dist/binaryTypes.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @react-router/architect v7.0.0-pre.2
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Remix Software Inc.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Common binary MIME types
|
|
17
|
-
* @see https://github.com/architect/functions/blob/45254fc1936a1794c185aac07e9889b241a2e5c6/src/http/helpers/binary-types.js
|
|
18
|
-
*/
|
|
19
|
-
const binaryTypes = ["application/octet-stream",
|
|
20
|
-
// Docs
|
|
21
|
-
"application/epub+zip", "application/msword", "application/pdf", "application/rtf", "application/vnd.amazon.ebook", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
22
|
-
// Fonts
|
|
23
|
-
"font/otf", "font/woff", "font/woff2",
|
|
24
|
-
// Images
|
|
25
|
-
"image/avif", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/tiff", "image/vnd.microsoft.icon", "image/webp",
|
|
26
|
-
// Audio
|
|
27
|
-
"audio/3gpp", "audio/aac", "audio/basic", "audio/mpeg", "audio/ogg", "audio/wav", "audio/webm", "audio/x-aiff", "audio/x-midi", "audio/x-wav",
|
|
28
|
-
// Video
|
|
29
|
-
"video/3gpp", "video/mp2t", "video/mpeg", "video/ogg", "video/quicktime", "video/webm", "video/x-msvideo",
|
|
30
|
-
// Archives
|
|
31
|
-
"application/java-archive", "application/vnd.apple.installer+xml", "application/x-7z-compressed", "application/x-apple-diskimage", "application/x-bzip", "application/x-bzip2", "application/x-gzip", "application/x-java-archive", "application/x-rar-compressed", "application/x-tar", "application/x-zip", "application/zip"];
|
|
32
|
-
function isBinaryType(contentType) {
|
|
33
|
-
if (!contentType) return false;
|
|
34
|
-
let [test] = contentType.split(";");
|
|
35
|
-
return binaryTypes.includes(test);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
exports.isBinaryType = isBinaryType;
|
package/dist/server.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { AppLoadContext, ServerBuild } from "react-router";
|
|
2
|
-
import type { APIGatewayProxyEventHeaders, APIGatewayProxyEventV2, APIGatewayProxyHandlerV2, APIGatewayProxyStructuredResultV2 } from "aws-lambda";
|
|
3
|
-
/**
|
|
4
|
-
* A function that returns the value to use as `context` in route `loader` and
|
|
5
|
-
* `action` functions.
|
|
6
|
-
*
|
|
7
|
-
* You can think of this as an escape hatch that allows you to pass
|
|
8
|
-
* environment/platform-specific values through to your loader/action.
|
|
9
|
-
*/
|
|
10
|
-
export type GetLoadContextFunction = (event: APIGatewayProxyEventV2) => Promise<AppLoadContext> | AppLoadContext;
|
|
11
|
-
export type RequestHandler = APIGatewayProxyHandlerV2;
|
|
12
|
-
/**
|
|
13
|
-
* Returns a request handler for Architect that serves the response using
|
|
14
|
-
* React Router.
|
|
15
|
-
*/
|
|
16
|
-
export declare function createRequestHandler({ build, getLoadContext, mode, }: {
|
|
17
|
-
build: ServerBuild;
|
|
18
|
-
getLoadContext?: GetLoadContextFunction;
|
|
19
|
-
mode?: string;
|
|
20
|
-
}): RequestHandler;
|
|
21
|
-
export declare function createReactRouterRequest(event: APIGatewayProxyEventV2): Request;
|
|
22
|
-
export declare function createReactRouterHeaders(requestHeaders: APIGatewayProxyEventHeaders, requestCookies?: string[]): Headers;
|
|
23
|
-
export declare function sendReactRouterResponse(nodeResponse: Response): Promise<APIGatewayProxyStructuredResultV2>;
|
package/dist/server.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @react-router/architect v7.0.0-pre.2
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Remix Software Inc.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
-
|
|
15
|
-
var reactRouter = require('react-router');
|
|
16
|
-
var node = require('@react-router/node');
|
|
17
|
-
var binaryTypes = require('./binaryTypes.js');
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* A function that returns the value to use as `context` in route `loader` and
|
|
21
|
-
* `action` functions.
|
|
22
|
-
*
|
|
23
|
-
* You can think of this as an escape hatch that allows you to pass
|
|
24
|
-
* environment/platform-specific values through to your loader/action.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Returns a request handler for Architect that serves the response using
|
|
29
|
-
* React Router.
|
|
30
|
-
*/
|
|
31
|
-
function createRequestHandler({
|
|
32
|
-
build,
|
|
33
|
-
getLoadContext,
|
|
34
|
-
mode = process.env.NODE_ENV
|
|
35
|
-
}) {
|
|
36
|
-
let handleRequest = reactRouter.createRequestHandler(build, mode);
|
|
37
|
-
return async event => {
|
|
38
|
-
let request = createReactRouterRequest(event);
|
|
39
|
-
let loadContext = await (getLoadContext === null || getLoadContext === void 0 ? void 0 : getLoadContext(event));
|
|
40
|
-
let response = await handleRequest(request, loadContext);
|
|
41
|
-
return sendReactRouterResponse(response);
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function createReactRouterRequest(event) {
|
|
45
|
-
var _event$headers$conten;
|
|
46
|
-
let host = event.headers["x-forwarded-host"] || event.headers.host;
|
|
47
|
-
let search = event.rawQueryString.length ? `?${event.rawQueryString}` : "";
|
|
48
|
-
let scheme = process.env.ARC_SANDBOX ? "http" : "https";
|
|
49
|
-
let url = new URL(`${scheme}://${host}${event.rawPath}${search}`);
|
|
50
|
-
let isFormData = (_event$headers$conten = event.headers["content-type"]) === null || _event$headers$conten === void 0 ? void 0 : _event$headers$conten.includes("multipart/form-data");
|
|
51
|
-
// Note: No current way to abort these for Architect, but our router expects
|
|
52
|
-
// requests to contain a signal, so it can detect aborted requests
|
|
53
|
-
let controller = new AbortController();
|
|
54
|
-
return new Request(url.href, {
|
|
55
|
-
method: event.requestContext.http.method,
|
|
56
|
-
headers: createReactRouterHeaders(event.headers, event.cookies),
|
|
57
|
-
signal: controller.signal,
|
|
58
|
-
body: event.body && event.isBase64Encoded ? isFormData ? Buffer.from(event.body, "base64") : Buffer.from(event.body, "base64").toString() : event.body
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
function createReactRouterHeaders(requestHeaders, requestCookies) {
|
|
62
|
-
let headers = new Headers();
|
|
63
|
-
for (let [header, value] of Object.entries(requestHeaders)) {
|
|
64
|
-
if (value) {
|
|
65
|
-
headers.append(header, value);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (requestCookies) {
|
|
69
|
-
headers.append("Cookie", requestCookies.join("; "));
|
|
70
|
-
}
|
|
71
|
-
return headers;
|
|
72
|
-
}
|
|
73
|
-
async function sendReactRouterResponse(nodeResponse) {
|
|
74
|
-
let cookies = [];
|
|
75
|
-
|
|
76
|
-
// Arc/AWS API Gateway will send back set-cookies outside of response headers.
|
|
77
|
-
for (let [key, value] of nodeResponse.headers.entries()) {
|
|
78
|
-
if (key.toLowerCase() === "set-cookie") {
|
|
79
|
-
cookies.push(value);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (cookies.length) {
|
|
83
|
-
nodeResponse.headers.delete("Set-Cookie");
|
|
84
|
-
}
|
|
85
|
-
let contentType = nodeResponse.headers.get("Content-Type");
|
|
86
|
-
let isBase64Encoded = binaryTypes.isBinaryType(contentType);
|
|
87
|
-
let body;
|
|
88
|
-
if (nodeResponse.body) {
|
|
89
|
-
if (isBase64Encoded) {
|
|
90
|
-
body = await node.readableStreamToString(nodeResponse.body, "base64");
|
|
91
|
-
} else {
|
|
92
|
-
body = await nodeResponse.text();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
statusCode: nodeResponse.status,
|
|
97
|
-
headers: Object.fromEntries(nodeResponse.headers.entries()),
|
|
98
|
-
cookies,
|
|
99
|
-
body,
|
|
100
|
-
isBase64Encoded
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
exports.createReactRouterHeaders = createReactRouterHeaders;
|
|
105
|
-
exports.createReactRouterRequest = createReactRouterRequest;
|
|
106
|
-
exports.createRequestHandler = createRequestHandler;
|
|
107
|
-
exports.sendReactRouterResponse = sendReactRouterResponse;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { SessionData, SessionStorage, SessionIdStorageStrategy } from "react-router";
|
|
2
|
-
import type { ArcTable } from "@architect/functions/types/tables";
|
|
3
|
-
interface ArcTableSessionStorageOptions {
|
|
4
|
-
/**
|
|
5
|
-
* The Cookie used to store the session id on the client, or options used
|
|
6
|
-
* to automatically create one.
|
|
7
|
-
*/
|
|
8
|
-
cookie?: SessionIdStorageStrategy["cookie"];
|
|
9
|
-
/**
|
|
10
|
-
* The table used to store sessions, or its name as it appears in your
|
|
11
|
-
* project's app.arc file.
|
|
12
|
-
*/
|
|
13
|
-
table: ArcTable<SessionData> | string;
|
|
14
|
-
/**
|
|
15
|
-
* The name of the DynamoDB attribute used to store the session ID.
|
|
16
|
-
* This should be the table's partition key.
|
|
17
|
-
*/
|
|
18
|
-
idx: string;
|
|
19
|
-
/**
|
|
20
|
-
* The name of the DynamoDB attribute used to store the expiration time.
|
|
21
|
-
* If absent, then no TTL will be stored and session records will not expire.
|
|
22
|
-
*/
|
|
23
|
-
ttl?: string;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Session storage using a DynamoDB table managed by Architect.
|
|
27
|
-
*
|
|
28
|
-
* Add the following lines to your project's `app.arc` file:
|
|
29
|
-
*
|
|
30
|
-
* @tables
|
|
31
|
-
* arc-sessions
|
|
32
|
-
* _idx *String
|
|
33
|
-
* _ttl TTL
|
|
34
|
-
*/
|
|
35
|
-
export declare function createArcTableSessionStorage<Data = SessionData, FlashData = Data>({ cookie, ...props }: ArcTableSessionStorageOptions): SessionStorage<Data, FlashData>;
|
|
36
|
-
export {};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @react-router/architect v7.0.0-pre.2
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Remix Software Inc.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
-
|
|
15
|
-
var reactRouter = require('react-router');
|
|
16
|
-
var arc = require('@architect/functions');
|
|
17
|
-
|
|
18
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
19
|
-
|
|
20
|
-
var arc__default = /*#__PURE__*/_interopDefaultLegacy(arc);
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Session storage using a DynamoDB table managed by Architect.
|
|
24
|
-
*
|
|
25
|
-
* Add the following lines to your project's `app.arc` file:
|
|
26
|
-
*
|
|
27
|
-
* @tables
|
|
28
|
-
* arc-sessions
|
|
29
|
-
* _idx *String
|
|
30
|
-
* _ttl TTL
|
|
31
|
-
*/
|
|
32
|
-
function createArcTableSessionStorage({
|
|
33
|
-
cookie,
|
|
34
|
-
...props
|
|
35
|
-
}) {
|
|
36
|
-
async function getTable() {
|
|
37
|
-
if (typeof props.table === "string") {
|
|
38
|
-
let tables = await arc__default["default"].tables();
|
|
39
|
-
return tables[props.table];
|
|
40
|
-
} else {
|
|
41
|
-
return props.table;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return reactRouter.createSessionStorage({
|
|
45
|
-
cookie,
|
|
46
|
-
async createData(data, expires) {
|
|
47
|
-
let table = await getTable();
|
|
48
|
-
while (true) {
|
|
49
|
-
let randomBytes = crypto.getRandomValues(new Uint8Array(8));
|
|
50
|
-
// This storage manages an id space of 2^64 ids, which is far greater
|
|
51
|
-
// than the maximum number of files allowed on an NTFS or ext4 volume
|
|
52
|
-
// (2^32). However, the larger id space should help to avoid collisions
|
|
53
|
-
// with existing ids when creating new sessions, which speeds things up.
|
|
54
|
-
let id = [...randomBytes].map(x => x.toString(16).padStart(2, "0")).join("");
|
|
55
|
-
if (await table.get({
|
|
56
|
-
[props.idx]: id
|
|
57
|
-
})) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
let params = {
|
|
61
|
-
[props.idx]: id,
|
|
62
|
-
...data
|
|
63
|
-
};
|
|
64
|
-
if (props.ttl) {
|
|
65
|
-
params[props.ttl] = expires ? Math.round(expires.getTime() / 1000) : undefined;
|
|
66
|
-
}
|
|
67
|
-
await table.put(params);
|
|
68
|
-
return id;
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
async readData(id) {
|
|
72
|
-
let table = await getTable();
|
|
73
|
-
let data = await table.get({
|
|
74
|
-
[props.idx]: id
|
|
75
|
-
});
|
|
76
|
-
if (data) {
|
|
77
|
-
delete data[props.idx];
|
|
78
|
-
if (props.ttl) delete data[props.ttl];
|
|
79
|
-
}
|
|
80
|
-
return data;
|
|
81
|
-
},
|
|
82
|
-
async updateData(id, data, expires) {
|
|
83
|
-
let table = await getTable();
|
|
84
|
-
let params = {
|
|
85
|
-
[props.idx]: id,
|
|
86
|
-
...data
|
|
87
|
-
};
|
|
88
|
-
if (props.ttl) {
|
|
89
|
-
params[props.ttl] = expires ? Math.round(expires.getTime() / 1000) : undefined;
|
|
90
|
-
}
|
|
91
|
-
await table.put(params);
|
|
92
|
-
},
|
|
93
|
-
async deleteData(id) {
|
|
94
|
-
let table = await getTable();
|
|
95
|
-
await table.delete({
|
|
96
|
-
[props.idx]: id
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
exports.createArcTableSessionStorage = createArcTableSessionStorage;
|