@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.
- package/dist/migrations/20250616215722_program_id.js +18 -0
- package/dist/migrations/20250630215722_transaction_program_id.js +18 -0
- package/dist/models/Release.js +35 -13
- package/dist/models/Transaction.js +2 -0
- package/package.json +4 -3
- package/src/migrations/20250616215722_program_id.js +19 -0
- package/src/migrations/20250630215722_transaction_program_id.js +19 -0
- package/src/models/Release.js +35 -15
- package/src/models/Transaction.js +2 -0
- package/dist/migrations/20250425215723_add_search_indexes.js +0 -54
- package/dist/migrations/20250523215722_add_search_indexes.js +0 -80
- package/src/migrations/20250523215722_add_search_indexes.js +0 -94
|
@@ -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
|
+
};
|
package/dist/models/Release.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
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(
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nina-protocol/nina-db",
|
|
3
|
-
"version": "0.0.
|
|
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
|
-
"@
|
|
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": "
|
|
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
|
+
};
|
package/src/models/Release.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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
|
-
};
|