@clioplaylists/clio 0.1.8 → 0.1.9

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.
Files changed (126) hide show
  1. package/dist/api/com/clioplaylists/alpha/feed/getRecommendedPlaylistsByUser.d.ts +3 -0
  2. package/dist/api/com/clioplaylists/alpha/feed/getRecommendedPlaylistsByUser.js +70 -0
  3. package/dist/api/health.js +10 -3
  4. package/dist/api/index.d.ts +1 -0
  5. package/dist/api/index.js +40 -2
  6. package/dist/api/oauth.d.ts +3 -0
  7. package/dist/api/oauth.js +63 -0
  8. package/dist/api/util.d.ts +1 -0
  9. package/dist/api/util.js +11 -6
  10. package/dist/api/well-known.js +8 -4
  11. package/dist/auth-verifier.d.ts +17 -4
  12. package/dist/auth-verifier.js +171 -165
  13. package/dist/client.js +15 -8
  14. package/dist/config.d.ts +21 -0
  15. package/dist/config.js +77 -7
  16. package/dist/context.d.ts +11 -0
  17. package/dist/context.js +14 -1
  18. package/dist/dataplane/client/hosts.js +5 -1
  19. package/dist/dataplane/client/index.d.ts +2 -0
  20. package/dist/dataplane/client/index.js +40 -17
  21. package/dist/dataplane/client/util.d.ts +20 -0
  22. package/dist/dataplane/client/util.js +92 -0
  23. package/dist/dataplane/index.js +18 -2
  24. package/dist/dataplane/server/background.d.ts +1 -1
  25. package/dist/dataplane/server/background.js +12 -5
  26. package/dist/dataplane/server/db/database-schema.d.ts +5 -1
  27. package/dist/dataplane/server/db/database-schema.js +2 -1
  28. package/dist/dataplane/server/db/db.js +60 -20
  29. package/dist/dataplane/server/db/index.js +17 -1
  30. package/dist/dataplane/server/db/migrations/20250515T045948368Z-init.d.ts +3 -0
  31. package/dist/dataplane/server/db/migrations/20250515T045948368Z-init.js +170 -0
  32. package/dist/dataplane/server/db/migrations/20260119T210000000Z-song-recommendation.d.ts +3 -0
  33. package/dist/dataplane/server/db/migrations/20260119T210000000Z-song-recommendation.js +36 -0
  34. package/dist/dataplane/server/db/migrations/20260119T220000000Z-oauth.d.ts +3 -0
  35. package/dist/dataplane/server/db/migrations/20260119T220000000Z-oauth.js +25 -0
  36. package/dist/dataplane/server/db/migrations/index.d.ts +3 -2
  37. package/dist/dataplane/server/db/migrations/index.js +39 -2
  38. package/dist/dataplane/server/db/migrations/provider.js +5 -1
  39. package/dist/dataplane/server/db/pagination.d.ts +1 -1
  40. package/dist/dataplane/server/db/pagination.js +38 -25
  41. package/dist/dataplane/server/db/tables/actor-sync.d.ts +2 -2
  42. package/dist/dataplane/server/db/tables/actor-sync.js +4 -1
  43. package/dist/dataplane/server/db/tables/actor.d.ts +3 -3
  44. package/dist/dataplane/server/db/tables/actor.js +4 -1
  45. package/dist/dataplane/server/db/tables/artist-list-item.d.ts +2 -2
  46. package/dist/dataplane/server/db/tables/artist-list-item.js +4 -1
  47. package/dist/dataplane/server/db/tables/artist.js +4 -1
  48. package/dist/dataplane/server/db/tables/oauth-session.d.ts +9 -0
  49. package/dist/dataplane/server/db/tables/oauth-session.js +4 -0
  50. package/dist/dataplane/server/db/tables/oauth-state.d.ts +10 -0
  51. package/dist/dataplane/server/db/tables/oauth-state.js +4 -0
  52. package/dist/dataplane/server/db/tables/playlist-idea.d.ts +3 -3
  53. package/dist/dataplane/server/db/tables/playlist-idea.js +4 -1
  54. package/dist/dataplane/server/db/tables/playlist-item.js +4 -1
  55. package/dist/dataplane/server/db/tables/playlist.d.ts +1 -0
  56. package/dist/dataplane/server/db/tables/playlist.js +4 -1
  57. package/dist/dataplane/server/db/tables/profile.d.ts +5 -5
  58. package/dist/dataplane/server/db/tables/profile.js +4 -1
  59. package/dist/dataplane/server/db/tables/record.d.ts +1 -1
  60. package/dist/dataplane/server/db/tables/record.js +4 -1
  61. package/dist/dataplane/server/db/tables/song-recommendation.d.ts +17 -0
  62. package/dist/dataplane/server/db/tables/song-recommendation.js +4 -0
  63. package/dist/dataplane/server/db/tables/song.d.ts +2 -2
  64. package/dist/dataplane/server/db/tables/song.js +4 -1
  65. package/dist/dataplane/server/db/tables/subscription-cursor.d.ts +9 -0
  66. package/dist/dataplane/server/db/tables/subscription-cursor.js +4 -0
  67. package/dist/dataplane/server/db/types.js +2 -1
  68. package/dist/dataplane/server/db/util.d.ts +7 -3
  69. package/dist/dataplane/server/db/util.js +26 -18
  70. package/dist/dataplane/server/index.js +21 -13
  71. package/dist/dataplane/server/indexing/index.d.ts +2 -0
  72. package/dist/dataplane/server/indexing/index.js +82 -66
  73. package/dist/dataplane/server/indexing/plugins/playlist-idea.d.ts +1 -2
  74. package/dist/dataplane/server/indexing/plugins/playlist-idea.js +50 -41
  75. package/dist/dataplane/server/indexing/plugins/profile.js +45 -12
  76. package/dist/dataplane/server/indexing/plugins/song-recommendation.d.ts +9 -0
  77. package/dist/dataplane/server/indexing/plugins/song-recommendation.js +101 -0
  78. package/dist/dataplane/server/indexing/processor.js +12 -11
  79. package/dist/dataplane/server/routes/identity.d.ts +19 -0
  80. package/dist/dataplane/server/routes/identity.js +32 -25
  81. package/dist/dataplane/server/routes/index.js +15 -10
  82. package/dist/dataplane/server/routes/profile.js +17 -25
  83. package/dist/dataplane/server/routes/records.d.ts +18 -0
  84. package/dist/dataplane/server/routes/records.js +48 -22
  85. package/dist/dataplane/server/routes/sync.js +5 -3
  86. package/dist/dataplane/server/storage/subscription-cursor.d.ts +3 -0
  87. package/dist/dataplane/server/storage/subscription-cursor.js +25 -0
  88. package/dist/dataplane/server/subscription.d.ts +6 -3
  89. package/dist/dataplane/server/subscription.js +73 -63
  90. package/dist/error.js +9 -5
  91. package/dist/index.d.ts +6 -3
  92. package/dist/index.js +91 -28
  93. package/dist/lexicons/index.d.ts +3 -210
  94. package/dist/lexicons/index.js +26 -403
  95. package/dist/lexicons/lexicons.d.ts +409 -8107
  96. package/dist/lexicons/lexicons.js +134 -4276
  97. package/dist/lexicons/types/com/atproto/repo/strongRef.d.ts +4 -4
  98. package/dist/lexicons/types/com/atproto/repo/strongRef.js +13 -9
  99. package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.d.ts +10 -8
  100. package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.js +13 -9
  101. package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.d.ts +20 -11
  102. package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.js +29 -14
  103. package/dist/lexicons/types/com/clioplaylists/alpha/feed/getRecommendedPlaylistsByUser.d.ts +36 -0
  104. package/dist/lexicons/types/com/clioplaylists/alpha/feed/getRecommendedPlaylistsByUser.js +6 -0
  105. package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.d.ts +11 -14
  106. package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.js +20 -23
  107. package/dist/lexicons/types/com/clioplaylists/alpha/feed/recommendedPlaylist.d.ts +18 -0
  108. package/dist/lexicons/types/com/clioplaylists/alpha/feed/recommendedPlaylist.js +15 -0
  109. package/dist/lexicons/types/com/clioplaylists/alpha/feed/songRecommendation.d.ts +18 -0
  110. package/dist/lexicons/types/com/clioplaylists/alpha/feed/songRecommendation.js +15 -0
  111. package/dist/lexicons/util.d.ts +33 -2
  112. package/dist/lexicons/util.js +32 -4
  113. package/dist/logger.js +16 -10
  114. package/dist/oauth/client.d.ts +14 -0
  115. package/dist/oauth/client.js +126 -0
  116. package/dist/oauth/pds-agent.d.ts +3 -0
  117. package/dist/oauth/pds-agent.js +15 -0
  118. package/dist/rpc/clio_connect.d.ts +101 -11
  119. package/dist/rpc/clio_connect.js +138 -45
  120. package/dist/rpc/clio_pb.d.ts +448 -30
  121. package/dist/rpc/clio_pb.js +967 -272
  122. package/dist/util/retry.js +10 -9
  123. package/dist/util/uris.js +6 -3
  124. package/dist/util.d.ts +0 -1
  125. package/dist/util.js +61 -20
  126. package/package.json +26 -5
