acrylblends 0.8.1 → 0.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/index.d.ts +2 -0
- package/dist/index.js +83 -7
- package/dist/index.js.map +1 -1
- package/lib/audit-BXnYsLge.d.ts +58 -0
- package/lib/cell-ChU41DZD.d.ts +32 -0
- package/lib/client-modules-CLvWOjbd.js +267 -0
- package/lib/connection-ZLEso7XL.d.ts +25 -0
- package/lib/conninfo.d.ts +1 -23
- package/lib/cordis/db-sqlite.d.ts +56 -0
- package/lib/cordis/db-sqlite.js +58 -0
- package/lib/cordis/db.d.ts +8 -0
- package/lib/cordis/db.js +1 -0
- package/lib/cordis/door.d.ts +159 -0
- package/lib/cordis/door.js +757 -0
- package/lib/cordis/inspect.d.ts +77 -0
- package/lib/cordis/inspect.js +149 -0
- package/lib/cordis/kv-db.d.ts +16 -0
- package/lib/cordis/kv-db.js +18 -0
- package/lib/cordis/kv-json.d.ts +16 -0
- package/lib/cordis/kv-json.js +44 -0
- package/lib/cordis/kv.d.ts +8 -0
- package/lib/cordis/kv.js +1 -0
- package/lib/cordis/node-server.d.ts +45 -0
- package/lib/cordis/node-server.js +93 -0
- package/lib/cordis/router-http.d.ts +56 -0
- package/lib/cordis/router-http.js +117 -0
- package/lib/cordis/router.d.ts +8 -0
- package/lib/cordis/router.js +7 -0
- package/lib/cordis/state/react.d.ts +6 -0
- package/lib/cordis/state/react.js +11 -0
- package/lib/cordis/state.d.ts +33 -0
- package/lib/cordis/state.js +163 -0
- package/lib/core-CaY8XDZ6.js +19 -0
- package/lib/database-DBHdwefi.d.ts +44 -0
- package/lib/db/conformance.d.ts +11 -0
- package/lib/db/conformance.js +267 -0
- package/lib/db/sqlite.d.ts +1 -1
- package/lib/db/sqlite.js +1 -196
- package/lib/db.d.ts +2 -1
- package/lib/{src-0hI7M7cN.js → deprecated-BP4fPt38.js} +0 -17
- package/lib/door/host.d.ts +24 -0
- package/lib/door/host.js +2 -0
- package/lib/door/page.d.ts +105 -0
- package/lib/door/page.js +1030 -0
- package/lib/door/protocol.d.ts +2 -0
- package/lib/door/protocol.js +197 -0
- package/lib/error-t4N2js2I.d.ts +8 -0
- package/lib/etag-DaKMOjty.js +135 -0
- package/lib/etag.js +1 -134
- package/lib/helpers-CvTauQT5.js +5 -0
- package/lib/http-exception-kpGJkmpi.d.ts +57 -0
- package/lib/http-exception.d.ts +1 -56
- package/lib/{index-BLTYsyc1.d.ts → index-BnGgRKTv.d.ts} +3 -39
- package/lib/index-BqVQkTnu.d.ts +98 -0
- package/lib/index-Dmst2QCQ.d.ts +44 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -1
- package/lib/jwk-LkzeoaU8.js +117 -0
- package/lib/jwk.js +1 -116
- package/lib/jwt-CskdhEW9.js +115 -0
- package/lib/jwt.js +2 -114
- package/lib/kv/conformance.d.ts +13 -0
- package/lib/kv/conformance.js +301 -0
- package/lib/kv/db.d.ts +2 -2
- package/lib/kv/json.d.ts +1 -1
- package/lib/kv-9f-AlRKN.d.ts +39 -0
- package/lib/kv.d.ts +2 -1
- package/lib/language-D9a4zqvn.js +198 -0
- package/lib/language.js +1 -197
- package/lib/middleware-CPQ8himN.js +12 -0
- package/lib/node-server/serve-static.d.ts +0 -1
- package/lib/node-server/serve-static.js +1 -1
- package/lib/node-server.d.ts +1 -7
- package/lib/node-server.js +3 -1586
- package/lib/open-CMhnJODn.js +197 -0
- package/lib/protocol-BizVt4J6.d.ts +144 -0
- package/lib/request-id-CKVvHOO1.js +34 -0
- package/lib/request-id.js +1 -33
- package/lib/secure-headers-mP3j6Hm6.js +163 -0
- package/lib/secure-headers.js +1 -162
- package/lib/{serve-static-B849HlX2.js → serve-static-3uo_9rjF.js} +1 -4
- package/lib/server-DvgMGtzo.js +1323 -0
- package/lib/snapshot-text-D3NspDyT.js +338 -0
- package/lib/src-CwABFr6r.js +328 -0
- package/lib/timeout.d.ts +1 -1
- package/lib/timing-Cky7C1Jf.js +183 -0
- package/lib/timing.js +1 -182
- package/package.json +89 -1
- package/plugins/acryl-db/plugin.json +6 -1
- package/plugins/acryl-db-sqlite/plugin.json +4 -0
- package/plugins/acryl-db-sqlite/src/facade/node.ts +1 -1
- package/plugins/acryl-db-sqlite/src/index.ts +2 -2
- package/plugins/acryl-db-sqlite/src/open.ts +2 -2
- package/plugins/acryl-door/plugin.json +4 -1
- package/plugins/acryl-door/src/host/http.ts +2 -2
- package/plugins/acryl-door/src/host/mcp-routes.ts +1 -1
- package/plugins/acryl-door/src/host/operator-routes.ts +1 -1
- package/plugins/acryl-door/src/host/page-routes.ts +3 -3
- package/plugins/acryl-door/src/index.ts +2 -2
- package/plugins/acryl-inspect/plugin.json +4 -1
- package/plugins/acryl-inspect/src/service.ts +2 -2
- package/plugins/acryl-kv/plugin.json +6 -1
- package/plugins/acryl-kv-db/plugin.json +4 -0
- package/plugins/acryl-kv-db/src/index.ts +1 -1
- package/plugins/acryl-kv-db/src/open.ts +3 -3
- package/plugins/acryl-kv-json/plugin.json +4 -0
- package/plugins/acryl-kv-json/src/index.ts +1 -1
- package/plugins/acryl-kv-json/src/open.ts +2 -2
- package/plugins/acryl-node-server/plugin.json +5 -1
- package/plugins/acryl-node-server/src/adapter/conninfo.ts +1 -1
- package/plugins/acryl-node-server/src/adapter/early-hints.ts +1 -1
- package/plugins/acryl-node-server/src/adapter/serve-static.ts +2 -2
- package/plugins/acryl-node-server/src/adapter/websocket.ts +2 -2
- package/plugins/acryl-node-server/src/client-modules.ts +2 -2
- package/plugins/acryl-node-server/src/index.ts +1 -1
- package/plugins/acryl-router/plugin.json +11 -1
- package/plugins/acryl-router/src/connection.d.ts +25 -0
- package/plugins/acryl-router/src/core/app-base.d.ts +215 -0
- package/plugins/acryl-router/src/core/app.d.ts +19 -0
- package/plugins/acryl-router/src/core/client/client.d.ts +4 -0
- package/plugins/acryl-router/src/core/client/fetch-result-please.d.ts +35 -0
- package/plugins/acryl-router/src/core/client/index.d.ts +7 -0
- package/plugins/acryl-router/src/core/client/types.d.ts +229 -0
- package/plugins/acryl-router/src/core/client/utils.d.ts +18 -0
- package/plugins/acryl-router/src/core/compose.d.ts +14 -0
- package/plugins/acryl-router/src/core/context.d.ts +443 -0
- package/plugins/acryl-router/src/core/helper/accepts/accepts.d.ts +30 -0
- package/plugins/acryl-router/src/core/helper/accepts/index.d.ts +5 -0
- package/plugins/acryl-router/src/core/helper/conninfo/index.d.ts +5 -0
- package/plugins/acryl-router/src/core/helper/conninfo/types.d.ts +36 -0
- package/plugins/acryl-router/src/core/helper/cookie/index.d.ts +25 -0
- package/plugins/acryl-router/src/core/helper/css/common.d.ts +59 -0
- package/plugins/acryl-router/src/core/helper/css/index.d.ts +80 -0
- package/plugins/acryl-router/src/core/helper/dev/index.d.ts +20 -0
- package/plugins/acryl-router/src/core/helper/factory/index.d.ts +82 -0
- package/plugins/acryl-router/src/core/helper/html/index.d.ts +8 -0
- package/plugins/acryl-router/src/core/helper/proxy/index.d.ts +73 -0
- package/plugins/acryl-router/src/core/helper/route/index.d.ts +75 -0
- package/plugins/acryl-router/src/core/helper/ssg/index.d.ts +7 -0
- package/plugins/acryl-router/src/core/helper/ssg/middleware.d.ts +44 -0
- package/plugins/acryl-router/src/core/helper/ssg/plugins.d.ts +27 -0
- package/plugins/acryl-router/src/core/helper/ssg/ssg.d.ts +91 -0
- package/plugins/acryl-router/src/core/helper/ssg/utils.d.ts +16 -0
- package/plugins/acryl-router/src/core/helper/streaming/index.d.ts +8 -0
- package/plugins/acryl-router/src/core/helper/streaming/sse.d.ts +13 -0
- package/plugins/acryl-router/src/core/helper/streaming/stream.d.ts +3 -0
- package/plugins/acryl-router/src/core/helper/streaming/text.d.ts +3 -0
- package/plugins/acryl-router/src/core/helper/streaming/utils.d.ts +1 -0
- package/plugins/acryl-router/src/core/helper/testing/index.d.ts +13 -0
- package/plugins/acryl-router/src/core/helper/websocket/index.d.ts +70 -0
- package/plugins/acryl-router/src/core/http-exception.d.ts +58 -0
- package/plugins/acryl-router/src/core/index.d.ts +37 -0
- package/plugins/acryl-router/src/core/jsx/base.d.ts +61 -0
- package/plugins/acryl-router/src/core/jsx/children.d.ts +9 -0
- package/plugins/acryl-router/src/core/jsx/components.d.ts +15 -0
- package/plugins/acryl-router/src/core/jsx/constants.d.ts +6 -0
- package/plugins/acryl-router/src/core/jsx/context.d.ts +51 -0
- package/plugins/acryl-router/src/core/jsx/dom/components.d.ts +10 -0
- package/plugins/acryl-router/src/core/jsx/dom/context.d.ts +3 -0
- package/plugins/acryl-router/src/core/jsx/dom/css.d.ts +83 -0
- package/plugins/acryl-router/src/core/jsx/dom/hooks/index.d.ts +39 -0
- package/plugins/acryl-router/src/core/jsx/dom/intrinsic-element/components.d.ts +16 -0
- package/plugins/acryl-router/src/core/jsx/dom/jsx-dev-runtime.d.ts +8 -0
- package/plugins/acryl-router/src/core/jsx/dom/jsx-runtime.d.ts +7 -0
- package/plugins/acryl-router/src/core/jsx/dom/render.d.ts +73 -0
- package/plugins/acryl-router/src/core/jsx/dom/utils.d.ts +1 -0
- package/plugins/acryl-router/src/core/jsx/hooks/index.d.ts +47 -0
- package/plugins/acryl-router/src/core/jsx/index.d.ts +76 -0
- package/plugins/acryl-router/src/core/jsx/intrinsic-element/common.d.ts +6 -0
- package/plugins/acryl-router/src/core/jsx/intrinsic-element/components.d.ts +13 -0
- package/plugins/acryl-router/src/core/jsx/intrinsic-elements.d.ts +735 -0
- package/plugins/acryl-router/src/core/jsx/streaming.d.ts +36 -0
- package/plugins/acryl-router/src/core/jsx/types.d.ts +36 -0
- package/plugins/acryl-router/src/core/jsx/utils.d.ts +4 -0
- package/plugins/acryl-router/src/core/request/constants.d.ts +1 -0
- package/plugins/acryl-router/src/core/request.d.ts +306 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/index.d.ts +6 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/matcher.d.ts +7 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/node.d.ts +13 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.d.ts +17 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/router.d.ts +11 -0
- package/plugins/acryl-router/src/core/router/reg-exp-router/trie.d.ts +8 -0
- package/plugins/acryl-router/src/core/router/smart-router/index.d.ts +5 -0
- package/plugins/acryl-router/src/core/router/smart-router/router.d.ts +11 -0
- package/plugins/acryl-router/src/core/router/trie-router/index.d.ts +5 -0
- package/plugins/acryl-router/src/core/router/trie-router/node.d.ts +6 -0
- package/plugins/acryl-router/src/core/router/trie-router/router.d.ts +7 -0
- package/plugins/acryl-router/src/core/router/utils.d.ts +1 -0
- package/plugins/acryl-router/src/core/router.d.ts +97 -0
- package/plugins/acryl-router/src/core/types.d.ts +573 -0
- package/plugins/acryl-router/src/core/utils/accept.d.ts +6 -0
- package/plugins/acryl-router/src/core/utils/body.d.ts +79 -0
- package/plugins/acryl-router/src/core/utils/buffer.d.ts +17 -0
- package/plugins/acryl-router/src/core/utils/color.d.ts +21 -0
- package/plugins/acryl-router/src/core/utils/concurrent.d.ts +11 -0
- package/plugins/acryl-router/src/core/utils/constants.d.ts +4 -0
- package/plugins/acryl-router/src/core/utils/cookie.d.ts +41 -0
- package/plugins/acryl-router/src/core/utils/crypto.d.ts +15 -0
- package/plugins/acryl-router/src/core/utils/handler.d.ts +6 -0
- package/plugins/acryl-router/src/core/utils/headers.d.ts +8 -0
- package/plugins/acryl-router/src/core/utils/html.d.ts +44 -0
- package/plugins/acryl-router/src/core/utils/http-status.d.ts +32 -0
- package/plugins/acryl-router/src/core/utils/mime.d.ts +70 -0
- package/plugins/acryl-router/src/core/utils/stream.d.ts +31 -0
- package/plugins/acryl-router/src/core/utils/types.d.ts +128 -0
- package/plugins/acryl-router/src/core/utils/url.d.ts +44 -0
- package/plugins/acryl-router/src/core/validator/index.d.ts +7 -0
- package/plugins/acryl-router/src/core/validator/utils.d.ts +29 -0
- package/plugins/acryl-router/src/core/validator/validator.d.ts +16 -0
- package/plugins/acryl-router/src/helpers/index.d.ts +17 -0
- package/plugins/acryl-router/src/helpers/schema-validator.d.ts +54 -0
- package/plugins/acryl-router-http/plugin.json +4 -1
- package/plugins/acryl-router-http/src/index.ts +1 -1
- package/plugins/acryl-state/plugin.json +5 -1
- package/plugins/acryl-state/src/service.ts +3 -3
- package/plugins/tsconfig.json +32 -20
- package/docs/framework/UPSTREAM.md +0 -3
- package/docs/framework/upstream.json +0 -9
- package/lib/index-D4FAsBZu.d.ts +0 -85
- package/plugins/acryl-db/upstream.json +0 -18
- package/plugins/acryl-db-sqlite/upstream.json +0 -21
- package/plugins/acryl-door/upstream.json +0 -28
- package/plugins/acryl-inspect/upstream.json +0 -18
- package/plugins/acryl-kv/upstream.json +0 -18
- package/plugins/acryl-kv-db/upstream.json +0 -21
- package/plugins/acryl-kv-json/upstream.json +0 -22
- package/plugins/acryl-node-server/upstream.json +0 -21
- package/plugins/acryl-router/upstream.json +0 -20
- package/plugins/acryl-router-http/upstream.json +0 -22
- package/plugins/acryl-state/NOTICE +0 -30
- package/plugins/acryl-state/upstream.json +0 -22
- package/plugins/desktop/upstream.json +0 -12
- package/plugins/desktop-web/upstream.json +0 -12
- package/templates/todo/upstream.json +0 -12
- /package/lib/{index-CTy4N7ng.d.ts → deprecated-CTy4N7ng.d.ts} +0 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { i as applyMigrations, n as MIGRATIONS_TABLE, r as readMigrationFiles } from "./src-MWcsMS8i.js";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { DatabaseSync } from "node:sqlite";
|
|
5
|
+
//#region ../../plugins/acryl-db-sqlite/src/facade/node.ts
|
|
6
|
+
const DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1e3;
|
|
7
|
+
const DEFAULT_BUSY_TIMEOUT_MS = 5e3;
|
|
8
|
+
const ignore = () => {};
|
|
9
|
+
/**
|
|
10
|
+
* Runs operations in call order. An operation starts immediately when nothing is running or waiting;
|
|
11
|
+
* otherwise it waits for everything before it. An asynchronous operation holds the queue until it settles.
|
|
12
|
+
*/
|
|
13
|
+
var SerialOperationQueue = class {
|
|
14
|
+
tail = Promise.resolve();
|
|
15
|
+
pending = 0;
|
|
16
|
+
run(operation) {
|
|
17
|
+
if (this.pending > 0) return this.enqueue(operation);
|
|
18
|
+
try {
|
|
19
|
+
return Promise.resolve(operation());
|
|
20
|
+
} catch (error) {
|
|
21
|
+
return Promise.reject(error);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
runAsync(operation) {
|
|
25
|
+
if (this.pending > 0) return this.enqueue(operation);
|
|
26
|
+
this.pending++;
|
|
27
|
+
const { promise: barrier, resolve: releaseBarrier } = Promise.withResolvers();
|
|
28
|
+
this.tail = barrier;
|
|
29
|
+
let started;
|
|
30
|
+
try {
|
|
31
|
+
started = operation();
|
|
32
|
+
} catch (error) {
|
|
33
|
+
started = Promise.reject(error);
|
|
34
|
+
}
|
|
35
|
+
return started.finally(() => {
|
|
36
|
+
this.pending--;
|
|
37
|
+
releaseBarrier();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
enqueue(operation) {
|
|
41
|
+
this.pending++;
|
|
42
|
+
return this.release(this.tail.then(operation));
|
|
43
|
+
}
|
|
44
|
+
release(operation) {
|
|
45
|
+
const settled = operation.finally(() => {
|
|
46
|
+
this.pending--;
|
|
47
|
+
});
|
|
48
|
+
this.tail = settled.then(ignore, ignore);
|
|
49
|
+
return settled;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Executes SQL on one connection. Prepared statements are cached per connection by SQL text, so the
|
|
54
|
+
* database and its transaction handles share them across transactions.
|
|
55
|
+
*/
|
|
56
|
+
var NodeSqliteExecutor = class {
|
|
57
|
+
database;
|
|
58
|
+
statements;
|
|
59
|
+
constructor(database, statements) {
|
|
60
|
+
this.database = database;
|
|
61
|
+
this.statements = statements;
|
|
62
|
+
}
|
|
63
|
+
exec(sql) {
|
|
64
|
+
return this.runOperation(() => {
|
|
65
|
+
this.database.exec(sql);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
run(sql, ...params) {
|
|
69
|
+
return this.runOperation(() => ({ changes: Number(this.statement(sql).run(...params).changes) }));
|
|
70
|
+
}
|
|
71
|
+
get(sql, ...params) {
|
|
72
|
+
return this.runOperation(() => this.statement(sql).get(...params));
|
|
73
|
+
}
|
|
74
|
+
all(sql, ...params) {
|
|
75
|
+
return this.runOperation(() => this.statement(sql).all(...params));
|
|
76
|
+
}
|
|
77
|
+
statement(sql) {
|
|
78
|
+
let statement = this.statements.get(sql);
|
|
79
|
+
if (statement === void 0) {
|
|
80
|
+
statement = this.database.prepare(sql);
|
|
81
|
+
this.statements.set(sql, statement);
|
|
82
|
+
}
|
|
83
|
+
return statement;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var NodeSqliteTransaction = class extends NodeSqliteExecutor {
|
|
87
|
+
scope;
|
|
88
|
+
constructor(database, statements, scope) {
|
|
89
|
+
super(database, statements);
|
|
90
|
+
this.scope = scope;
|
|
91
|
+
}
|
|
92
|
+
async runOperation(operation) {
|
|
93
|
+
if (!this.scope.active) throw new Error("SQLite transaction handle is no longer active");
|
|
94
|
+
return operation();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
/** `Db` adapter backed by Node's built-in `node:sqlite`. */
|
|
98
|
+
var NodeSqliteDatabase = class extends NodeSqliteExecutor {
|
|
99
|
+
access = new SerialOperationQueue();
|
|
100
|
+
closed = false;
|
|
101
|
+
constructor(database) {
|
|
102
|
+
super(database, /* @__PURE__ */ new Map());
|
|
103
|
+
}
|
|
104
|
+
transaction(callback) {
|
|
105
|
+
return this.access.runAsync(async () => {
|
|
106
|
+
this.database.exec("BEGIN IMMEDIATE");
|
|
107
|
+
const scope = { active: true };
|
|
108
|
+
try {
|
|
109
|
+
const result = await callback(new NodeSqliteTransaction(this.database, this.statements, scope));
|
|
110
|
+
scope.active = false;
|
|
111
|
+
this.database.exec("COMMIT");
|
|
112
|
+
return result;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
scope.active = false;
|
|
115
|
+
try {
|
|
116
|
+
this.database.exec("ROLLBACK");
|
|
117
|
+
} catch (rollbackError) {
|
|
118
|
+
throw new AggregateError([error, rollbackError], "SQLite transaction failed and rollback failed");
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
close() {
|
|
125
|
+
return this.access.run(() => {
|
|
126
|
+
if (this.closed) return;
|
|
127
|
+
this.closed = true;
|
|
128
|
+
this.statements.clear();
|
|
129
|
+
try {
|
|
130
|
+
this.database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
131
|
+
} finally {
|
|
132
|
+
this.database.close();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
runOperation(operation) {
|
|
137
|
+
return this.access.run(operation);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
/** Open and configure a Node-backed SQLite database facade. */
|
|
141
|
+
async function openNodeSqliteDatabase(path, options = {}) {
|
|
142
|
+
const checkpointPages = options.walAutoCheckpointPages ?? DEFAULT_WAL_AUTO_CHECKPOINT_PAGES;
|
|
143
|
+
const timeout = options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS;
|
|
144
|
+
if (path !== ":memory:") await mkdir(dirname(path), { recursive: true });
|
|
145
|
+
const adapter = new NodeSqliteDatabase(new DatabaseSync(path, { timeout }));
|
|
146
|
+
try {
|
|
147
|
+
await adapter.exec("PRAGMA journal_mode = WAL");
|
|
148
|
+
await adapter.exec("PRAGMA synchronous = NORMAL");
|
|
149
|
+
await adapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);
|
|
150
|
+
return adapter;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
try {
|
|
153
|
+
await adapter.close();
|
|
154
|
+
} catch {}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region ../../plugins/acryl-db-sqlite/src/open.ts
|
|
160
|
+
/**
|
|
161
|
+
* The plain way to open the SQLite provider, for code without Cordis (an acrylblends app): `openDb({ path, migrations })` opens one
|
|
162
|
+
* `node:sqlite` file with the ported facade's settings (WAL, `synchronous = NORMAL`, a busy timeout) and foreign keys enforced, applies the
|
|
163
|
+
* numbered migrations, and resolves the `db` port with the function that closes it. The Cordis plugin is a thin wrapper over this, so both
|
|
164
|
+
* run one code path.
|
|
165
|
+
* This entry imports nothing from Cordis.
|
|
166
|
+
*/
|
|
167
|
+
/**
|
|
168
|
+
* Open, configure and migrate a SQLite database.
|
|
169
|
+
* @throws when the migration files are misnamed or misnumbered, or a migration fails (the file is closed, and unchanged), or the
|
|
170
|
+
* database's schema is newer than the migrations.
|
|
171
|
+
*/
|
|
172
|
+
async function openDb(options) {
|
|
173
|
+
const migrations = options.migrations === void 0 ? [] : await readMigrationFiles(options.migrations);
|
|
174
|
+
const database = await openNodeSqliteDatabase(options.path, {
|
|
175
|
+
...options.busyTimeoutMs === void 0 ? {} : { busyTimeoutMs: options.busyTimeoutMs },
|
|
176
|
+
...options.walAutoCheckpointPages === void 0 ? {} : { walAutoCheckpointPages: options.walAutoCheckpointPages }
|
|
177
|
+
});
|
|
178
|
+
try {
|
|
179
|
+
await database.exec("PRAGMA foreign_keys = ON");
|
|
180
|
+
await applyMigrations(database, migrations, { table: MIGRATIONS_TABLE });
|
|
181
|
+
} catch (error) {
|
|
182
|
+
await database.close();
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
db: {
|
|
187
|
+
exec: (sql) => database.exec(sql),
|
|
188
|
+
run: (sql, ...params) => database.run(sql, ...params),
|
|
189
|
+
get: (sql, ...params) => database.get(sql, ...params),
|
|
190
|
+
all: (sql, ...params) => database.all(sql, ...params),
|
|
191
|
+
transaction: (work) => database.transaction(work)
|
|
192
|
+
},
|
|
193
|
+
close: () => database.close()
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//#endregion
|
|
197
|
+
export { NodeSqliteDatabase as n, openNodeSqliteDatabase as r, openDb as t };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-door/src/page/protocol.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The one shape of a door call, shared by the Host and the in-page driver (moved from `acryl-agent-control`, spec 041).
|
|
4
|
+
*
|
|
5
|
+
* The Host turns a verb's arguments into a {@link UiRequest}, sends it to the page over the channel, and gets a {@link UiResult} back.
|
|
6
|
+
* Everything crossing the channel is validated here once, so neither side trusts the other's JSON. The page imports this file too, so it
|
|
7
|
+
* lives with the page code and has no Node imports.
|
|
8
|
+
*/
|
|
9
|
+
/** The operations the driver performs on the page. */
|
|
10
|
+
declare const UI_OPS: readonly ["snapshot", "click", "type", "select", "press", "scroll", "wait"];
|
|
11
|
+
type UiOp = (typeof UI_OPS)[number];
|
|
12
|
+
/** Operations that change the page, so each call needs approval. `snapshot`, `scroll` and `wait` only look. */
|
|
13
|
+
declare const MUTATING_OPS: readonly UiOp[];
|
|
14
|
+
declare const MAX_TEXT_LENGTH = 10000;
|
|
15
|
+
declare const MAX_WAIT_MS = 10000;
|
|
16
|
+
declare const MAX_SNAPSHOT_NODES = 1000;
|
|
17
|
+
declare const DEFAULT_SNAPSHOT_NODES = 300;
|
|
18
|
+
/** Why a call did not do what was asked. Every failure is one of these, never a silent wrong action. */
|
|
19
|
+
type UiErrorCode = 'no-window' | 'stale-ref' | 'unknown-ref' | 'sensitive' | 'protected' | 'not-actionable' | 'not-found' | 'killed' | 'timeout' | 'aborted' | 'unloaded' | 'disconnected' | 'invalid';
|
|
20
|
+
declare class UiControlError extends Error {
|
|
21
|
+
readonly code: UiErrorCode;
|
|
22
|
+
constructor(code: UiErrorCode, message: string);
|
|
23
|
+
}
|
|
24
|
+
/** One element in a snapshot. */
|
|
25
|
+
interface UiNode {
|
|
26
|
+
/** `<generation>.<n>`; valid only until the next snapshot. */
|
|
27
|
+
readonly ref: string;
|
|
28
|
+
readonly role: string;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly depth: number;
|
|
31
|
+
/** Short state words: `disabled`, `checked`, `expanded`, `selected`, `focused`, `protected`, ... */
|
|
32
|
+
readonly states: readonly string[];
|
|
33
|
+
/** The text of an editable field, when it is not sensitive. */
|
|
34
|
+
readonly value?: string;
|
|
35
|
+
/** Heading level, when it is a heading. */
|
|
36
|
+
readonly level?: number;
|
|
37
|
+
}
|
|
38
|
+
interface UiSnapshot {
|
|
39
|
+
readonly generation: number;
|
|
40
|
+
readonly title: string;
|
|
41
|
+
readonly nodes: readonly UiNode[];
|
|
42
|
+
/** How many elements matched in all; more than `nodes.length` when the page was cut. */
|
|
43
|
+
readonly total: number;
|
|
44
|
+
/** Pass to the next snapshot call to continue, or absent when this is everything. */
|
|
45
|
+
readonly nextCursor?: number;
|
|
46
|
+
}
|
|
47
|
+
type UiRequest = {
|
|
48
|
+
readonly op: 'snapshot';
|
|
49
|
+
readonly cursor?: number;
|
|
50
|
+
readonly maxNodes?: number;
|
|
51
|
+
} | {
|
|
52
|
+
readonly op: 'click';
|
|
53
|
+
readonly ref: string;
|
|
54
|
+
} | {
|
|
55
|
+
readonly op: 'type';
|
|
56
|
+
readonly ref: string;
|
|
57
|
+
readonly text: string;
|
|
58
|
+
readonly submit?: boolean;
|
|
59
|
+
readonly clear?: boolean;
|
|
60
|
+
} | {
|
|
61
|
+
readonly op: 'select';
|
|
62
|
+
readonly ref: string;
|
|
63
|
+
readonly option: string;
|
|
64
|
+
} | {
|
|
65
|
+
readonly op: 'press';
|
|
66
|
+
readonly key: string;
|
|
67
|
+
readonly ref?: string;
|
|
68
|
+
} | {
|
|
69
|
+
readonly op: 'scroll';
|
|
70
|
+
readonly direction: 'up' | 'down' | 'left' | 'right';
|
|
71
|
+
readonly ref?: string;
|
|
72
|
+
readonly amount?: number;
|
|
73
|
+
} | {
|
|
74
|
+
readonly op: 'wait';
|
|
75
|
+
readonly text?: string;
|
|
76
|
+
readonly role?: string;
|
|
77
|
+
readonly name?: string;
|
|
78
|
+
readonly gone?: boolean;
|
|
79
|
+
readonly timeoutMs?: number;
|
|
80
|
+
};
|
|
81
|
+
/** What the page did, and to which control (for the audit log and the approval prompt). */
|
|
82
|
+
interface UiActionResult {
|
|
83
|
+
readonly ok: true;
|
|
84
|
+
readonly target?: {
|
|
85
|
+
readonly role: string;
|
|
86
|
+
readonly name: string;
|
|
87
|
+
};
|
|
88
|
+
readonly detail?: string;
|
|
89
|
+
}
|
|
90
|
+
type UiResult = UiSnapshot | UiActionResult;
|
|
91
|
+
/**
|
|
92
|
+
* Messages the page and the Host exchange over the channel. The Host sends calls down the page's event stream (`event: call`); the page
|
|
93
|
+
* opens that stream with its window id and focus, and sends everything else up by POST, naming its window id.
|
|
94
|
+
*/
|
|
95
|
+
type ChannelToPage = {
|
|
96
|
+
readonly t: 'call';
|
|
97
|
+
readonly id: number;
|
|
98
|
+
readonly request: UiRequest;
|
|
99
|
+
};
|
|
100
|
+
type ChannelToHost = {
|
|
101
|
+
readonly t: 'focus';
|
|
102
|
+
readonly focused: boolean;
|
|
103
|
+
} | {
|
|
104
|
+
readonly t: 'result';
|
|
105
|
+
readonly id: number;
|
|
106
|
+
readonly value: UiResult;
|
|
107
|
+
} | {
|
|
108
|
+
readonly t: 'error';
|
|
109
|
+
readonly id: number;
|
|
110
|
+
readonly code: UiErrorCode;
|
|
111
|
+
readonly message: string;
|
|
112
|
+
};
|
|
113
|
+
/** @param value - untrusted JSON. @throws UiControlError `invalid`. */
|
|
114
|
+
declare function parseUiRequest(value: unknown): UiRequest;
|
|
115
|
+
/** @param text - one `call` event's data from the Host. @throws when it is not a well-formed call. */
|
|
116
|
+
declare function parseChannelToPage(text: string): ChannelToPage;
|
|
117
|
+
/** Every code a {@link UiControlError} can carry, so a code read off the wire is validated, not cast. */
|
|
118
|
+
declare const UI_ERROR_CODES: readonly UiErrorCode[];
|
|
119
|
+
/** A window id the page chose: short, printable, so it can travel in a query string and a log line. */
|
|
120
|
+
declare const WINDOW_ID: RegExp;
|
|
121
|
+
/** @param value - one parsed message from the page; null when it is not a well-formed message. */
|
|
122
|
+
declare function parseChannelToHost(value: unknown): ChannelToHost | null;
|
|
123
|
+
/** One line of the audit log: what the agent did, never what it typed. */
|
|
124
|
+
interface AuditEntry {
|
|
125
|
+
/** ISO time of the call. */
|
|
126
|
+
readonly at: string;
|
|
127
|
+
readonly tool: string;
|
|
128
|
+
/** The control touched, when the call had one. */
|
|
129
|
+
readonly target?: {
|
|
130
|
+
readonly role: string;
|
|
131
|
+
readonly name: string;
|
|
132
|
+
};
|
|
133
|
+
readonly outcome: 'ok' | 'refused' | 'failed';
|
|
134
|
+
/** The error code for a refusal or failure, or a short note for a success. */
|
|
135
|
+
readonly detail?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Whether the user was asked first (`asked`), approval was switched off (`none`), the call needed no
|
|
138
|
+
* approval (`not-needed`), or it came from an operator holding this run's secret (`token`, spec 041 TB30): authorized by the secret,
|
|
139
|
+
* which only the OS user who started the app can read, and watched by the person at the page through the indicator and its kill switch.
|
|
140
|
+
*/
|
|
141
|
+
readonly approval: 'asked' | 'none' | 'not-needed' | 'token';
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
export { parseUiRequest as S, UiResult as _, MAX_SNAPSHOT_NODES as a, parseChannelToHost as b, MUTATING_OPS as c, UiActionResult as d, UiControlError as f, UiRequest as g, UiOp as h, DEFAULT_SNAPSHOT_NODES as i, UI_ERROR_CODES as l, UiNode as m, ChannelToHost as n, MAX_TEXT_LENGTH as o, UiErrorCode as p, ChannelToPage as r, MAX_WAIT_MS as s, AuditEntry as t, UI_OPS as u, UiSnapshot as v, parseChannelToPage as x, WINDOW_ID as y };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region ../../plugins/acryl-router/src/core/middleware/request-id/request-id.ts
|
|
2
|
+
/**
|
|
3
|
+
* Request ID Middleware for Acryl.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} options - Options for Request ID middleware.
|
|
6
|
+
* @param {number} [options.limitLength=255] - The maximum length of request id.
|
|
7
|
+
* @param {string} [options.headerName=X-Request-Id] - The header name used in request id.
|
|
8
|
+
* @param {generator} [options.generator=() => crypto.randomUUID()] - The request id generation function.
|
|
9
|
+
*
|
|
10
|
+
* @returns {MiddlewareHandler} The middleware handler function.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* type Variables = RequestIdVariables
|
|
15
|
+
* const app = new Acryl<{Variables: Variables}>()
|
|
16
|
+
*
|
|
17
|
+
* app.use(requestId())
|
|
18
|
+
* app.get('/', (c) => {
|
|
19
|
+
* console.log(c.get('requestId')) // Debug
|
|
20
|
+
* return c.text('Hello World!')
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
const requestId = ({ limitLength = 255, headerName = "X-Request-Id", generator = () => crypto.randomUUID() } = {}) => {
|
|
25
|
+
return async function requestId(c, next) {
|
|
26
|
+
let reqId = headerName ? c.req.header(headerName) : void 0;
|
|
27
|
+
if (!reqId || reqId.length > limitLength || /[^\w\-=]/.test(reqId)) reqId = generator(c);
|
|
28
|
+
c.set("requestId", reqId);
|
|
29
|
+
if (headerName) c.header(headerName, reqId);
|
|
30
|
+
await next();
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { requestId as t };
|
package/lib/request-id.js
CHANGED
|
@@ -1,34 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Request ID Middleware for Acryl.
|
|
4
|
-
*
|
|
5
|
-
* @param {object} options - Options for Request ID middleware.
|
|
6
|
-
* @param {number} [options.limitLength=255] - The maximum length of request id.
|
|
7
|
-
* @param {string} [options.headerName=X-Request-Id] - The header name used in request id.
|
|
8
|
-
* @param {generator} [options.generator=() => crypto.randomUUID()] - The request id generation function.
|
|
9
|
-
*
|
|
10
|
-
* @returns {MiddlewareHandler} The middleware handler function.
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* type Variables = RequestIdVariables
|
|
15
|
-
* const app = new Acryl<{Variables: Variables}>()
|
|
16
|
-
*
|
|
17
|
-
* app.use(requestId())
|
|
18
|
-
* app.get('/', (c) => {
|
|
19
|
-
* console.log(c.get('requestId')) // Debug
|
|
20
|
-
* return c.text('Hello World!')
|
|
21
|
-
* })
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
const requestId = ({ limitLength = 255, headerName = "X-Request-Id", generator = () => crypto.randomUUID() } = {}) => {
|
|
25
|
-
return async function requestId(c, next) {
|
|
26
|
-
let reqId = headerName ? c.req.header(headerName) : void 0;
|
|
27
|
-
if (!reqId || reqId.length > limitLength || /[^\w\-=]/.test(reqId)) reqId = generator(c);
|
|
28
|
-
c.set("requestId", reqId);
|
|
29
|
-
if (headerName) c.header(headerName, reqId);
|
|
30
|
-
await next();
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
//#endregion
|
|
1
|
+
import { t as requestId } from "./request-id-CKVvHOO1.js";
|
|
34
2
|
export { requestId };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { encodeBase64 } from "./utils/encode.js";
|
|
2
|
+
//#region ../../plugins/acryl-router/src/core/middleware/secure-headers/secure-headers.ts
|
|
3
|
+
const HEADERS_MAP = {
|
|
4
|
+
crossOriginEmbedderPolicy: ["Cross-Origin-Embedder-Policy", "require-corp"],
|
|
5
|
+
crossOriginResourcePolicy: ["Cross-Origin-Resource-Policy", "same-origin"],
|
|
6
|
+
crossOriginOpenerPolicy: ["Cross-Origin-Opener-Policy", "same-origin"],
|
|
7
|
+
originAgentCluster: ["Origin-Agent-Cluster", "?1"],
|
|
8
|
+
referrerPolicy: ["Referrer-Policy", "no-referrer"],
|
|
9
|
+
strictTransportSecurity: ["Strict-Transport-Security", "max-age=15552000; includeSubDomains"],
|
|
10
|
+
xContentTypeOptions: ["X-Content-Type-Options", "nosniff"],
|
|
11
|
+
xDnsPrefetchControl: ["X-DNS-Prefetch-Control", "off"],
|
|
12
|
+
xDownloadOptions: ["X-Download-Options", "noopen"],
|
|
13
|
+
xFrameOptions: ["X-Frame-Options", "SAMEORIGIN"],
|
|
14
|
+
xPermittedCrossDomainPolicies: ["X-Permitted-Cross-Domain-Policies", "none"],
|
|
15
|
+
xXssProtection: ["X-XSS-Protection", "0"]
|
|
16
|
+
};
|
|
17
|
+
const DEFAULT_OPTIONS = {
|
|
18
|
+
crossOriginEmbedderPolicy: false,
|
|
19
|
+
crossOriginResourcePolicy: true,
|
|
20
|
+
crossOriginOpenerPolicy: true,
|
|
21
|
+
originAgentCluster: true,
|
|
22
|
+
referrerPolicy: true,
|
|
23
|
+
strictTransportSecurity: true,
|
|
24
|
+
xContentTypeOptions: true,
|
|
25
|
+
xDnsPrefetchControl: true,
|
|
26
|
+
xDownloadOptions: true,
|
|
27
|
+
xFrameOptions: true,
|
|
28
|
+
xPermittedCrossDomainPolicies: true,
|
|
29
|
+
xXssProtection: true,
|
|
30
|
+
removePoweredBy: true,
|
|
31
|
+
permissionsPolicy: {}
|
|
32
|
+
};
|
|
33
|
+
const generateNonce = () => {
|
|
34
|
+
const arrayBuffer = /* @__PURE__ */ new Uint8Array(16);
|
|
35
|
+
crypto.getRandomValues(arrayBuffer);
|
|
36
|
+
return encodeBase64(arrayBuffer.buffer);
|
|
37
|
+
};
|
|
38
|
+
const NONCE = (ctx) => {
|
|
39
|
+
const key = "secureHeadersNonce";
|
|
40
|
+
const init = ctx.get(key);
|
|
41
|
+
const nonce = init || generateNonce();
|
|
42
|
+
if (init == null) ctx.set(key, nonce);
|
|
43
|
+
return `'nonce-${nonce}'`;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Secure Headers Middleware for Acryl.
|
|
47
|
+
*
|
|
48
|
+
*
|
|
49
|
+
* @param {Partial<SecureHeadersOptions>} [customOptions] - The options for the secure headers middleware.
|
|
50
|
+
* @param {ContentSecurityPolicyOptions} [customOptions.contentSecurityPolicy] - Settings for the Content-Security-Policy header.
|
|
51
|
+
* @param {ContentSecurityPolicyOptions} [customOptions.contentSecurityPolicyReportOnly] - Settings for the Content-Security-Policy-Report-Only header.
|
|
52
|
+
* @param {overridableHeader} [customOptions.crossOriginEmbedderPolicy=false] - Settings for the Cross-Origin-Embedder-Policy header.
|
|
53
|
+
* @param {overridableHeader} [customOptions.crossOriginResourcePolicy=true] - Settings for the Cross-Origin-Resource-Policy header.
|
|
54
|
+
* @param {overridableHeader} [customOptions.crossOriginOpenerPolicy=true] - Settings for the Cross-Origin-Opener-Policy header.
|
|
55
|
+
* @param {overridableHeader} [customOptions.originAgentCluster=true] - Settings for the Origin-Agent-Cluster header.
|
|
56
|
+
* @param {overridableHeader} [customOptions.referrerPolicy=true] - Settings for the Referrer-Policy header.
|
|
57
|
+
* @param {ReportingEndpointOptions[]} [customOptions.reportingEndpoints] - Settings for the Reporting-Endpoints header.
|
|
58
|
+
* @param {ReportToOptions[]} [customOptions.reportTo] - Settings for the Report-To header.
|
|
59
|
+
* @param {overridableHeader} [customOptions.strictTransportSecurity=true] - Settings for the Strict-Transport-Security header.
|
|
60
|
+
* @param {overridableHeader} [customOptions.xContentTypeOptions=true] - Settings for the X-Content-Type-Options header.
|
|
61
|
+
* @param {overridableHeader} [customOptions.xDnsPrefetchControl=true] - Settings for the X-DNS-Prefetch-Control header.
|
|
62
|
+
* @param {overridableHeader} [customOptions.xDownloadOptions=true] - Settings for the X-Download-Options header.
|
|
63
|
+
* @param {overridableHeader} [customOptions.xFrameOptions=true] - Settings for the X-Frame-Options header.
|
|
64
|
+
* @param {overridableHeader} [customOptions.xPermittedCrossDomainPolicies=true] - Settings for the X-Permitted-Cross-Domain-Policies header.
|
|
65
|
+
* @param {overridableHeader} [customOptions.xXssProtection=true] - Settings for the X-XSS-Protection header.
|
|
66
|
+
* @param {boolean} [customOptions.removePoweredBy=true] - Settings for remove X-Powered-By header.
|
|
67
|
+
* @param {PermissionsPolicyOptions} [customOptions.permissionsPolicy] - Settings for the Permissions-Policy header.
|
|
68
|
+
* @returns {MiddlewareHandler} The middleware handler function.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* const app = new Acryl()
|
|
73
|
+
* app.use(secureHeaders())
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
const secureHeaders = (customOptions) => {
|
|
77
|
+
const options = {
|
|
78
|
+
...DEFAULT_OPTIONS,
|
|
79
|
+
...customOptions
|
|
80
|
+
};
|
|
81
|
+
const headersToSet = getFilteredHeaders(options);
|
|
82
|
+
const callbacks = [];
|
|
83
|
+
if (options.contentSecurityPolicy) {
|
|
84
|
+
const [callback, value] = getCSPDirectives(options.contentSecurityPolicy, "Content-Security-Policy");
|
|
85
|
+
if (callback) callbacks.push(callback);
|
|
86
|
+
headersToSet.push(["Content-Security-Policy", value]);
|
|
87
|
+
}
|
|
88
|
+
if (options.contentSecurityPolicyReportOnly) {
|
|
89
|
+
const [callback, value] = getCSPDirectives(options.contentSecurityPolicyReportOnly, "Content-Security-Policy-Report-Only");
|
|
90
|
+
if (callback) callbacks.push(callback);
|
|
91
|
+
headersToSet.push(["Content-Security-Policy-Report-Only", value]);
|
|
92
|
+
}
|
|
93
|
+
if (options.permissionsPolicy && Object.keys(options.permissionsPolicy).length > 0) headersToSet.push(["Permissions-Policy", getPermissionsPolicyDirectives(options.permissionsPolicy)]);
|
|
94
|
+
if (options.reportingEndpoints) headersToSet.push(["Reporting-Endpoints", getReportingEndpoints(options.reportingEndpoints)]);
|
|
95
|
+
if (options.reportTo) headersToSet.push(["Report-To", getReportToOptions(options.reportTo)]);
|
|
96
|
+
return async function secureHeaders(ctx, next) {
|
|
97
|
+
const headersToSetForReq = callbacks.length === 0 ? headersToSet : callbacks.reduce((acc, cb) => cb(ctx, acc), headersToSet);
|
|
98
|
+
await next();
|
|
99
|
+
setHeaders(ctx, headersToSetForReq);
|
|
100
|
+
if (options?.removePoweredBy) ctx.res.headers.delete("X-Powered-By");
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
function getFilteredHeaders(options) {
|
|
104
|
+
return Object.entries(HEADERS_MAP).filter(([key]) => options[key]).map(([key, defaultValue]) => {
|
|
105
|
+
const overrideValue = options[key];
|
|
106
|
+
return typeof overrideValue === "string" ? [defaultValue[0], overrideValue] : defaultValue;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function getCSPDirectives(contentSecurityPolicy, headerName) {
|
|
110
|
+
const callbacks = [];
|
|
111
|
+
const resultValues = [];
|
|
112
|
+
for (const [directive, value] of Object.entries(contentSecurityPolicy)) {
|
|
113
|
+
const valueArray = Array.isArray(value) ? value : [value];
|
|
114
|
+
valueArray.forEach((value, i) => {
|
|
115
|
+
if (typeof value === "function") {
|
|
116
|
+
const index = i * 2 + 2 + resultValues.length;
|
|
117
|
+
callbacks.push((ctx, values) => {
|
|
118
|
+
values[index] = value(ctx, directive);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
resultValues.push(directive.replace(/[A-Z]+(?![a-z])|[A-Z]/g, (match, offset) => offset ? "-" + match.toLowerCase() : match.toLowerCase()), ...valueArray.flatMap((value) => [" ", value]), "; ");
|
|
123
|
+
}
|
|
124
|
+
resultValues.pop();
|
|
125
|
+
return callbacks.length === 0 ? [void 0, resultValues.join("")] : [(ctx, headersToSet) => headersToSet.map((values) => {
|
|
126
|
+
if (values[0] === headerName) {
|
|
127
|
+
const clone = values[1].slice();
|
|
128
|
+
callbacks.forEach((cb) => {
|
|
129
|
+
cb(ctx, clone);
|
|
130
|
+
});
|
|
131
|
+
return [values[0], clone.join("")];
|
|
132
|
+
} else return values;
|
|
133
|
+
}), resultValues];
|
|
134
|
+
}
|
|
135
|
+
function getPermissionsPolicyDirectives(policy) {
|
|
136
|
+
return Object.entries(policy).map(([directive, value]) => {
|
|
137
|
+
const kebabDirective = camelToKebab(directive);
|
|
138
|
+
if (typeof value === "boolean") return `${kebabDirective}=${value ? "*" : "()"}`;
|
|
139
|
+
if (Array.isArray(value)) {
|
|
140
|
+
if (value.length === 0) return `${kebabDirective}=()`;
|
|
141
|
+
if (value.length === 1 && value[0] === "*") return `${kebabDirective}=*`;
|
|
142
|
+
if (value.length === 1 && value[0] === "none") return `${kebabDirective}=()`;
|
|
143
|
+
return `${kebabDirective}=(${value.map((item) => ["self", "src"].includes(item) ? item : `"${item}"`).join(" ")})`;
|
|
144
|
+
}
|
|
145
|
+
return "";
|
|
146
|
+
}).filter(Boolean).join(", ");
|
|
147
|
+
}
|
|
148
|
+
function camelToKebab(str) {
|
|
149
|
+
return str.replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
|
|
150
|
+
}
|
|
151
|
+
function getReportingEndpoints(reportingEndpoints = []) {
|
|
152
|
+
return reportingEndpoints.map((endpoint) => `${endpoint.name}="${endpoint.url}"`).join(", ");
|
|
153
|
+
}
|
|
154
|
+
function getReportToOptions(reportTo = []) {
|
|
155
|
+
return reportTo.map((option) => JSON.stringify(option)).join(", ");
|
|
156
|
+
}
|
|
157
|
+
function setHeaders(ctx, headersToSet) {
|
|
158
|
+
headersToSet.forEach(([header, value]) => {
|
|
159
|
+
ctx.res.headers.set(header, value);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
export { secureHeaders as n, NONCE as t };
|