@depup/miniflare 4.20260317.0-depup.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/README.md +31 -0
- package/bootstrap.js +11 -0
- package/changes.json +10 -0
- package/dist/local-explorer-ui/assets/Breadcrumbs-7hjI0sYt.js +1 -0
- package/dist/local-explorer-ui/assets/TableSelect-_bi6l6Iv.js +25 -0
- package/dist/local-explorer-ui/assets/_className-gSkjniQn.js +1 -0
- package/dist/local-explorer-ui/assets/_databaseId-DWcfgBis.js +1 -0
- package/dist/local-explorer-ui/assets/_namespaceId-8ViM8VDL.js +1 -0
- package/dist/local-explorer-ui/assets/_objectId-X6x-JUph.js +1 -0
- package/dist/local-explorer-ui/assets/dropdown-DFeFcKfn-BCd_NRZS.js +1 -0
- package/dist/local-explorer-ui/assets/index-BFNDwiew.js +42 -0
- package/dist/local-explorer-ui/assets/index-CLSFsgi0.js +1 -0
- package/dist/local-explorer-ui/assets/index-KG4JeHCX.js +1 -0
- package/dist/local-explorer-ui/assets/index-mgoUmSld.css +1 -0
- package/dist/local-explorer-ui/assets/table-BUmvaBj8-v-EIZgOz.js +1 -0
- package/dist/local-explorer-ui/favicon.svg +3 -0
- package/dist/local-explorer-ui/index.html +14 -0
- package/dist/src/index.d.ts +8703 -0
- package/dist/src/index.js +83666 -0
- package/dist/src/index.js.map +6 -0
- package/dist/src/shared/dev-registry.worker.js +69801 -0
- package/dist/src/shared/dev-registry.worker.js.map +6 -0
- package/dist/src/workers/analytics-engine/analytics-engine.worker.js +15 -0
- package/dist/src/workers/analytics-engine/analytics-engine.worker.js.map +6 -0
- package/dist/src/workers/assets/assets-kv.worker.js +28 -0
- package/dist/src/workers/assets/assets-kv.worker.js.map +6 -0
- package/dist/src/workers/assets/assets.worker.js +9014 -0
- package/dist/src/workers/assets/assets.worker.js.map +6 -0
- package/dist/src/workers/assets/router.worker.js +9625 -0
- package/dist/src/workers/assets/router.worker.js.map +6 -0
- package/dist/src/workers/assets/rpc-proxy.worker.js +29 -0
- package/dist/src/workers/assets/rpc-proxy.worker.js.map +6 -0
- package/dist/src/workers/browser-rendering/binding.worker.js +129 -0
- package/dist/src/workers/browser-rendering/binding.worker.js.map +6 -0
- package/dist/src/workers/cache/cache-entry-noop.worker.js +19 -0
- package/dist/src/workers/cache/cache-entry-noop.worker.js.map +6 -0
- package/dist/src/workers/cache/cache-entry.worker.js +28 -0
- package/dist/src/workers/cache/cache-entry.worker.js.map +6 -0
- package/dist/src/workers/cache/cache.worker.js +653 -0
- package/dist/src/workers/cache/cache.worker.js.map +6 -0
- package/dist/src/workers/core/do-wrapper.worker.js +43 -0
- package/dist/src/workers/core/do-wrapper.worker.js.map +6 -0
- package/dist/src/workers/core/entry.worker.js +4633 -0
- package/dist/src/workers/core/entry.worker.js.map +6 -0
- package/dist/src/workers/core/strip-cf-connecting-ip.worker.js +11 -0
- package/dist/src/workers/core/strip-cf-connecting-ip.worker.js.map +6 -0
- package/dist/src/workers/d1/database.worker.js +219 -0
- package/dist/src/workers/d1/database.worker.js.map +6 -0
- package/dist/src/workers/dispatch-namespace/dispatch-namespace-proxy.worker.js +2271 -0
- package/dist/src/workers/dispatch-namespace/dispatch-namespace-proxy.worker.js.map +6 -0
- package/dist/src/workers/dispatch-namespace/dispatch-namespace.worker.js +12 -0
- package/dist/src/workers/dispatch-namespace/dispatch-namespace.worker.js.map +6 -0
- package/dist/src/workers/email/email.worker.js +23 -0
- package/dist/src/workers/email/email.worker.js.map +6 -0
- package/dist/src/workers/email/send_email.worker.js +3294 -0
- package/dist/src/workers/email/send_email.worker.js.map +6 -0
- package/dist/src/workers/hello-world/binding.worker.js +19 -0
- package/dist/src/workers/hello-world/binding.worker.js.map +6 -0
- package/dist/src/workers/hello-world/object.worker.js +14 -0
- package/dist/src/workers/hello-world/object.worker.js.map +6 -0
- package/dist/src/workers/images/images.worker.js +155 -0
- package/dist/src/workers/images/images.worker.js.map +6 -0
- package/dist/src/workers/kv/namespace.worker.js +322 -0
- package/dist/src/workers/kv/namespace.worker.js.map +6 -0
- package/dist/src/workers/kv/sites.worker.js +146 -0
- package/dist/src/workers/kv/sites.worker.js.map +6 -0
- package/dist/src/workers/local-explorer/explorer.worker.js +5245 -0
- package/dist/src/workers/local-explorer/explorer.worker.js.map +6 -0
- package/dist/src/workers/pipelines/pipeline.worker.js +10 -0
- package/dist/src/workers/pipelines/pipeline.worker.js.map +6 -0
- package/dist/src/workers/queues/broker.worker.js +289 -0
- package/dist/src/workers/queues/broker.worker.js.map +6 -0
- package/dist/src/workers/r2/bucket.worker.js +1134 -0
- package/dist/src/workers/r2/bucket.worker.js.map +6 -0
- package/dist/src/workers/ratelimit/ratelimit.worker.js +54 -0
- package/dist/src/workers/ratelimit/ratelimit.worker.js.map +6 -0
- package/dist/src/workers/secrets-store/secret.worker.js +65 -0
- package/dist/src/workers/secrets-store/secret.worker.js.map +6 -0
- package/dist/src/workers/shared/index.worker.js +693 -0
- package/dist/src/workers/shared/index.worker.js.map +6 -0
- package/dist/src/workers/shared/object-entry.worker.js +21 -0
- package/dist/src/workers/shared/object-entry.worker.js.map +6 -0
- package/dist/src/workers/shared/remote-proxy-client.worker.js +2271 -0
- package/dist/src/workers/shared/remote-proxy-client.worker.js.map +6 -0
- package/dist/src/workers/shared/zod.worker.js +2954 -0
- package/dist/src/workers/shared/zod.worker.js.map +6 -0
- package/dist/src/workers/workflows/binding.worker.js +2422 -0
- package/dist/src/workers/workflows/binding.worker.js.map +6 -0
- package/dist/src/workers/workflows/wrapped-binding.worker.js +71 -0
- package/dist/src/workers/workflows/wrapped-binding.worker.js.map +6 -0
- package/package.json +139 -0
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
// src/workers/shared/blob.worker.ts
|
|
2
|
+
import assert from "node-internal:internal_assert";
|
|
3
|
+
import { Buffer as Buffer2 } from "node-internal:internal_buffer";
|
|
4
|
+
|
|
5
|
+
// src/workers/shared/data.ts
|
|
6
|
+
import { Buffer } from "node-internal:internal_buffer";
|
|
7
|
+
function viewToBuffer(view) {
|
|
8
|
+
return view.buffer.slice(
|
|
9
|
+
view.byteOffset,
|
|
10
|
+
view.byteOffset + view.byteLength
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
function base64Encode(value) {
|
|
14
|
+
return Buffer.from(value, "utf8").toString("base64");
|
|
15
|
+
}
|
|
16
|
+
function base64Decode(encoded) {
|
|
17
|
+
return Buffer.from(encoded, "base64").toString("utf8");
|
|
18
|
+
}
|
|
19
|
+
var dotRegexp = /(^|\/|\\)(\.+)(\/|\\|$)/g, illegalRegexp = /[?<>*"'^/\\:|\x00-\x1f\x80-\x9f]/g, windowsReservedRegexp = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i, leadingRegexp = /^[ /\\]+/, trailingRegexp = /[ /\\]+$/;
|
|
20
|
+
function dotReplacement(match, g1, g2, g3) {
|
|
21
|
+
return `${g1}${"".padStart(g2.length, "_")}${g3}`;
|
|
22
|
+
}
|
|
23
|
+
function underscoreReplacement(match) {
|
|
24
|
+
return "".padStart(match.length, "_");
|
|
25
|
+
}
|
|
26
|
+
function sanitisePath(unsafe) {
|
|
27
|
+
return unsafe.replace(dotRegexp, dotReplacement).replace(dotRegexp, dotReplacement).replace(illegalRegexp, "_").replace(windowsReservedRegexp, "_").replace(leadingRegexp, underscoreReplacement).replace(trailingRegexp, underscoreReplacement).substring(0, 255);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/workers/shared/blob.worker.ts
|
|
31
|
+
var ENCODER = new TextEncoder();
|
|
32
|
+
async function readPrefix(stream, prefixLength) {
|
|
33
|
+
let reader = await stream.getReader({ mode: "byob" }), result = await reader.readAtLeast(
|
|
34
|
+
prefixLength,
|
|
35
|
+
new Uint8Array(prefixLength)
|
|
36
|
+
);
|
|
37
|
+
assert(result.value !== void 0), reader.releaseLock();
|
|
38
|
+
let rest = stream.pipeThrough(new IdentityTransformStream());
|
|
39
|
+
return [result.value, rest];
|
|
40
|
+
}
|
|
41
|
+
function rangeHeaders(range) {
|
|
42
|
+
return { Range: `bytes=${range.start}-${range.end}` };
|
|
43
|
+
}
|
|
44
|
+
function assertFullRangeRequest(range, contentLength) {
|
|
45
|
+
assert(
|
|
46
|
+
range.start === 0 && range.end === contentLength - 1,
|
|
47
|
+
"Received full content, but requested partial content"
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
async function fetchSingleRange(fetcher, url, range) {
|
|
51
|
+
let headers = range === void 0 ? {} : rangeHeaders(range), res = await fetcher.fetch(url, { headers });
|
|
52
|
+
if (res.status === 404) return null;
|
|
53
|
+
if (assert(res.ok && res.body !== null), range !== void 0 && res.status !== 206) {
|
|
54
|
+
let contentLength = parseInt(res.headers.get("Content-Length"));
|
|
55
|
+
assert(!Number.isNaN(contentLength)), assertFullRangeRequest(range, contentLength);
|
|
56
|
+
}
|
|
57
|
+
return res.body;
|
|
58
|
+
}
|
|
59
|
+
async function writeMultipleRanges(fetcher, url, ranges, boundary, writable, contentLength, contentType) {
|
|
60
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
61
|
+
let range = ranges[i], writer2 = writable.getWriter();
|
|
62
|
+
i > 0 && await writer2.write(ENCODER.encode(`\r
|
|
63
|
+
`)), await writer2.write(ENCODER.encode(`--${boundary}\r
|
|
64
|
+
`)), contentType !== void 0 && await writer2.write(ENCODER.encode(`Content-Type: ${contentType}\r
|
|
65
|
+
`));
|
|
66
|
+
let start = range.start, end = Math.min(range.end, contentLength - 1);
|
|
67
|
+
await writer2.write(
|
|
68
|
+
ENCODER.encode(
|
|
69
|
+
`Content-Range: bytes ${start}-${end}/${contentLength}\r
|
|
70
|
+
\r
|
|
71
|
+
`
|
|
72
|
+
)
|
|
73
|
+
), writer2.releaseLock();
|
|
74
|
+
let res = await fetcher.fetch(url, { headers: rangeHeaders(range) });
|
|
75
|
+
assert(
|
|
76
|
+
res.ok && res.body !== null,
|
|
77
|
+
`Failed to fetch ${url}[${range.start},${range.end}], received ${res.status} ${res.statusText}`
|
|
78
|
+
), res.status !== 206 && assertFullRangeRequest(range, contentLength), await res.body.pipeTo(writable, { preventClose: !0 });
|
|
79
|
+
}
|
|
80
|
+
let writer = writable.getWriter();
|
|
81
|
+
ranges.length > 0 && await writer.write(ENCODER.encode(`\r
|
|
82
|
+
`)), await writer.write(ENCODER.encode(`--${boundary}--`)), await writer.close();
|
|
83
|
+
}
|
|
84
|
+
async function fetchMultipleRanges(fetcher, url, ranges, opts) {
|
|
85
|
+
let res = await fetcher.fetch(url, { method: "HEAD" });
|
|
86
|
+
if (res.status === 404) return null;
|
|
87
|
+
assert(res.ok);
|
|
88
|
+
let contentLength = parseInt(res.headers.get("Content-Length"));
|
|
89
|
+
assert(!Number.isNaN(contentLength));
|
|
90
|
+
let boundary = `miniflare-boundary-${crypto.randomUUID()}`, multipartContentType = `multipart/byteranges; boundary=${boundary}`, { readable, writable } = new IdentityTransformStream();
|
|
91
|
+
return writeMultipleRanges(
|
|
92
|
+
fetcher,
|
|
93
|
+
url,
|
|
94
|
+
ranges,
|
|
95
|
+
boundary,
|
|
96
|
+
writable,
|
|
97
|
+
contentLength,
|
|
98
|
+
opts?.contentType
|
|
99
|
+
).catch((e) => console.error("Error writing multipart stream:", e)), { multipartContentType, body: readable };
|
|
100
|
+
}
|
|
101
|
+
async function fetchRange(fetcher, url, range, opts) {
|
|
102
|
+
return Array.isArray(range) ? fetchMultipleRanges(fetcher, url, range, opts) : fetchSingleRange(fetcher, url, range);
|
|
103
|
+
}
|
|
104
|
+
function generateBlobId() {
|
|
105
|
+
let idBuffer = Buffer2.alloc(40);
|
|
106
|
+
return crypto.getRandomValues(
|
|
107
|
+
new Uint8Array(idBuffer.buffer, idBuffer.byteOffset, 32)
|
|
108
|
+
), idBuffer.writeBigInt64BE(
|
|
109
|
+
BigInt(performance.timeOrigin + performance.now()),
|
|
110
|
+
32
|
|
111
|
+
), idBuffer.toString("hex");
|
|
112
|
+
}
|
|
113
|
+
var BlobStore = class {
|
|
114
|
+
// Database for binary large objects. Provides single and multi-ranged
|
|
115
|
+
// streaming reads and writes.
|
|
116
|
+
//
|
|
117
|
+
// Blobs have unguessable identifiers, can be deleted, but are otherwise
|
|
118
|
+
// immutable. These properties make it possible to perform atomic updates with
|
|
119
|
+
// the SQLite metadata store. No other operations will be able to interact
|
|
120
|
+
// with the blob until it's committed to the metadata store, because they
|
|
121
|
+
// won't be able to guess the ID, and we don't allow listing blobs.
|
|
122
|
+
//
|
|
123
|
+
// For example, if we put a blob in the store, then fail to insert the blob ID
|
|
124
|
+
// into the SQLite database for some reason during a transaction (e.g.
|
|
125
|
+
// `onlyIf` condition failed), no other operations can read that blob because
|
|
126
|
+
// the ID is lost (we'll just background-delete the blob in this case).
|
|
127
|
+
#fetcher;
|
|
128
|
+
#baseURL;
|
|
129
|
+
#stickyBlobs;
|
|
130
|
+
constructor(fetcher, namespace, stickyBlobs) {
|
|
131
|
+
namespace = encodeURIComponent(sanitisePath(namespace)), this.#fetcher = fetcher, this.#baseURL = `http://placeholder/${namespace}/blobs/`, this.#stickyBlobs = stickyBlobs;
|
|
132
|
+
}
|
|
133
|
+
idURL(id) {
|
|
134
|
+
let url = new URL(this.#baseURL + id);
|
|
135
|
+
return url.toString().startsWith(this.#baseURL) ? url : null;
|
|
136
|
+
}
|
|
137
|
+
async get(id, range, opts) {
|
|
138
|
+
let idURL = this.idURL(id);
|
|
139
|
+
return idURL === null ? null : fetchRange(this.#fetcher, idURL, range, opts);
|
|
140
|
+
}
|
|
141
|
+
async put(stream) {
|
|
142
|
+
let id = generateBlobId(), idURL = this.idURL(id);
|
|
143
|
+
return assert(idURL !== null), await this.#fetcher.fetch(idURL, {
|
|
144
|
+
method: "PUT",
|
|
145
|
+
body: stream
|
|
146
|
+
}), id;
|
|
147
|
+
}
|
|
148
|
+
async delete(id) {
|
|
149
|
+
if (this.#stickyBlobs) return;
|
|
150
|
+
let idURL = this.idURL(id);
|
|
151
|
+
if (idURL === null) return;
|
|
152
|
+
let res = await this.#fetcher.fetch(idURL, { method: "DELETE" });
|
|
153
|
+
assert(res.ok || res.status === 404);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// src/workers/shared/constants.ts
|
|
158
|
+
var SharedHeaders = {
|
|
159
|
+
LOG_LEVEL: "MF-Log-Level"
|
|
160
|
+
}, SharedBindings = {
|
|
161
|
+
TEXT_NAMESPACE: "MINIFLARE_NAMESPACE",
|
|
162
|
+
DURABLE_OBJECT_NAMESPACE_OBJECT: "MINIFLARE_OBJECT",
|
|
163
|
+
MAYBE_SERVICE_BLOBS: "MINIFLARE_BLOBS",
|
|
164
|
+
MAYBE_SERVICE_LOOPBACK: "MINIFLARE_LOOPBACK",
|
|
165
|
+
MAYBE_JSON_ENABLE_CONTROL_ENDPOINTS: "MINIFLARE_ENABLE_CONTROL_ENDPOINTS",
|
|
166
|
+
MAYBE_JSON_ENABLE_STICKY_BLOBS: "MINIFLARE_STICKY_BLOBS"
|
|
167
|
+
}, LogLevel = /* @__PURE__ */ ((LogLevel3) => (LogLevel3[LogLevel3.NONE = 0] = "NONE", LogLevel3[LogLevel3.ERROR = 1] = "ERROR", LogLevel3[LogLevel3.WARN = 2] = "WARN", LogLevel3[LogLevel3.INFO = 3] = "INFO", LogLevel3[LogLevel3.DEBUG = 4] = "DEBUG", LogLevel3[LogLevel3.VERBOSE = 5] = "VERBOSE", LogLevel3))(LogLevel || {});
|
|
168
|
+
|
|
169
|
+
// src/workers/shared/keyvalue.worker.ts
|
|
170
|
+
import assert3 from "node-internal:internal_assert";
|
|
171
|
+
|
|
172
|
+
// src/workers/shared/sql.worker.ts
|
|
173
|
+
import assert2 from "node-internal:internal_assert";
|
|
174
|
+
function isTypedValue(value) {
|
|
175
|
+
return value === null || typeof value == "string" || typeof value == "number" || value instanceof ArrayBuffer;
|
|
176
|
+
}
|
|
177
|
+
function createStatementFactory(sql) {
|
|
178
|
+
return (query) => {
|
|
179
|
+
let keyIndices = /* @__PURE__ */ new Map();
|
|
180
|
+
query = query.replace(/[:@$]([a-z0-9_]+)/gi, (_, name) => {
|
|
181
|
+
let index = keyIndices.get(name);
|
|
182
|
+
return index === void 0 && (index = keyIndices.size, keyIndices.set(name, index)), `?${index + 1}`;
|
|
183
|
+
});
|
|
184
|
+
let stmt = sql.prepare(query);
|
|
185
|
+
return (argsObject) => {
|
|
186
|
+
let entries = Object.entries(argsObject);
|
|
187
|
+
assert2.strictEqual(
|
|
188
|
+
entries.length,
|
|
189
|
+
keyIndices.size,
|
|
190
|
+
"Expected same number of keys in bindings and query"
|
|
191
|
+
);
|
|
192
|
+
let argsArray = new Array(entries.length);
|
|
193
|
+
for (let [key, value] of entries) {
|
|
194
|
+
let index = keyIndices.get(key);
|
|
195
|
+
assert2(index !== void 0, `Unexpected binding key: ${key}`), argsArray[index] = value;
|
|
196
|
+
}
|
|
197
|
+
return stmt(...argsArray);
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function createTransactionFactory(storage) {
|
|
202
|
+
return (closure) => (...args) => storage.transactionSync(() => closure(...args));
|
|
203
|
+
}
|
|
204
|
+
function createTypedSql(storage) {
|
|
205
|
+
let sql = storage.sql;
|
|
206
|
+
return sql.stmt = createStatementFactory(sql), sql.txn = createTransactionFactory(storage), sql;
|
|
207
|
+
}
|
|
208
|
+
function get(cursor) {
|
|
209
|
+
let result;
|
|
210
|
+
for (let row of cursor) result ??= row;
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
function all(cursor) {
|
|
214
|
+
return Array.from(cursor);
|
|
215
|
+
}
|
|
216
|
+
function drain(cursor) {
|
|
217
|
+
for (let _ of cursor)
|
|
218
|
+
;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/workers/shared/keyvalue.worker.ts
|
|
222
|
+
var SQL_SCHEMA = `
|
|
223
|
+
CREATE TABLE IF NOT EXISTS _mf_entries (
|
|
224
|
+
key TEXT PRIMARY KEY,
|
|
225
|
+
blob_id TEXT NOT NULL,
|
|
226
|
+
expiration INTEGER,
|
|
227
|
+
metadata TEXT
|
|
228
|
+
);
|
|
229
|
+
CREATE INDEX IF NOT EXISTS _mf_entries_expiration_idx ON _mf_entries(expiration);
|
|
230
|
+
`;
|
|
231
|
+
function sqlStmts(db) {
|
|
232
|
+
let stmtGetBlobIdByKey = db.stmt(
|
|
233
|
+
"SELECT blob_id FROM _mf_entries WHERE key = :key"
|
|
234
|
+
), stmtPut = db.stmt(
|
|
235
|
+
`INSERT OR REPLACE INTO _mf_entries (key, blob_id, expiration, metadata)
|
|
236
|
+
VALUES (:key, :blob_id, :expiration, :metadata)`
|
|
237
|
+
);
|
|
238
|
+
return {
|
|
239
|
+
db,
|
|
240
|
+
getByKey: db.prepare(
|
|
241
|
+
"SELECT key, blob_id, expiration, metadata FROM _mf_entries WHERE key = ?1"
|
|
242
|
+
),
|
|
243
|
+
put: db.txn((newEntry) => {
|
|
244
|
+
let key = newEntry.key, previousEntry = get(stmtGetBlobIdByKey({ key }));
|
|
245
|
+
return stmtPut(newEntry), previousEntry?.blob_id;
|
|
246
|
+
}),
|
|
247
|
+
deleteByKey: db.stmt(
|
|
248
|
+
"DELETE FROM _mf_entries WHERE key = :key RETURNING blob_id, expiration"
|
|
249
|
+
),
|
|
250
|
+
deleteExpired: db.stmt(
|
|
251
|
+
// `expiration` may be `NULL`, but `NULL < ...` should be falsy
|
|
252
|
+
"DELETE FROM _mf_entries WHERE expiration < :now RETURNING blob_id"
|
|
253
|
+
),
|
|
254
|
+
deleteAll: db.prepare(
|
|
255
|
+
"DELETE FROM _mf_entries RETURNING blob_id"
|
|
256
|
+
),
|
|
257
|
+
list: db.stmt(
|
|
258
|
+
`SELECT key, expiration, metadata FROM _mf_entries
|
|
259
|
+
WHERE substr(key, 1, length(:prefix)) = :prefix
|
|
260
|
+
AND key > :start_after
|
|
261
|
+
AND (expiration IS NULL OR expiration >= :now)
|
|
262
|
+
ORDER BY key LIMIT :limit`
|
|
263
|
+
)
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function rowEntry(entry) {
|
|
267
|
+
return {
|
|
268
|
+
key: entry.key,
|
|
269
|
+
expiration: entry.expiration ?? void 0,
|
|
270
|
+
metadata: entry.metadata === null ? void 0 : JSON.parse(entry.metadata)
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
var KeyValueStorage = class {
|
|
274
|
+
#stmts;
|
|
275
|
+
#blob;
|
|
276
|
+
#timers;
|
|
277
|
+
constructor(object) {
|
|
278
|
+
object.db.exec("PRAGMA case_sensitive_like = TRUE"), object.db.exec(SQL_SCHEMA), this.#stmts = sqlStmts(object.db), this.#blob = object.blob, this.#timers = object.timers;
|
|
279
|
+
}
|
|
280
|
+
#hasExpired(entry) {
|
|
281
|
+
return entry.expiration !== null && entry.expiration <= this.#timers.now();
|
|
282
|
+
}
|
|
283
|
+
#backgroundDelete(blobId) {
|
|
284
|
+
this.#timers.queueMicrotask(
|
|
285
|
+
() => this.#blob.delete(blobId).catch(() => {
|
|
286
|
+
})
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
async get(key, optsFactory) {
|
|
290
|
+
let row = get(this.#stmts.getByKey(key));
|
|
291
|
+
if (row === void 0) return null;
|
|
292
|
+
if (this.#hasExpired(row))
|
|
293
|
+
return drain(this.#stmts.deleteByKey({ key })), this.#backgroundDelete(row.blob_id), null;
|
|
294
|
+
let entry = rowEntry(row), opts = entry.metadata && optsFactory?.(entry.metadata);
|
|
295
|
+
if (opts?.ranges === void 0 || opts.ranges.length <= 1) {
|
|
296
|
+
let value = await this.#blob.get(row.blob_id, opts?.ranges?.[0]);
|
|
297
|
+
return value === null ? null : { ...entry, value };
|
|
298
|
+
} else {
|
|
299
|
+
let value = await this.#blob.get(row.blob_id, opts.ranges, opts);
|
|
300
|
+
return value === null ? null : { ...entry, value };
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
async put(entry) {
|
|
304
|
+
assert3(entry.key !== "");
|
|
305
|
+
let blobId = await this.#blob.put(entry.value);
|
|
306
|
+
entry.signal?.aborted && (this.#backgroundDelete(blobId), entry.signal.throwIfAborted());
|
|
307
|
+
let maybeOldBlobId = this.#stmts.put({
|
|
308
|
+
key: entry.key,
|
|
309
|
+
blob_id: blobId,
|
|
310
|
+
expiration: entry.expiration ?? null,
|
|
311
|
+
metadata: entry.metadata === void 0 ? null : JSON.stringify(await entry.metadata)
|
|
312
|
+
});
|
|
313
|
+
maybeOldBlobId !== void 0 && this.#backgroundDelete(maybeOldBlobId);
|
|
314
|
+
}
|
|
315
|
+
async delete(key) {
|
|
316
|
+
let cursor = this.#stmts.deleteByKey({ key }), row = get(cursor);
|
|
317
|
+
return row === void 0 ? !1 : (this.#backgroundDelete(row.blob_id), !this.#hasExpired(row));
|
|
318
|
+
}
|
|
319
|
+
deleteAll() {
|
|
320
|
+
let rows = all(this.#stmts.deleteAll());
|
|
321
|
+
for (let { blob_id } of rows)
|
|
322
|
+
this.#backgroundDelete(blob_id);
|
|
323
|
+
return rows.length;
|
|
324
|
+
}
|
|
325
|
+
async list(opts) {
|
|
326
|
+
let now = this.#timers.now(), prefix = opts.prefix ?? "", start_after = opts.cursor === void 0 ? "" : base64Decode(opts.cursor), limit = opts.limit + 1, rowsCursor = this.#stmts.list({
|
|
327
|
+
now,
|
|
328
|
+
prefix,
|
|
329
|
+
start_after,
|
|
330
|
+
limit
|
|
331
|
+
}), rows = Array.from(rowsCursor), expiredRows = this.#stmts.deleteExpired({ now });
|
|
332
|
+
for (let row of expiredRows) this.#backgroundDelete(row.blob_id);
|
|
333
|
+
let hasMoreRows = rows.length === opts.limit + 1;
|
|
334
|
+
rows.splice(opts.limit, 1);
|
|
335
|
+
let keys = rows.map((row) => rowEntry(row)), nextCursor = hasMoreRows ? base64Encode(rows[opts.limit - 1].key) : void 0;
|
|
336
|
+
return { keys, cursor: nextCursor };
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// src/workers/shared/matcher.ts
|
|
341
|
+
function testRegExps(matcher, value) {
|
|
342
|
+
for (let exclude of matcher.exclude) if (exclude.test(value)) return !1;
|
|
343
|
+
for (let include of matcher.include) if (include.test(value)) return !0;
|
|
344
|
+
return !1;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/workers/shared/object.worker.ts
|
|
348
|
+
import assert5 from "node-internal:internal_assert";
|
|
349
|
+
|
|
350
|
+
// src/workers/shared/router.worker.ts
|
|
351
|
+
var HttpError = class extends Error {
|
|
352
|
+
constructor(code, message) {
|
|
353
|
+
super(message);
|
|
354
|
+
this.code = code;
|
|
355
|
+
Object.setPrototypeOf(this, new.target.prototype), this.name = `${new.target.name} [${code}]`;
|
|
356
|
+
}
|
|
357
|
+
toResponse() {
|
|
358
|
+
return new Response(this.message, {
|
|
359
|
+
status: this.code,
|
|
360
|
+
// Custom statusMessage is required for runtime error messages
|
|
361
|
+
statusText: this.message.substring(0, 512)
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}, kRoutesTemplate = /* @__PURE__ */ Symbol("kRoutesTemplate"), Router = class {
|
|
365
|
+
// Routes added by @METHOD decorators
|
|
366
|
+
#routes;
|
|
367
|
+
constructor() {
|
|
368
|
+
this.#routes = new.target.prototype[kRoutesTemplate];
|
|
369
|
+
}
|
|
370
|
+
async fetch(req) {
|
|
371
|
+
let url = new URL(req.url), methodRoutes = this.#routes?.get(req.method);
|
|
372
|
+
if (methodRoutes === void 0) return new Response(null, { status: 405 });
|
|
373
|
+
let handlers = this;
|
|
374
|
+
try {
|
|
375
|
+
for (let [path, key] of methodRoutes) {
|
|
376
|
+
let match = path.exec(url.pathname);
|
|
377
|
+
if (match !== null) return await handlers[key](req, match.groups, url);
|
|
378
|
+
}
|
|
379
|
+
return new Response(null, { status: 404 });
|
|
380
|
+
} catch (e) {
|
|
381
|
+
if (e instanceof HttpError)
|
|
382
|
+
return e.toResponse();
|
|
383
|
+
throw e;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
function pathToRegexp(path) {
|
|
388
|
+
return path === void 0 ? /^.*$/ : (path.endsWith("/") || (path += "/?"), path = path.replace(/\//g, "\\/"), path = path.replace(/:(\w+)/g, "(?<$1>[^\\/]+)"), new RegExp(`^${path}$`));
|
|
389
|
+
}
|
|
390
|
+
var createRouteDecorator = (method) => (path) => (prototype, key) => {
|
|
391
|
+
let route = [pathToRegexp(path), key], routes = prototype[kRoutesTemplate] ??= /* @__PURE__ */ new Map(), methodRoutes = routes.get(method);
|
|
392
|
+
methodRoutes ? methodRoutes.push(route) : routes.set(method, [route]);
|
|
393
|
+
}, GET = createRouteDecorator("GET"), HEAD = createRouteDecorator("HEAD"), POST = createRouteDecorator("POST"), PUT = createRouteDecorator("PUT"), DELETE = createRouteDecorator("DELETE"), PURGE = createRouteDecorator("PURGE"), PATCH = createRouteDecorator("PATCH");
|
|
394
|
+
|
|
395
|
+
// src/workers/shared/timers.worker.ts
|
|
396
|
+
import assert4 from "node-internal:internal_assert";
|
|
397
|
+
var kFakeTimerHandle = /* @__PURE__ */ Symbol("kFakeTimerHandle"), Timers = class {
|
|
398
|
+
// Fake unix time in milliseconds. If defined, fake timers will be enabled.
|
|
399
|
+
#fakeTimestamp;
|
|
400
|
+
#fakeNextTimerHandle = 0;
|
|
401
|
+
#fakePendingTimeouts = /* @__PURE__ */ new Map();
|
|
402
|
+
#fakeRunningTasks = /* @__PURE__ */ new Set();
|
|
403
|
+
// Timers API
|
|
404
|
+
now = () => this.#fakeTimestamp ?? Date.now();
|
|
405
|
+
setTimeout(closure, delay, ...args) {
|
|
406
|
+
if (this.#fakeTimestamp === void 0)
|
|
407
|
+
return setTimeout(closure, delay, ...args);
|
|
408
|
+
let handle = this.#fakeNextTimerHandle++, argsClosure = () => closure(...args);
|
|
409
|
+
if (delay === 0)
|
|
410
|
+
this.queueMicrotask(argsClosure);
|
|
411
|
+
else {
|
|
412
|
+
let timeout = {
|
|
413
|
+
triggerTimestamp: this.#fakeTimestamp + delay,
|
|
414
|
+
closure: argsClosure
|
|
415
|
+
};
|
|
416
|
+
this.#fakePendingTimeouts.set(handle, timeout);
|
|
417
|
+
}
|
|
418
|
+
return { [kFakeTimerHandle]: handle };
|
|
419
|
+
}
|
|
420
|
+
clearTimeout(handle) {
|
|
421
|
+
if (typeof handle == "number") return clearTimeout(handle);
|
|
422
|
+
this.#fakePendingTimeouts.delete(handle[kFakeTimerHandle]);
|
|
423
|
+
}
|
|
424
|
+
queueMicrotask(closure) {
|
|
425
|
+
if (this.#fakeTimestamp === void 0) return queueMicrotask(closure);
|
|
426
|
+
let result = closure();
|
|
427
|
+
result instanceof Promise && (this.#fakeRunningTasks.add(result), result.finally(() => this.#fakeRunningTasks.delete(result)));
|
|
428
|
+
}
|
|
429
|
+
// Fake Timers Control API
|
|
430
|
+
#runPendingTimeouts() {
|
|
431
|
+
if (this.#fakeTimestamp !== void 0)
|
|
432
|
+
for (let [handle, timeout] of this.#fakePendingTimeouts)
|
|
433
|
+
timeout.triggerTimestamp <= this.#fakeTimestamp && (this.#fakePendingTimeouts.delete(handle), this.queueMicrotask(timeout.closure));
|
|
434
|
+
}
|
|
435
|
+
enableFakeTimers(timestamp) {
|
|
436
|
+
this.#fakeTimestamp = timestamp, this.#runPendingTimeouts();
|
|
437
|
+
}
|
|
438
|
+
disableFakeTimers() {
|
|
439
|
+
this.#fakeTimestamp = void 0, this.#fakePendingTimeouts.clear();
|
|
440
|
+
}
|
|
441
|
+
advanceFakeTime(delta) {
|
|
442
|
+
assert4(
|
|
443
|
+
this.#fakeTimestamp !== void 0,
|
|
444
|
+
"Expected fake timers to be enabled before `advanceFakeTime()` call"
|
|
445
|
+
), this.#fakeTimestamp += delta, this.#runPendingTimeouts();
|
|
446
|
+
}
|
|
447
|
+
async waitForFakeTasks() {
|
|
448
|
+
for (; this.#fakeRunningTasks.size > 0; )
|
|
449
|
+
await Promise.all(this.#fakeRunningTasks);
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
// src/workers/shared/types.ts
|
|
454
|
+
function reduceError(e) {
|
|
455
|
+
return {
|
|
456
|
+
name: e?.name,
|
|
457
|
+
message: e?.message ?? String(e),
|
|
458
|
+
stack: e?.stack,
|
|
459
|
+
cause: e?.cause === void 0 ? void 0 : reduceError(e.cause)
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function maybeApply(f, maybeValue) {
|
|
463
|
+
return maybeValue === void 0 ? void 0 : f(maybeValue);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/workers/shared/object.worker.ts
|
|
467
|
+
var MiniflareDurableObject = class extends Router {
|
|
468
|
+
constructor(state, env) {
|
|
469
|
+
super();
|
|
470
|
+
this.state = state;
|
|
471
|
+
this.env = env;
|
|
472
|
+
}
|
|
473
|
+
timers = new Timers();
|
|
474
|
+
// If this Durable Object receives a control op, assume it's being tested.
|
|
475
|
+
// We use this to adjust some limits in tests.
|
|
476
|
+
beingTested = !1;
|
|
477
|
+
#db;
|
|
478
|
+
get db() {
|
|
479
|
+
return this.#db ??= createTypedSql(this.state.storage);
|
|
480
|
+
}
|
|
481
|
+
#name;
|
|
482
|
+
get name() {
|
|
483
|
+
return assert5(
|
|
484
|
+
this.#name !== void 0,
|
|
485
|
+
"Expected `MiniflareDurableObject#fetch()` call before `name` access"
|
|
486
|
+
), this.#name;
|
|
487
|
+
}
|
|
488
|
+
#blob;
|
|
489
|
+
get blob() {
|
|
490
|
+
if (this.#blob !== void 0) return this.#blob;
|
|
491
|
+
let maybeBlobsService = this.env[SharedBindings.MAYBE_SERVICE_BLOBS], stickyBlobs = !!this.env[SharedBindings.MAYBE_JSON_ENABLE_STICKY_BLOBS];
|
|
492
|
+
return assert5(
|
|
493
|
+
maybeBlobsService !== void 0,
|
|
494
|
+
`Expected ${SharedBindings.MAYBE_SERVICE_BLOBS} service binding`
|
|
495
|
+
), this.#blob = new BlobStore(maybeBlobsService, this.name, stickyBlobs), this.#blob;
|
|
496
|
+
}
|
|
497
|
+
async logWithLevel(level, message) {
|
|
498
|
+
await this.env[SharedBindings.MAYBE_SERVICE_LOOPBACK]?.fetch(
|
|
499
|
+
"http://localhost/core/log",
|
|
500
|
+
{
|
|
501
|
+
method: "POST",
|
|
502
|
+
headers: { [SharedHeaders.LOG_LEVEL]: level.toString() },
|
|
503
|
+
body: message
|
|
504
|
+
}
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
async #handleControlOp({
|
|
508
|
+
name,
|
|
509
|
+
args
|
|
510
|
+
}) {
|
|
511
|
+
if (this.beingTested = !0, name === "sqlQuery") {
|
|
512
|
+
assert5(args !== void 0);
|
|
513
|
+
let [query, ...params] = args;
|
|
514
|
+
assert5(typeof query == "string"), assert5(params.every(isTypedValue));
|
|
515
|
+
let results = all(this.db.prepare(query)(...params));
|
|
516
|
+
return Response.json(results);
|
|
517
|
+
} else if (name === "getBlob") {
|
|
518
|
+
assert5(args !== void 0);
|
|
519
|
+
let [id] = args;
|
|
520
|
+
assert5(typeof id == "string");
|
|
521
|
+
let stream = await this.blob.get(id);
|
|
522
|
+
return new Response(stream, { status: stream === null ? 404 : 200 });
|
|
523
|
+
} else {
|
|
524
|
+
let func = this.timers[name];
|
|
525
|
+
assert5(typeof func == "function");
|
|
526
|
+
let result = await func.apply(this.timers, args);
|
|
527
|
+
return Response.json(result ?? null);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
async fetch(req) {
|
|
531
|
+
if (this.env[SharedBindings.MAYBE_JSON_ENABLE_CONTROL_ENDPOINTS] === !0) {
|
|
532
|
+
let controlOp = req?.cf?.miniflare?.controlOp;
|
|
533
|
+
if (controlOp !== void 0) return this.#handleControlOp(controlOp);
|
|
534
|
+
}
|
|
535
|
+
let name = req.cf?.miniflare?.name;
|
|
536
|
+
assert5(name !== void 0, "Expected `cf.miniflare.name`"), this.#name = name;
|
|
537
|
+
try {
|
|
538
|
+
return await super.fetch(req);
|
|
539
|
+
} catch (e) {
|
|
540
|
+
let error = reduceError(e), fallback = error.stack ?? error.message, loopbackService = this.env[SharedBindings.MAYBE_SERVICE_LOOPBACK];
|
|
541
|
+
return loopbackService !== void 0 ? loopbackService.fetch("http://localhost/core/error", {
|
|
542
|
+
method: "POST",
|
|
543
|
+
body: JSON.stringify(error)
|
|
544
|
+
}).catch(() => {
|
|
545
|
+
console.error(fallback);
|
|
546
|
+
}) : console.error(fallback), new Response(fallback, { status: 500 });
|
|
547
|
+
} finally {
|
|
548
|
+
req.body !== null && !req.bodyUsed && await req.body.pipeTo(new WritableStream());
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
// src/workers/shared/range.ts
|
|
554
|
+
var rangePrefixRegexp = /^ *bytes *=/i, rangeRegexp = /^ *(?<start>\d+)? *- *(?<end>\d+)? *$/;
|
|
555
|
+
function parseRanges(rangeHeader, length) {
|
|
556
|
+
let prefixMatch = rangePrefixRegexp.exec(rangeHeader);
|
|
557
|
+
if (prefixMatch === null) return;
|
|
558
|
+
if (rangeHeader = rangeHeader.substring(prefixMatch[0].length), rangeHeader.trimStart() === "") return [];
|
|
559
|
+
let ranges = rangeHeader.split(","), result = [];
|
|
560
|
+
for (let range of ranges) {
|
|
561
|
+
let match = rangeRegexp.exec(range);
|
|
562
|
+
if (match === null) return;
|
|
563
|
+
let { start, end } = match.groups;
|
|
564
|
+
if (start !== void 0 && end !== void 0) {
|
|
565
|
+
let rangeStart = parseInt(start), rangeEnd = parseInt(end);
|
|
566
|
+
if (rangeStart > rangeEnd || rangeStart >= length) return;
|
|
567
|
+
rangeEnd >= length && (rangeEnd = length - 1), result.push({ start: rangeStart, end: rangeEnd });
|
|
568
|
+
} else if (start !== void 0 && end === void 0) {
|
|
569
|
+
let rangeStart = parseInt(start);
|
|
570
|
+
if (rangeStart >= length) return;
|
|
571
|
+
result.push({ start: rangeStart, end: length - 1 });
|
|
572
|
+
} else if (start === void 0 && end !== void 0) {
|
|
573
|
+
let suffix = parseInt(end);
|
|
574
|
+
if (suffix >= length) return [];
|
|
575
|
+
if (suffix === 0) continue;
|
|
576
|
+
result.push({ start: length - suffix, end: length - 1 });
|
|
577
|
+
} else
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
return result;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// src/workers/shared/sync.ts
|
|
584
|
+
import assert6 from "node-internal:internal_assert";
|
|
585
|
+
var DeferredPromise = class extends Promise {
|
|
586
|
+
resolve;
|
|
587
|
+
reject;
|
|
588
|
+
constructor(executor = () => {
|
|
589
|
+
}) {
|
|
590
|
+
let promiseResolve, promiseReject;
|
|
591
|
+
super((resolve, reject) => (promiseResolve = resolve, promiseReject = reject, executor(resolve, reject))), this.resolve = promiseResolve, this.reject = promiseReject;
|
|
592
|
+
}
|
|
593
|
+
}, Mutex = class {
|
|
594
|
+
locked = !1;
|
|
595
|
+
resolveQueue = [];
|
|
596
|
+
drainQueue = [];
|
|
597
|
+
lock() {
|
|
598
|
+
if (!this.locked) {
|
|
599
|
+
this.locked = !0;
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
return new Promise((resolve) => this.resolveQueue.push(resolve));
|
|
603
|
+
}
|
|
604
|
+
unlock() {
|
|
605
|
+
if (assert6(this.locked), this.resolveQueue.length > 0)
|
|
606
|
+
this.resolveQueue.shift()?.();
|
|
607
|
+
else {
|
|
608
|
+
this.locked = !1;
|
|
609
|
+
let resolve;
|
|
610
|
+
for (; (resolve = this.drainQueue.shift()) !== void 0; ) resolve();
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
get hasWaiting() {
|
|
614
|
+
return this.resolveQueue.length > 0;
|
|
615
|
+
}
|
|
616
|
+
async runWith(closure) {
|
|
617
|
+
let acquireAwaitable = this.lock();
|
|
618
|
+
acquireAwaitable instanceof Promise && await acquireAwaitable;
|
|
619
|
+
try {
|
|
620
|
+
let awaitable = closure();
|
|
621
|
+
return awaitable instanceof Promise ? await awaitable : awaitable;
|
|
622
|
+
} finally {
|
|
623
|
+
this.unlock();
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
async drained() {
|
|
627
|
+
if (!(this.resolveQueue.length === 0 && !this.locked))
|
|
628
|
+
return new Promise((resolve) => this.drainQueue.push(resolve));
|
|
629
|
+
}
|
|
630
|
+
}, WaitGroup = class {
|
|
631
|
+
counter = 0;
|
|
632
|
+
resolveQueue = [];
|
|
633
|
+
add() {
|
|
634
|
+
this.counter++;
|
|
635
|
+
}
|
|
636
|
+
done() {
|
|
637
|
+
if (assert6(this.counter > 0), this.counter--, this.counter === 0) {
|
|
638
|
+
let resolve;
|
|
639
|
+
for (; (resolve = this.resolveQueue.shift()) !== void 0; ) resolve();
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
wait() {
|
|
643
|
+
return this.counter === 0 ? Promise.resolve() : new Promise((resolve) => this.resolveQueue.push(resolve));
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
export {
|
|
647
|
+
BlobStore,
|
|
648
|
+
DELETE,
|
|
649
|
+
DeferredPromise,
|
|
650
|
+
GET,
|
|
651
|
+
HEAD,
|
|
652
|
+
HttpError,
|
|
653
|
+
KeyValueStorage,
|
|
654
|
+
LogLevel,
|
|
655
|
+
MiniflareDurableObject,
|
|
656
|
+
Mutex,
|
|
657
|
+
PATCH,
|
|
658
|
+
POST,
|
|
659
|
+
PURGE,
|
|
660
|
+
PUT,
|
|
661
|
+
Router,
|
|
662
|
+
SharedBindings,
|
|
663
|
+
SharedHeaders,
|
|
664
|
+
Timers,
|
|
665
|
+
WaitGroup,
|
|
666
|
+
all,
|
|
667
|
+
base64Decode,
|
|
668
|
+
base64Encode,
|
|
669
|
+
drain,
|
|
670
|
+
get,
|
|
671
|
+
maybeApply,
|
|
672
|
+
parseRanges,
|
|
673
|
+
readPrefix,
|
|
674
|
+
reduceError,
|
|
675
|
+
testRegExps,
|
|
676
|
+
viewToBuffer
|
|
677
|
+
};
|
|
678
|
+
/*! Path sanitisation regexps adapted from node-sanitize-filename:
|
|
679
|
+
* https://github.com/parshap/node-sanitize-filename/blob/209c39b914c8eb48ee27bcbde64b2c7822fdf3de/index.js#L4-L37
|
|
680
|
+
*
|
|
681
|
+
* Licensed under the ISC license:
|
|
682
|
+
*
|
|
683
|
+
* Copyright Parsha Pourkhomami <parshap@gmail.com>
|
|
684
|
+
*
|
|
685
|
+
* Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the
|
|
686
|
+
* above copyright notice and this permission notice appear in all copies.
|
|
687
|
+
*
|
|
688
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
689
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
|
690
|
+
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
691
|
+
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
692
|
+
*/
|
|
693
|
+
//# sourceMappingURL=index.worker.js.map
|