@@ -1,15 +1,19 @@
1
- import { keyBy } from '@atproto/common';
2
- import { AtUri } from '@atproto/syntax';
3
- import { Timestamp } from '@bufbuild/protobuf';
4
- import * as ui8 from 'uint8arrays';
5
- import { ids } from '../../../lexicons/lexicons';
6
- import { Record } from '../../../rpc/clio_pb';
7
- export default (db) => ({
8
- getProfileRecords: getRecords(db, ids.ComClioplaylistsAlphaActorProfile),
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRecommendedPlaylistsForPlaylistIdea = exports.getRecords = void 0;
4
+ const common_1 = require("@atproto/common");
5
+ const syntax_1 = require("@atproto/syntax");
6
+ const protobuf_1 = require("@bufbuild/protobuf");
7
+ const node_buffer_1 = require("node:buffer");
8
+ const lexicons_1 = require("../../../lexicons/lexicons");
9
+ const clio_pb_1 = require("../../../rpc/clio_pb");
10
+ exports.default = (db) => ({
11
+ getProfileRecords: (0, exports.getRecords)(db, lexicons_1.ids.ComClioplaylistsAlphaActorProfile),
12
+ getRecommendedPlaylistsForPlaylistIdea: (0, exports.getRecommendedPlaylistsForPlaylistIdea)(db),
9
13
  });
10
- export const getRecords = (db, collection) => async (req) => {
14
+ const getRecords = (db, collection) => async (req) => {
11
15
  const validUris = collection
12
- ? req.uris.filter((uri) => new AtUri(uri).collection === collection)
16
+ ? req.uris.filter((uri) => new syntax_1.AtUri(uri).collection === collection)
13
17
  : req.uris;
14
18
  const res = validUris.length
15
19
  ? await db.db
@@ -18,34 +22,56 @@ export const getRecords = (db, collection) => async (req) => {
18
22
  .where('uri', 'in', validUris)
19
23
  .execute()
20
24
  : [];
21
- const byUri = keyBy(res, 'uri');
25
+ const byUri = (0, common_1.keyBy)(res, 'uri');
22
26
  const records = req.uris.map((uri) => {
23
27
  const row = byUri.get(uri);
24
28
  const json = row ? row.json : JSON.stringify(null);
25
29
  const createdAtRaw = new Date(JSON.parse(json)?.['createdAt']);
26
30
  const createdAt = !isNaN(createdAtRaw.getTime())
27
- ? Timestamp.fromDate(createdAtRaw)
31
+ ? protobuf_1.Timestamp.fromDate(createdAtRaw)
28
32
  : undefined;
29
33
  const indexedAt = row?.indexed_at
30
- ? Timestamp.fromDate(new Date(row?.indexed_at))
34
+ ? protobuf_1.Timestamp.fromDate(new Date(row?.indexed_at))
31
35
  : undefined;
32
- const recordBytes = ui8.fromString(json, 'utf8');
33
- return new Record({
36
+ const recordBytes = node_buffer_1.Buffer.from(json, 'utf8');
37
+ return new clio_pb_1.Record({
34
38
  record: recordBytes,
35
39
  cid: row?.cid,
36
40
  createdAt,
37
41
  indexedAt,
38
- sortedAt: compositeTime(createdAt, indexedAt),
39
42
  takenDown: !!row?.takedown_ref,
40
43
  takedownRef: row?.takedown_ref ?? undefined,
41
44
  });
42
45
  });
43
46
  return { records };
44
47
  };
45
- const compositeTime = (ts1, ts2) => {
46
- if (!ts1)
47
- return ts2;
48
- if (!ts2)
49
- return ts1;
50
- return ts1.toDate() < ts2.toDate() ? ts1 : ts2;
48
+ exports.getRecords = getRecords;
49
+ const getRecommendedPlaylistsForPlaylistIdea = (db) => async (req) => {
50
+ const res = await db.db
51
+ .selectFrom('record as r')
52
+ .innerJoin('song_recommendation as sr', 'sr.uri', 'r.uri')
53
+ .select(['r.uri', 'r.cid', 'r.json', 'r.indexed_at', 'r.takedown_ref'])
54
+ .where('sr.playlist_idea_uri', '=', req.playlistIdeaUri)
55
+ .execute();
56
+ const records = res.map((row) => {
57
+ const json = row.json;
58
+ const createdAtRaw = new Date(JSON.parse(json)?.['createdAt']);
59
+ const createdAt = !isNaN(createdAtRaw.getTime())
60
+ ? protobuf_1.Timestamp.fromDate(createdAtRaw)
61
+ : undefined;
62
+ const indexedAt = row.indexed_at
63
+ ? protobuf_1.Timestamp.fromDate(new Date(row.indexed_at))
64
+ : undefined;
65
+ const recordBytes = node_buffer_1.Buffer.from(json, 'utf8');
66
+ return new clio_pb_1.Record({
67
+ record: recordBytes,
68
+ cid: row.cid,
69
+ createdAt,
70
+ indexedAt,
71
+ takenDown: !!row.takedown_ref,
72
+ takedownRef: row.takedown_ref ?? undefined,
73
+ });
74
+ });
75
+ return { records };
51
76
  };
77
+ exports.getRecommendedPlaylistsForPlaylistIdea = getRecommendedPlaylistsForPlaylistIdea;
@@ -1,12 +1,14 @@
1
- export default (db) => ({
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = (db) => ({
2
4
  async getLatestRev(req) {
3
5
  const res = await db.db
4
6
  .selectFrom('actor_sync')
5
7
  .where('did', '=', req.actorDid)
6
- .select('repoRev')
8
+ .select('repo_rev')
7
9
  .executeTakeFirst();
8
10
  return {
9
- rev: res?.repoRev ?? undefined,
11
+ rev: res?.repo_rev ?? undefined,
10
12
  };
11
13
  },
12
14
  });
@@ -0,0 +1,3 @@
1
+ import { Database } from '../db';
2
+ export declare const getSubscriptionCursor: (db: Database, service: string) => Promise<number>;
3
+ export declare const setSubscriptionCursor: (db: Database, service: string, cursor: number) => Promise<void>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setSubscriptionCursor = exports.getSubscriptionCursor = void 0;
4
+ const getSubscriptionCursor = async (db, service) => {
5
+ const row = await db.db
6
+ .selectFrom('subscription_cursor')
7
+ .select(['cursor'])
8
+ .where('service', '=', service)
9
+ .executeTakeFirst();
10
+ return row?.cursor ?? 0;
11
+ };
12
+ exports.getSubscriptionCursor = getSubscriptionCursor;
13
+ const setSubscriptionCursor = async (db, service, cursor) => {
14
+ const updatedAt = Date.now();
15
+ await db.db
16
+ .insertInto('subscription_cursor')
17
+ .values({
18
+ service,
19
+ cursor,
20
+ updated_at: updatedAt,
21
+ })
22
+ .onConflict((oc) => oc.column('service').doUpdateSet({ cursor, updated_at: updatedAt }))
23
+ .execute();
24
+ };
25
+ exports.setSubscriptionCursor = setSubscriptionCursor;
@@ -9,8 +9,8 @@ export declare class RepoSubscription {
9
9
  db: Database;
10
10
  idResolver: IdResolver;
11
11
  };
12
- firehose: Firehose;
13
- runner: MemoryRunner;
12
+ firehose?: Firehose;
13
+ runner?: MemoryRunner;
14
14
  background: BackgroundQueue;
15
15
  indexingSvc: IndexingService;
16
16
  constructor(opts: {
@@ -18,8 +18,11 @@ export declare class RepoSubscription {
18
18
  db: Database;
19
19
  idResolver: IdResolver;
20
20
  });
21
- start(): void;
21
+ start(): Promise<void>;
22
22
  restart(): Promise<void>;
23
23
  processAll(): Promise<void>;
24
24
  destroy(): Promise<void>;
25
+ private initPromise?;
26
+ private ensureInit;
27
+ private init;
25
28
  }
@@ -1,9 +1,13 @@
1
- import { WriteOpAction } from '@atproto/repo';
2
- import { Firehose, MemoryRunner } from '@atproto/sync';
3
- import { subLogger as log } from '../../logger';
4
- import { BackgroundQueue } from './background';
5
- import { IndexingService } from './indexing';
6
- export class RepoSubscription {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RepoSubscription = void 0;
4
+ const repo_1 = require("@atproto/repo");
5
+ const sync_1 = require("@atproto/sync");
6
+ const logger_1 = require("../../logger");
7
+ const background_1 = require("./background");
8
+ const indexing_1 = require("./indexing");
9
+ const subscription_cursor_1 = require("./storage/subscription-cursor");
10
+ class RepoSubscription {
7
11
  opts;
8
12
  firehose;
9
13
  runner;
@@ -11,76 +15,82 @@ export class RepoSubscription {
11
15
  indexingSvc;
12
16
  constructor(opts) {
13
17
  this.opts = opts;
14
- const { service, db, idResolver } = opts;
15
- this.background = new BackgroundQueue(db);
16
- this.indexingSvc = new IndexingService(db, idResolver);
17
- const { runner, firehose } = createFirehose({
18
- idResolver,
19
- service,
20
- indexingSvc: this.indexingSvc,
21
- });
22
- this.runner = runner;
23
- this.firehose = firehose;
18
+ const { db, idResolver } = opts;
19
+ this.background = new background_1.BackgroundQueue(db);
20
+ this.indexingSvc = new indexing_1.IndexingService(db, idResolver);
24
21
  }
25
- start() {
26
- this.firehose.start();
22
+ async start() {
23
+ await this.ensureInit();
24
+ this.firehose?.start();
27
25
  }
28
26
  async restart() {
29
27
  await this.destroy();
30
- const { runner, firehose } = createFirehose({
31
- idResolver: this.opts.idResolver,
32
- service: this.opts.service,
33
- indexingSvc: this.indexingSvc,
34
- });
35
- this.runner = runner;
36
- this.firehose = firehose;
37
- this.start();
28
+ await this.ensureInit(true);
29
+ await this.start();
38
30
  }
39
31
  async processAll() {
40
- await this.runner.processAll();
32
+ await this.ensureInit();
33
+ await this.runner?.processAll();
41
34
  await this.background.processAll();
42
35
  }
43
36
  async destroy() {
44
- await this.firehose.destroy();
45
- await this.runner.destroy();
37
+ await this.firehose?.destroy();
38
+ await this.runner?.destroy();
46
39
  await this.background.processAll();
40
+ this.firehose = undefined;
41
+ this.runner = undefined;
42
+ }
43
+ initPromise;
44
+ async ensureInit(force = false) {
45
+ if (force)
46
+ this.initPromise = undefined;
47
+ if (!this.initPromise) {
48
+ this.initPromise = this.init();
49
+ }
50
+ await this.initPromise;
51
+ }
52
+ async init() {
53
+ const { idResolver, service, db } = this.opts;
54
+ const startCursor = await (0, subscription_cursor_1.getSubscriptionCursor)(db, service);
55
+ const runner = new sync_1.MemoryRunner({
56
+ startCursor,
57
+ setCursor: async (cursor) => {
58
+ await (0, subscription_cursor_1.setSubscriptionCursor)(db, service, cursor);
59
+ },
60
+ });
61
+ const firehose = new sync_1.Firehose({
62
+ idResolver,
63
+ runner,
64
+ service,
65
+ unauthenticatedHandles: true,
66
+ unauthenticatedCommits: true,
67
+ onError: (err) => logger_1.subLogger.error({ err }, 'error in subscription'),
68
+ handleEvent: createHandleEvent(this.indexingSvc),
69
+ });
70
+ this.runner = runner;
71
+ this.firehose = firehose;
47
72
  }
48
73
  }
49
- const createFirehose = (opts) => {
50
- const { idResolver, service, indexingSvc } = opts;
51
- const runner = new MemoryRunner({ startCursor: 0 });
52
- const firehose = new Firehose({
53
- idResolver,
54
- runner,
55
- service,
56
- unauthenticatedHandles: true, // indexing service handles these
57
- unauthenticatedCommits: true, // @TODO there seems to be a very rare issue where the authenticator thinks a block is missing in deletion ops
58
- onError: (err) => log.error({ err }, 'error in subscription'),
59
- handleEvent: async (evt) => {
60
- if (evt.event === 'identity') {
61
- await indexingSvc.indexHandle(evt.did, evt.time, true);
62
- }
63
- else if (evt.event === 'account') {
64
- if (evt.active === false && evt.status === 'deleted') {
65
- await indexingSvc.deleteActor(evt.did);
66
- }
67
- else {
68
- await indexingSvc.updateActorStatus(evt.did, evt.active, evt.status);
69
- }
74
+ exports.RepoSubscription = RepoSubscription;
75
+ const createHandleEvent = (indexingSvc) => {
76
+ return async (evt) => {
77
+ if (evt.event === 'identity') {
78
+ await indexingSvc.indexHandle(evt.did, evt.time, true);
79
+ return;
80
+ }
81
+ if (evt.event === 'account') {
82
+ const status = evt.status ?? '';
83
+ if (evt.active === false && status === 'deleted') {
84
+ await indexingSvc.deleteActor(evt.did);
70
85
  }
71
86
  else {
72
- const indexFn = evt.event === 'delete'
73
- ? indexingSvc.deleteRecord(evt.uri)
74
- : indexingSvc.indexRecord(evt.uri, evt.cid, evt.record, evt.event === 'create'
75
- ? WriteOpAction.Create
76
- : WriteOpAction.Update, evt.time);
77
- await Promise.all([
78
- indexFn,
79
- indexingSvc.setCommitLastSeen(evt.did, evt.commit, evt.rev),
80
- indexingSvc.indexHandle(evt.did, evt.time),
81
- ]);
87
+ await indexingSvc.updateActorStatus(evt.did, evt.active, status);
82
88
  }
83
- },
84
- });
85
- return { firehose, runner };
89
+ return;
90
+ }
91
+ const indexFn = evt.event === 'delete'
92
+ ? indexingSvc.deleteRecord(evt.uri)
93
+ : indexingSvc.indexRecord(evt.uri, evt.cid, evt.record, evt.event === 'create' ? repo_1.WriteOpAction.Create : repo_1.WriteOpAction.Update, evt.time);
94
+ await Promise.all([indexFn, indexingSvc.setCommitLastSeen(evt.did, evt.commit, evt.rev), indexingSvc.indexHandle(evt.did, evt.time)]);
95
+ };
86
96
  };
package/dist/error.js CHANGED
@@ -1,10 +1,14 @@
1
- import { XRPCError } from '@atproto/xrpc-server';
2
- import { httpLogger as log } from './logger';
3
- export const handler = (err, _req, res, next) => {
4
- log.error(err, 'unexpected internal server error');
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = void 0;
4
+ const xrpc_server_1 = require("@atproto/xrpc-server");
5
+ const logger_1 = require("./logger");
6
+ const handler = (err, _req, res, next) => {
7
+ logger_1.httpLogger.error(err, 'unexpected internal server error');
5
8
  if (res.headersSent) {
6
9
  return next(err);
7
10
  }
8
- const serverError = XRPCError.fromError(err);
11
+ const serverError = xrpc_server_1.XRPCError.fromError(err);
9
12
  res.status(serverError.type).json(serverError.payload);
10
13
  };
14
+ exports.handler = handler;
package/dist/index.d.ts CHANGED
@@ -1,16 +1,19 @@
1
1
  import { Keypair } from '@atproto/crypto';
2
- import express from 'express';
3
2
  import { Server } from 'http';
4
3
  import { ServerConfig } from './config';
5
4
  import AppContext from './context';
5
+ type ExpressApp = {
6
+ use: (...args: unknown[]) => unknown;
7
+ listen(port: number, callback?: () => void): Server;
8
+ };
6
9
  export declare class ClioAppView {
7
10
  ctx: AppContext;
8
- app: express.Application;
11
+ app: ExpressApp;
9
12
  server?: Server;
10
13
  private terminator?;
11
14
  constructor(opts: {
12
15
  ctx: AppContext;
13
- app: express.Application;
16
+ app: ExpressApp;
14
17
  });
15
18
  static create(opts: {
16
19
  config: ServerConfig;
package/dist/index.js CHANGED
@@ -1,18 +1,60 @@
1
- import { DAY, SECOND } from '@atproto/common';
2
- import cors from 'cors';
3
- import { config } from 'dotenv';
4
- import events from 'events';
5
- import express from 'express';
6
- import { createHttpTerminator } from 'http-terminator';
7
- import API, { health } from './api';
8
- import AppContext from './context';
9
- import { createDataPlaneClient } from './dataplane';
10
- import { BasicHostList } from './dataplane/client/hosts';
11
- import * as error from './error';
12
- import { createServer } from './lexicons';
13
- import { loggerMiddleware } from './logger';
14
- config();
15
- export class ClioAppView {
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ClioAppView = void 0;
40
+ const common_1 = require("@atproto/common");
41
+ const identity_1 = require("@atproto/identity");
42
+ const cors_1 = __importDefault(require("cors"));
43
+ const dotenv_1 = require("dotenv");
44
+ const events_1 = __importDefault(require("events"));
45
+ const express_1 = __importDefault(require("express"));
46
+ const http_terminator_1 = require("http-terminator");
47
+ const api_1 = __importStar(require("./api"));
48
+ const oauth = __importStar(require("./api/oauth"));
49
+ const auth_verifier_1 = require("./auth-verifier");
50
+ const context_1 = __importDefault(require("./context"));
51
+ const dataplane_1 = require("./dataplane");
52
+ const hosts_1 = require("./dataplane/client/hosts");
53
+ const error = __importStar(require("./error"));
54
+ const lexicons_1 = require("./lexicons");
55
+ const logger_1 = require("./logger");
56
+ (0, dotenv_1.config)();
57
+ class ClioAppView {
16
58
  ctx;
17
59
  app;
18
60
  server;
@@ -23,33 +65,53 @@ export class ClioAppView {
23
65
  }
24
66
  static create(opts) {
25
67
  const { config, signingKey } = opts;
26
- const app = express();
27
- app.use(cors({ maxAge: DAY / SECOND }));
28
- app.use(loggerMiddleware);
29
- const dataplaneHostList = new BasicHostList(config.dataplaneUrls);
30
- const dataplane = createDataPlaneClient(dataplaneHostList, {
68
+ const app = (0, express_1.default)();
69
+ // used solely for handle resolution: identity lookups occur on dataplane
70
+ const idResolver = new identity_1.IdResolver({
71
+ plcUrl: config.didPlcUrl,
72
+ backupNameservers: config.handleResolverNameservers,
73
+ });
74
+ const dataplaneHostList = new hosts_1.BasicHostList(config.dataplaneUrls);
75
+ const dataplane = (0, dataplane_1.createDataPlaneClient)(dataplaneHostList, {
31
76
  httpVersion: '2',
32
77
  rejectUnauthorized: false,
33
78
  });
34
- const server = createServer();
35
- const ctx = new AppContext({
79
+ const authVerifier = new auth_verifier_1.AuthVerifier(dataplane, {
80
+ ownDid: config.serverDid,
81
+ alternateAudienceDids: [],
82
+ modServiceDid: '',
83
+ adminPasses: config.adminPasswords,
84
+ });
85
+ const server = (0, lexicons_1.createServer)();
86
+ const ctx = new context_1.default({
36
87
  cfg: config,
37
88
  dataplane,
38
89
  signingKey,
90
+ dataplaneHostList,
91
+ idResolver,
92
+ authVerifier,
39
93
  });
40
- const api = API(server, ctx);
41
- app.use(health.createRouter(ctx));
94
+ const api = (0, api_1.default)(server, ctx);
95
+ app.use(api_1.health.createRouter(ctx));
96
+ app.use(api_1.wellKnown.createRouter(ctx));
97
+ app.use(oauth.createRouter(ctx));
42
98
  app.use(api.xrpc.router);
43
99
  app.use(error.handler);
100
+ app.use((0, cors_1.default)({ maxAge: common_1.DAY / common_1.SECOND }));
101
+ app.use(logger_1.loggerMiddleware);
44
102
  return new ClioAppView({ ctx, app });
45
103
  }
46
104
  async start() {
47
105
  console.log('Starting Clio AppView...');
48
- const server = this.app.listen(this.ctx.cfg.port);
106
+ const listenPort = this.ctx.cfg.port;
107
+ if (!listenPort) {
108
+ throw new Error('Missing port in config');
109
+ }
110
+ const server = this.app.listen(listenPort);
49
111
  this.server = server;
50
112
  server.keepAliveTimeout = 90000;
51
- this.terminator = createHttpTerminator({ server });
52
- await events.once(server, 'listening');
113
+ this.terminator = (0, http_terminator_1.createHttpTerminator)({ server });
114
+ await events_1.default.once(server, 'listening');
53
115
  const { port } = server.address();
54
116
  this.ctx.cfg.assignPort(port);
55
117
  return server;
@@ -58,4 +120,5 @@ export class ClioAppView {
58
120
  await this.terminator?.terminate();
59
121
  }
60
122
  }
61
- export default ClioAppView;
123
+ exports.ClioAppView = ClioAppView;
124
+ exports.default = ClioAppView;