@hatk/hatk 0.0.1-alpha.84 → 0.0.1-alpha.85
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/config.d.ts.map +1 -1
- package/dist/config.js +5 -1
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +201 -140
- package/dist/database/dialect.js +2 -2
- package/dist/database/fts.d.ts.map +1 -1
- package/dist/database/fts.js +6 -2
- package/dist/database/schema.d.ts.map +1 -1
- package/dist/database/schema.js +6 -1
- package/dist/hooks.d.ts +8 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +24 -1
- package/dist/indexer.d.ts +4 -3
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +81 -64
- package/dist/opengraph.d.ts.map +1 -1
- package/dist/opengraph.js +16 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +68 -5
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +1 -1
- package/package.json +4 -2
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -40,7 +40,11 @@ export async function loadConfig(configPath) {
|
|
|
40
40
|
const database = env.DATABASE || parsed.database;
|
|
41
41
|
const config = {
|
|
42
42
|
relay: env.RELAY || parsed.relay || 'ws://localhost:2583',
|
|
43
|
-
relays: env.RELAYS
|
|
43
|
+
relays: env.RELAYS
|
|
44
|
+
? env.RELAYS.split(',')
|
|
45
|
+
.map((s) => s.trim())
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
: parsed.relays || [],
|
|
44
48
|
jetstream: env.JETSTREAM_URL ? { url: env.JETSTREAM_URL } : parsed.jetstream || null,
|
|
45
49
|
plc: env.DID_PLC_URL || parsed.plc || 'https://plc.directory',
|
|
46
50
|
port: parseInt(env.PORT || '') || parsed.port || 3000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/database/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAI1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAM1D,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AACD,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAMD,wBAAsB,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnG;AAMD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,WAAW,EAAE,EAC3B,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CAiJf;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAoED,wBAAsB,aAAa,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA6F3F;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/database/db.ts"],"names":[],"mappings":"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"}
|
package/dist/database/db.js
CHANGED
|
@@ -328,6 +328,15 @@ async function applyMigrationChanges(changes) {
|
|
|
328
328
|
for (const change of changes) {
|
|
329
329
|
const quotedTable = `"${change.table}"`;
|
|
330
330
|
const quotedColumn = `"${change.column}"`;
|
|
331
|
+
// Index naming mirrors generateCreateTableSQL and the 'add' branch below:
|
|
332
|
+
// the table name with dots replaced by underscores, then the column name.
|
|
333
|
+
const indexName = `idx_${change.table.replace(/\./g, '_')}_${change.column}`;
|
|
334
|
+
// SQLite refuses to drop a column an index still references ("error in
|
|
335
|
+
// index ... after drop column"), so any DROP COLUMN has to clear it first.
|
|
336
|
+
const dropColumn = async () => {
|
|
337
|
+
await run(`DROP INDEX IF EXISTS "${indexName}"`);
|
|
338
|
+
await run(`ALTER TABLE ${quotedTable} DROP COLUMN ${quotedColumn}`);
|
|
339
|
+
};
|
|
331
340
|
try {
|
|
332
341
|
switch (change.action) {
|
|
333
342
|
case 'add': {
|
|
@@ -335,17 +344,18 @@ async function applyMigrationChanges(changes) {
|
|
|
335
344
|
emit('migration', 'add_column', { table: change.table, column: change.column, type: change.type });
|
|
336
345
|
const schema = schemas.get(change.table);
|
|
337
346
|
if (schema?.refColumns.includes(change.column)) {
|
|
338
|
-
|
|
339
|
-
await run(`CREATE INDEX IF NOT EXISTS idx_${prefix}_${change.column} ON ${quotedTable}(${quotedColumn})`);
|
|
347
|
+
await run(`CREATE INDEX IF NOT EXISTS ${indexName} ON ${quotedTable}(${quotedColumn})`);
|
|
340
348
|
}
|
|
341
349
|
break;
|
|
342
350
|
}
|
|
343
351
|
case 'drop':
|
|
344
|
-
await
|
|
352
|
+
await dropColumn();
|
|
345
353
|
emit('migration', 'drop_column', { table: change.table, column: change.column });
|
|
346
354
|
break;
|
|
347
355
|
case 'retype':
|
|
348
|
-
|
|
356
|
+
// A ref column is always TEXT, so a type change means it stopped
|
|
357
|
+
// being one — the index goes with the old column and is not rebuilt.
|
|
358
|
+
await dropColumn();
|
|
349
359
|
await run(`ALTER TABLE ${quotedTable} ADD COLUMN ${quotedColumn} ${change.type}`);
|
|
350
360
|
emit('migration', 'retype_column', { table: change.table, column: change.column, type: change.type });
|
|
351
361
|
break;
|
|
@@ -737,6 +747,12 @@ export async function queryLabelsForUris(uris) {
|
|
|
737
747
|
}
|
|
738
748
|
return result;
|
|
739
749
|
}
|
|
750
|
+
/** Per-process token + counter, so concurrent calls never share a staging table. */
|
|
751
|
+
const STAGING_TOKEN = Math.floor(Math.random() * 0xffffff).toString(36);
|
|
752
|
+
let stagingCounter = 0;
|
|
753
|
+
function nextStagingId() {
|
|
754
|
+
return `${STAGING_TOKEN}_${(stagingCounter++).toString(36)}`;
|
|
755
|
+
}
|
|
740
756
|
export async function bulkInsertRecords(records) {
|
|
741
757
|
if (records.length === 0)
|
|
742
758
|
return 0;
|
|
@@ -752,171 +768,191 @@ export async function bulkInsertRecords(records) {
|
|
|
752
768
|
const schema = schemas.get(collection);
|
|
753
769
|
if (!schema)
|
|
754
770
|
continue;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
...schema.columns.map((c) => {
|
|
763
|
-
const t = c.sqlType;
|
|
764
|
-
// Use TEXT for timestamp columns in staging (will cast on merge)
|
|
765
|
-
return `${q(c.name)} ${t === 'TIMESTAMP' || t === 'TIMESTAMPTZ' ? 'TEXT' : t}`;
|
|
766
|
-
}),
|
|
767
|
-
];
|
|
768
|
-
await port.execute(`DROP TABLE IF EXISTS ${stagingTable}`, []);
|
|
769
|
-
await port.execute(`CREATE TABLE ${stagingTable} (${colDefs.join(', ')})`, []);
|
|
770
|
-
const inserter = await port.createBulkInserter(stagingTable, allCols);
|
|
771
|
-
const now = new Date().toISOString();
|
|
772
|
-
for (const rec of recs) {
|
|
773
|
-
try {
|
|
774
|
-
const values = [rec.uri, rec.cid, rec.did, now];
|
|
775
|
-
for (const col of schema.columns) {
|
|
776
|
-
values.push(resolveColumnValue(col, rec.record));
|
|
777
|
-
}
|
|
778
|
-
inserter.append(values);
|
|
779
|
-
inserted++;
|
|
780
|
-
}
|
|
781
|
-
catch {
|
|
782
|
-
// Skip bad records
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
await inserter.close();
|
|
786
|
-
// Merge into target, filtering rows that would violate NOT NULL
|
|
787
|
-
const selectCols = allCols.map((name) => {
|
|
788
|
-
const col = schema.columns.find((c) => q(c.name) === name);
|
|
789
|
-
if (name === 'indexed_at' || (col && (col.sqlType === 'TIMESTAMP' || col.sqlType === 'TIMESTAMPTZ'))) {
|
|
790
|
-
return `${dialect.tryCastTimestamp(name)} AS ${name}`;
|
|
791
|
-
}
|
|
771
|
+
// Staging tables are named per call, not per collection: runBackfill
|
|
772
|
+
// imports repos in parallel, so two workers on the same collection would
|
|
773
|
+
// otherwise drop and recreate each other's staging table mid-insert.
|
|
774
|
+
const stagingTables = [];
|
|
775
|
+
const stagingName = (suffix) => {
|
|
776
|
+
const name = `_staging_${collection.replace(/\./g, '_')}${suffix}_${nextStagingId()}`;
|
|
777
|
+
stagingTables.push(name);
|
|
792
778
|
return name;
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
const whereClause = notNullChecks.length ? ` WHERE ${notNullChecks.join(' AND ')}` : '';
|
|
806
|
-
await port.execute(`INSERT OR REPLACE INTO ${schema.tableName} (${allCols.join(', ')}) SELECT ${selectCols.join(', ')} FROM ${stagingTable}${whereClause}`, []);
|
|
807
|
-
await port.execute(`DROP TABLE ${stagingTable}`, []);
|
|
808
|
-
// Populate child tables
|
|
809
|
-
for (const child of schema.children) {
|
|
810
|
-
const childStagingTable = `_staging_${collection.replace(/\./g, '_')}__${child.fieldName}`;
|
|
811
|
-
const childColDefs = [
|
|
812
|
-
'parent_uri TEXT',
|
|
813
|
-
'parent_did TEXT',
|
|
814
|
-
...child.columns.map((c) => {
|
|
779
|
+
};
|
|
780
|
+
try {
|
|
781
|
+
const stagingTable = stagingName('');
|
|
782
|
+
const allCols = ['uri', 'cid', 'did', 'indexed_at', ...schema.columns.map((c) => q(c.name))];
|
|
783
|
+
const colDefs = [
|
|
784
|
+
'uri TEXT',
|
|
785
|
+
'cid TEXT',
|
|
786
|
+
'did TEXT',
|
|
787
|
+
'indexed_at TEXT',
|
|
788
|
+
...schema.columns.map((c) => {
|
|
815
789
|
const t = c.sqlType;
|
|
790
|
+
// Use TEXT for timestamp columns in staging (will cast on merge)
|
|
816
791
|
return `${q(c.name)} ${t === 'TIMESTAMP' || t === 'TIMESTAMPTZ' ? 'TEXT' : t}`;
|
|
817
792
|
}),
|
|
818
793
|
];
|
|
819
|
-
|
|
820
|
-
await port.execute(`
|
|
821
|
-
|
|
822
|
-
const
|
|
794
|
+
await port.execute(`DROP TABLE IF EXISTS ${stagingTable}`, []);
|
|
795
|
+
await port.execute(`CREATE TABLE ${stagingTable} (${colDefs.join(', ')})`, []);
|
|
796
|
+
const inserter = await port.createBulkInserter(stagingTable, allCols);
|
|
797
|
+
const now = new Date().toISOString();
|
|
823
798
|
for (const rec of recs) {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
try {
|
|
829
|
-
const values = [rec.uri, rec.did];
|
|
830
|
-
for (const col of child.columns) {
|
|
831
|
-
values.push(resolveRawColumnValue(col, item));
|
|
832
|
-
}
|
|
833
|
-
childInserter.append(values);
|
|
834
|
-
}
|
|
835
|
-
catch {
|
|
836
|
-
// Skip bad items
|
|
799
|
+
try {
|
|
800
|
+
const values = [rec.uri, rec.cid, rec.did, now];
|
|
801
|
+
for (const col of schema.columns) {
|
|
802
|
+
values.push(resolveColumnValue(col, rec.record));
|
|
837
803
|
}
|
|
804
|
+
inserter.append(values);
|
|
805
|
+
inserted++;
|
|
806
|
+
}
|
|
807
|
+
catch {
|
|
808
|
+
// Skip bad records
|
|
838
809
|
}
|
|
839
810
|
}
|
|
840
|
-
await
|
|
841
|
-
//
|
|
842
|
-
const
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
const col = child.columns.find((c) => q(c.name) === name);
|
|
846
|
-
if (col && (col.sqlType === 'TIMESTAMP' || col.sqlType === 'TIMESTAMPTZ')) {
|
|
811
|
+
await inserter.close();
|
|
812
|
+
// Merge into target, filtering rows that would violate NOT NULL
|
|
813
|
+
const selectCols = allCols.map((name) => {
|
|
814
|
+
const col = schema.columns.find((c) => q(c.name) === name);
|
|
815
|
+
if (name === 'indexed_at' || (col && (col.sqlType === 'TIMESTAMP' || col.sqlType === 'TIMESTAMPTZ'))) {
|
|
847
816
|
return `${dialect.tryCastTimestamp(name)} AS ${name}`;
|
|
848
817
|
}
|
|
849
818
|
return name;
|
|
850
819
|
});
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
820
|
+
const notNullChecks = ['uri IS NOT NULL', 'did IS NOT NULL'];
|
|
821
|
+
for (const col of schema.columns) {
|
|
822
|
+
if (col.notNull) {
|
|
823
|
+
if (col.sqlType === 'TIMESTAMP' || col.sqlType === 'TIMESTAMPTZ') {
|
|
824
|
+
notNullChecks.push(`${dialect.tryCastTimestamp(q(col.name))} IS NOT NULL`);
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
notNullChecks.push(`${q(col.name)} IS NOT NULL`);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
const whereClause = notNullChecks.length ? ` WHERE ${notNullChecks.join(' AND ')}` : '';
|
|
832
|
+
await port.execute(`INSERT OR REPLACE INTO ${schema.tableName} (${allCols.join(', ')}) SELECT ${selectCols.join(', ')} FROM ${stagingTable}${whereClause}`, []);
|
|
833
|
+
await port.execute(`DROP TABLE ${stagingTable}`, []);
|
|
834
|
+
// Populate child tables
|
|
835
|
+
for (const child of schema.children) {
|
|
836
|
+
const childStagingTable = stagingName(`__${child.fieldName}`);
|
|
837
|
+
const childColDefs = [
|
|
859
838
|
'parent_uri TEXT',
|
|
860
839
|
'parent_did TEXT',
|
|
861
|
-
...
|
|
840
|
+
...child.columns.map((c) => {
|
|
862
841
|
const t = c.sqlType;
|
|
863
842
|
return `${q(c.name)} ${t === 'TIMESTAMP' || t === 'TIMESTAMPTZ' ? 'TEXT' : t}`;
|
|
864
843
|
}),
|
|
865
844
|
];
|
|
866
|
-
const
|
|
867
|
-
await port.execute(`DROP TABLE IF EXISTS ${
|
|
868
|
-
await port.execute(`CREATE TABLE ${
|
|
869
|
-
const
|
|
845
|
+
const childAllCols = ['parent_uri', 'parent_did', ...child.columns.map((c) => q(c.name))];
|
|
846
|
+
await port.execute(`DROP TABLE IF EXISTS ${childStagingTable}`, []);
|
|
847
|
+
await port.execute(`CREATE TABLE ${childStagingTable} (${childColDefs.join(', ')})`, []);
|
|
848
|
+
const childInserter = await port.createBulkInserter(childStagingTable, childAllCols);
|
|
870
849
|
for (const rec of recs) {
|
|
871
|
-
const
|
|
872
|
-
if (!
|
|
850
|
+
const items = rec.record[child.fieldName];
|
|
851
|
+
if (!Array.isArray(items))
|
|
873
852
|
continue;
|
|
874
|
-
|
|
875
|
-
continue;
|
|
876
|
-
if (branch.isArray && branch.arrayField) {
|
|
877
|
-
const items = resolveBranchData(unionValue, branch)[branch.arrayField];
|
|
878
|
-
if (!Array.isArray(items))
|
|
879
|
-
continue;
|
|
880
|
-
for (const item of items) {
|
|
881
|
-
try {
|
|
882
|
-
const values = [rec.uri, rec.did];
|
|
883
|
-
for (const col of branch.columns) {
|
|
884
|
-
values.push(resolveRawColumnValue(col, item));
|
|
885
|
-
}
|
|
886
|
-
branchInserter.append(values);
|
|
887
|
-
}
|
|
888
|
-
catch {
|
|
889
|
-
// Skip bad items
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
else {
|
|
853
|
+
for (const item of items) {
|
|
894
854
|
try {
|
|
895
|
-
const branchData = resolveBranchData(unionValue, branch);
|
|
896
855
|
const values = [rec.uri, rec.did];
|
|
897
|
-
for (const col of
|
|
898
|
-
values.push(resolveRawColumnValue(col,
|
|
856
|
+
for (const col of child.columns) {
|
|
857
|
+
values.push(resolveRawColumnValue(col, item));
|
|
899
858
|
}
|
|
900
|
-
|
|
859
|
+
childInserter.append(values);
|
|
901
860
|
}
|
|
902
861
|
catch {
|
|
903
|
-
// Skip bad
|
|
862
|
+
// Skip bad items
|
|
904
863
|
}
|
|
905
864
|
}
|
|
906
865
|
}
|
|
907
|
-
await
|
|
908
|
-
// Delete existing
|
|
866
|
+
await childInserter.close();
|
|
867
|
+
// Delete existing child rows for these URIs, then merge staging
|
|
909
868
|
const uriPlaceholders = recs.map((_, i) => `$${i + 1}`).join(',');
|
|
910
|
-
await port.execute(`DELETE FROM ${
|
|
911
|
-
const
|
|
912
|
-
const col =
|
|
869
|
+
await port.execute(`DELETE FROM ${child.tableName} WHERE parent_uri IN (${uriPlaceholders})`, recs.map((r) => r.uri));
|
|
870
|
+
const childSelectCols = childAllCols.map((name) => {
|
|
871
|
+
const col = child.columns.find((c) => q(c.name) === name);
|
|
913
872
|
if (col && (col.sqlType === 'TIMESTAMP' || col.sqlType === 'TIMESTAMPTZ')) {
|
|
914
873
|
return `${dialect.tryCastTimestamp(name)} AS ${name}`;
|
|
915
874
|
}
|
|
916
875
|
return name;
|
|
917
876
|
});
|
|
918
|
-
await port.execute(`INSERT INTO ${
|
|
919
|
-
await port.execute(`DROP TABLE ${
|
|
877
|
+
await port.execute(`INSERT INTO ${child.tableName} (${childAllCols.join(', ')}) SELECT ${childSelectCols.join(', ')} FROM ${childStagingTable} WHERE parent_uri IS NOT NULL`, []);
|
|
878
|
+
await port.execute(`DROP TABLE ${childStagingTable}`, []);
|
|
879
|
+
}
|
|
880
|
+
// Populate union branch tables
|
|
881
|
+
for (const union of schema.unions) {
|
|
882
|
+
for (const branch of union.branches) {
|
|
883
|
+
const branchStagingTable = stagingName(`__${toSnakeCase(union.fieldName)}_${branch.branchName}`);
|
|
884
|
+
const branchColDefs = [
|
|
885
|
+
'parent_uri TEXT',
|
|
886
|
+
'parent_did TEXT',
|
|
887
|
+
...branch.columns.map((c) => {
|
|
888
|
+
const t = c.sqlType;
|
|
889
|
+
return `${q(c.name)} ${t === 'TIMESTAMP' || t === 'TIMESTAMPTZ' ? 'TEXT' : t}`;
|
|
890
|
+
}),
|
|
891
|
+
];
|
|
892
|
+
const branchAllCols = ['parent_uri', 'parent_did', ...branch.columns.map((c) => q(c.name))];
|
|
893
|
+
await port.execute(`DROP TABLE IF EXISTS ${branchStagingTable}`, []);
|
|
894
|
+
await port.execute(`CREATE TABLE ${branchStagingTable} (${branchColDefs.join(', ')})`, []);
|
|
895
|
+
const branchInserter = await port.createBulkInserter(branchStagingTable, branchAllCols);
|
|
896
|
+
for (const rec of recs) {
|
|
897
|
+
const unionValue = rec.record[union.fieldName];
|
|
898
|
+
if (!unionValue || typeof unionValue !== 'object')
|
|
899
|
+
continue;
|
|
900
|
+
if (unionValue.$type !== branch.type)
|
|
901
|
+
continue;
|
|
902
|
+
if (branch.isArray && branch.arrayField) {
|
|
903
|
+
const items = resolveBranchData(unionValue, branch)[branch.arrayField];
|
|
904
|
+
if (!Array.isArray(items))
|
|
905
|
+
continue;
|
|
906
|
+
for (const item of items) {
|
|
907
|
+
try {
|
|
908
|
+
const values = [rec.uri, rec.did];
|
|
909
|
+
for (const col of branch.columns) {
|
|
910
|
+
values.push(resolveRawColumnValue(col, item));
|
|
911
|
+
}
|
|
912
|
+
branchInserter.append(values);
|
|
913
|
+
}
|
|
914
|
+
catch {
|
|
915
|
+
// Skip bad items
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
try {
|
|
921
|
+
const branchData = resolveBranchData(unionValue, branch);
|
|
922
|
+
const values = [rec.uri, rec.did];
|
|
923
|
+
for (const col of branch.columns) {
|
|
924
|
+
values.push(resolveRawColumnValue(col, branchData));
|
|
925
|
+
}
|
|
926
|
+
branchInserter.append(values);
|
|
927
|
+
}
|
|
928
|
+
catch {
|
|
929
|
+
// Skip bad records
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
await branchInserter.close();
|
|
934
|
+
// Delete existing branch rows for these URIs, then merge staging
|
|
935
|
+
const uriPlaceholders = recs.map((_, i) => `$${i + 1}`).join(',');
|
|
936
|
+
await port.execute(`DELETE FROM ${branch.tableName} WHERE parent_uri IN (${uriPlaceholders})`, recs.map((r) => r.uri));
|
|
937
|
+
const branchSelectCols = branchAllCols.map((name) => {
|
|
938
|
+
const col = branch.columns.find((c) => q(c.name) === name);
|
|
939
|
+
if (col && (col.sqlType === 'TIMESTAMP' || col.sqlType === 'TIMESTAMPTZ')) {
|
|
940
|
+
return `${dialect.tryCastTimestamp(name)} AS ${name}`;
|
|
941
|
+
}
|
|
942
|
+
return name;
|
|
943
|
+
});
|
|
944
|
+
await port.execute(`INSERT INTO ${branch.tableName} (${branchAllCols.join(', ')}) SELECT ${branchSelectCols.join(', ')} FROM ${branchStagingTable} WHERE parent_uri IS NOT NULL`, []);
|
|
945
|
+
await port.execute(`DROP TABLE ${branchStagingTable}`, []);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
finally {
|
|
950
|
+
// Drop on the error path too, so a failed batch leaves nothing behind.
|
|
951
|
+
for (const name of stagingTables) {
|
|
952
|
+
try {
|
|
953
|
+
await port.execute(`DROP TABLE IF EXISTS ${name}`, []);
|
|
954
|
+
}
|
|
955
|
+
catch { }
|
|
920
956
|
}
|
|
921
957
|
}
|
|
922
958
|
}
|
|
@@ -961,6 +997,16 @@ export async function queryRecords(collection, opts = {}) {
|
|
|
961
997
|
if (!schema)
|
|
962
998
|
throw new Error(`Unknown collection: ${collection}`);
|
|
963
999
|
const { limit = 20, cursor, filters, sort = 'indexed_at', order = 'desc' } = opts;
|
|
1000
|
+
// `order` is interpolated into the ORDER BY clause, not bound as a
|
|
1001
|
+
// parameter, so it has to be an exact match rather than a trusted caller
|
|
1002
|
+
// value — anything else is SQL reaching the engine verbatim.
|
|
1003
|
+
const direction = String(order).toUpperCase();
|
|
1004
|
+
if (direction !== 'ASC' && direction !== 'DESC')
|
|
1005
|
+
throw new Error(`Invalid sort order: ${order}`);
|
|
1006
|
+
// SQLite (and DuckDB) read a negative LIMIT as unbounded, so an unchecked
|
|
1007
|
+
// -1 returns the entire table.
|
|
1008
|
+
if (!Number.isInteger(limit) || limit < 1)
|
|
1009
|
+
throw new Error(`Invalid limit: ${limit}`);
|
|
964
1010
|
// Validate sort field exists
|
|
965
1011
|
const sortCol = sort === 'indexed_at' ? 'indexed_at' : schema.columns.find((c) => c.originalName === sort || c.name === sort);
|
|
966
1012
|
const sortName = typeof sortCol === 'string' ? sortCol : sortCol?.name;
|
|
@@ -973,7 +1019,7 @@ export async function queryRecords(collection, opts = {}) {
|
|
|
973
1019
|
if (cursor) {
|
|
974
1020
|
const parsed = unpackCursor(cursor);
|
|
975
1021
|
if (parsed) {
|
|
976
|
-
const op =
|
|
1022
|
+
const op = direction === 'DESC' ? '<' : '>';
|
|
977
1023
|
const pSort1 = `$${paramIdx++}`;
|
|
978
1024
|
const pSort2 = `$${paramIdx++}`;
|
|
979
1025
|
const pCid = `$${paramIdx++}`;
|
|
@@ -996,7 +1042,7 @@ export async function queryRecords(collection, opts = {}) {
|
|
|
996
1042
|
let sql = `SELECT t.*, r.handle FROM ${schema.tableName} t LEFT JOIN _repos r ON t.did = r.did WHERE (r.status IS NULL OR r.status != 'takendown')`;
|
|
997
1043
|
if (conditions.length)
|
|
998
1044
|
sql += ' AND ' + conditions.join(' AND ');
|
|
999
|
-
sql += ` ORDER BY t.${sortName} ${
|
|
1045
|
+
sql += ` ORDER BY t.${sortName} ${direction}, t.cid ${direction} LIMIT $${paramIdx++}`;
|
|
1000
1046
|
params.push(limit + 1); // fetch one extra for cursor
|
|
1001
1047
|
const rows = await all(sql, params);
|
|
1002
1048
|
const hasMore = rows.length > limit;
|
|
@@ -1355,6 +1401,22 @@ export async function getChildRows(childTableName, parentUris) {
|
|
|
1355
1401
|
}
|
|
1356
1402
|
return result;
|
|
1357
1403
|
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Normalize one stored column back to its record value. JSON columns are
|
|
1406
|
+
* written with JSON.stringify on insert, so they have to be parsed on the way
|
|
1407
|
+
* out — on child and union-branch rows just as much as on the main table.
|
|
1408
|
+
*/
|
|
1409
|
+
function decodeColumn(col, raw) {
|
|
1410
|
+
const val = normalizeValue(raw);
|
|
1411
|
+
if (!col.isJson || typeof val !== 'string')
|
|
1412
|
+
return val;
|
|
1413
|
+
try {
|
|
1414
|
+
return JSON.parse(val);
|
|
1415
|
+
}
|
|
1416
|
+
catch {
|
|
1417
|
+
return val;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1358
1420
|
export function reshapeRow(row, childData, unionData) {
|
|
1359
1421
|
if (!row)
|
|
1360
1422
|
return null;
|
|
@@ -1404,8 +1466,7 @@ export function reshapeRow(row, childData, unionData) {
|
|
|
1404
1466
|
value[child.fieldName] = childRows.map((cr) => {
|
|
1405
1467
|
const item = {};
|
|
1406
1468
|
for (const col of child.columns) {
|
|
1407
|
-
|
|
1408
|
-
item[col.originalName] = normalizeValue(raw);
|
|
1469
|
+
item[col.originalName] = decodeColumn(col, cr[col.name]);
|
|
1409
1470
|
}
|
|
1410
1471
|
return item;
|
|
1411
1472
|
});
|
|
@@ -1429,7 +1490,7 @@ export function reshapeRow(row, childData, unionData) {
|
|
|
1429
1490
|
const items = branchRows.map((br) => {
|
|
1430
1491
|
const item = {};
|
|
1431
1492
|
for (const col of branch.columns) {
|
|
1432
|
-
item[col.originalName] =
|
|
1493
|
+
item[col.originalName] = decodeColumn(col, br[col.name]);
|
|
1433
1494
|
}
|
|
1434
1495
|
return item;
|
|
1435
1496
|
});
|
|
@@ -1441,7 +1502,7 @@ export function reshapeRow(row, childData, unionData) {
|
|
|
1441
1502
|
const br = branchRows[0];
|
|
1442
1503
|
const props = {};
|
|
1443
1504
|
for (const col of branch.columns) {
|
|
1444
|
-
props[col.originalName] =
|
|
1505
|
+
props[col.originalName] = decodeColumn(col, br[col.name]);
|
|
1445
1506
|
}
|
|
1446
1507
|
if (branch.wrapperField) {
|
|
1447
1508
|
value[union.fieldName] = { $type: branch.type, [branch.wrapperField]: props };
|
package/dist/database/dialect.js
CHANGED
|
@@ -16,7 +16,7 @@ export const DUCKDB_DIALECT = {
|
|
|
16
16
|
upsertPrefix: 'INSERT OR REPLACE INTO',
|
|
17
17
|
jsonExtractString: (col, path) => `json_extract_string(${col}, '${path}')`,
|
|
18
18
|
jsonArrayStringAgg: (col, path) => `list_string_agg(json_extract_string(${col}, '${path}'))`,
|
|
19
|
-
listTablesQuery: `SELECT table_name FROM information_schema.tables WHERE table_schema = 'main' AND table_name NOT LIKE '\\_%' ESCAPE '
|
|
19
|
+
listTablesQuery: `SELECT table_name FROM information_schema.tables WHERE table_schema = 'main' AND table_name NOT LIKE '\\_%' ESCAPE '\\'`,
|
|
20
20
|
checkpointSQL: 'CHECKPOINT',
|
|
21
21
|
currentTimestamp: 'CURRENT_TIMESTAMP',
|
|
22
22
|
ilike: 'ILIKE',
|
|
@@ -48,7 +48,7 @@ export const SQLITE_DIALECT = {
|
|
|
48
48
|
jsonArrayStringAgg: (col, path) => {
|
|
49
49
|
return `(SELECT group_concat(je.value, ' ') FROM json_each(${col}, '${path}') je)`;
|
|
50
50
|
},
|
|
51
|
-
listTablesQuery: `SELECT name AS table_name FROM sqlite_master WHERE type='table' AND name NOT LIKE '\\_%' ESCAPE '
|
|
51
|
+
listTablesQuery: `SELECT name AS table_name FROM sqlite_master WHERE type='table' AND name NOT LIKE '\\_%' ESCAPE '\\'`,
|
|
52
52
|
checkpointSQL: null,
|
|
53
53
|
currentTimestamp: 'CURRENT_TIMESTAMP',
|
|
54
54
|
ilike: 'LIKE',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fts.d.ts","sourceRoot":"","sources":["../../src/database/fts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAuE5C,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAE3D;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAEjD;AAWD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;
|
|
1
|
+
{"version":3,"file":"fts.d.ts","sourceRoot":"","sources":["../../src/database/fts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAuE5C,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAE3D;AAED,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAEjD;AAWD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAqFD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBrE;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAehH;AAED,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAepF;AAED,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpF;AAokBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4B5E"}
|
package/dist/database/fts.js
CHANGED
|
@@ -102,14 +102,18 @@ function computeFtsSchema(collection) {
|
|
|
102
102
|
const selectExprs = ['t.uri', 't.cid', 't.did', 't.indexed_at'];
|
|
103
103
|
const searchColNames = [];
|
|
104
104
|
for (const col of schema.columns) {
|
|
105
|
+
// A blob column holds {ref, mimeType, size} metadata — no searchable text.
|
|
106
|
+
// This has to be decided on isJson, not on sqlType: SQLite's jsonType is
|
|
107
|
+
// TEXT, so a blob column would otherwise fall into the plain-TEXT branch
|
|
108
|
+
// below and be indexed as raw JSON.
|
|
109
|
+
if (col.isJson && record?.properties?.[col.originalName]?.type === 'blob')
|
|
110
|
+
continue;
|
|
105
111
|
if (col.sqlType === 'TEXT') {
|
|
106
112
|
selectExprs.push(`t.${q(col.name)}`);
|
|
107
113
|
searchColNames.push(col.name);
|
|
108
114
|
}
|
|
109
115
|
else if (col.isJson && record?.properties) {
|
|
110
116
|
const prop = record.properties[col.originalName];
|
|
111
|
-
if (prop?.type === 'blob')
|
|
112
|
-
continue; // skip blobs
|
|
113
117
|
if (prop && lexicon) {
|
|
114
118
|
const derived = jsonSearchColumns(`t.${q(col.name)}`, prop, lexicon, dialect);
|
|
115
119
|
if (derived.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/database/schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB;AAGD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAGD,wBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtC;AA+CD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CASlE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,EAAE,CASxE;AAID,wBAAgB,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAI9D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAExD;AAED,wBAAgB,cAAc,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,CAEtE;AAED,iFAAiF;AACjF,wBAAgB,eAAe,IAAI,GAAG,EAAE,CAEvC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/database/schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB;AAGD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAGD,wBAAgB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtC;AA+CD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CASlE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,EAAE,CASxE;AAID,wBAAgB,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAI9D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAExD;AAED,wBAAgB,cAAc,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,CAEtE;AAED,iFAAiF;AACjF,wBAAgB,eAAe,IAAI,GAAG,EAAE,CAEvC;AA8HD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,GAAG,EACZ,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,GAAE,UAA2B,GACnC,WAAW,CA+Gb;AAGD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,UAA2B,GAAG,MAAM,CAsExG;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,GAAE,UAA2B,GACnC;IAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CA2BrD"}
|
package/dist/database/schema.js
CHANGED
|
@@ -158,7 +158,10 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons, dialect)
|
|
|
158
158
|
let arrayField;
|
|
159
159
|
let wrapperField;
|
|
160
160
|
let propSource = branchDef.properties;
|
|
161
|
-
|
|
161
|
+
// `required` has to travel with propSource: once the columns come from the
|
|
162
|
+
// item (or wrapper target) def, the outer branch's `required` describes the
|
|
163
|
+
// wrapper property, not these columns.
|
|
164
|
+
let branchRequired = new Set(branchDef.required || []);
|
|
162
165
|
// Check for single-property wrapper patterns
|
|
163
166
|
const propEntries = Object.entries(branchDef.properties);
|
|
164
167
|
if (propEntries.length === 1) {
|
|
@@ -171,6 +174,7 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons, dialect)
|
|
|
171
174
|
isArray = true;
|
|
172
175
|
arrayField = onlyField;
|
|
173
176
|
propSource = itemDef.properties;
|
|
177
|
+
branchRequired = new Set(itemDef.required || []);
|
|
174
178
|
}
|
|
175
179
|
}
|
|
176
180
|
else if (onlyProp.type === 'ref' && onlyProp.ref) {
|
|
@@ -179,6 +183,7 @@ function resolveUnionBranch(ref, collection, fieldName, defs, lexicons, dialect)
|
|
|
179
183
|
if (refDef?.type === 'object' && refDef.properties) {
|
|
180
184
|
wrapperField = onlyField;
|
|
181
185
|
propSource = refDef.properties;
|
|
186
|
+
branchRequired = new Set(refDef.required || []);
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
189
|
}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -65,6 +65,14 @@ export declare function defineHook(event: 'on-commit', options: {
|
|
|
65
65
|
/**
|
|
66
66
|
* Discover and load the on-login hook from the project's `hooks/` directory.
|
|
67
67
|
* Looks for `on-login.ts` or `on-login.js`. Safe to call if no hook exists.
|
|
68
|
+
*
|
|
69
|
+
* The documented contract is `export default defineHook('on-login', handler)`,
|
|
70
|
+
* which is an object carrying the handler — the same shape the `server/`
|
|
71
|
+
* scanner recognizes by its `__type` tag. A bare async function is still
|
|
72
|
+
* accepted, because that is what the legacy `hooks/` directory used before
|
|
73
|
+
* `defineHook` existed. Anything else is reported rather than installed: a
|
|
74
|
+
* non-callable hook would otherwise fail silently on every login, since
|
|
75
|
+
* `fireOnLoginHook` swallows what the hook throws.
|
|
68
76
|
*/
|
|
69
77
|
export declare function loadOnLoginHook(hooksDir: string): Promise<void>;
|
|
70
78
|
/** Register a hook from a scanned server/ module. */
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.js
CHANGED
|
@@ -63,6 +63,14 @@ const onCommitHooks = [];
|
|
|
63
63
|
/**
|
|
64
64
|
* Discover and load the on-login hook from the project's `hooks/` directory.
|
|
65
65
|
* Looks for `on-login.ts` or `on-login.js`. Safe to call if no hook exists.
|
|
66
|
+
*
|
|
67
|
+
* The documented contract is `export default defineHook('on-login', handler)`,
|
|
68
|
+
* which is an object carrying the handler — the same shape the `server/`
|
|
69
|
+
* scanner recognizes by its `__type` tag. A bare async function is still
|
|
70
|
+
* accepted, because that is what the legacy `hooks/` directory used before
|
|
71
|
+
* `defineHook` existed. Anything else is reported rather than installed: a
|
|
72
|
+
* non-callable hook would otherwise fail silently on every login, since
|
|
73
|
+
* `fireOnLoginHook` swallows what the hook throws.
|
|
66
74
|
*/
|
|
67
75
|
export async function loadOnLoginHook(hooksDir) {
|
|
68
76
|
const tsPath = resolve(hooksDir, 'on-login.ts');
|
|
@@ -71,9 +79,24 @@ export async function loadOnLoginHook(hooksDir) {
|
|
|
71
79
|
if (!path)
|
|
72
80
|
return;
|
|
73
81
|
const mod = await import(__rewriteRelativeImportExtension(/* @vite-ignore */ `${path}?t=${Date.now()}`));
|
|
74
|
-
|
|
82
|
+
const handler = resolveHookHandler(mod.default);
|
|
83
|
+
if (!handler) {
|
|
84
|
+
emit('hooks', 'on_login_load_error', {
|
|
85
|
+
path,
|
|
86
|
+
error: 'default export is not a function or a defineHook("on-login", ...) result',
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
onLoginHook = handler;
|
|
75
91
|
log('[hooks] on-login hook loaded');
|
|
76
92
|
}
|
|
93
|
+
/** Unwrap a hook module's default export into the callable handler, if it has one. */
|
|
94
|
+
function resolveHookHandler(exported) {
|
|
95
|
+
if (typeof exported === 'function')
|
|
96
|
+
return exported;
|
|
97
|
+
const handler = exported?.handler;
|
|
98
|
+
return typeof handler === 'function' ? handler : null;
|
|
99
|
+
}
|
|
77
100
|
/** Mark a DID as pending, trigger auto-backfill, and wait for completion. */
|
|
78
101
|
async function ensureRepo(did) {
|
|
79
102
|
await setRepoStatus(did, 'pending');
|
package/dist/indexer.d.ts
CHANGED
|
@@ -33,9 +33,10 @@ export declare function resumeCursor(liveSeq: number | null, bootCursor: string
|
|
|
33
33
|
/** Reset module cursor state between tests. */
|
|
34
34
|
export declare function _resetCursorStateForTests(): void;
|
|
35
35
|
/**
|
|
36
|
-
* Drain the write buffer
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* Drain the write buffer instead of waiting out FLUSH_INTERVAL_MS. Lets
|
|
37
|
+
* end-to-end tests assert on rows immediately after feeding a frame — deletes
|
|
38
|
+
* included, since they are buffered alongside puts and so are covered by the
|
|
39
|
+
* same await.
|
|
39
40
|
*/
|
|
40
41
|
export declare function _flushForTests(): Promise<void>;
|
|
41
42
|
/**
|
package/dist/indexer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"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"}
|
package/dist/indexer.js
CHANGED
|
@@ -45,9 +45,10 @@ let indexerMaxRetries;
|
|
|
45
45
|
let indexerPlcUrl;
|
|
46
46
|
let maxConcurrentBackfills = 3;
|
|
47
47
|
/**
|
|
48
|
-
* Flush the write buffer —
|
|
49
|
-
* run label rules on inserted records, and
|
|
50
|
-
* threshold is reached. Emits a wide event
|
|
48
|
+
* Flush the write buffer — apply all buffered puts and deletes in arrival
|
|
49
|
+
* order, update the relay cursor, run label rules on inserted records, and
|
|
50
|
+
* trigger FTS rebuilds when the write threshold is reached. Emits a wide event
|
|
51
|
+
* with batch stats.
|
|
51
52
|
*/
|
|
52
53
|
async function flushBuffer() {
|
|
53
54
|
if (buffer.length === 0)
|
|
@@ -55,14 +56,38 @@ async function flushBuffer() {
|
|
|
55
56
|
const elapsed = timer();
|
|
56
57
|
const batch = buffer.splice(0);
|
|
57
58
|
let insertedCount = 0;
|
|
59
|
+
let deletedCount = 0;
|
|
58
60
|
const errors = [];
|
|
59
61
|
let cursorError;
|
|
60
62
|
const inserted = [];
|
|
63
|
+
const applied = [];
|
|
64
|
+
// Strictly sequential: two writes to the same URI in one batch must land in
|
|
65
|
+
// the order they arrived, so nothing here may run concurrently.
|
|
61
66
|
for (const item of batch) {
|
|
62
67
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
if (item.action === 'delete') {
|
|
69
|
+
await deleteRecord(item.collection, item.uri);
|
|
70
|
+
deletedCount++;
|
|
71
|
+
applied.push({
|
|
72
|
+
action: 'delete',
|
|
73
|
+
collection: item.collection,
|
|
74
|
+
uri: item.uri,
|
|
75
|
+
authorDid: item.authorDid,
|
|
76
|
+
record: null,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
await insertRecord(item.collection, item.uri, item.cid, item.authorDid, item.record);
|
|
81
|
+
insertedCount++;
|
|
82
|
+
inserted.push(item);
|
|
83
|
+
applied.push({
|
|
84
|
+
action: 'create',
|
|
85
|
+
collection: item.collection,
|
|
86
|
+
uri: item.uri,
|
|
87
|
+
authorDid: item.authorDid,
|
|
88
|
+
record: item.record,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
66
91
|
}
|
|
67
92
|
catch (err) {
|
|
68
93
|
errors.push(err.message);
|
|
@@ -88,14 +113,9 @@ async function flushBuffer() {
|
|
|
88
113
|
value: item.record,
|
|
89
114
|
}).catch(() => { });
|
|
90
115
|
}
|
|
91
|
-
// Fire on-commit hooks for
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
collection: item.collection,
|
|
95
|
-
uri: item.uri,
|
|
96
|
-
authorDid: item.authorDid,
|
|
97
|
-
record: item.record,
|
|
98
|
-
})));
|
|
116
|
+
// Fire on-commit hooks for everything the batch applied, in the order it was
|
|
117
|
+
// applied (async, non-blocking)
|
|
118
|
+
fireOnCommitHooks(applied);
|
|
99
119
|
// Aggregate collection counts and unique DIDs for wide event
|
|
100
120
|
const collections = {};
|
|
101
121
|
const dids = new Set();
|
|
@@ -106,6 +126,7 @@ async function flushBuffer() {
|
|
|
106
126
|
emit('indexer', 'flush', {
|
|
107
127
|
batch_size: batch.length,
|
|
108
128
|
inserted_count: insertedCount,
|
|
129
|
+
deleted_count: deletedCount,
|
|
109
130
|
error_count: errors.length,
|
|
110
131
|
cursor_seq: lastSeq,
|
|
111
132
|
duration_ms: elapsed(),
|
|
@@ -125,16 +146,32 @@ async function flushBuffer() {
|
|
|
125
146
|
}
|
|
126
147
|
}
|
|
127
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Run a flush once every flush already queued has finished.
|
|
151
|
+
*
|
|
152
|
+
* Nothing awaits the flush a full batch triggers, and the interval timer can
|
|
153
|
+
* fire while that flush is still waiting on the database. Two flushes in flight
|
|
154
|
+
* hold disjoint batches but interleave their awaits, so a write in the later
|
|
155
|
+
* batch can reach the database before one in the earlier batch — which would
|
|
156
|
+
* give back exactly the cross-batch reordering the single buffer removes.
|
|
157
|
+
* Chaining them costs nothing on an idle indexer and keeps the queue global.
|
|
158
|
+
*/
|
|
159
|
+
let flushChain = Promise.resolve();
|
|
160
|
+
function enqueueFlush() {
|
|
161
|
+
const next = flushChain.then(() => flushBuffer(), () => flushBuffer());
|
|
162
|
+
flushChain = next;
|
|
163
|
+
return next;
|
|
164
|
+
}
|
|
128
165
|
/** Schedule a flush after FLUSH_INTERVAL_MS if one isn't already pending. */
|
|
129
166
|
function scheduleFlush() {
|
|
130
167
|
if (flushTimer)
|
|
131
168
|
return;
|
|
132
|
-
flushTimer = setTimeout(
|
|
169
|
+
flushTimer = setTimeout(() => {
|
|
133
170
|
flushTimer = null;
|
|
134
|
-
|
|
171
|
+
void enqueueFlush().catch(() => { });
|
|
135
172
|
}, FLUSH_INTERVAL_MS);
|
|
136
173
|
}
|
|
137
|
-
/** Add a
|
|
174
|
+
/** Add a write to the buffer. Flushes immediately if BATCH_SIZE is reached. */
|
|
138
175
|
function bufferWrite(item) {
|
|
139
176
|
buffer.push(item);
|
|
140
177
|
if (buffer.length >= BATCH_SIZE) {
|
|
@@ -142,7 +179,7 @@ function bufferWrite(item) {
|
|
|
142
179
|
clearTimeout(flushTimer);
|
|
143
180
|
flushTimer = null;
|
|
144
181
|
}
|
|
145
|
-
|
|
182
|
+
void enqueueFlush().catch(() => { });
|
|
146
183
|
}
|
|
147
184
|
else {
|
|
148
185
|
scheduleFlush();
|
|
@@ -196,16 +233,17 @@ export function _resetCursorStateForTests() {
|
|
|
196
233
|
cursorKey = 'relay';
|
|
197
234
|
}
|
|
198
235
|
/**
|
|
199
|
-
* Drain the write buffer
|
|
200
|
-
*
|
|
201
|
-
*
|
|
236
|
+
* Drain the write buffer instead of waiting out FLUSH_INTERVAL_MS. Lets
|
|
237
|
+
* end-to-end tests assert on rows immediately after feeding a frame — deletes
|
|
238
|
+
* included, since they are buffered alongside puts and so are covered by the
|
|
239
|
+
* same await.
|
|
202
240
|
*/
|
|
203
241
|
export async function _flushForTests() {
|
|
204
242
|
if (flushTimer) {
|
|
205
243
|
clearTimeout(flushTimer);
|
|
206
244
|
flushTimer = null;
|
|
207
245
|
}
|
|
208
|
-
await
|
|
246
|
+
await enqueueFlush();
|
|
209
247
|
}
|
|
210
248
|
/**
|
|
211
249
|
* Auto-backfill a DID's repo when first seen on the firehose.
|
|
@@ -262,7 +300,14 @@ export async function triggerAutoBackfill(did, attempt = 0) {
|
|
|
262
300
|
backfillInFlight.delete(did);
|
|
263
301
|
for (const item of buffered) {
|
|
264
302
|
try {
|
|
265
|
-
|
|
303
|
+
if (item.action === 'delete') {
|
|
304
|
+
// A delete that arrived mid-backfill has to be replayed after the CAR
|
|
305
|
+
// export lands, or the export's snapshot of the record outlives it.
|
|
306
|
+
await deleteRecord(item.collection, item.uri);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
await insertRecord(item.collection, item.uri, item.cid, item.authorDid, item.record);
|
|
310
|
+
}
|
|
266
311
|
}
|
|
267
312
|
catch {
|
|
268
313
|
replayErrors++;
|
|
@@ -295,28 +340,6 @@ export async function triggerAutoBackfill(did, attempt = 0) {
|
|
|
295
340
|
}, delayMs);
|
|
296
341
|
}
|
|
297
342
|
}
|
|
298
|
-
/** Emit a memory diagnostics wide event every 30s for observability. */
|
|
299
|
-
function startMemoryDiagnostics() {
|
|
300
|
-
setInterval(() => {
|
|
301
|
-
const mem = process.memoryUsage();
|
|
302
|
-
let pendingBufferItems = 0;
|
|
303
|
-
for (const [, items] of pendingBuffers) {
|
|
304
|
-
pendingBufferItems += items.length;
|
|
305
|
-
}
|
|
306
|
-
emit('diagnostics', 'memory', {
|
|
307
|
-
heap_used_mb: Math.round(mem.heapUsed / 1024 / 1024),
|
|
308
|
-
heap_total_mb: Math.round(mem.heapTotal / 1024 / 1024),
|
|
309
|
-
rss_mb: Math.round(mem.rss / 1024 / 1024),
|
|
310
|
-
external_mb: Math.round(mem.external / 1024 / 1024),
|
|
311
|
-
array_buffers_mb: Math.round(mem.arrayBuffers / 1024 / 1024),
|
|
312
|
-
write_buffer_len: buffer.length,
|
|
313
|
-
pending_buffer_dids: pendingBuffers.size,
|
|
314
|
-
pending_buffer_items: pendingBufferItems,
|
|
315
|
-
backfill_in_flight: backfillInFlight.size,
|
|
316
|
-
repo_status_cache_size: repoStatusCache.size,
|
|
317
|
-
});
|
|
318
|
-
}, 30_000);
|
|
319
|
-
}
|
|
320
343
|
/**
|
|
321
344
|
* Connect to the AT Protocol relay firehose and begin indexing.
|
|
322
345
|
*
|
|
@@ -346,7 +369,6 @@ export async function configureIndexer(opts) {
|
|
|
346
369
|
}
|
|
347
370
|
log(`[indexer] Warmed repo status cache with ${statuses.length} entries`);
|
|
348
371
|
}
|
|
349
|
-
// startMemoryDiagnostics()
|
|
350
372
|
// Checkpoint the cursor on a timer regardless of write activity (see
|
|
351
373
|
// checkpointCursor). Guarded so reconnects don't stack intervals; unref'd so
|
|
352
374
|
// it never keeps the process alive.
|
|
@@ -558,19 +580,21 @@ export function applyCommit(did, ops) {
|
|
|
558
580
|
// For non-signal ops (e.g. profile updates), only process if this DID is already tracked
|
|
559
581
|
if (!hasSignalOp && repoStatus === null)
|
|
560
582
|
return;
|
|
583
|
+
/** Queue a write behind anything already queued for this DID. */
|
|
584
|
+
const enqueue = (item) => {
|
|
585
|
+
// If DID is mid-backfill, buffer instead of writing directly
|
|
586
|
+
if (pendingBuffers.has(did))
|
|
587
|
+
pendingBuffers.get(did).push(item);
|
|
588
|
+
else
|
|
589
|
+
bufferWrite(item);
|
|
590
|
+
};
|
|
561
591
|
for (const op of ops) {
|
|
562
592
|
const uri = `at://${did}/${op.collection}/${op.rkey}`;
|
|
563
593
|
if (op.action === 'delete') {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
collection: op.collection,
|
|
569
|
-
uri,
|
|
570
|
-
authorDid: did,
|
|
571
|
-
record: null,
|
|
572
|
-
},
|
|
573
|
-
]);
|
|
594
|
+
// Buffered, not applied here: see {@link WriteBuffer}. The on-commit hook
|
|
595
|
+
// fires from the flush too, so a handler never sees a delete announced
|
|
596
|
+
// before the row is actually gone.
|
|
597
|
+
enqueue({ action: 'delete', collection: op.collection, uri, authorDid: did });
|
|
574
598
|
continue;
|
|
575
599
|
}
|
|
576
600
|
const record = op.record;
|
|
@@ -588,14 +612,7 @@ export function applyCommit(did, ops) {
|
|
|
588
612
|
});
|
|
589
613
|
continue;
|
|
590
614
|
}
|
|
591
|
-
|
|
592
|
-
// If DID is mid-backfill, buffer instead of writing directly
|
|
593
|
-
if (pendingBuffers.has(did)) {
|
|
594
|
-
pendingBuffers.get(did).push(item);
|
|
595
|
-
}
|
|
596
|
-
else {
|
|
597
|
-
bufferWrite(item);
|
|
598
|
-
}
|
|
615
|
+
enqueue({ action: 'put', collection: op.collection, uri, cid: op.cid, authorDid: did, record });
|
|
599
616
|
}
|
|
600
617
|
}
|
|
601
618
|
/**
|
package/dist/opengraph.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opengraph.d.ts","sourceRoot":"","sources":["../src/opengraph.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC3B,QAAQ,CAAC,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAA;QAC3C,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;CACF;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACpD;AAED,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAA;IAC5D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAChD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC;;;oBAA7C,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC;EAEnG;
|
|
1
|
+
{"version":3,"file":"opengraph.d.ts","sourceRoot":"","sources":["../src/opengraph.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC3B,QAAQ,CAAC,EAAE,CAAC,UAAU,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAAA;QAC3C,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;CACF;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACpD;AAED,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAA;IAC5D,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAChD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC;;;oBAA7C,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC;EAEnG;AAiDD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEhE;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAC9D,GAAG,IAAI,CAqDP;AAED,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+BrF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyC3E"}
|
package/dist/opengraph.js
CHANGED
|
@@ -32,6 +32,20 @@ let defaultFont = null;
|
|
|
32
32
|
const cache = new Map();
|
|
33
33
|
const CACHE_TTL = 5 * 60 * 1000;
|
|
34
34
|
const CACHE_MAX = 200;
|
|
35
|
+
/**
|
|
36
|
+
* Read a font file as an ArrayBuffer holding *only* that font's bytes.
|
|
37
|
+
*
|
|
38
|
+
* `readFileSync` returns a Buffer that, for small files, is a view into Node's
|
|
39
|
+
* shared 64 KB allocation pool — so `buffer.buffer` is the whole pool, not the
|
|
40
|
+
* font, and the font generally starts at a nonzero `byteOffset`. Handing that
|
|
41
|
+
* to satori makes it read whatever happened to be pooled before the font and
|
|
42
|
+
* reject the result with "Unsupported OpenType signature". Slice out the
|
|
43
|
+
* view's own range instead.
|
|
44
|
+
*/
|
|
45
|
+
function readFontData(fontPath) {
|
|
46
|
+
const fontData = readFileSync(fontPath);
|
|
47
|
+
return fontData.buffer.slice(fontData.byteOffset, fontData.byteOffset + fontData.byteLength);
|
|
48
|
+
}
|
|
35
49
|
function compilePath(path) {
|
|
36
50
|
const paramNames = [];
|
|
37
51
|
const re = path.replace(/:([^/]+)/g, (_, name) => {
|
|
@@ -44,8 +58,7 @@ export async function initOpengraph(ogDir) {
|
|
|
44
58
|
// Load default font
|
|
45
59
|
try {
|
|
46
60
|
const fontPath = resolve(import.meta.dirname, '..', 'fonts', 'Inter-Regular.woff');
|
|
47
|
-
|
|
48
|
-
defaultFont = { name: 'Inter', data: fontData.buffer, weight: 400, style: 'normal' };
|
|
61
|
+
defaultFont = { name: 'Inter', data: readFontData(fontPath), weight: 400, style: 'normal' };
|
|
49
62
|
log('[opengraph] loaded default font: Inter');
|
|
50
63
|
}
|
|
51
64
|
catch {
|
|
@@ -121,8 +134,7 @@ export function registerOgHandler(ogMod) {
|
|
|
121
134
|
if (!defaultFont) {
|
|
122
135
|
try {
|
|
123
136
|
const fontPath = resolve(import.meta.dirname, '..', 'fonts', 'Inter-Regular.woff');
|
|
124
|
-
|
|
125
|
-
defaultFont = { name: 'Inter', data: fontData.buffer, weight: 400, style: 'normal' };
|
|
137
|
+
defaultFont = { name: 'Inter', data: readFontData(fontPath), weight: 400, style: 'normal' };
|
|
126
138
|
}
|
|
127
139
|
catch { }
|
|
128
140
|
}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAsEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAsEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAyD9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAuM3F;AAgDD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxF,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAwkC5F;AAGD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,MAAM,GAAE,MAAM,EAAO,EACrB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,OAAO,WAAW,EAAE,MAAM,CAG5B"}
|
package/dist/server.js
CHANGED
|
@@ -20,6 +20,36 @@ import { json, jsonError, cors, withCors, file, notFound } from "./response.js";
|
|
|
20
20
|
import { collectionFromUri, isPrivateCollection } from "./private-collections.js";
|
|
21
21
|
import { serve } from "./adapter.js";
|
|
22
22
|
import { renderPage } from "./renderer.js";
|
|
23
|
+
/**
|
|
24
|
+
* Parse a client-supplied `limit`, or null if it is not a usable one.
|
|
25
|
+
*
|
|
26
|
+
* `parseInt` alone lets `limit=abc` through as NaN and `limit=-5` through as a
|
|
27
|
+
* negative bound, both of which reach the database driver: the first as a
|
|
28
|
+
* datatype error, the second as "no limit at all" on SQLite. Neither is a
|
|
29
|
+
* server fault, so the caller turns a null into a 400.
|
|
30
|
+
*/
|
|
31
|
+
function parseLimit(raw, fallback) {
|
|
32
|
+
if (raw === null || raw === '')
|
|
33
|
+
return fallback;
|
|
34
|
+
if (!/^\d+$/.test(raw))
|
|
35
|
+
return null;
|
|
36
|
+
const value = Number(raw);
|
|
37
|
+
return value >= 1 ? value : null;
|
|
38
|
+
}
|
|
39
|
+
/** Whether `sort` names a column queryRecords can order this collection by. */
|
|
40
|
+
function isSortableField(collection, sort) {
|
|
41
|
+
if (sort === 'indexed_at')
|
|
42
|
+
return true;
|
|
43
|
+
const schema = getSchema(collection);
|
|
44
|
+
return !!schema?.columns.some((c) => c.originalName === sort || c.name === sort);
|
|
45
|
+
}
|
|
46
|
+
/** Narrow a client-supplied `order` to the two values that may reach ORDER BY. */
|
|
47
|
+
function parseOrder(raw) {
|
|
48
|
+
if (!raw)
|
|
49
|
+
return undefined;
|
|
50
|
+
const lowered = raw.toLowerCase();
|
|
51
|
+
return lowered === 'asc' || lowered === 'desc' ? lowered : null;
|
|
52
|
+
}
|
|
23
53
|
function scopeMissingResponse(acceptEncoding, handle) {
|
|
24
54
|
const res = withCors(json({ error: 'ScopeMissingError', ...(handle ? { handle } : {}) }, 401, acceptEncoding));
|
|
25
55
|
res.headers.append('Set-Cookie', clearSessionCookieHeader());
|
|
@@ -45,7 +75,11 @@ export function registerCoreHandlers(collections, oauth) {
|
|
|
45
75
|
if (!getSchema(collection))
|
|
46
76
|
throw new NotFoundError(`Unknown collection: ${collection}`);
|
|
47
77
|
const sort = params.sort || undefined;
|
|
48
|
-
|
|
78
|
+
if (sort && !isSortableField(collection, sort))
|
|
79
|
+
throw new InvalidRequestError(`Invalid sort field: ${sort}`);
|
|
80
|
+
const order = parseOrder(params.order);
|
|
81
|
+
if (order === null)
|
|
82
|
+
throw new InvalidRequestError(`Invalid order: ${params.order}`);
|
|
49
83
|
const reserved = new Set(['collection', 'limit', 'cursor', 'sort', 'order']);
|
|
50
84
|
const filters = {};
|
|
51
85
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -358,11 +392,23 @@ export function createHandler(config) {
|
|
|
358
392
|
return withCors(jsonError(404, `Unknown collection: ${collection}`, acceptEncoding));
|
|
359
393
|
if (!getSchema(collection))
|
|
360
394
|
return withCors(jsonError(404, `Unknown collection: ${collection}`, acceptEncoding));
|
|
361
|
-
|
|
395
|
+
// Every one of these is attacker-controlled, and queryRecords trusts
|
|
396
|
+
// what it is handed: `sort` and `order` reach the ORDER BY clause and a
|
|
397
|
+
// non-numeric `limit` reaches the driver. Rejecting them here keeps a
|
|
398
|
+
// bad query string a 400 instead of a 500 (or worse).
|
|
399
|
+
const limit = parseLimit(url.searchParams.get('limit'), 20);
|
|
400
|
+
if (limit === null)
|
|
401
|
+
return withCors(jsonError(400, 'Invalid limit parameter', acceptEncoding));
|
|
362
402
|
const cursor = url.searchParams.get('cursor') || undefined;
|
|
363
403
|
const sort = url.searchParams.get('sort') || undefined;
|
|
364
|
-
const order = (url.searchParams.get('order')
|
|
365
|
-
|
|
404
|
+
const order = parseOrder(url.searchParams.get('order'));
|
|
405
|
+
if (order === null)
|
|
406
|
+
return withCors(jsonError(400, `Invalid order: ${url.searchParams.get('order')}`, acceptEncoding));
|
|
407
|
+
if (sort && !isSortableField(collection, sort))
|
|
408
|
+
return withCors(jsonError(400, `Invalid sort field: ${sort}`, acceptEncoding));
|
|
409
|
+
// Collect field filters (everything except reserved params). An
|
|
410
|
+
// unknown field is ignored rather than rejected — queryRecords does
|
|
411
|
+
// the same, and clients rely on passing through extra params.
|
|
366
412
|
const reserved = new Set(['collection', 'limit', 'cursor', 'sort', 'order']);
|
|
367
413
|
const filters = {};
|
|
368
414
|
for (const [key, value] of url.searchParams) {
|
|
@@ -920,7 +966,24 @@ export function createHandler(config) {
|
|
|
920
966
|
}
|
|
921
967
|
if (!code)
|
|
922
968
|
return withCors(jsonError(400, 'Missing code', acceptEncoding));
|
|
923
|
-
|
|
969
|
+
let result;
|
|
970
|
+
try {
|
|
971
|
+
result = await handleCallback(oauth, code, state, iss);
|
|
972
|
+
}
|
|
973
|
+
catch (err) {
|
|
974
|
+
// Same convention as the token endpoint below: an error that names
|
|
975
|
+
// its own status keeps it, anything else is a genuine failure and
|
|
976
|
+
// falls through to the 500.
|
|
977
|
+
if (err instanceof OAuthError)
|
|
978
|
+
return withCors(json({ error: err.code, error_description: err.description }, err.status, acceptEncoding));
|
|
979
|
+
// A callback matching no pending authorization request is a stale
|
|
980
|
+
// redirect, not a server fault — the request expired while a login
|
|
981
|
+
// tab sat open, or the user came back to a login they already
|
|
982
|
+
// finished. Answer like the other client errors on this route.
|
|
983
|
+
if (err instanceof Error && err.message === 'No matching authorization request found')
|
|
984
|
+
return withCors(jsonError(400, err.message, acceptEncoding));
|
|
985
|
+
throw err;
|
|
986
|
+
}
|
|
924
987
|
const isSecure = requestOrigin.startsWith('https');
|
|
925
988
|
const handle = (await getRepoHandle(result.did)) ?? result.did;
|
|
926
989
|
const session = { did: result.did, handle };
|
package/dist/xrpc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xrpc.d.ts","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"xrpc.d.ts","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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"}
|
package/dist/xrpc.js
CHANGED
|
@@ -62,7 +62,7 @@ let _cdn = null;
|
|
|
62
62
|
export function isLocalRelay() {
|
|
63
63
|
try {
|
|
64
64
|
const host = new URL(_relayUrl).hostname;
|
|
65
|
-
return host === 'localhost' || host === '127.0.0.1' || host === '[::1]' || host === '::1' || host.endsWith('.localhost');
|
|
65
|
+
return (host === 'localhost' || host === '127.0.0.1' || host === '[::1]' || host === '::1' || host.endsWith('.localhost'));
|
|
66
66
|
}
|
|
67
67
|
catch {
|
|
68
68
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hatk/hatk",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.85",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"hatk": "dist/cli.js"
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"clean": "rm -rf dist",
|
|
32
32
|
"build": "npm run clean && tsc -p tsconfig.build.json && cp -r src/templates dist/templates && cp -r src/lexicons dist/lexicons",
|
|
33
33
|
"prepublishOnly": "npm run build",
|
|
34
|
-
"test": "vitest run"
|
|
34
|
+
"test": "vitest run --coverage",
|
|
35
|
+
"test:watch": "vitest"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
38
|
"@bigmoves/lexicon": "^0.2.2",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@types/better-sqlite3": "^7.6.13",
|
|
48
49
|
"@types/react": "^19.2.14",
|
|
50
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
49
51
|
"vite": "^8.0.0"
|
|
50
52
|
},
|
|
51
53
|
"peerDependencies": {
|