@clioplaylists/clio 0.1.7 → 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 (129) 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.d.ts +3 -0
  11. package/dist/api/well-known.js +35 -0
  12. package/dist/auth-verifier.d.ts +17 -4
  13. package/dist/auth-verifier.js +171 -165
  14. package/dist/client.js +15 -8
  15. package/dist/config.d.ts +23 -0
  16. package/dist/config.js +87 -7
  17. package/dist/context.d.ts +14 -0
  18. package/dist/context.js +17 -1
  19. package/dist/dataplane/client/hosts.d.ts +21 -0
  20. package/dist/dataplane/client/hosts.js +29 -0
  21. package/dist/dataplane/client/index.d.ts +13 -0
  22. package/dist/dataplane/client/index.js +120 -0
  23. package/dist/dataplane/client/util.d.ts +20 -0
  24. package/dist/dataplane/client/util.js +92 -0
  25. package/dist/dataplane/index.js +18 -2
  26. package/dist/dataplane/server/background.d.ts +1 -1
  27. package/dist/dataplane/server/background.js +12 -5
  28. package/dist/dataplane/server/db/database-schema.d.ts +5 -1
  29. package/dist/dataplane/server/db/database-schema.js +2 -1
  30. package/dist/dataplane/server/db/db.js +60 -20
  31. package/dist/dataplane/server/db/index.js +17 -1
  32. package/dist/dataplane/server/db/migrations/20250515T045948368Z-init.d.ts +3 -0
  33. package/dist/dataplane/server/db/migrations/20250515T045948368Z-init.js +170 -0
  34. package/dist/dataplane/server/db/migrations/20260119T210000000Z-song-recommendation.d.ts +3 -0
  35. package/dist/dataplane/server/db/migrations/20260119T210000000Z-song-recommendation.js +36 -0
  36. package/dist/dataplane/server/db/migrations/20260119T220000000Z-oauth.d.ts +3 -0
  37. package/dist/dataplane/server/db/migrations/20260119T220000000Z-oauth.js +25 -0
  38. package/dist/dataplane/server/db/migrations/index.d.ts +3 -2
  39. package/dist/dataplane/server/db/migrations/index.js +39 -2
  40. package/dist/dataplane/server/db/migrations/provider.js +5 -1
  41. package/dist/dataplane/server/db/pagination.d.ts +1 -1
  42. package/dist/dataplane/server/db/pagination.js +38 -25
  43. package/dist/dataplane/server/db/tables/actor-sync.d.ts +2 -2
  44. package/dist/dataplane/server/db/tables/actor-sync.js +4 -1
  45. package/dist/dataplane/server/db/tables/actor.d.ts +3 -3
  46. package/dist/dataplane/server/db/tables/actor.js +4 -1
  47. package/dist/dataplane/server/db/tables/artist-list-item.d.ts +2 -2
  48. package/dist/dataplane/server/db/tables/artist-list-item.js +4 -1
  49. package/dist/dataplane/server/db/tables/artist.js +4 -1
  50. package/dist/dataplane/server/db/tables/oauth-session.d.ts +9 -0
  51. package/dist/dataplane/server/db/tables/oauth-session.js +4 -0
  52. package/dist/dataplane/server/db/tables/oauth-state.d.ts +10 -0
  53. package/dist/dataplane/server/db/tables/oauth-state.js +4 -0
  54. package/dist/dataplane/server/db/tables/playlist-idea.d.ts +3 -3
  55. package/dist/dataplane/server/db/tables/playlist-idea.js +4 -1
  56. package/dist/dataplane/server/db/tables/playlist-item.js +4 -1
  57. package/dist/dataplane/server/db/tables/playlist.d.ts +1 -0
  58. package/dist/dataplane/server/db/tables/playlist.js +4 -1
  59. package/dist/dataplane/server/db/tables/profile.d.ts +5 -5
  60. package/dist/dataplane/server/db/tables/profile.js +4 -1
  61. package/dist/dataplane/server/db/tables/record.d.ts +1 -1
  62. package/dist/dataplane/server/db/tables/record.js +4 -1
  63. package/dist/dataplane/server/db/tables/song-recommendation.d.ts +17 -0
  64. package/dist/dataplane/server/db/tables/song-recommendation.js +4 -0
  65. package/dist/dataplane/server/db/tables/song.d.ts +2 -2
  66. package/dist/dataplane/server/db/tables/song.js +4 -1
  67. package/dist/dataplane/server/db/tables/subscription-cursor.d.ts +9 -0
  68. package/dist/dataplane/server/db/tables/subscription-cursor.js +4 -0
  69. package/dist/dataplane/server/db/types.js +2 -1
  70. package/dist/dataplane/server/db/util.d.ts +7 -3
  71. package/dist/dataplane/server/db/util.js +26 -18
  72. package/dist/dataplane/server/index.js +21 -13
  73. package/dist/dataplane/server/indexing/index.d.ts +2 -0
  74. package/dist/dataplane/server/indexing/index.js +82 -66
  75. package/dist/dataplane/server/indexing/plugins/playlist-idea.d.ts +1 -2
  76. package/dist/dataplane/server/indexing/plugins/playlist-idea.js +50 -41
  77. package/dist/dataplane/server/indexing/plugins/profile.js +45 -12
  78. package/dist/dataplane/server/indexing/plugins/song-recommendation.d.ts +9 -0
  79. package/dist/dataplane/server/indexing/plugins/song-recommendation.js +101 -0
  80. package/dist/dataplane/server/indexing/processor.js +12 -11
  81. package/dist/dataplane/server/routes/identity.d.ts +19 -0
  82. package/dist/dataplane/server/routes/identity.js +32 -25
  83. package/dist/dataplane/server/routes/index.js +15 -10
  84. package/dist/dataplane/server/routes/profile.js +17 -25
  85. package/dist/dataplane/server/routes/records.d.ts +18 -0
  86. package/dist/dataplane/server/routes/records.js +48 -22
  87. package/dist/dataplane/server/routes/sync.js +5 -3
  88. package/dist/dataplane/server/storage/subscription-cursor.d.ts +3 -0
  89. package/dist/dataplane/server/storage/subscription-cursor.js +25 -0
  90. package/dist/dataplane/server/subscription.d.ts +6 -3
  91. package/dist/dataplane/server/subscription.js +73 -63
  92. package/dist/error.js +9 -5
  93. package/dist/index.d.ts +8 -3
  94. package/dist/index.js +96 -27
  95. package/dist/lexicons/index.d.ts +3 -210
  96. package/dist/lexicons/index.js +26 -403
  97. package/dist/lexicons/lexicons.d.ts +409 -8107
  98. package/dist/lexicons/lexicons.js +134 -4276
  99. package/dist/lexicons/types/com/atproto/repo/strongRef.d.ts +4 -4
  100. package/dist/lexicons/types/com/atproto/repo/strongRef.js +13 -9
  101. package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.d.ts +10 -8
  102. package/dist/lexicons/types/com/clioplaylists/alpha/actor/profile.js +13 -9
  103. package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.d.ts +20 -11
  104. package/dist/lexicons/types/com/clioplaylists/alpha/feed/defs.js +29 -14
  105. package/dist/lexicons/types/com/clioplaylists/alpha/feed/getRecommendedPlaylistsByUser.d.ts +36 -0
  106. package/dist/lexicons/types/com/clioplaylists/alpha/feed/getRecommendedPlaylistsByUser.js +6 -0
  107. package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.d.ts +11 -14
  108. package/dist/lexicons/types/com/clioplaylists/alpha/feed/playlistIdea.js +20 -23
  109. package/dist/lexicons/types/com/clioplaylists/alpha/feed/recommendedPlaylist.d.ts +18 -0
  110. package/dist/lexicons/types/com/clioplaylists/alpha/feed/recommendedPlaylist.js +15 -0
  111. package/dist/lexicons/types/com/clioplaylists/alpha/feed/songRecommendation.d.ts +18 -0
  112. package/dist/lexicons/types/com/clioplaylists/alpha/feed/songRecommendation.js +15 -0
  113. package/dist/lexicons/util.d.ts +33 -2
  114. package/dist/lexicons/util.js +32 -4
  115. package/dist/logger.js +16 -10
  116. package/dist/oauth/client.d.ts +14 -0
  117. package/dist/oauth/client.js +126 -0
  118. package/dist/oauth/pds-agent.d.ts +3 -0
  119. package/dist/oauth/pds-agent.js +15 -0
  120. package/dist/rpc/clio_connect.d.ts +101 -11
  121. package/dist/rpc/clio_connect.js +138 -45
  122. package/dist/rpc/clio_pb.d.ts +448 -30
  123. package/dist/rpc/clio_pb.js +967 -272
  124. package/dist/start.js +9 -1
  125. package/dist/util/retry.js +10 -9
  126. package/dist/util/uris.js +6 -3
  127. package/dist/util.d.ts +0 -1
  128. package/dist/util.js +61 -20
  129. package/package.json +26 -5
