birdclaw 0.9.1 → 0.9.2
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
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 0.9.2 - 2026-07-04
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Split oversized backup JSONL outputs into deterministic 48 MiB part files and serialize and validate them sequentially, keeping large archives below hosted Git limits without Git LFS.
|
|
8
|
+
|
|
3
9
|
## 0.9.1 - 2026-07-02
|
|
4
10
|
|
|
5
11
|
### Added
|
package/README.md
CHANGED
|
@@ -598,9 +598,11 @@ data/dms/conversations.jsonl
|
|
|
598
598
|
data/dms/YYYY.jsonl
|
|
599
599
|
data/moderation/blocks.jsonl
|
|
600
600
|
data/moderation/mutes.jsonl
|
|
601
|
+
data/<logical-shard>.part-NNNN.jsonl
|
|
601
602
|
```
|
|
602
603
|
|
|
603
604
|
Tweets are sharded by year for human browsing and yearly analysis. Collection-only tweets whose real creation date is unknown go into `data/tweets/unknown.jsonl` instead of pretending they belong to 1970. Timeline membership is stored in `data/timeline_edges`; likes and bookmarks are stored as account-scoped collection edges in `data/collections`. DMs are sharded by year with `conversation_id` in each row; this keeps Git fast while preserving conversation membership.
|
|
605
|
+
Any logical shard larger than 48 MiB is split into deterministic `.part-0001.jsonl` files. Import and validation accept both numbered parts and the earlier unsplit layout, so large private backups remain ordinary Git repositories without Git LFS.
|
|
604
606
|
|
|
605
607
|
Use `backup sync` when the target is a private Git repo. It pulls first, merge-imports the remote backup into local SQLite, exports the local union back into text shards, commits, and pushes.
|
|
606
608
|
|
package/dist/cli/birdclaw.js
CHANGED
|
@@ -187,6 +187,10 @@ var __test__ = {
|
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
// src/lib/backup-table-codecs.ts
|
|
190
|
+
var BACKUP_SHARD_PART_PATTERN = /\.part-\d{4,}\.jsonl$/u;
|
|
191
|
+
function logicalBackupShardPath(relativePath) {
|
|
192
|
+
return relativePath.replace(BACKUP_SHARD_PART_PATTERN, ".jsonl");
|
|
193
|
+
}
|
|
190
194
|
function fixedShard(relativePath, countKey) {
|
|
191
195
|
return {
|
|
192
196
|
shardPath: () => relativePath,
|
|
@@ -1205,7 +1209,8 @@ function adaptLegacyTweetState(schemaVersion, tweets, collections, timelineEdges
|
|
|
1205
1209
|
return { collections: nextCollections, timelineEdges: nextTimelineEdges };
|
|
1206
1210
|
}
|
|
1207
1211
|
function backupCodecForPath(relativePath, codecs = BACKUP_TABLE_CODECS) {
|
|
1208
|
-
const
|
|
1212
|
+
const logicalPath = logicalBackupShardPath(relativePath);
|
|
1213
|
+
const matches = codecs.filter((codec) => codec.matchesPath(logicalPath));
|
|
1209
1214
|
if (matches.length !== 1) {
|
|
1210
1215
|
throw new Error(
|
|
1211
1216
|
matches.length === 0 ? `No backup codec owns path: ${relativePath}` : `Multiple backup codecs own path: ${relativePath}`
|
|
@@ -1234,7 +1239,7 @@ function countBackupFiles(files, codecs = BACKUP_TABLE_CODECS) {
|
|
|
1234
1239
|
for (const file of files) {
|
|
1235
1240
|
if (!file.path.startsWith("data/")) continue;
|
|
1236
1241
|
const codec = backupCodecForPath(file.path, codecs);
|
|
1237
|
-
const key = codec.countKey(file.path);
|
|
1242
|
+
const key = codec.countKey(logicalBackupShardPath(file.path));
|
|
1238
1243
|
counts[key] = (counts[key] ?? 0) + file.rows;
|
|
1239
1244
|
}
|
|
1240
1245
|
return counts;
|
|
@@ -3716,8 +3721,9 @@ function runSubprocessEffect(options) {
|
|
|
3716
3721
|
}
|
|
3717
3722
|
|
|
3718
3723
|
// src/lib/backup.ts
|
|
3719
|
-
var BACKUP_SCHEMA_VERSION =
|
|
3724
|
+
var BACKUP_SCHEMA_VERSION = 4;
|
|
3720
3725
|
var MIN_SUPPORTED_BACKUP_SCHEMA_VERSION = 1;
|
|
3726
|
+
var DEFAULT_MAX_BACKUP_SHARD_BYTES = 48 * 1024 * 1024;
|
|
3721
3727
|
var MANIFEST_PATH = "manifest.json";
|
|
3722
3728
|
var DATA_DIR = "data";
|
|
3723
3729
|
var GITATTRIBUTES_PATH = ".gitattributes";
|
|
@@ -3815,6 +3821,50 @@ function getExportRowSets(db) {
|
|
|
3815
3821
|
function buildShards(db) {
|
|
3816
3822
|
return buildBackupShardsFromRowSets(getExportRowSets(db));
|
|
3817
3823
|
}
|
|
3824
|
+
function normalizeMaxBackupShardBytes(value) {
|
|
3825
|
+
const maxBytes = value ?? DEFAULT_MAX_BACKUP_SHARD_BYTES;
|
|
3826
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) {
|
|
3827
|
+
throw new Error("Backup shard byte limit must be a positive integer");
|
|
3828
|
+
}
|
|
3829
|
+
return maxBytes;
|
|
3830
|
+
}
|
|
3831
|
+
function partPath(relativePath, partNumber) {
|
|
3832
|
+
if (!relativePath.endsWith(".jsonl")) {
|
|
3833
|
+
throw new Error(`Backup shard path must end in .jsonl: ${relativePath}`);
|
|
3834
|
+
}
|
|
3835
|
+
return relativePath.replace(
|
|
3836
|
+
/\.jsonl$/u,
|
|
3837
|
+
`.part-${String(partNumber).padStart(4, "0")}.jsonl`
|
|
3838
|
+
);
|
|
3839
|
+
}
|
|
3840
|
+
function splitJsonlShard(relativePath, rows, maxBytes) {
|
|
3841
|
+
const parts = [];
|
|
3842
|
+
let currentRows = [];
|
|
3843
|
+
let currentBytes = 0;
|
|
3844
|
+
for (const [index, row] of rows.entries()) {
|
|
3845
|
+
const rowBytes = Buffer.byteLength(jsonlStringify(row)) + 1;
|
|
3846
|
+
if (rowBytes > maxBytes) {
|
|
3847
|
+
throw new Error(
|
|
3848
|
+
`Backup row exceeds shard byte limit: ${relativePath}:${index + 1} is ${rowBytes} bytes (limit ${maxBytes})`
|
|
3849
|
+
);
|
|
3850
|
+
}
|
|
3851
|
+
if (currentRows.length > 0 && currentBytes + rowBytes > maxBytes) {
|
|
3852
|
+
parts.push(currentRows);
|
|
3853
|
+
currentRows = [];
|
|
3854
|
+
currentBytes = 0;
|
|
3855
|
+
}
|
|
3856
|
+
currentRows.push(row);
|
|
3857
|
+
currentBytes += rowBytes;
|
|
3858
|
+
}
|
|
3859
|
+
if (currentRows.length > 0) parts.push(currentRows);
|
|
3860
|
+
if (parts.length <= 1) {
|
|
3861
|
+
return [{ relativePath, rows: parts[0] ?? [] }];
|
|
3862
|
+
}
|
|
3863
|
+
return parts.map((partRows, index) => ({
|
|
3864
|
+
relativePath: partPath(relativePath, index + 1),
|
|
3865
|
+
rows: partRows
|
|
3866
|
+
}));
|
|
3867
|
+
}
|
|
3818
3868
|
function writeJsonlFileEffect(repoPath, relativePath, rows) {
|
|
3819
3869
|
return Effect5.gen(function* () {
|
|
3820
3870
|
const fullPath = yield* trySync2(
|
|
@@ -3951,6 +4001,7 @@ data/follow_events.jsonl
|
|
|
3951
4001
|
\`\`\`
|
|
3952
4002
|
|
|
3953
4003
|
Tweets are sharded by creation year. Collection-only tweets whose creation date is unknown live in \`data/tweets/unknown.jsonl\`. Timeline edges keep account-scoped home/mention membership separate from canonical tweet content. DMs are sharded by year and keep \`conversation_id\` in each row.
|
|
4004
|
+
Logical shards larger than 48 MiB are split into deterministic \`.part-0001.jsonl\` files so ordinary Git hosting remains usable without Git LFS.
|
|
3954
4005
|
The links shard stores expanded short URLs and their source tweet/DM occurrences so linked-tweet search can be rebuilt without re-expanding every \`t.co\` URL.
|
|
3955
4006
|
|
|
3956
4007
|
Never commit live tokens, browser cookies, raw SQLite WAL/SHM sidecars, or temporary cache files here.
|
|
@@ -4202,7 +4253,8 @@ function exportBackupEffect({
|
|
|
4202
4253
|
commit = false,
|
|
4203
4254
|
push = false,
|
|
4204
4255
|
message = "archive: update birdclaw backup",
|
|
4205
|
-
validate = true
|
|
4256
|
+
validate = true,
|
|
4257
|
+
maxShardBytes
|
|
4206
4258
|
}) {
|
|
4207
4259
|
return Effect5.gen(function* () {
|
|
4208
4260
|
const resolvedRepoPath = yield* trySync2(() => path2.resolve(repoPath));
|
|
@@ -4216,19 +4268,27 @@ function exportBackupEffect({
|
|
|
4216
4268
|
}
|
|
4217
4269
|
yield* ensureBackupGitattributesEffect(resolvedRepoPath);
|
|
4218
4270
|
yield* ensureBackupReadmeEffect(resolvedRepoPath);
|
|
4271
|
+
const maxBytes = yield* trySync2(
|
|
4272
|
+
() => normalizeMaxBackupShardBytes(maxShardBytes)
|
|
4273
|
+
);
|
|
4219
4274
|
const shards = yield* trySync2(() => buildShards(database));
|
|
4220
4275
|
const shardEntries = yield* trySync2(
|
|
4221
4276
|
() => [...shards.entries()].sort(
|
|
4222
4277
|
([left], [right]) => left.localeCompare(right)
|
|
4223
4278
|
)
|
|
4224
4279
|
);
|
|
4280
|
+
const shardParts = yield* trySync2(
|
|
4281
|
+
() => shardEntries.flatMap(
|
|
4282
|
+
([relativePath, rows]) => splitJsonlShard(relativePath, rows, maxBytes)
|
|
4283
|
+
)
|
|
4284
|
+
);
|
|
4225
4285
|
const expectedPaths = yield* trySync2(
|
|
4226
|
-
() => new Set(
|
|
4286
|
+
() => new Set(shardParts.map(({ relativePath }) => relativePath))
|
|
4227
4287
|
);
|
|
4228
4288
|
const files = yield* Effect5.forEach(
|
|
4229
|
-
|
|
4230
|
-
(
|
|
4231
|
-
{ concurrency:
|
|
4289
|
+
shardParts,
|
|
4290
|
+
({ relativePath, rows }) => writeJsonlFileEffect(resolvedRepoPath, relativePath, rows),
|
|
4291
|
+
{ concurrency: 1 }
|
|
4232
4292
|
);
|
|
4233
4293
|
yield* removeStaleBackupFilesEffect(resolvedRepoPath, expectedPaths);
|
|
4234
4294
|
const counts = yield* trySync2(() => countBackupFiles(files));
|
|
@@ -4416,7 +4476,7 @@ function readBackupImportRowsEffect(resolvedRepoPath, manifest) {
|
|
|
4416
4476
|
});
|
|
4417
4477
|
}
|
|
4418
4478
|
function rowsForManifestPath(manifest, predicate) {
|
|
4419
|
-
return manifest.files.map((file) => file.path).filter(predicate).sort();
|
|
4479
|
+
return manifest.files.map((file) => file.path).filter((relativePath) => predicate(logicalBackupShardPath(relativePath))).sort();
|
|
4420
4480
|
}
|
|
4421
4481
|
function importBackupEffect({
|
|
4422
4482
|
repoPath,
|
|
@@ -4886,7 +4946,7 @@ function validateBackupEffect(repoPath) {
|
|
|
4886
4946
|
}
|
|
4887
4947
|
return { file, errors: fileErrors };
|
|
4888
4948
|
}),
|
|
4889
|
-
{ concurrency:
|
|
4949
|
+
{ concurrency: 1 }
|
|
4890
4950
|
);
|
|
4891
4951
|
const files = [];
|
|
4892
4952
|
for (const result of results) {
|
|
@@ -2546,6 +2546,10 @@ var Route$17 = createFileRoute("/api/xurl-rate-limits")({ server: { handlers: {
|
|
|
2546
2546
|
})) } } });
|
|
2547
2547
|
//#endregion
|
|
2548
2548
|
//#region src/lib/backup-table-codecs.ts
|
|
2549
|
+
var BACKUP_SHARD_PART_PATTERN = /\.part-\d{4,}\.jsonl$/u;
|
|
2550
|
+
function logicalBackupShardPath(relativePath) {
|
|
2551
|
+
return relativePath.replace(BACKUP_SHARD_PART_PATTERN, ".jsonl");
|
|
2552
|
+
}
|
|
2549
2553
|
function fixedShard(relativePath, countKey) {
|
|
2550
2554
|
return {
|
|
2551
2555
|
shardPath: () => relativePath,
|
|
@@ -3567,7 +3571,8 @@ function adaptLegacyTweetState(schemaVersion, tweets, collections, timelineEdges
|
|
|
3567
3571
|
};
|
|
3568
3572
|
}
|
|
3569
3573
|
function backupCodecForPath(relativePath, codecs = BACKUP_TABLE_CODECS) {
|
|
3570
|
-
const
|
|
3574
|
+
const logicalPath = logicalBackupShardPath(relativePath);
|
|
3575
|
+
const matches = codecs.filter((codec) => codec.matchesPath(logicalPath));
|
|
3571
3576
|
if (matches.length !== 1) throw new Error(matches.length === 0 ? `No backup codec owns path: ${relativePath}` : `Multiple backup codecs own path: ${relativePath}`);
|
|
3572
3577
|
return matches[0];
|
|
3573
3578
|
}
|
|
@@ -3590,7 +3595,7 @@ function countBackupFiles(files, codecs = BACKUP_TABLE_CODECS) {
|
|
|
3590
3595
|
const counts = {};
|
|
3591
3596
|
for (const file of files) {
|
|
3592
3597
|
if (!file.path.startsWith("data/")) continue;
|
|
3593
|
-
const key = backupCodecForPath(file.path, codecs).countKey(file.path);
|
|
3598
|
+
const key = backupCodecForPath(file.path, codecs).countKey(logicalBackupShardPath(file.path));
|
|
3594
3599
|
counts[key] = (counts[key] ?? 0) + file.rows;
|
|
3595
3600
|
}
|
|
3596
3601
|
return counts;
|
|
@@ -3996,8 +4001,9 @@ function runSubprocessEffect(options) {
|
|
|
3996
4001
|
}
|
|
3997
4002
|
//#endregion
|
|
3998
4003
|
//#region src/lib/backup.ts
|
|
3999
|
-
var BACKUP_SCHEMA_VERSION =
|
|
4004
|
+
var BACKUP_SCHEMA_VERSION = 4;
|
|
4000
4005
|
var MIN_SUPPORTED_BACKUP_SCHEMA_VERSION = 1;
|
|
4006
|
+
var DEFAULT_MAX_BACKUP_SHARD_BYTES = 48 * 1024 * 1024;
|
|
4001
4007
|
var MANIFEST_PATH = "manifest.json";
|
|
4002
4008
|
var DATA_DIR = "data";
|
|
4003
4009
|
var GITATTRIBUTES_PATH = ".gitattributes";
|
|
@@ -4080,6 +4086,40 @@ function getExportRowSets(db) {
|
|
|
4080
4086
|
function buildShards(db) {
|
|
4081
4087
|
return buildBackupShardsFromRowSets(getExportRowSets(db));
|
|
4082
4088
|
}
|
|
4089
|
+
function normalizeMaxBackupShardBytes(value) {
|
|
4090
|
+
const maxBytes = value ?? DEFAULT_MAX_BACKUP_SHARD_BYTES;
|
|
4091
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) throw new Error("Backup shard byte limit must be a positive integer");
|
|
4092
|
+
return maxBytes;
|
|
4093
|
+
}
|
|
4094
|
+
function partPath(relativePath, partNumber) {
|
|
4095
|
+
if (!relativePath.endsWith(".jsonl")) throw new Error(`Backup shard path must end in .jsonl: ${relativePath}`);
|
|
4096
|
+
return relativePath.replace(/\.jsonl$/u, `.part-${String(partNumber).padStart(4, "0")}.jsonl`);
|
|
4097
|
+
}
|
|
4098
|
+
function splitJsonlShard(relativePath, rows, maxBytes) {
|
|
4099
|
+
const parts = [];
|
|
4100
|
+
let currentRows = [];
|
|
4101
|
+
let currentBytes = 0;
|
|
4102
|
+
for (const [index, row] of rows.entries()) {
|
|
4103
|
+
const rowBytes = Buffer.byteLength(jsonlStringify(row)) + 1;
|
|
4104
|
+
if (rowBytes > maxBytes) throw new Error(`Backup row exceeds shard byte limit: ${relativePath}:${index + 1} is ${rowBytes} bytes (limit ${maxBytes})`);
|
|
4105
|
+
if (currentRows.length > 0 && currentBytes + rowBytes > maxBytes) {
|
|
4106
|
+
parts.push(currentRows);
|
|
4107
|
+
currentRows = [];
|
|
4108
|
+
currentBytes = 0;
|
|
4109
|
+
}
|
|
4110
|
+
currentRows.push(row);
|
|
4111
|
+
currentBytes += rowBytes;
|
|
4112
|
+
}
|
|
4113
|
+
if (currentRows.length > 0) parts.push(currentRows);
|
|
4114
|
+
if (parts.length <= 1) return [{
|
|
4115
|
+
relativePath,
|
|
4116
|
+
rows: parts[0] ?? []
|
|
4117
|
+
}];
|
|
4118
|
+
return parts.map((partRows, index) => ({
|
|
4119
|
+
relativePath: partPath(relativePath, index + 1),
|
|
4120
|
+
rows: partRows
|
|
4121
|
+
}));
|
|
4122
|
+
}
|
|
4083
4123
|
function writeJsonlFileEffect(repoPath, relativePath, rows) {
|
|
4084
4124
|
return Effect.gen(function* () {
|
|
4085
4125
|
const fullPath = yield* trySync$10(() => resolveBackupFilePath(repoPath, relativePath));
|
|
@@ -4165,6 +4205,7 @@ data/follow_events.jsonl
|
|
|
4165
4205
|
\`\`\`
|
|
4166
4206
|
|
|
4167
4207
|
Tweets are sharded by creation year. Collection-only tweets whose creation date is unknown live in \`data/tweets/unknown.jsonl\`. Timeline edges keep account-scoped home/mention membership separate from canonical tweet content. DMs are sharded by year and keep \`conversation_id\` in each row.
|
|
4208
|
+
Logical shards larger than 48 MiB are split into deterministic \`.part-0001.jsonl\` files so ordinary Git hosting remains usable without Git LFS.
|
|
4168
4209
|
The links shard stores expanded short URLs and their source tweet/DM occurrences so linked-tweet search can be rebuilt without re-expanding every \`t.co\` URL.
|
|
4169
4210
|
|
|
4170
4211
|
Never commit live tokens, browser cookies, raw SQLite WAL/SHM sidecars, or temporary cache files here.
|
|
@@ -4398,7 +4439,7 @@ function pullBackupGitRepoEffect(repoPath) {
|
|
|
4398
4439
|
]).pipe(Effect.as(true), Effect.catchAll(() => Effect.succeed(false)))));
|
|
4399
4440
|
});
|
|
4400
4441
|
}
|
|
4401
|
-
function exportBackupEffect({ repoPath, db, commit = false, push = false, message = "archive: update birdclaw backup", validate = true }) {
|
|
4442
|
+
function exportBackupEffect({ repoPath, db, commit = false, push = false, message = "archive: update birdclaw backup", validate = true, maxShardBytes }) {
|
|
4402
4443
|
return Effect.gen(function* () {
|
|
4403
4444
|
const resolvedRepoPath = yield* trySync$10(() => path.resolve(repoPath));
|
|
4404
4445
|
const database = db ?? (yield* trySync$10(() => getNativeDb({ seedDemoData: false })));
|
|
@@ -4407,10 +4448,12 @@ function exportBackupEffect({ repoPath, db, commit = false, push = false, messag
|
|
|
4407
4448
|
if (!repoStat.isDirectory() || repoStat.isSymbolicLink()) return yield* Effect.fail(/* @__PURE__ */ new Error("Backup repository path must be a real directory"));
|
|
4408
4449
|
yield* ensureBackupGitattributesEffect(resolvedRepoPath);
|
|
4409
4450
|
yield* ensureBackupReadmeEffect(resolvedRepoPath);
|
|
4451
|
+
const maxBytes = yield* trySync$10(() => normalizeMaxBackupShardBytes(maxShardBytes));
|
|
4410
4452
|
const shards = yield* trySync$10(() => buildShards(database));
|
|
4411
4453
|
const shardEntries = yield* trySync$10(() => [...shards.entries()].sort(([left], [right]) => left.localeCompare(right)));
|
|
4412
|
-
const
|
|
4413
|
-
const
|
|
4454
|
+
const shardParts = yield* trySync$10(() => shardEntries.flatMap(([relativePath, rows]) => splitJsonlShard(relativePath, rows, maxBytes)));
|
|
4455
|
+
const expectedPaths = yield* trySync$10(() => new Set(shardParts.map(({ relativePath }) => relativePath)));
|
|
4456
|
+
const files = yield* Effect.forEach(shardParts, ({ relativePath, rows }) => writeJsonlFileEffect(resolvedRepoPath, relativePath, rows), { concurrency: 1 });
|
|
4414
4457
|
yield* removeStaleBackupFilesEffect(resolvedRepoPath, expectedPaths);
|
|
4415
4458
|
const counts = yield* trySync$10(() => countBackupFiles(files));
|
|
4416
4459
|
const backupHash = yield* trySync$10(() => computeBackupHash(files));
|
|
@@ -4526,7 +4569,7 @@ function readBackupImportRowsEffect(resolvedRepoPath, manifest) {
|
|
|
4526
4569
|
});
|
|
4527
4570
|
}
|
|
4528
4571
|
function rowsForManifestPath(manifest, predicate) {
|
|
4529
|
-
return manifest.files.map((file) => file.path).filter(predicate).sort();
|
|
4572
|
+
return manifest.files.map((file) => file.path).filter((relativePath) => predicate(logicalBackupShardPath(relativePath))).sort();
|
|
4530
4573
|
}
|
|
4531
4574
|
function importBackupEffect({ repoPath, db: providedDb, validate = true, mode = "merge" }) {
|
|
4532
4575
|
return Effect.gen(function* () {
|
|
@@ -4901,7 +4944,7 @@ function validateBackupEffect(repoPath) {
|
|
|
4901
4944
|
file,
|
|
4902
4945
|
errors: fileErrors
|
|
4903
4946
|
};
|
|
4904
|
-
}), { concurrency:
|
|
4947
|
+
}), { concurrency: 1 });
|
|
4905
4948
|
const files = [];
|
|
4906
4949
|
for (const result of results) {
|
|
4907
4950
|
errors.push(...result.errors);
|
package/dist/server/server.js
CHANGED
|
@@ -5130,7 +5130,7 @@ var getBaseManifest = getProdBaseManifest;
|
|
|
5130
5130
|
var createEarlyHintsForRequest = createEarlyHintsCollector;
|
|
5131
5131
|
async function loadEntries() {
|
|
5132
5132
|
const [routerEntry, startEntry, pluginAdapters] = await Promise.all([
|
|
5133
|
-
import("./assets/router-
|
|
5133
|
+
import("./assets/router-D8AUR_Gz.js"),
|
|
5134
5134
|
import("./assets/start-FaDOTmto.js"),
|
|
5135
5135
|
import("./assets/empty-plugin-adapters-DzrEkdBF.js")
|
|
5136
5136
|
]);
|
package/package.json
CHANGED