@clioplaylists/clio 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.env +7 -0
- package/dist/api/com/clioplaylists/alpha/actor/getProfile.js +37 -0
- package/dist/api/com/clioplaylists/alpha/feed/getSongs.js +37 -0
- package/dist/api/health.js +32 -0
- package/dist/api/index.js +43 -0
- package/dist/api/util.js +17 -0
- package/dist/auth-verifier.js +473 -0
- package/dist/client.js +40 -0
- package/dist/config.js +65 -0
- package/dist/context.js +19 -0
- package/dist/dataplane/bsync/index.js +150 -0
- package/dist/dataplane/client.js +165 -0
- package/dist/dataplane/index.js +18 -0
- package/dist/dataplane/server/background.js +51 -0
- package/dist/dataplane/server/db/database-schema.js +2 -0
- package/dist/dataplane/server/db/db.js +228 -0
- package/dist/dataplane/server/db/index.js +17 -0
- package/dist/dataplane/server/db/migrations/20230309T045948368Z-init.js +117 -0
- package/dist/dataplane/server/db/migrations/20230420T211446071Z-did-cache.js +15 -0
- package/dist/dataplane/server/db/migrations/index.js +41 -0
- package/dist/dataplane/server/db/migrations/provider.js +31 -0
- package/dist/dataplane/server/db/pagination.js +144 -0
- package/dist/dataplane/server/db/tables/actor-sync.js +4 -0
- package/dist/dataplane/server/db/tables/actor.js +4 -0
- package/dist/dataplane/server/db/tables/artist-list-item.js +4 -0
- package/dist/dataplane/server/db/tables/artist.js +4 -0
- package/dist/dataplane/server/db/tables/playlist-idea.js +4 -0
- package/dist/dataplane/server/db/tables/playlist-item.js +4 -0
- package/dist/dataplane/server/db/tables/playlist.js +4 -0
- package/dist/dataplane/server/db/tables/profile.js +4 -0
- package/dist/dataplane/server/db/tables/record.js +4 -0
- package/dist/dataplane/server/db/tables/song.js +4 -0
- package/dist/dataplane/server/db/types.js +2 -0
- package/dist/dataplane/server/db/util.js +48 -0
- package/dist/dataplane/server/index.js +52 -0
- package/dist/dataplane/server/indexing/index.js +321 -0
- package/dist/dataplane/server/indexing/plugins/playlist-idea.js +163 -0
- package/dist/dataplane/server/indexing/plugins/profile.js +81 -0
- package/dist/dataplane/server/indexing/processor.js +90 -0
- package/dist/dataplane/server/routes/blocks.js +95 -0
- package/dist/dataplane/server/routes/feed-gens.js +56 -0
- package/dist/dataplane/server/routes/feeds.js +128 -0
- package/dist/dataplane/server/routes/follows.js +122 -0
- package/dist/dataplane/server/routes/identity.js +56 -0
- package/dist/dataplane/server/routes/index.js +19 -0
- package/dist/dataplane/server/routes/interactions.js +111 -0
- package/dist/dataplane/server/routes/labels.js +73 -0
- package/dist/dataplane/server/routes/likes.js +76 -0
- package/dist/dataplane/server/routes/lists.js +77 -0
- package/dist/dataplane/server/routes/moderation.js +92 -0
- package/dist/dataplane/server/routes/mutes.js +166 -0
- package/dist/dataplane/server/routes/notifs.js +137 -0
- package/dist/dataplane/server/routes/posts.js +19 -0
- package/dist/dataplane/server/routes/profile.js +61 -0
- package/dist/dataplane/server/routes/quotes.js +26 -0
- package/dist/dataplane/server/routes/records.js +88 -0
- package/dist/dataplane/server/routes/relationships.js +157 -0
- package/dist/dataplane/server/routes/reposts.js +59 -0
- package/dist/dataplane/server/routes/search.js +70 -0
- package/dist/dataplane/server/routes/starter-packs.js +24 -0
- package/dist/dataplane/server/routes/suggestions.js +134 -0
- package/dist/dataplane/server/routes/sync.js +14 -0
- package/dist/dataplane/server/routes/threads.js +31 -0
- package/dist/dataplane/server/subscription.js +114 -0
- package/dist/dataplane/server/util.js +117 -0
- package/dist/error.js +14 -0
- package/dist/index.js +115 -0
- package/dist/lexicons/index.js +638 -0
- package/dist/lexicons/lexicons.js +4551 -0
- package/dist/lexicons/types/com/atproto/admin/defs.js +54 -0
- package/dist/lexicons/types/com/atproto/admin/deleteAccount.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/disableAccountInvites.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/disableInviteCodes.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/enableAccountInvites.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/getAccountInfo.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/getAccountInfos.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/getInviteCodes.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/getSubjectStatus.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/searchAccounts.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/sendEmail.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/updateAccountEmail.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/updateAccountHandle.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/updateAccountPassword.js +2 -0
- package/dist/lexicons/types/com/atproto/admin/updateSubjectStatus.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/defs.js +14 -0
- package/dist/lexicons/types/com/atproto/identity/getRecommendedDidCredentials.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/refreshIdentity.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/requestPlcOperationSignature.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/resolveDid.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/resolveHandle.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/resolveIdentity.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/signPlcOperation.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/submitPlcOperation.js +2 -0
- package/dist/lexicons/types/com/atproto/identity/updateHandle.js +2 -0
- package/dist/lexicons/types/com/atproto/label/defs.js +54 -0
- package/dist/lexicons/types/com/atproto/label/queryLabels.js +2 -0
- package/dist/lexicons/types/com/atproto/label/subscribeLabels.js +24 -0
- package/dist/lexicons/types/com/atproto/lexicon/schema.js +15 -0
- package/dist/lexicons/types/com/atproto/moderation/createReport.js +2 -0
- package/dist/lexicons/types/com/atproto/moderation/defs.js +20 -0
- package/dist/lexicons/types/com/atproto/repo/applyWrites.js +64 -0
- package/dist/lexicons/types/com/atproto/repo/createRecord.js +2 -0
- package/dist/lexicons/types/com/atproto/repo/defs.js +14 -0
- package/dist/lexicons/types/com/atproto/repo/deleteRecord.js +2 -0
- package/dist/lexicons/types/com/atproto/repo/describeRepo.js +2 -0
- package/dist/lexicons/types/com/atproto/repo/getRecord.js +2 -0
- package/dist/lexicons/types/com/atproto/repo/importRepo.js +2 -0
- package/dist/lexicons/types/com/atproto/repo/listMissingBlobs.js +14 -0
- package/dist/lexicons/types/com/atproto/repo/listRecords.js +14 -0
- package/dist/lexicons/types/com/atproto/repo/putRecord.js +2 -0
- package/dist/lexicons/types/com/atproto/repo/strongRef.js +15 -0
- package/dist/lexicons/types/com/atproto/repo/uploadBlob.js +2 -0
- package/dist/lexicons/types/com/atproto/server/activateAccount.js +2 -0
- package/dist/lexicons/types/com/atproto/server/checkAccountStatus.js +2 -0
- package/dist/lexicons/types/com/atproto/server/confirmEmail.js +2 -0
- package/dist/lexicons/types/com/atproto/server/createAccount.js +2 -0
- package/dist/lexicons/types/com/atproto/server/createAppPassword.js +14 -0
- package/dist/lexicons/types/com/atproto/server/createInviteCode.js +2 -0
- package/dist/lexicons/types/com/atproto/server/createInviteCodes.js +14 -0
- package/dist/lexicons/types/com/atproto/server/createSession.js +2 -0
- package/dist/lexicons/types/com/atproto/server/deactivateAccount.js +2 -0
- package/dist/lexicons/types/com/atproto/server/defs.js +24 -0
- package/dist/lexicons/types/com/atproto/server/deleteAccount.js +2 -0
- package/dist/lexicons/types/com/atproto/server/deleteSession.js +2 -0
- package/dist/lexicons/types/com/atproto/server/describeServer.js +24 -0
- package/dist/lexicons/types/com/atproto/server/getAccountInviteCodes.js +2 -0
- package/dist/lexicons/types/com/atproto/server/getServiceAuth.js +2 -0
- package/dist/lexicons/types/com/atproto/server/getSession.js +2 -0
- package/dist/lexicons/types/com/atproto/server/listAppPasswords.js +14 -0
- package/dist/lexicons/types/com/atproto/server/refreshSession.js +2 -0
- package/dist/lexicons/types/com/atproto/server/requestAccountDelete.js +2 -0
- package/dist/lexicons/types/com/atproto/server/requestEmailConfirmation.js +2 -0
- package/dist/lexicons/types/com/atproto/server/requestEmailUpdate.js +2 -0
- package/dist/lexicons/types/com/atproto/server/requestPasswordReset.js +2 -0
- package/dist/lexicons/types/com/atproto/server/reserveSigningKey.js +2 -0
- package/dist/lexicons/types/com/atproto/server/resetPassword.js +2 -0
- package/dist/lexicons/types/com/atproto/server/revokeAppPassword.js +2 -0
- package/dist/lexicons/types/com/atproto/server/updateEmail.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getBlob.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getBlocks.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getCheckout.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getHead.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getLatestCommit.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getRecord.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getRepo.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/getRepoStatus.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/listBlobs.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/listRepos.js +14 -0
- package/dist/lexicons/types/com/atproto/sync/listReposByCollection.js +14 -0
- package/dist/lexicons/types/com/atproto/sync/notifyOfUpdate.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/requestCrawl.js +2 -0
- package/dist/lexicons/types/com/atproto/sync/subscribeRepos.js +64 -0
- package/dist/lexicons/types/com/atproto/temp/addReservedHandle.js +2 -0
- package/dist/lexicons/types/com/atproto/temp/checkSignupQueue.js +2 -0
- package/dist/lexicons/types/com/atproto/temp/fetchLabels.js +2 -0
- package/dist/lexicons/types/com/atproto/temp/requestPhoneVerification.js +2 -0
- package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.js +15 -0
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.js +24 -0
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/getSongs.js +2 -0
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.js +35 -0
- package/dist/lexicons/types/com/clioplaylists/alpha/feed/song.js +25 -0
- package/dist/lexicons/util.js +13 -0
- package/dist/logger.js +26 -0
- package/dist/rpc/clio_connect.js +110 -0
- package/dist/rpc/clio_pb.js +1365 -0
- package/dist/start.js +13 -0
- package/dist/util/retry.js +16 -0
- package/dist/util/uris.js +7 -0
- package/dist/util.js +119 -0
- package/package.json +73 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dummyDialect = exports.valuesList = exports.noMatch = exports.excluded = exports.countAll = exports.softDeleted = exports.notSoftDeletedClause = exports.actorWhereClause = void 0;
|
|
4
|
+
const kysely_1 = require("kysely");
|
|
5
|
+
const actorWhereClause = (actor) => {
|
|
6
|
+
if (actor.startsWith('did:')) {
|
|
7
|
+
return (0, kysely_1.sql) `"actor"."did" = ${actor}`;
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
return (0, kysely_1.sql) `"actor"."handle" = ${actor}`;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
exports.actorWhereClause = actorWhereClause;
|
|
14
|
+
// Applies to actor or record table
|
|
15
|
+
const notSoftDeletedClause = (alias) => {
|
|
16
|
+
return (0, kysely_1.sql) `${alias}."takedownRef" is null`;
|
|
17
|
+
};
|
|
18
|
+
exports.notSoftDeletedClause = notSoftDeletedClause;
|
|
19
|
+
const softDeleted = (actorOrRecord) => {
|
|
20
|
+
return actorOrRecord.takedownRef !== null;
|
|
21
|
+
};
|
|
22
|
+
exports.softDeleted = softDeleted;
|
|
23
|
+
exports.countAll = (0, kysely_1.sql) `count(*)`;
|
|
24
|
+
// For use with doUpdateSet()
|
|
25
|
+
const excluded = (db, col) => {
|
|
26
|
+
return (0, kysely_1.sql) `${db.dynamic.ref(`excluded.${col}`)}`;
|
|
27
|
+
};
|
|
28
|
+
exports.excluded = excluded;
|
|
29
|
+
exports.noMatch = (0, kysely_1.sql) `1 = 0`;
|
|
30
|
+
// Can be useful for large where-in clauses, to get the db to use a hash lookup on the list
|
|
31
|
+
const valuesList = (vals) => {
|
|
32
|
+
return (0, kysely_1.sql) `(values (${kysely_1.sql.join(vals, (0, kysely_1.sql) `), (`)}))`;
|
|
33
|
+
};
|
|
34
|
+
exports.valuesList = valuesList;
|
|
35
|
+
exports.dummyDialect = {
|
|
36
|
+
createAdapter() {
|
|
37
|
+
return new kysely_1.SqliteAdapter();
|
|
38
|
+
},
|
|
39
|
+
createDriver() {
|
|
40
|
+
return new kysely_1.DummyDriver();
|
|
41
|
+
},
|
|
42
|
+
createIntrospector(db) {
|
|
43
|
+
return new kysely_1.SqliteIntrospector(db);
|
|
44
|
+
},
|
|
45
|
+
createQueryCompiler() {
|
|
46
|
+
return new kysely_1.SqliteQueryCompiler();
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DataPlaneServer = exports.RepoSubscription = void 0;
|
|
7
|
+
const identity_1 = require("@atproto/identity");
|
|
8
|
+
const connect_express_1 = require("@connectrpc/connect-express");
|
|
9
|
+
const express_1 = __importDefault(require("express"));
|
|
10
|
+
const node_events_1 = __importDefault(require("node:events"));
|
|
11
|
+
const routes_1 = __importDefault(require("./routes"));
|
|
12
|
+
var subscription_1 = require("./subscription");
|
|
13
|
+
Object.defineProperty(exports, "RepoSubscription", { enumerable: true, get: function () { return subscription_1.RepoSubscription; } });
|
|
14
|
+
class DataPlaneServer {
|
|
15
|
+
constructor(server, idResolver) {
|
|
16
|
+
Object.defineProperty(this, "server", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: server
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "idResolver", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: idResolver
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
static async create(db, port, plcUrl) {
|
|
30
|
+
const app = (0, express_1.default)();
|
|
31
|
+
const didCache = new identity_1.MemoryCache();
|
|
32
|
+
const idResolver = new identity_1.IdResolver({ plcUrl, didCache });
|
|
33
|
+
const routes = (0, routes_1.default)(db, idResolver);
|
|
34
|
+
app.use((0, connect_express_1.expressConnectMiddleware)({ routes }));
|
|
35
|
+
const server = app.listen(port);
|
|
36
|
+
await node_events_1.default.once(server, 'listening');
|
|
37
|
+
return new DataPlaneServer(server, idResolver);
|
|
38
|
+
}
|
|
39
|
+
async destroy() {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
this.server.close((err) => {
|
|
42
|
+
if (err) {
|
|
43
|
+
reject(err);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
resolve();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.DataPlaneServer = DataPlaneServer;
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.IndexingService = void 0;
|
|
37
|
+
const api_1 = require("@atproto/api");
|
|
38
|
+
const common_1 = require("@atproto/common");
|
|
39
|
+
const identity_1 = require("@atproto/identity");
|
|
40
|
+
const lexicon_1 = require("@atproto/lexicon");
|
|
41
|
+
const repo_1 = require("@atproto/repo");
|
|
42
|
+
const syntax_1 = require("@atproto/syntax");
|
|
43
|
+
const kysely_1 = require("kysely");
|
|
44
|
+
const cid_1 = require("multiformats/cid");
|
|
45
|
+
const logger_1 = require("../../../logger");
|
|
46
|
+
const retry_1 = require("../../../util/retry");
|
|
47
|
+
const PlaylistIdea = __importStar(require("./plugins/playlist-idea"));
|
|
48
|
+
const Profile = __importStar(require("./plugins/profile"));
|
|
49
|
+
class IndexingService {
|
|
50
|
+
constructor(db, idResolver) {
|
|
51
|
+
Object.defineProperty(this, "db", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
configurable: true,
|
|
54
|
+
writable: true,
|
|
55
|
+
value: db
|
|
56
|
+
});
|
|
57
|
+
Object.defineProperty(this, "idResolver", {
|
|
58
|
+
enumerable: true,
|
|
59
|
+
configurable: true,
|
|
60
|
+
writable: true,
|
|
61
|
+
value: idResolver
|
|
62
|
+
});
|
|
63
|
+
Object.defineProperty(this, "records", {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
writable: true,
|
|
67
|
+
value: void 0
|
|
68
|
+
});
|
|
69
|
+
this.records = {
|
|
70
|
+
playlistIdea: PlaylistIdea.makePlugin(this.db),
|
|
71
|
+
profile: Profile.makePlugin(this.db),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
transact(txn) {
|
|
75
|
+
txn.assertTransaction();
|
|
76
|
+
return new IndexingService(txn, this.idResolver);
|
|
77
|
+
}
|
|
78
|
+
async indexRecord(uri, cid, obj, action, timestamp) {
|
|
79
|
+
this.db.assertNotTransaction();
|
|
80
|
+
await this.db.transaction(async (txn) => {
|
|
81
|
+
const indexingTx = this.transact(txn);
|
|
82
|
+
const indexer = indexingTx.findIndexerForCollection(uri.collection);
|
|
83
|
+
if (!indexer)
|
|
84
|
+
return;
|
|
85
|
+
if (action === repo_1.WriteOpAction.Create) {
|
|
86
|
+
await indexer.insertRecord(uri, cid, obj, timestamp);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
await indexer.updateRecord(uri, cid, obj, timestamp);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async deleteRecord(uri, cascading = false) {
|
|
94
|
+
this.db.assertNotTransaction();
|
|
95
|
+
await this.db.transaction(async (txn) => {
|
|
96
|
+
const indexingTx = this.transact(txn);
|
|
97
|
+
const indexer = indexingTx.findIndexerForCollection(uri.collection);
|
|
98
|
+
if (!indexer)
|
|
99
|
+
return;
|
|
100
|
+
await indexer.deleteRecord(uri, cascading);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async indexHandle(did, timestamp, force = false) {
|
|
104
|
+
this.db.assertNotTransaction();
|
|
105
|
+
const actor = await this.db.db
|
|
106
|
+
.selectFrom('actor')
|
|
107
|
+
.where('did', '=', did)
|
|
108
|
+
.selectAll()
|
|
109
|
+
.executeTakeFirst();
|
|
110
|
+
if (!force && !needsHandleReindex(actor, timestamp)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const atpData = await this.idResolver.did.resolveAtprotoData(did, true);
|
|
114
|
+
const handleToDid = await this.idResolver.handle.resolve(atpData.handle);
|
|
115
|
+
const handle = did === handleToDid ? atpData.handle.toLowerCase() : null;
|
|
116
|
+
const actorWithHandle = handle !== null
|
|
117
|
+
? await this.db.db
|
|
118
|
+
.selectFrom('actor')
|
|
119
|
+
.where('handle', '=', handle)
|
|
120
|
+
.selectAll()
|
|
121
|
+
.executeTakeFirst()
|
|
122
|
+
: null;
|
|
123
|
+
// handle contention
|
|
124
|
+
if (handle && actorWithHandle && did !== actorWithHandle.did) {
|
|
125
|
+
await this.db.db
|
|
126
|
+
.updateTable('actor')
|
|
127
|
+
.where('actor.did', '=', actorWithHandle.did)
|
|
128
|
+
.set({ handle: null })
|
|
129
|
+
.execute();
|
|
130
|
+
}
|
|
131
|
+
const actorInfo = { handle, indexed_at: timestamp };
|
|
132
|
+
await this.db.db
|
|
133
|
+
.insertInto('actor')
|
|
134
|
+
.values({ did, ...actorInfo })
|
|
135
|
+
.onConflict((oc) => oc.column('did').doUpdateSet(actorInfo))
|
|
136
|
+
.returning('did')
|
|
137
|
+
.executeTakeFirst();
|
|
138
|
+
}
|
|
139
|
+
async indexRepo(did, commit) {
|
|
140
|
+
this.db.assertNotTransaction();
|
|
141
|
+
const now = new Date().toISOString();
|
|
142
|
+
const { pds, signingKey } = await this.idResolver.did.resolveAtprotoData(did, true);
|
|
143
|
+
const agent = new api_1.Agent(pds);
|
|
144
|
+
const { data: car } = await (0, retry_1.retryXrpc)(() => agent.com.atproto.sync.getRepo({ did }));
|
|
145
|
+
const { root, blocks } = await (0, repo_1.readCarWithRoot)(car);
|
|
146
|
+
const verifiedRepo = await (0, repo_1.verifyRepo)(blocks, root, did, signingKey);
|
|
147
|
+
const currRecords = await this.getCurrentRecords(did);
|
|
148
|
+
const repoRecords = formatCheckout(did, verifiedRepo);
|
|
149
|
+
const diff = findDiffFromCheckout(currRecords, repoRecords);
|
|
150
|
+
await Promise.all(diff.map(async (op) => {
|
|
151
|
+
const { uri, cid } = op;
|
|
152
|
+
try {
|
|
153
|
+
if (op.op === 'delete') {
|
|
154
|
+
await this.deleteRecord(uri);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const parsed = await (0, repo_1.getAndParseRecord)(blocks, cid);
|
|
158
|
+
await this.indexRecord(uri, cid, parsed.record, op.op === 'create' ? repo_1.WriteOpAction.Create : repo_1.WriteOpAction.Update, now);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
if (err instanceof lexicon_1.ValidationError) {
|
|
163
|
+
logger_1.httpLogger.warn({ did, commit, uri: uri.toString(), cid: cid.toString() }, 'skipping indexing of invalid record');
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
logger_1.httpLogger.error({ err, did, commit, uri: uri.toString(), cid: cid.toString() }, 'skipping indexing due to error processing record');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
async updateActorStatus(did, active, status = '') {
|
|
172
|
+
let upstreamStatus;
|
|
173
|
+
if (active) {
|
|
174
|
+
upstreamStatus = null;
|
|
175
|
+
}
|
|
176
|
+
else if (['deactivated', 'suspended', 'takendown'].includes(status)) {
|
|
177
|
+
upstreamStatus = status;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
throw new Error(`Unrecognized account status: ${status}`);
|
|
181
|
+
}
|
|
182
|
+
await this.db.db
|
|
183
|
+
.updateTable('actor')
|
|
184
|
+
.set({ upstreamStatus })
|
|
185
|
+
.where('did', '=', did)
|
|
186
|
+
.execute();
|
|
187
|
+
}
|
|
188
|
+
async setCommitLastSeen(did, commit, rev) {
|
|
189
|
+
const { ref } = this.db.db.dynamic;
|
|
190
|
+
await this.db.db
|
|
191
|
+
.insertInto('actor_sync')
|
|
192
|
+
.values({
|
|
193
|
+
did,
|
|
194
|
+
commitCid: commit.toString(),
|
|
195
|
+
repoRev: rev ?? null,
|
|
196
|
+
})
|
|
197
|
+
.onConflict((oc) => {
|
|
198
|
+
const excluded = (col) => ref(`excluded.${col}`);
|
|
199
|
+
return oc.column('did').doUpdateSet({
|
|
200
|
+
commitCid: (0, kysely_1.sql) `${excluded('commitCid')}`,
|
|
201
|
+
repoRev: (0, kysely_1.sql) `${excluded('repoRev')}`,
|
|
202
|
+
});
|
|
203
|
+
})
|
|
204
|
+
.execute();
|
|
205
|
+
}
|
|
206
|
+
async getCurrentRecords(did) {
|
|
207
|
+
const res = await this.db.db
|
|
208
|
+
.selectFrom('record')
|
|
209
|
+
.where('did', '=', did)
|
|
210
|
+
.select(['uri', 'cid'])
|
|
211
|
+
.execute();
|
|
212
|
+
return res.reduce((acc, cur) => {
|
|
213
|
+
acc[cur.uri] = {
|
|
214
|
+
uri: new syntax_1.AtUri(cur.uri),
|
|
215
|
+
cid: cid_1.CID.parse(cur.cid),
|
|
216
|
+
};
|
|
217
|
+
return acc;
|
|
218
|
+
}, {});
|
|
219
|
+
}
|
|
220
|
+
findIndexerForCollection(collection) {
|
|
221
|
+
const indexers = Object.values(this.records);
|
|
222
|
+
return indexers.find((indexer) => indexer.collection === collection);
|
|
223
|
+
}
|
|
224
|
+
async deleteActor(did) {
|
|
225
|
+
this.db.assertNotTransaction();
|
|
226
|
+
const actorIsHosted = await this.getActorIsHosted(did);
|
|
227
|
+
if (actorIsHosted === false) {
|
|
228
|
+
await this.db.db.deleteFrom('actor').where('did', '=', did).execute();
|
|
229
|
+
await this.unindexActor(did);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async getActorIsHosted(did) {
|
|
233
|
+
const doc = await this.idResolver.did.resolve(did, true);
|
|
234
|
+
const pds = doc && (0, identity_1.getPds)(doc);
|
|
235
|
+
if (!pds)
|
|
236
|
+
return false;
|
|
237
|
+
const agent = new api_1.Agent(pds);
|
|
238
|
+
try {
|
|
239
|
+
await (0, retry_1.retryXrpc)(() => agent.com.atproto.sync.getLatestCommit({ did }));
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
if (err instanceof api_1.ComAtprotoSyncGetLatestCommit.RepoNotFoundError) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async unindexActor(did) {
|
|
250
|
+
this.db.assertNotTransaction();
|
|
251
|
+
await this.db.db.deleteFrom('profile').where('creator', '=', did).execute();
|
|
252
|
+
await this.db.db.deleteFrom('record').where('did', '=', did).execute();
|
|
253
|
+
const deletedPlaylistIdeas = await this.db.db
|
|
254
|
+
.deleteFrom('playlist_idea')
|
|
255
|
+
.where('owner_did', '=', did)
|
|
256
|
+
.returningAll()
|
|
257
|
+
.execute();
|
|
258
|
+
const deletedPlaylistIdeaUris = deletedPlaylistIdeas.map((deletedPlaylistIdea) => {
|
|
259
|
+
return deletedPlaylistIdea.uri;
|
|
260
|
+
});
|
|
261
|
+
const deletedPlaylists = await this.db.db
|
|
262
|
+
.deleteFrom('playlist')
|
|
263
|
+
.where('playlist_idea_uri', 'in', deletedPlaylistIdeaUris)
|
|
264
|
+
.returningAll()
|
|
265
|
+
.execute();
|
|
266
|
+
const deletedPlaylistIds = deletedPlaylists.map((deletedPlaylist) => {
|
|
267
|
+
return deletedPlaylist.id;
|
|
268
|
+
});
|
|
269
|
+
await this.db.db
|
|
270
|
+
.deleteFrom('playlist_item')
|
|
271
|
+
.where('playlist_id', 'in', deletedPlaylistIds)
|
|
272
|
+
.execute();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
exports.IndexingService = IndexingService;
|
|
276
|
+
const findDiffFromCheckout = (curr, checkout) => {
|
|
277
|
+
const ops = [];
|
|
278
|
+
for (const uri of Object.keys(checkout)) {
|
|
279
|
+
const record = checkout[uri];
|
|
280
|
+
if (!curr[uri]) {
|
|
281
|
+
ops.push({ op: 'create', ...record });
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
if (curr[uri].cid.equals(record.cid)) {
|
|
285
|
+
// no-op
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
ops.push({ op: 'update', ...record });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (const uri of Object.keys(curr)) {
|
|
292
|
+
const record = curr[uri];
|
|
293
|
+
if (!checkout[uri]) {
|
|
294
|
+
ops.push({ op: 'delete', ...record });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return ops;
|
|
298
|
+
};
|
|
299
|
+
const formatCheckout = (did, verifiedRepo) => {
|
|
300
|
+
const records = {};
|
|
301
|
+
for (const create of verifiedRepo.creates) {
|
|
302
|
+
const uri = syntax_1.AtUri.make(did, create.collection, create.rkey);
|
|
303
|
+
records[uri.toString()] = {
|
|
304
|
+
uri,
|
|
305
|
+
cid: create.cid,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
return records;
|
|
309
|
+
};
|
|
310
|
+
const needsHandleReindex = (actor, timestamp) => {
|
|
311
|
+
if (!actor)
|
|
312
|
+
return true;
|
|
313
|
+
const timeDiff = new Date(timestamp).getTime() - new Date(actor.indexed_at).getTime();
|
|
314
|
+
// revalidate daily
|
|
315
|
+
if (timeDiff > common_1.DAY)
|
|
316
|
+
return true;
|
|
317
|
+
// revalidate more aggressively for invalidated handles
|
|
318
|
+
if (actor.handle === null && timeDiff > common_1.HOUR)
|
|
319
|
+
return true;
|
|
320
|
+
return false;
|
|
321
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.makePlugin = void 0;
|
|
37
|
+
const syntax_1 = require("@atproto/syntax");
|
|
38
|
+
const lex = __importStar(require("../../../../lexicons/lexicons"));
|
|
39
|
+
const processor_1 = require("../processor");
|
|
40
|
+
const lexId = lex.ids.ComClioplaylistsAlphaFeedPlaylistIdea;
|
|
41
|
+
const insertFn = async (db, uri, cid, obj, timestamp) => {
|
|
42
|
+
const masterPlaylist = obj.masterPlaylist;
|
|
43
|
+
const recommendedPlaylist = obj.recommendedPlaylist;
|
|
44
|
+
let masterPlaylistId;
|
|
45
|
+
let recommendedPlaylistId;
|
|
46
|
+
if (masterPlaylist) {
|
|
47
|
+
const playlist = {
|
|
48
|
+
playlist_idea_uri: uri.toString(),
|
|
49
|
+
type: 'master',
|
|
50
|
+
};
|
|
51
|
+
const insertedPlaylistIdResponse = await db
|
|
52
|
+
.insertInto('playlist')
|
|
53
|
+
.values(playlist)
|
|
54
|
+
.onConflict((oc) => oc.doNothing())
|
|
55
|
+
.returning('id')
|
|
56
|
+
.executeTakeFirst();
|
|
57
|
+
let songs = masterPlaylist.songs.map((song) => {
|
|
58
|
+
return {
|
|
59
|
+
track_name: song.trackName,
|
|
60
|
+
track_mb_id: song.trackMbId,
|
|
61
|
+
album_artwork_ref: song.albumArtwork?.ref.toString(),
|
|
62
|
+
created_at: song.createdAt,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
const insertedSongIdsResponse = await db
|
|
66
|
+
.insertInto('song')
|
|
67
|
+
.values(songs)
|
|
68
|
+
.onConflict((oc) => oc.doNothing())
|
|
69
|
+
.returning('id')
|
|
70
|
+
.execute();
|
|
71
|
+
if (insertedPlaylistIdResponse?.id) {
|
|
72
|
+
const playlistItems = insertedSongIdsResponse.map((songIdResponse, index) => {
|
|
73
|
+
return {
|
|
74
|
+
playlist_id: insertedPlaylistIdResponse.id,
|
|
75
|
+
song_id: songIdResponse.id,
|
|
76
|
+
position: index + 1,
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
await db.insertInto('playlist_item').values(playlistItems).execute();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (recommendedPlaylist) {
|
|
83
|
+
const playlist = {
|
|
84
|
+
playlist_idea_uri: uri.toString(),
|
|
85
|
+
type: 'recommended',
|
|
86
|
+
};
|
|
87
|
+
await db
|
|
88
|
+
.insertInto('playlist')
|
|
89
|
+
.values(playlist)
|
|
90
|
+
.onConflict((oc) => oc.doNothing())
|
|
91
|
+
.execute();
|
|
92
|
+
}
|
|
93
|
+
const playlistIdea = {
|
|
94
|
+
uri: uri.toString(),
|
|
95
|
+
title: obj.title,
|
|
96
|
+
description: obj.description,
|
|
97
|
+
creator_did: obj.creatorDid,
|
|
98
|
+
owner_did: obj.ownerDid,
|
|
99
|
+
master_playlist_id: masterPlaylistId,
|
|
100
|
+
recommended_playlist_id: recommendedPlaylistId,
|
|
101
|
+
created_at: (0, syntax_1.normalizeDatetimeAlways)(obj.createdAt),
|
|
102
|
+
};
|
|
103
|
+
const [insertedPlaylistIdea] = await Promise.all([
|
|
104
|
+
db
|
|
105
|
+
.insertInto('playlist_idea')
|
|
106
|
+
.values(playlistIdea)
|
|
107
|
+
.onConflict((oc) => oc.doNothing())
|
|
108
|
+
.returningAll()
|
|
109
|
+
.executeTakeFirst(),
|
|
110
|
+
]);
|
|
111
|
+
if (!insertedPlaylistIdea) {
|
|
112
|
+
return null; // PlaylistIdea already indexed
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
playlistIdea: insertedPlaylistIdea,
|
|
116
|
+
masterPlaylist: masterPlaylist,
|
|
117
|
+
recommendedPlaylist: recommendedPlaylist,
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
const findDuplicate = async () => {
|
|
121
|
+
return null;
|
|
122
|
+
};
|
|
123
|
+
const deleteFn = async (db, uri) => {
|
|
124
|
+
const uriStr = uri.toString();
|
|
125
|
+
const [deletedPlaylistIdea, deletedPlaylists] = await Promise.all([
|
|
126
|
+
db
|
|
127
|
+
.deleteFrom('playlist_idea')
|
|
128
|
+
.where('uri', '=', uriStr)
|
|
129
|
+
.returningAll()
|
|
130
|
+
.executeTakeFirst(),
|
|
131
|
+
db
|
|
132
|
+
.deleteFrom('playlist')
|
|
133
|
+
.where('playlist_idea_uri', '=', uriStr)
|
|
134
|
+
.returningAll()
|
|
135
|
+
.execute(),
|
|
136
|
+
]);
|
|
137
|
+
const deletedPlaylistIds = deletedPlaylists.map((deletedPlaylist) => {
|
|
138
|
+
return deletedPlaylist.id;
|
|
139
|
+
});
|
|
140
|
+
if (deletedPlaylists) {
|
|
141
|
+
await db
|
|
142
|
+
.deleteFrom('playlist_item')
|
|
143
|
+
.where('playlist_id', 'in', deletedPlaylistIds)
|
|
144
|
+
.execute();
|
|
145
|
+
}
|
|
146
|
+
return deletedPlaylistIdea
|
|
147
|
+
? {
|
|
148
|
+
playlistIdea: deletedPlaylistIdea,
|
|
149
|
+
masterPlaylist: undefined, // TODO: Figure out if this should be undefined
|
|
150
|
+
recommendedPlaylist: undefined, // TODO: Figure out if this should be undefined
|
|
151
|
+
}
|
|
152
|
+
: null;
|
|
153
|
+
};
|
|
154
|
+
const makePlugin = (db) => {
|
|
155
|
+
return new processor_1.RecordProcessor(db, {
|
|
156
|
+
lexId,
|
|
157
|
+
insertFn,
|
|
158
|
+
findDuplicate,
|
|
159
|
+
deleteFn,
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
exports.makePlugin = makePlugin;
|
|
163
|
+
exports.default = exports.makePlugin;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.makePlugin = void 0;
|
|
37
|
+
const lex = __importStar(require("../../../../lexicons/lexicons"));
|
|
38
|
+
const processor_1 = require("../processor");
|
|
39
|
+
const lexId = lex.ids.ComClioplaylistsAlphaActorProfile;
|
|
40
|
+
const insertFn = async (db, uri, cid, obj, timestamp) => {
|
|
41
|
+
if (uri.rkey !== 'self')
|
|
42
|
+
return null;
|
|
43
|
+
const inserted = await db
|
|
44
|
+
.insertInto('profile')
|
|
45
|
+
.values({
|
|
46
|
+
uri: uri.toString(),
|
|
47
|
+
cid: cid.toString(),
|
|
48
|
+
creator: uri.host,
|
|
49
|
+
display_name: obj.displayName,
|
|
50
|
+
description: obj.description,
|
|
51
|
+
avatar_cid: obj.avatar?.ref.toString(),
|
|
52
|
+
banner_cid: obj.banner?.ref.toString(),
|
|
53
|
+
created_at: obj.createdAt ?? new Date().toISOString(),
|
|
54
|
+
indexed_at: timestamp,
|
|
55
|
+
})
|
|
56
|
+
.onConflict((oc) => oc.doNothing())
|
|
57
|
+
.returningAll()
|
|
58
|
+
.executeTakeFirst();
|
|
59
|
+
return inserted || null;
|
|
60
|
+
};
|
|
61
|
+
const findDuplicate = async () => {
|
|
62
|
+
return null;
|
|
63
|
+
};
|
|
64
|
+
const deleteFn = async (db, uri) => {
|
|
65
|
+
const deleted = await db
|
|
66
|
+
.deleteFrom('profile')
|
|
67
|
+
.where('uri', '=', uri.toString())
|
|
68
|
+
.returningAll()
|
|
69
|
+
.executeTakeFirst();
|
|
70
|
+
return deleted || null;
|
|
71
|
+
};
|
|
72
|
+
const makePlugin = (db) => {
|
|
73
|
+
return new processor_1.RecordProcessor(db, {
|
|
74
|
+
lexId,
|
|
75
|
+
insertFn,
|
|
76
|
+
findDuplicate,
|
|
77
|
+
deleteFn,
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
exports.makePlugin = makePlugin;
|
|
81
|
+
exports.default = exports.makePlugin;
|