@@ -1,16 +1,55 @@
1
- import { Kysely, Migrator, PostgresDialect, } from 'kysely';
2
- import assert from 'node:assert';
3
- import EventEmitter from 'node:events';
4
- import { Pool as PgPool, types as pgTypes } from 'pg';
5
- import { dbLogger } from '../../../logger';
6
- import * as migrations from './migrations';
7
- import { CtxMigrationProvider } from './migrations/provider';
8
- export class Database {
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.Database = void 0;
40
+ const kysely_1 = require("kysely");
41
+ const node_assert_1 = __importDefault(require("node:assert"));
42
+ const node_events_1 = __importDefault(require("node:events"));
43
+ const pg_1 = require("pg");
44
+ const logger_1 = require("../../../logger");
45
+ const migrations = __importStar(require("./migrations"));
46
+ const provider_1 = require("./migrations/provider");
47
+ class Database {
9
48
  opts;
10
49
  pool;
11
50
  db;
12
51
  migrator;
13
- txEvt = new EventEmitter();
52
+ txEvt = new node_events_1.default();
14
53
  destroyed = false;
15
54
  constructor(opts, instances) {
16
55
  this.opts = opts;
@@ -24,14 +63,14 @@ export class Database {
24
63
  // else create a pool & connect
25
64
  const { schema, url } = opts;
26
65
  const pool = opts.pool ??
27
- new PgPool({
66
+ new pg_1.Pool({
28
67
  connectionString: url,
29
68
  max: opts.poolSize,
30
69
  maxUses: opts.poolMaxUses,
31
70
  idleTimeoutMillis: opts.poolIdleTimeoutMs,
32
71
  });
33
72
  // Select count(*) and other pg bigints as js integer
34
- pgTypes.setTypeParser(pgTypes.builtins.INT8, (n) => parseInt(n, 10));
73
+ pg_1.types.setTypeParser(pg_1.types.builtins.INT8, (n) => parseInt(n, 10));
35
74
  // Setup schema usage, primarily for test parallelism (each test suite runs in its own pg schema)
36
75
  if (schema && !/^[a-z_]+$/i.test(schema)) {
37
76
  throw new Error(`Postgres schema must only contain [A-Za-z_]: ${schema}`);
@@ -47,13 +86,13 @@ export class Database {
47
86
  }
48
87
  });
49
88
  this.pool = pool;
50
- this.db = new Kysely({
51
- dialect: new PostgresDialect({ pool }),
89
+ this.db = new kysely_1.Kysely({
90
+ dialect: new kysely_1.PostgresDialect({ pool }),
52
91
  });
53
- this.migrator = new Migrator({
92
+ this.migrator = new kysely_1.Migrator({
54
93
  db: this.db,
55
94
  migrationTableSchema: opts.schema,
56
- provider: new CtxMigrationProvider(migrations, 'pg'),
95
+ provider: new provider_1.CtxMigrationProvider(migrations, 'pg'),
57
96
  });
58
97
  }
59
98
  get schema() {
@@ -87,10 +126,10 @@ export class Database {
87
126
  return this.db.isTransaction;
88
127
  }
89
128
  assertTransaction() {
90
- assert(this.isTransaction, 'Transaction required');
129
+ (0, node_assert_1.default)(this.isTransaction, 'Transaction required');
91
130
  }
92
131
  assertNotTransaction() {
93
- assert(!this.isTransaction, 'Cannot be in a transaction');
132
+ (0, node_assert_1.default)(!this.isTransaction, 'Cannot be in a transaction');
94
133
  }
95
134
  onCommit(fn) {
96
135
  this.assertTransaction();
@@ -129,9 +168,10 @@ export class Database {
129
168
  this.destroyed = true;
130
169
  }
131
170
  }
132
- export default Database;
133
- const onPoolError = (err) => dbLogger.error({ err }, 'db pool error');
134
- const onClientError = (err) => dbLogger.error({ err }, 'db client error');
171
+ exports.Database = Database;
172
+ exports.default = Database;
173
+ const onPoolError = (err) => logger_1.dbLogger.error({ err }, 'db pool error');
174
+ const onClientError = (err) => logger_1.dbLogger.error({ err }, 'db client error');
135
175
  // utils
136
176
  // -------
137
177
  class LeakyTxPlugin {
@@ -1 +1,17 @@
1
- export * from './db';
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./db"), exports);
@@ -0,0 +1,3 @@
1
+ import { Kysely } from 'kysely';
2
+ export declare function up(db: Kysely<unknown>): Promise<void>;
3
+ export declare function down(db: Kysely<unknown>): Promise<void>;
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.up = up;
4
+ exports.down = down;
5
+ // @TODO subject indexes, naming?
6
+ // @TODO drop indexes in down()?
7
+ async function up(db) {
8
+ // actor
9
+ await db.schema
10
+ .createTable('actor')
11
+ .addColumn('did', 'varchar', (col) => col.primaryKey())
12
+ .addColumn('handle', 'varchar', (col) => col.unique())
13
+ .addColumn('indexed_at', 'varchar', (col) => col.notNull())
14
+ .addColumn('takedown_ref', 'varchar')
15
+ .addColumn('upstream_status', 'varchar')
16
+ .execute();
17
+ // await db.schema // Supports user search
18
+ // .createIndex(`actor_handle_tgrm_idx`)
19
+ // .on('actor')
20
+ // .using('gist')
21
+ // .expression(sql`"handle" gist_trgm_ops`)
22
+ // .execute()
23
+ // actor_sync
24
+ await db.schema
25
+ .createTable('actor_sync')
26
+ .addColumn('did', 'varchar', (col) => col.primaryKey())
27
+ .addForeignKeyConstraint('fx_actor_sync_did_to_actor_did', ['did'], 'actor', ['did'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
28
+ .addColumn('commit_cid', 'varchar', (col) => col.notNull())
29
+ .addColumn('repo_rev', 'varchar', (col) => col.notNull())
30
+ .execute();
31
+ // artist
32
+ await db.schema
33
+ .createTable('artist')
34
+ .addColumn('id', 'integer', (col) => {
35
+ col.primaryKey();
36
+ col.generatedAlwaysAsIdentity();
37
+ return col;
38
+ })
39
+ .addColumn('name', 'varchar', (col) => col.notNull())
40
+ .addColumn('mb_id', 'varchar(36)', (col) => col.notNull())
41
+ .execute();
42
+ // song
43
+ await db.schema
44
+ .createTable('song')
45
+ .addColumn('id', 'integer', (col) => {
46
+ col.primaryKey();
47
+ col.generatedAlwaysAsIdentity();
48
+ return col;
49
+ })
50
+ .addColumn('track_name', 'varchar', (col) => col.notNull())
51
+ .addColumn('track_mb_id', 'varchar', (col) => col.notNull().unique())
52
+ .addColumn('album_artwork_ref', 'varchar')
53
+ .addColumn('indexed_at', 'varchar', (col) => col.notNull())
54
+ .execute();
55
+ // did_cache
56
+ await db.schema
57
+ .createTable('did_cache')
58
+ .addColumn('did', 'varchar', (col) => col.primaryKey())
59
+ .addColumn('doc', 'text', (col) => col.notNull())
60
+ .addColumn('updatedAt', 'bigint', (col) => col.notNull())
61
+ .execute();
62
+ // playlist_idea
63
+ await db.schema
64
+ .createTable('playlist_idea')
65
+ .addColumn('id', 'integer', (col) => {
66
+ col.primaryKey();
67
+ col.generatedAlwaysAsIdentity();
68
+ return col;
69
+ })
70
+ .addColumn('uri', 'varchar', (col) => {
71
+ col.notNull();
72
+ col.unique();
73
+ return col;
74
+ })
75
+ .addColumn('title', 'varchar', (col) => col.notNull())
76
+ .addColumn('description', 'varchar')
77
+ .addColumn('creator_did', 'varchar', (col) => col.notNull())
78
+ .addForeignKeyConstraint('fx_playlist_idea_creator_did_to_actor_did', ['creator_did'], 'actor', ['did'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
79
+ .addColumn('owner_did', 'varchar', (col) => col.notNull())
80
+ .addForeignKeyConstraint('fx_playlist_idea_owner_did_to_actor_did', ['owner_did'], 'actor', ['did'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
81
+ .addColumn('created_at', 'varchar', (col) => col.notNull())
82
+ .execute();
83
+ // playlist
84
+ await db.schema
85
+ .createTable('playlist')
86
+ .addColumn('id', 'integer', (col) => {
87
+ col.primaryKey();
88
+ col.generatedAlwaysAsIdentity();
89
+ return col;
90
+ })
91
+ .addColumn('playlist_idea_uri', 'varchar', (col) => col.notNull())
92
+ .addForeignKeyConstraint('fx_playlist_playlist_idea_uri_to_playlist_idea_uri', ['playlist_idea_uri'], 'playlist_idea', ['uri'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
93
+ .addColumn('type', 'varchar', (col) => col.notNull())
94
+ .addColumn('name', 'varchar', (col) => col.notNull())
95
+ .execute();
96
+ // playlist_item
97
+ await db.schema
98
+ .createTable('playlist_item')
99
+ .addColumn('id', 'integer', (col) => {
100
+ col.primaryKey();
101
+ col.generatedAlwaysAsIdentity();
102
+ return col;
103
+ })
104
+ .addColumn('playlist_id', 'integer', (col) => col.notNull())
105
+ .addForeignKeyConstraint('fx_playlist_item_playlist_id_to_playlist_id', ['playlist_id'], 'playlist', ['id'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
106
+ .addColumn('song_id', 'integer', (col) => col.notNull())
107
+ .addForeignKeyConstraint('fx_playlist_item_song_id_to_song_id', ['song_id'], 'song', ['id'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
108
+ .addColumn('position', 'integer', (col) => col.notNull())
109
+ .execute();
110
+ // artist_list_item
111
+ await db.schema
112
+ .createTable('artist_list_item')
113
+ .addColumn('id', 'integer', (col) => {
114
+ col.primaryKey();
115
+ col.generatedAlwaysAsIdentity();
116
+ return col;
117
+ })
118
+ .addColumn('artist_id', 'integer', (col) => col.notNull())
119
+ .addForeignKeyConstraint('fx_artist_list_item_artist_id_to_artist_id', ['artist_id'], 'artist', ['id'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
120
+ .addColumn('song_id', 'integer', (col) => col.notNull())
121
+ .addForeignKeyConstraint('fx_artist_list_item_song_id_to_song_id', ['song_id'], 'song', ['id'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
122
+ .addColumn('position', 'integer', (col) => col.notNull())
123
+ .execute();
124
+ // profile
125
+ await db.schema
126
+ .createTable('profile')
127
+ .addColumn('uri', 'varchar', (col) => col.primaryKey())
128
+ .addColumn('cid', 'varchar', (col) => col.notNull())
129
+ .addColumn('creator_did', 'varchar', (col) => col.notNull())
130
+ .addForeignKeyConstraint('fx_profile_creator_did_to_actor_did', ['creator_did'], 'actor', ['did'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
131
+ .addColumn('display_name', 'varchar')
132
+ .addColumn('description', 'varchar')
133
+ .addColumn('avatar_cid', 'varchar')
134
+ .addColumn('banner_cid', 'varchar')
135
+ .addColumn('created_at', 'varchar', (col) => col.notNull())
136
+ .addColumn('indexed_at', 'varchar', (col) => col.notNull())
137
+ .execute();
138
+ // record
139
+ await db.schema
140
+ .createTable('record')
141
+ .addColumn('uri', 'varchar', (col) => col.primaryKey())
142
+ .addColumn('cid', 'varchar', (col) => col.notNull())
143
+ .addColumn('did', 'varchar', (col) => col.notNull())
144
+ .addForeignKeyConstraint('fx_record_did_to_actor_did', ['did'], 'actor', ['did'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
145
+ .addColumn('json', 'text', (col) => col.notNull())
146
+ .addColumn('indexed_at', 'varchar', (col) => col.notNull())
147
+ .addColumn('takedown_ref', 'varchar')
148
+ .execute();
149
+ // subscription_cursor
150
+ await db.schema
151
+ .createTable('subscription_cursor')
152
+ .addColumn('service', 'varchar', (col) => col.primaryKey())
153
+ .addColumn('cursor', 'bigint', (col) => col.notNull())
154
+ .addColumn('updated_at', 'bigint', (col) => col.notNull())
155
+ .execute();
156
+ }
157
+ async function down(db) {
158
+ await db.schema.dropTable('subscription_cursor').execute();
159
+ await db.schema.dropTable('record').execute();
160
+ await db.schema.dropTable('profile').execute();
161
+ await db.schema.dropTable('artist_list_item').execute();
162
+ await db.schema.dropTable('playlist_item').execute();
163
+ await db.schema.dropTable('playlist').execute();
164
+ await db.schema.dropTable('playlist_idea').execute();
165
+ await db.schema.dropTable('did_cache').execute();
166
+ await db.schema.dropTable('song').execute();
167
+ await db.schema.dropTable('artist').execute();
168
+ await db.schema.dropTable('actor_sync').execute();
169
+ await db.schema.dropTable('actor').execute();
170
+ }
@@ -0,0 +1,3 @@
1
+ import { Kysely } from 'kysely';
2
+ export declare function up(db: Kysely<unknown>): Promise<void>;
3
+ export declare function down(db: Kysely<unknown>): Promise<void>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.up = up;
4
+ exports.down = down;
5
+ async function up(db) {
6
+ await db.schema
7
+ .createTable('song_recommendation')
8
+ .addColumn('id', 'integer', (col) => {
9
+ col.primaryKey();
10
+ col.generatedAlwaysAsIdentity();
11
+ return col;
12
+ })
13
+ .addColumn('uri', 'varchar', (col) => col.notNull().unique())
14
+ .addColumn('cid', 'varchar', (col) => col.notNull())
15
+ .addColumn('recommender_did', 'varchar', (col) => col.notNull())
16
+ .addForeignKeyConstraint('fx_song_rec_recommender_did_to_actor_did', ['recommender_did'], 'actor', ['did'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
17
+ .addColumn('playlist_idea_uri', 'varchar', (col) => col.notNull())
18
+ .addForeignKeyConstraint('fx_song_rec_playlist_idea_uri_to_playlist_idea_uri', ['playlist_idea_uri'], 'playlist_idea', ['uri'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
19
+ .addColumn('playlist_idea_cid', 'varchar', (col) => col.notNull())
20
+ .addColumn('song_id', 'integer', (col) => col.notNull())
21
+ .addForeignKeyConstraint('fx_song_rec_song_id_to_song_id', ['song_id'], 'song', ['id'], (cb) => cb.onDelete('cascade').onUpdate('cascade'))
22
+ .addColumn('note', 'varchar')
23
+ .addColumn('created_at', 'varchar', (col) => col.notNull())
24
+ .addColumn('indexed_at', 'varchar', (col) => col.notNull())
25
+ .execute();
26
+ await db.schema
27
+ .createIndex('song_rec_dedup_idx')
28
+ .on('song_recommendation')
29
+ .columns(['recommender_did', 'playlist_idea_uri', 'song_id'])
30
+ .unique()
31
+ .execute();
32
+ }
33
+ async function down(db) {
34
+ await db.schema.dropIndex('song_rec_dedup_idx').execute();
35
+ await db.schema.dropTable('song_recommendation').execute();
36
+ }
@@ -0,0 +1,3 @@
1
+ import { Kysely } from 'kysely';
2
+ export declare function up(db: Kysely<unknown>): Promise<void>;
3
+ export declare function down(db: Kysely<unknown>): Promise<void>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.up = up;
4
+ exports.down = down;
5
+ async function up(db) {
6
+ await db.schema
7
+ .createTable('oauth_state')
8
+ .addColumn('key', 'varchar', (col) => col.primaryKey())
9
+ .addColumn('value', 'jsonb', (col) => col.notNull())
10
+ .addColumn('created_at', 'bigint', (col) => col.notNull())
11
+ .addColumn('expires_at', 'bigint', (col) => col.notNull())
12
+ .execute();
13
+ await db.schema.createIndex('oauth_state_expires_at_idx').on('oauth_state').column('expires_at').execute();
14
+ await db.schema
15
+ .createTable('oauth_session')
16
+ .addColumn('key', 'varchar', (col) => col.primaryKey())
17
+ .addColumn('value', 'jsonb', (col) => col.notNull())
18
+ .addColumn('updated_at', 'bigint', (col) => col.notNull())
19
+ .execute();
20
+ }
21
+ async function down(db) {
22
+ await db.schema.dropTable('oauth_session').execute();
23
+ await db.schema.dropIndex('oauth_state_expires_at_idx').execute();
24
+ await db.schema.dropTable('oauth_state').execute();
25
+ }
@@ -1,2 +1,3 @@
1
- export * as _20230309T045948368Z from './20230309T045948368Z-init';
2
- export * as _20230420T211446071Z from './20230420T211446071Z-did-cache';
1
+ export * as _20230309T045948368Z from './20250515T045948368Z-init';
2
+ export * as _20260119T210000000Z from './20260119T210000000Z-song-recommendation';
3
+ export * as _20260119T220000000Z from './20260119T220000000Z-oauth';
@@ -1,5 +1,42 @@
1
+ "use strict";
1
2
  // NOTE this file can be edited by hand, but it is also appended to by the migration:create command.
2
3
  // It's important that every migration is exported from here with the proper name. We'd simplify
3
4
  // this with kysely's FileMigrationProvider, but it doesn't play nicely with the build process.
4
- export * as _20230309T045948368Z from './20230309T045948368Z-init';
5
- export * as _20230420T211446071Z from './20230420T211446071Z-did-cache';
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports._20260119T220000000Z = exports._20260119T210000000Z = exports._20230309T045948368Z = void 0;
40
+ exports._20230309T045948368Z = __importStar(require("./20250515T045948368Z-init"));
41
+ exports._20260119T210000000Z = __importStar(require("./20260119T210000000Z-song-recommendation"));
42
+ exports._20260119T220000000Z = __importStar(require("./20260119T220000000Z-oauth"));
@@ -1,5 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CtxMigrationProvider = void 0;
1
4
  // Passes a context argument to migrations. We use this to thread the dialect into migrations
2
- export class CtxMigrationProvider {
5
+ class CtxMigrationProvider {
3
6
  migrations;
4
7
  ctx;
5
8
  constructor(migrations, ctx) {
@@ -17,3 +20,4 @@ export class CtxMigrationProvider {
17
20
  return ctxMigrations;
18
21
  }
19
22
  }
23
+ exports.CtxMigrationProvider = CtxMigrationProvider;
@@ -33,7 +33,7 @@ export declare abstract class GenericKeyset<R, LR extends LabeledResult> {
33
33
  unpack(cursorStr?: string): LR | undefined;
34
34
  packCursor(cursor?: Cursor): string | undefined;
35
35
  unpackCursor(cursorStr?: string): Cursor | undefined;
36
- getSql(labeled?: LR, direction?: 'asc' | 'desc', tryIndex?: boolean): import("kysely").RawBuilder<unknown> | undefined;
36
+ getSql(labeled?: LR, direction?: 'asc' | 'desc', tryIndex?: boolean): import("kysely").RawBuilder<0 | 1> | undefined;
37
37
  }
38
38
  type SortAtCidResult = {
39
39
  sortAt: string;
@@ -1,5 +1,8 @@
1
- import { InvalidRequestError } from '@atproto/xrpc-server';
2
- import { sql } from 'kysely';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.paginate = exports.IndexedAtDidKeyset = exports.CreatedAtDidKeyset = exports.TimeCidKeyset = exports.GenericKeyset = void 0;
4
+ const xrpc_server_1 = require("@atproto/xrpc-server");
5
+ const kysely_1 = require("kysely");
3
6
  /**
4
7
  * The GenericKeyset is an abstract class that sets-up the interface and partial implementation
5
8
  * of a keyset-paginated cursor with two parts. There are three types involved:
@@ -14,7 +17,7 @@ import { sql } from 'kysely';
14
17
  * Result -*-> LabeledResult <-*-> Cursor <--> packed/string cursor
15
18
  * ↳ SQL Condition
16
19
  */
17
- export class GenericKeyset {
20
+ class GenericKeyset {
18
21
  primary;
19
22
  secondary;
20
23
  constructor(primary, secondary) {
@@ -50,7 +53,7 @@ export class GenericKeyset {
50
53
  const result = cursorStr.split('__');
51
54
  const [primary, secondary, ...others] = result;
52
55
  if (!primary || !secondary || others.length > 0) {
53
- throw new InvalidRequestError('Malformed cursor');
56
+ throw new xrpc_server_1.InvalidRequestError('Malformed cursor');
54
57
  }
55
58
  return {
56
59
  primary,
@@ -63,24 +66,25 @@ export class GenericKeyset {
63
66
  if (tryIndex) {
64
67
  // The tryIndex param will likely disappear and become the default implementation: here for now for gradual rollout query-by-query.
65
68
  if (direction === 'asc') {
66
- return sql `((${this.primary}, ${this.secondary}) > (${labeled.primary}, ${labeled.secondary}))`;
69
+ return (0, kysely_1.sql) `((${this.primary}, ${this.secondary}) > (${labeled.primary}, ${labeled.secondary}))`;
67
70
  }
68
71
  else {
69
- return sql `((${this.primary}, ${this.secondary}) < (${labeled.primary}, ${labeled.secondary}))`;
72
+ return (0, kysely_1.sql) `((${this.primary}, ${this.secondary}) < (${labeled.primary}, ${labeled.secondary}))`;
70
73
  }
71
74
  }
72
75
  else {
73
76
  // @NOTE this implementation can struggle to use an index on (primary, secondary) for pagination due to the "or" usage.
74
77
  if (direction === 'asc') {
75
- return sql `((${this.primary} > ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} > ${labeled.secondary}))`;
78
+ return (0, kysely_1.sql) `((${this.primary} > ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} > ${labeled.secondary}))`;
76
79
  }
77
80
  else {
78
- return sql `((${this.primary} < ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} < ${labeled.secondary}))`;
81
+ return (0, kysely_1.sql) `((${this.primary} < ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} < ${labeled.secondary}))`;
79
82
  }
80
83
  }
81
84
  }
82
85
  }
83
- export class TimeCidKeyset extends GenericKeyset {
86
+ exports.GenericKeyset = GenericKeyset;
87
+ class TimeCidKeyset extends GenericKeyset {
84
88
  labelResult(result) {
85
89
  return { primary: result.sortAt, secondary: result.cid };
86
90
  }
@@ -93,7 +97,7 @@ export class TimeCidKeyset extends GenericKeyset {
93
97
  cursorToLabeledResult(cursor) {
94
98
  const primaryDate = new Date(parseInt(cursor.primary, 10));
95
99
  if (isNaN(primaryDate.getTime())) {
96
- throw new InvalidRequestError('Malformed cursor');
100
+ throw new xrpc_server_1.InvalidRequestError('Malformed cursor');
97
101
  }
98
102
  return {
99
103
  primary: primaryDate.toISOString(),
@@ -101,28 +105,37 @@ export class TimeCidKeyset extends GenericKeyset {
101
105
  };
102
106
  }
103
107
  }
104
- export class CreatedAtDidKeyset extends TimeCidKeyset {
108
+ exports.TimeCidKeyset = TimeCidKeyset;
109
+ class CreatedAtDidKeyset extends TimeCidKeyset {
105
110
  labelResult(result) {
106
111
  return { primary: result.createdAt, secondary: result.did };
107
112
  }
108
113
  }
109
- export class IndexedAtDidKeyset extends TimeCidKeyset {
114
+ exports.CreatedAtDidKeyset = CreatedAtDidKeyset;
115
+ class IndexedAtDidKeyset extends TimeCidKeyset {
110
116
  labelResult(result) {
111
117
  return { primary: result.indexedAt, secondary: result.did };
112
118
  }
113
119
  }
114
- export const paginate = (qb, opts) => {
115
- const { limit, cursor, keyset, direction = 'desc', tryIndex, nullsLast, } = opts;
120
+ exports.IndexedAtDidKeyset = IndexedAtDidKeyset;
121
+ const paginate = (qb, opts) => {
122
+ const { limit, cursor, keyset, direction = 'desc', tryIndex, nullsLast } = opts;
116
123
  const keysetSql = keyset.getSql(keyset.unpack(cursor), direction, tryIndex);
117
- return qb
118
- .if(!!limit, (q) => q.limit(limit))
119
- .if(!nullsLast, (q) => q.orderBy(keyset.primary, direction).orderBy(keyset.secondary, direction))
120
- .if(!!nullsLast, (q) => q
121
- .orderBy(direction === 'asc'
122
- ? sql `${keyset.primary} asc nulls last`
123
- : sql `${keyset.primary} desc nulls last`)
124
- .orderBy(direction === 'asc'
125
- ? sql `${keyset.secondary} asc nulls last`
126
- : sql `${keyset.secondary} desc nulls last`))
127
- .if(!!keysetSql, (qb) => (keysetSql ? qb.where(keysetSql) : qb));
124
+ let q = qb;
125
+ if (typeof limit === 'number') {
126
+ q = q.limit(limit);
127
+ }
128
+ if (nullsLast) {
129
+ q = q
130
+ .orderBy(direction === 'asc' ? (0, kysely_1.sql) `${keyset.primary} asc nulls last` : (0, kysely_1.sql) `${keyset.primary} desc nulls last`)
131
+ .orderBy(direction === 'asc' ? (0, kysely_1.sql) `${keyset.secondary} asc nulls last` : (0, kysely_1.sql) `${keyset.secondary} desc nulls last`);
132
+ }
133
+ else {
134
+ q = q.orderBy(keyset.primary, direction).orderBy(keyset.secondary, direction);
135
+ }
136
+ if (keysetSql) {
137
+ q = q.where(keysetSql);
138
+ }
139
+ return q;
128
140
  };
141
+ exports.paginate = paginate;
@@ -1,8 +1,8 @@
1
1
  export declare const tableName = "actor_sync";
2
2
  export interface ActorSync {
3
3
  did: string;
4
- commitCid: string;
5
- repoRev: string | null;
4
+ commit_cid: string;
5
+ repo_rev: string;
6
6
  }
7
7
  export type PartialDB = {
8
8
  [tableName]: ActorSync;
@@ -1 +1,4 @@
1
- export const tableName = 'actor_sync';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tableName = void 0;
4
+ exports.tableName = 'actor_sync';
@@ -1,10 +1,10 @@
1
1
  export declare const tableName = "actor";
2
2
  export interface ActorTable {
3
3
  did: string;
4
- handle?: string | null;
4
+ handle: string | null;
5
5
  indexed_at: string;
6
- takedownRef?: string | null;
7
- upstreamStatus?: string | null;
6
+ takedown_ref: string | null;
7
+ upstream_status: string | null;
8
8
  }
9
9
  export type PartialDB = {
10
10
  [tableName]: ActorTable;
@@ -1 +1,4 @@
1
- export const tableName = 'actor';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tableName = void 0;
4
+ exports.tableName = 'actor';
@@ -2,9 +2,9 @@ import { Generated } from 'kysely';
2
2
  export declare const tableName = "artist_list_item";
3
3
  export interface ArtistListItemTable {
4
4
  id: Generated<number>;
5
- song_id: number;
6
- seq_num: number;
7
5
  artist_id: number;
6
+ song_id: number;
7
+ position: number;
8
8
  }
9
9
  export type PartialDB = {
10
10
  [tableName]: ArtistListItemTable;