@nina-protocol/nina-db 0.0.101 → 0.0.102

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.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ export const up = function (knex) {
6
+ return knex.schema.table('releases', table => {
7
+ table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
8
+ });
9
+ };
10
+ /**
11
+ * @param { import("knex").Knex } knex
12
+ * @returns { Promise<void> }
13
+ */
14
+ export const down = function (knex) {
15
+ return knex.schema.table('releases', table => {
16
+ table.dropColumn('programId');
17
+ });
18
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ export const up = function (knex) {
6
+ return knex.schema.table('transactions', table => {
7
+ table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
8
+ });
9
+ };
10
+ /**
11
+ * @param { import("knex").Knex } knex
12
+ * @returns { Promise<void> }
13
+ */
14
+ export const down = function (knex) {
15
+ return knex.schema.table('transactions', table => {
16
+ table.dropColumn('programId');
17
+ });
18
+ };
@@ -1,4 +1,5 @@
1
- import anchor from '@project-serum/anchor';
1
+ import * as anchorSerum from '@project-serum/anchor';
2
+ import * as anchorCoral from '@coral-xyz/anchor';
2
3
  import { Metaplex } from '@metaplex-foundation/js';
3
4
  import { Model } from 'objection';
4
5
  import { stripHtmlIfNeeded, tweetNewRelease } from '../utils/index.js';
@@ -10,6 +11,13 @@ import Tag from './Tag.js';
10
11
  import axios from 'axios';
11
12
  import promiseRetry from 'promise-retry';
12
13
  import { customAlphabet } from 'nanoid';
14
+ import { getTokenMetadata } from '@solana/spl-token';
15
+ const ensureHttps = (uri) => {
16
+ if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
17
+ return `https://${uri}`;
18
+ }
19
+ return uri;
20
+ };
13
21
  const alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
14
22
  const randomStringGenerator = customAlphabet(alphabet, 12);
15
23
  export default class Release extends Model {
@@ -46,21 +54,25 @@ export default class Release extends Model {
46
54
  archived: { type: 'boolean' },
47
55
  },
48
56
  };
49
- static findOrCreate = async (publicKey, hubPublicKey = null) => {
57
+ static findOrCreate = async (publicKey, hubPublicKey = null, programId = process.env.NINA_PROGRAM_V2_ID) => {
50
58
  try {
59
+ console.log('Release.findOrCreate', publicKey, programId);
51
60
  let release = await Release.query().findOne({ publicKey });
52
61
  if (release) {
62
+ console.log('release found', release);
53
63
  return release;
54
64
  }
65
+ let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
55
66
  const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
56
67
  const provider = new anchor.AnchorProvider(connection, {}, { commitment: 'confirmed' });
57
- const program = await anchor.Program.at(process.env.NINA_PROGRAM_ID, provider);
68
+ const program = await anchor.Program.at(programId, provider);
69
+ const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
58
70
  const metaplex = new Metaplex(connection);
59
71
  let attempts = 0;
60
72
  const releaseAccount = await promiseRetry(async (retry) => {
61
73
  try {
62
74
  attempts += 1;
63
- const result = await program.account.release.fetch(new anchor.web3.PublicKey(publicKey), 'confirmed');
75
+ const result = await program.account[programModelName].fetch(new anchor.web3.PublicKey(publicKey), 'confirmed');
64
76
  return result;
65
77
  }
66
78
  catch (error) {
@@ -72,27 +84,34 @@ export default class Release extends Model {
72
84
  minTimeout: 500,
73
85
  maxTimeout: 1500,
74
86
  });
75
- let metadataAccount = (await metaplex.nfts().findAllByMintList({ mints: [releaseAccount.releaseMint] }, { commitment: 'confirmed' }))[0];
87
+ let metadataAccount;
88
+ if (programId === process.env.NINA_PROGRAM_V2_ID) {
89
+ metadataAccount = await getTokenMetadata(connection, releaseAccount.mint, 'confirmed');
90
+ }
91
+ else {
92
+ metadataAccount = (await metaplex.nfts().findAllByMintList({ mints: [releaseAccount.releaseMint] }, { commitment: 'confirmed' }))[0];
93
+ }
76
94
  if (!metadataAccount) {
77
95
  throw new Error('No metadata account found for release - is not a complete release');
78
96
  }
79
97
  let json;
80
98
  try {
81
- json = (await axios.get(metadataAccount.uri.replace('www.', '').replace('arweave.net', 'gateway.irys.xyz'))).data;
99
+ json = (await axios.get(ensureHttps(metadataAccount.uri.replace('www.', '').replace('arweave.net', 'gateway.irys.xyz')))).data;
82
100
  }
83
101
  catch (error) {
84
- json = (await axios.get(metadataAccount.uri.replace('gateway.irys.xyz', 'arweave.net'))).data;
102
+ json = (await axios.get(ensureHttps(metadataAccount.uri.replace('gateway.irys.xyz', 'arweave.net')))).data;
85
103
  }
86
104
  const slug = await this.generateSlug(json);
87
105
  let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
88
106
  release = await this.createRelease({
89
107
  publicKey,
90
- mint: releaseAccount.releaseMint.toBase58(),
108
+ mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
91
109
  metadata: json,
92
- datetime: new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
110
+ datetime: programId === process.env.NINA_PROGRAM_V2_ID ? new Date().toISOString() : new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
93
111
  slug,
94
112
  publisherId: publisher.id,
95
- releaseAccount
113
+ releaseAccount,
114
+ programId,
96
115
  });
97
116
  if (hubPublicKey) {
98
117
  const hub = await Hub.query().findOne({ publicKey: hubPublicKey });
@@ -108,7 +127,7 @@ export default class Release extends Model {
108
127
  return null;
109
128
  }
110
129
  };
111
- static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount }) => {
130
+ static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId }) => {
112
131
  const slug = await this.generateSlug(metadata);
113
132
  const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
114
133
  const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
@@ -121,7 +140,8 @@ export default class Release extends Model {
121
140
  publisherId,
122
141
  price: `${price}`,
123
142
  paymentMint,
124
- archived: false
143
+ archived: false,
144
+ programId,
125
145
  });
126
146
  if (metadata.properties.tags) {
127
147
  for await (let tag of metadata.properties.tags) {
@@ -129,7 +149,9 @@ export default class Release extends Model {
129
149
  await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
130
150
  }
131
151
  }
132
- await this.processRevenueShares(releaseAccount, release);
152
+ if (programId === process.env.NINA_PROGRAM_ID) {
153
+ await this.processRevenueShares(releaseAccount, release);
154
+ }
133
155
  tweetNewRelease(metadata, publisherId, slug);
134
156
  return release;
135
157
  };
@@ -20,6 +20,8 @@ class Transaction extends Model {
20
20
  type: {
21
21
  type: 'string',
22
22
  enum: [
23
+ 'ReleaseInitV2',
24
+ 'ReleaseUpdate',
23
25
  'ExchangeAccept',
24
26
  'ExchangeCancel',
25
27
  'ExchangeInit',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nina-protocol/nina-db",
3
- "version": "0.0.101",
3
+ "version": "0.0.102",
4
4
  "description": "",
5
5
  "source": "src/index.js",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,8 @@
23
23
  "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
24
24
  "@babel/preset-es2015": "^7.0.0-beta.53",
25
25
  "@metaplex-foundation/js": "^0.18.1",
26
- "@project-serum/anchor": "^0.25.0",
26
+ "@coral-xyz/anchor": "^0.31.0",
27
+ "@solana/spl-token": "^0.4.9",
27
28
  "axios": "^0.27.2",
28
29
  "knex": "^2.2.0",
29
30
  "nanoid": "^4.0.2",
@@ -46,6 +47,6 @@
46
47
  "rollup-plugin-babel": "^4.4.0",
47
48
  "rollup-plugin-commonjs": "^10.1.0",
48
49
  "rollup-plugin-terser": "^7.0.2",
49
- "typescript": "4.3.5"
50
+ "typescript": "5.7.3"
50
51
  }
51
52
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ export const up = function(knex) {
6
+ return knex.schema.table('releases', table => {
7
+ table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
8
+ });
9
+ };
10
+
11
+ /**
12
+ * @param { import("knex").Knex } knex
13
+ * @returns { Promise<void> }
14
+ */
15
+ export const down = function(knex) {
16
+ return knex.schema.table('releases', table => {
17
+ table.dropColumn('programId');
18
+ });
19
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ export const up = function(knex) {
6
+ return knex.schema.table('transactions', table => {
7
+ table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
8
+ });
9
+ };
10
+
11
+ /**
12
+ * @param { import("knex").Knex } knex
13
+ * @returns { Promise<void> }
14
+ */
15
+ export const down = function(knex) {
16
+ return knex.schema.table('transactions', table => {
17
+ table.dropColumn('programId');
18
+ });
19
+ };
@@ -1,4 +1,5 @@
1
- import anchor from '@project-serum/anchor';
1
+ import * as anchorSerum from '@project-serum/anchor';
2
+ import * as anchorCoral from '@coral-xyz/anchor';
2
3
  import { Metaplex } from '@metaplex-foundation/js';
3
4
  import { Model } from 'objection';
4
5
  import { stripHtmlIfNeeded, tweetNewRelease }from '../utils/index.js';
@@ -10,7 +11,14 @@ import Tag from './Tag.js';
10
11
  import axios from 'axios';
11
12
  import promiseRetry from 'promise-retry';
12
13
  import { customAlphabet } from 'nanoid';
13
- import promiseRetry from 'promise-retry';
14
+ import { getTokenMetadata } from '@solana/spl-token';
15
+
16
+ const ensureHttps = (uri) => {
17
+ if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
18
+ return `https://${uri}`;
19
+ }
20
+ return uri;
21
+ };
14
22
 
15
23
  const alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
16
24
  const randomStringGenerator = customAlphabet(alphabet, 12);
@@ -50,27 +58,30 @@ export default class Release extends Model {
50
58
  },
51
59
  }
52
60
 
53
- static findOrCreate = async (publicKey, hubPublicKey=null) => {
61
+ static findOrCreate = async (publicKey, hubPublicKey=null, programId=process.env.NINA_PROGRAM_V2_ID) => {
54
62
  try {
63
+ console.log('Release.findOrCreate', publicKey, programId)
55
64
  let release = await Release.query().findOne({ publicKey });
56
65
  if (release) {
66
+ console.log('release found', release)
57
67
  return release;
58
68
  }
59
69
 
70
+ let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
60
71
  const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
61
72
  const provider = new anchor.AnchorProvider(connection, {}, {commitment: 'confirmed'})
62
73
  const program = await anchor.Program.at(
63
- process.env.NINA_PROGRAM_ID,
74
+ programId,
64
75
  provider,
65
76
  )
77
+ const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
66
78
  const metaplex = new Metaplex(connection);
67
79
  let attempts = 0;
68
-
69
80
  const releaseAccount = await promiseRetry(
70
81
  async (retry) => {
71
82
  try {
72
83
  attempts += 1
73
- const result = await program.account.release.fetch(new anchor.web3.PublicKey(publicKey), 'confirmed')
84
+ const result = await program.account[programModelName].fetch(new anchor.web3.PublicKey(publicKey), 'confirmed')
74
85
  return result
75
86
  } catch (error) {
76
87
  console.log('error fetching release account', error)
@@ -83,27 +94,33 @@ export default class Release extends Model {
83
94
  }
84
95
  )
85
96
 
86
- let metadataAccount = (await metaplex.nfts().findAllByMintList({mints: [releaseAccount.releaseMint]}, { commitment: 'confirmed' }))[0];
97
+ let metadataAccount
98
+ if (programId === process.env.NINA_PROGRAM_V2_ID) {
99
+ metadataAccount = await getTokenMetadata(connection, releaseAccount.mint, 'confirmed')
100
+ } else {
101
+ metadataAccount = (await metaplex.nfts().findAllByMintList({mints: [releaseAccount.releaseMint]}, { commitment: 'confirmed' }))[0];
102
+ }
87
103
  if (!metadataAccount) {
88
104
  throw new Error('No metadata account found for release - is not a complete release')
89
105
  }
90
106
  let json
91
107
  try {
92
- json = (await axios.get(metadataAccount.uri.replace('www.','').replace('arweave.net', 'gateway.irys.xyz'))).data
108
+ json = (await axios.get(ensureHttps(metadataAccount.uri.replace('www.','').replace('arweave.net', 'gateway.irys.xyz')))).data
93
109
  } catch (error) {
94
- json = (await axios.get(metadataAccount.uri.replace('gateway.irys.xyz', 'arweave.net'))).data
110
+ json = (await axios.get(ensureHttps(metadataAccount.uri.replace('gateway.irys.xyz', 'arweave.net')))).data
95
111
  }
96
112
 
97
113
  const slug = await this.generateSlug(json);
98
114
  let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
99
115
  release = await this.createRelease({
100
116
  publicKey,
101
- mint: releaseAccount.releaseMint.toBase58(),
117
+ mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
102
118
  metadata: json,
103
- datetime: new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
119
+ datetime: programId === process.env.NINA_PROGRAM_V2_ID ? new Date().toISOString() : new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
104
120
  slug,
105
121
  publisherId: publisher.id,
106
- releaseAccount
122
+ releaseAccount,
123
+ programId,
107
124
  });
108
125
 
109
126
  if (hubPublicKey) {
@@ -122,7 +139,7 @@ export default class Release extends Model {
122
139
  }
123
140
  }
124
141
 
125
- static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount}) => {
142
+ static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId}) => {
126
143
  const slug = await this.generateSlug(metadata);
127
144
  const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
128
145
  const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
@@ -135,7 +152,8 @@ export default class Release extends Model {
135
152
  publisherId,
136
153
  price: `${price}`,
137
154
  paymentMint,
138
- archived: false
155
+ archived: false,
156
+ programId,
139
157
  })
140
158
  if (metadata.properties.tags) {
141
159
  for await (let tag of metadata.properties.tags) {
@@ -143,7 +161,9 @@ export default class Release extends Model {
143
161
  await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
144
162
  }
145
163
  }
146
- await this.processRevenueShares(releaseAccount, release);
164
+ if (programId === process.env.NINA_PROGRAM_ID) {
165
+ await this.processRevenueShares(releaseAccount, release);
166
+ }
147
167
  tweetNewRelease(metadata, publisherId, slug);
148
168
  return release;
149
169
  }
@@ -21,6 +21,8 @@ class Transaction extends Model {
21
21
  type: {
22
22
  type: 'string',
23
23
  enum: [
24
+ 'ReleaseInitV2',
25
+ 'ReleaseUpdate',
24
26
  'ExchangeAccept',
25
27
  'ExchangeCancel',
26
28
  'ExchangeInit',
@@ -1,54 +0,0 @@
1
- /**
2
- * @param { import("knex").Knex } knex
3
- * @returns { Promise<void> }
4
- */
5
- export const up = function (knex) {
6
- return Promise.all([
7
- // Accounts table indexes
8
- knex.schema.alterTable('accounts', table => {
9
- table.index('displayName');
10
- table.index('handle');
11
- }),
12
- // Hubs table indexes
13
- knex.schema.raw('CREATE INDEX idx_hubs_handle ON hubs (handle)'),
14
- knex.schema.raw('CREATE INDEX idx_hubs_display_name ON hubs ((data->>\'displayName\'))'),
15
- // Tags table index
16
- knex.schema.alterTable('tags', table => {
17
- table.index('value');
18
- }),
19
- // Releases table indexes for search
20
- knex.schema.raw('CREATE INDEX idx_releases_metadata_name ON releases ((metadata->>\'name\'))'),
21
- knex.schema.raw('CREATE INDEX idx_releases_metadata_artist ON releases ((metadata->\'properties\'->>\'artist\'))'),
22
- knex.schema.raw('CREATE INDEX idx_releases_metadata_title ON releases ((metadata->\'properties\'->>\'title\'))'),
23
- // GIN indexes for JSON fields
24
- knex.schema.raw('CREATE INDEX idx_hubs_data_gin ON hubs USING GIN (data)'),
25
- knex.schema.raw('CREATE INDEX idx_releases_metadata_gin ON releases USING GIN (metadata)')
26
- ]);
27
- };
28
- /**
29
- * @param { import("knex").Knex } knex
30
- * @returns { Promise<void> }
31
- */
32
- export const down = function (knex) {
33
- return Promise.all([
34
- // Drop Accounts table indexes
35
- knex.schema.alterTable('accounts', table => {
36
- table.dropIndex('displayName');
37
- table.dropIndex('handle');
38
- }),
39
- // Drop Hubs table indexes
40
- knex.schema.raw('DROP INDEX IF EXISTS idx_hubs_handle'),
41
- knex.schema.raw('DROP INDEX IF EXISTS idx_hubs_display_name'),
42
- // Drop Tags table index
43
- knex.schema.alterTable('tags', table => {
44
- table.dropIndex('value');
45
- }),
46
- // Drop Releases table indexes
47
- knex.schema.raw('DROP INDEX IF EXISTS idx_releases_metadata_name'),
48
- knex.schema.raw('DROP INDEX IF EXISTS idx_releases_metadata_artist'),
49
- knex.schema.raw('DROP INDEX IF EXISTS idx_releases_metadata_title'),
50
- // Drop GIN indexes
51
- knex.schema.raw('DROP INDEX IF EXISTS idx_hubs_data_gin'),
52
- knex.schema.raw('DROP INDEX IF EXISTS idx_releases_metadata_gin')
53
- ]);
54
- };
@@ -1,80 +0,0 @@
1
- export const up = async (knex) => {
2
- // Add indexes for JSON fields commonly used in search
3
- await knex.raw(`
4
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_artist
5
- ON releases ((metadata->'properties'->>'artist'));
6
- `);
7
- await knex.raw(`
8
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_title
9
- ON releases ((metadata->'properties'->>'title'));
10
- `);
11
- await knex.raw(`
12
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_tags
13
- ON releases ((metadata->'properties'->>'tags'));
14
- `);
15
- await knex.raw(`
16
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_symbol
17
- ON releases ((metadata->'properties'->>'symbol'));
18
- `);
19
- // Add index for hub search
20
- await knex.raw(`
21
- CREATE INDEX IF NOT EXISTS idx_hubs_data_displayname
22
- ON hubs ((data->>'displayName'));
23
- `);
24
- // Add index for post search
25
- await knex.raw(`
26
- CREATE INDEX IF NOT EXISTS idx_posts_data_title
27
- ON posts ((data->>'title'));
28
- `);
29
- await knex.raw(`
30
- CREATE INDEX IF NOT EXISTS idx_posts_data_description
31
- ON posts ((data->>'description'));
32
- `);
33
- // Add indexes for regular fields
34
- await knex.raw(`
35
- CREATE INDEX IF NOT EXISTS idx_accounts_displayname
36
- ON accounts (display_name);
37
- `);
38
- await knex.raw(`
39
- CREATE INDEX IF NOT EXISTS idx_accounts_handle
40
- ON accounts (handle);
41
- `);
42
- await knex.raw(`
43
- CREATE INDEX IF NOT EXISTS idx_hubs_handle
44
- ON hubs (handle);
45
- `);
46
- await knex.raw(`
47
- CREATE INDEX IF NOT EXISTS idx_releases_archived
48
- ON releases (archived);
49
- `);
50
- await knex.raw(`
51
- CREATE INDEX IF NOT EXISTS idx_releases_datetime
52
- ON releases (datetime);
53
- `);
54
- await knex.raw(`
55
- CREATE INDEX IF NOT EXISTS idx_posts_datetime
56
- ON posts (datetime);
57
- `);
58
- // Add composite indexes for common query patterns
59
- await knex.raw(`
60
- CREATE INDEX IF NOT EXISTS idx_releases_archived_datetime
61
- ON releases (archived, datetime);
62
- `);
63
- };
64
- export const down = async (knex) => {
65
- // Remove all created indexes
66
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_artist;`);
67
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_title;`);
68
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_tags;`);
69
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_symbol;`);
70
- await knex.raw(`DROP INDEX IF EXISTS idx_hubs_data_displayname;`);
71
- await knex.raw(`DROP INDEX IF EXISTS idx_posts_data_title;`);
72
- await knex.raw(`DROP INDEX IF EXISTS idx_posts_data_description;`);
73
- await knex.raw(`DROP INDEX IF EXISTS idx_accounts_displayname;`);
74
- await knex.raw(`DROP INDEX IF EXISTS idx_accounts_handle;`);
75
- await knex.raw(`DROP INDEX IF EXISTS idx_hubs_handle;`);
76
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_archived;`);
77
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_datetime;`);
78
- await knex.raw(`DROP INDEX IF EXISTS idx_posts_datetime;`);
79
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_archived_datetime;`);
80
- };
@@ -1,94 +0,0 @@
1
- export const up = async (knex) => {
2
- // Add indexes for JSON fields commonly used in search
3
- await knex.raw(`
4
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_artist
5
- ON releases ((metadata->'properties'->>'artist'));
6
- `);
7
-
8
- await knex.raw(`
9
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_title
10
- ON releases ((metadata->'properties'->>'title'));
11
- `);
12
-
13
- await knex.raw(`
14
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_tags
15
- ON releases ((metadata->'properties'->>'tags'));
16
- `);
17
-
18
- await knex.raw(`
19
- CREATE INDEX IF NOT EXISTS idx_releases_metadata_symbol
20
- ON releases ((metadata->'properties'->>'symbol'));
21
- `);
22
-
23
- // Add index for hub search
24
- await knex.raw(`
25
- CREATE INDEX IF NOT EXISTS idx_hubs_data_displayname
26
- ON hubs ((data->>'displayName'));
27
- `);
28
-
29
- // Add index for post search
30
- await knex.raw(`
31
- CREATE INDEX IF NOT EXISTS idx_posts_data_title
32
- ON posts ((data->>'title'));
33
- `);
34
-
35
- await knex.raw(`
36
- CREATE INDEX IF NOT EXISTS idx_posts_data_description
37
- ON posts ((data->>'description'));
38
- `);
39
-
40
- // Add indexes for regular fields
41
- await knex.raw(`
42
- CREATE INDEX IF NOT EXISTS idx_accounts_displayname
43
- ON accounts (display_name);
44
- `);
45
-
46
- await knex.raw(`
47
- CREATE INDEX IF NOT EXISTS idx_accounts_handle
48
- ON accounts (handle);
49
- `);
50
-
51
- await knex.raw(`
52
- CREATE INDEX IF NOT EXISTS idx_hubs_handle
53
- ON hubs (handle);
54
- `);
55
-
56
- await knex.raw(`
57
- CREATE INDEX IF NOT EXISTS idx_releases_archived
58
- ON releases (archived);
59
- `);
60
-
61
- await knex.raw(`
62
- CREATE INDEX IF NOT EXISTS idx_releases_datetime
63
- ON releases (datetime);
64
- `);
65
-
66
- await knex.raw(`
67
- CREATE INDEX IF NOT EXISTS idx_posts_datetime
68
- ON posts (datetime);
69
- `);
70
-
71
- // Add composite indexes for common query patterns
72
- await knex.raw(`
73
- CREATE INDEX IF NOT EXISTS idx_releases_archived_datetime
74
- ON releases (archived, datetime);
75
- `);
76
- };
77
-
78
- export const down = async (knex) => {
79
- // Remove all created indexes
80
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_artist;`);
81
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_title;`);
82
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_tags;`);
83
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_metadata_symbol;`);
84
- await knex.raw(`DROP INDEX IF EXISTS idx_hubs_data_displayname;`);
85
- await knex.raw(`DROP INDEX IF EXISTS idx_posts_data_title;`);
86
- await knex.raw(`DROP INDEX IF EXISTS idx_posts_data_description;`);
87
- await knex.raw(`DROP INDEX IF EXISTS idx_accounts_displayname;`);
88
- await knex.raw(`DROP INDEX IF EXISTS idx_accounts_handle;`);
89
- await knex.raw(`DROP INDEX IF EXISTS idx_hubs_handle;`);
90
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_archived;`);
91
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_datetime;`);
92
- await knex.raw(`DROP INDEX IF EXISTS idx_posts_datetime;`);
93
- await knex.raw(`DROP INDEX IF EXISTS idx_releases_archived_datetime;`);
94
- };