mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
refactor: shared internal postgres package around slonik (#7887)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: n1ru4l <14338007+n1ru4l@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Laurin Quast <laurinquast@googlemail.com>
This commit is contained in:
parent
e83bc29e2a
commit
aac23596ec
194 changed files with 3635 additions and 3333 deletions
|
|
@ -20,6 +20,7 @@
|
||||||
"@graphql-hive/core": "workspace:*",
|
"@graphql-hive/core": "workspace:*",
|
||||||
"@graphql-typed-document-node/core": "3.2.0",
|
"@graphql-typed-document-node/core": "3.2.0",
|
||||||
"@hive/commerce": "workspace:*",
|
"@hive/commerce": "workspace:*",
|
||||||
|
"@hive/postgres": "workspace:*",
|
||||||
"@hive/schema": "workspace:*",
|
"@hive/schema": "workspace:*",
|
||||||
"@hive/server": "workspace:*",
|
"@hive/server": "workspace:*",
|
||||||
"@hive/service-common": "workspace:*",
|
"@hive/service-common": "workspace:*",
|
||||||
|
|
@ -42,7 +43,6 @@
|
||||||
"human-id": "4.1.1",
|
"human-id": "4.1.1",
|
||||||
"ioredis": "5.8.2",
|
"ioredis": "5.8.2",
|
||||||
"set-cookie-parser": "2.7.1",
|
"set-cookie-parser": "2.7.1",
|
||||||
"slonik": "30.4.4",
|
|
||||||
"strip-ansi": "7.1.2",
|
"strip-ansi": "7.1.2",
|
||||||
"tslib": "2.8.1",
|
"tslib": "2.8.1",
|
||||||
"vitest": "4.0.9",
|
"vitest": "4.0.9",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { DatabasePool } from 'slonik';
|
|
||||||
import {
|
import {
|
||||||
AccessTokenKeyContainer,
|
AccessTokenKeyContainer,
|
||||||
hashPassword,
|
hashPassword,
|
||||||
} from '@hive/api/modules/auth/lib/supertokens-at-home/crypto';
|
} from '@hive/api/modules/auth/lib/supertokens-at-home/crypto';
|
||||||
import { SuperTokensStore } from '@hive/api/modules/auth/providers/supertokens-store';
|
import { SuperTokensStore } from '@hive/api/modules/auth/providers/supertokens-store';
|
||||||
import { NoopLogger } from '@hive/api/modules/shared/providers/logger';
|
import { NoopLogger } from '@hive/api/modules/shared/providers/logger';
|
||||||
|
import { PostgresDatabasePool } from '@hive/postgres';
|
||||||
import type { InternalApi } from '@hive/server';
|
import type { InternalApi } from '@hive/server';
|
||||||
import { createNewSession } from '@hive/server/supertokens-at-home/shared';
|
import { createNewSession } from '@hive/server/supertokens-at-home/shared';
|
||||||
import { createTRPCProxyClient, httpLink } from '@trpc/client';
|
import { createTRPCProxyClient, httpLink } from '@trpc/client';
|
||||||
|
|
@ -76,7 +76,7 @@ const tokenResponsePromise: {
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
export async function authenticate(
|
export async function authenticate(
|
||||||
pool: DatabasePool,
|
pool: PostgresDatabasePool,
|
||||||
email: string,
|
email: string,
|
||||||
oidcIntegrationId?: string,
|
oidcIntegrationId?: string,
|
||||||
): Promise<{ access_token: string; refresh_token: string; supertokensUserId: string }> {
|
): Promise<{ access_token: string; refresh_token: string; supertokensUserId: string }> {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import type { AddressInfo } from 'node:net';
|
import type { AddressInfo } from 'node:net';
|
||||||
import humanId from 'human-id';
|
import humanId from 'human-id';
|
||||||
import setCookie from 'set-cookie-parser';
|
import setCookie from 'set-cookie-parser';
|
||||||
import { sql, type DatabasePool } from 'slonik';
|
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
import formDataPlugin from '@fastify/formbody';
|
import formDataPlugin from '@fastify/formbody';
|
||||||
|
import { psql, type PostgresDatabasePool } from '@hive/postgres';
|
||||||
import { createServer, type FastifyReply, type FastifyRequest } from '@hive/service-common';
|
import { createServer, type FastifyReply, type FastifyRequest } from '@hive/service-common';
|
||||||
import { graphql } from './gql';
|
import { graphql } from './gql';
|
||||||
import { execute } from './graphql';
|
import { execute } from './graphql';
|
||||||
|
|
@ -157,7 +157,7 @@ const VerifyEmailMutation = graphql(`
|
||||||
export async function createOIDCIntegration(args: {
|
export async function createOIDCIntegration(args: {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
getPool: () => Promise<DatabasePool>;
|
getPool: () => Promise<PostgresDatabasePool>;
|
||||||
}) {
|
}) {
|
||||||
const { accessToken: authToken, getPool } = args;
|
const { accessToken: authToken, getPool } = args;
|
||||||
const result = await execute({
|
const result = await execute({
|
||||||
|
|
@ -192,7 +192,7 @@ export async function createOIDCIntegration(args: {
|
||||||
}) + '.local';
|
}) + '.local';
|
||||||
|
|
||||||
const pool = await getPool();
|
const pool = await getPool();
|
||||||
const query = sql`
|
const query = psql`
|
||||||
INSERT INTO "oidc_integration_domains" (
|
INSERT INTO "oidc_integration_domains" (
|
||||||
"organization_id"
|
"organization_id"
|
||||||
, "oidc_integration_id"
|
, "oidc_integration_id"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { formatISO, subHours } from 'date-fns';
|
import { formatISO, subHours } from 'date-fns';
|
||||||
import { humanId } from 'human-id';
|
import { humanId } from 'human-id';
|
||||||
import { createPool, sql } from 'slonik';
|
import z from 'zod';
|
||||||
import { NoopLogger } from '@hive/api/modules/shared/providers/logger';
|
import { NoopLogger } from '@hive/api/modules/shared/providers/logger';
|
||||||
import { createRedisClient } from '@hive/api/modules/shared/providers/redis';
|
import { createRedisClient } from '@hive/api/modules/shared/providers/redis';
|
||||||
|
import { createPostgresDatabasePool, psql } from '@hive/postgres';
|
||||||
import type { Report } from '../../packages/libraries/core/src/client/usage.js';
|
import type { Report } from '../../packages/libraries/core/src/client/usage.js';
|
||||||
import { authenticate, userEmail } from './auth';
|
import { authenticate, userEmail } from './auth';
|
||||||
import {
|
import {
|
||||||
|
|
@ -82,9 +83,9 @@ function createConnectionPool() {
|
||||||
db: ensureEnv('POSTGRES_DB'),
|
db: ensureEnv('POSTGRES_DB'),
|
||||||
};
|
};
|
||||||
|
|
||||||
return createPool(
|
return createPostgresDatabasePool({
|
||||||
`postgres://${pg.user}:${pg.password}@${pg.host}:${pg.port}/${pg.db}?sslmode=disable`,
|
connectionParameters: `postgres://${pg.user}:${pg.password}@${pg.host}:${pg.port}/${pg.db}?sslmode=disable`,
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createDbConnection() {
|
async function createDbConnection() {
|
||||||
|
|
@ -97,9 +98,9 @@ async function createDbConnection() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initSeed() {
|
let sharedDBPoolPromise: ReturnType<typeof createDbConnection>;
|
||||||
let sharedDBPoolPromise: ReturnType<typeof createDbConnection>;
|
|
||||||
|
|
||||||
|
export function initSeed() {
|
||||||
function getPool() {
|
function getPool() {
|
||||||
if (!sharedDBPoolPromise) {
|
if (!sharedDBPoolPromise) {
|
||||||
sharedDBPoolPromise = createDbConnection();
|
sharedDBPoolPromise = createDbConnection();
|
||||||
|
|
@ -118,7 +119,7 @@ export function initSeed() {
|
||||||
|
|
||||||
if (opts?.verifyEmail ?? true) {
|
if (opts?.verifyEmail ?? true) {
|
||||||
const pool = await getPool();
|
const pool = await getPool();
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
INSERT INTO "email_verifications" ("user_identity_id", "email", "verified_at")
|
INSERT INTO "email_verifications" ("user_identity_id", "email", "verified_at")
|
||||||
VALUES (${auth.supertokensUserId}, ${email}, NOW())
|
VALUES (${auth.supertokensUserId}, ${email}, NOW())
|
||||||
`);
|
`);
|
||||||
|
|
@ -142,18 +143,22 @@ export function initSeed() {
|
||||||
pollForEmailVerificationLink,
|
pollForEmailVerificationLink,
|
||||||
async purgeOIDCDomains() {
|
async purgeOIDCDomains() {
|
||||||
const pool = await getPool();
|
const pool = await getPool();
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
TRUNCATE "oidc_integration_domains"
|
TRUNCATE "oidc_integration_domains"
|
||||||
`);
|
`);
|
||||||
},
|
},
|
||||||
async forgeOIDCDNSChallenge(orgSlug: string) {
|
async forgeOIDCDNSChallenge(orgSlug: string) {
|
||||||
const pool = await getPool();
|
const pool = await getPool();
|
||||||
|
|
||||||
const domainChallengeId = await pool.oneFirst<string>(sql`
|
const domainChallengeId = await pool
|
||||||
|
.oneFirst(
|
||||||
|
psql`
|
||||||
SELECT "oidc_integration_domains"."id"
|
SELECT "oidc_integration_domains"."id"
|
||||||
FROM "oidc_integration_domains" INNER JOIN "organizations" ON "oidc_integration_domains"."organization_id" = "organizations"."id"
|
FROM "oidc_integration_domains" INNER JOIN "organizations" ON "oidc_integration_domains"."organization_id" = "organizations"."id"
|
||||||
WHERE "organizations"."clean_id" = ${orgSlug}
|
WHERE "organizations"."clean_id" = ${orgSlug}
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(z.string().parse);
|
||||||
const key = `hive:oidcDomainChallenge:${domainChallengeId}`;
|
const key = `hive:oidcDomainChallenge:${domainChallengeId}`;
|
||||||
|
|
||||||
const challenge = {
|
const challenge = {
|
||||||
|
|
@ -208,7 +213,7 @@ export function initSeed() {
|
||||||
async overrideOrgPlan(plan: 'PRO' | 'ENTERPRISE' | 'HOBBY') {
|
async overrideOrgPlan(plan: 'PRO' | 'ENTERPRISE' | 'HOBBY') {
|
||||||
const pool = await createConnectionPool();
|
const pool = await createConnectionPool();
|
||||||
|
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
UPDATE organizations SET plan_name = ${plan} WHERE id = ${organization.id}
|
UPDATE organizations SET plan_name = ${plan} WHERE id = ${organization.id}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
@ -260,8 +265,8 @@ export function initSeed() {
|
||||||
async setFeatureFlag(name: string, value: boolean | string[]) {
|
async setFeatureFlag(name: string, value: boolean | string[]) {
|
||||||
const pool = await createConnectionPool();
|
const pool = await createConnectionPool();
|
||||||
|
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
UPDATE organizations SET feature_flags = ${sql.jsonb({
|
UPDATE organizations SET feature_flags = ${psql.jsonb({
|
||||||
[name]: value,
|
[name]: value,
|
||||||
})}
|
})}
|
||||||
WHERE id = ${organization.id}
|
WHERE id = ${organization.id}
|
||||||
|
|
@ -272,7 +277,7 @@ export function initSeed() {
|
||||||
async setDataRetention(days: number) {
|
async setDataRetention(days: number) {
|
||||||
const pool = await createConnectionPool();
|
const pool = await createConnectionPool();
|
||||||
|
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
UPDATE organizations SET limit_retention_days = ${days} WHERE id = ${organization.id}
|
UPDATE organizations SET limit_retention_days = ${days} WHERE id = ${organization.id}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
@ -340,13 +345,15 @@ export function initSeed() {
|
||||||
/** Expires tokens */
|
/** Expires tokens */
|
||||||
async forceExpireTokens(tokenIds: string[]) {
|
async forceExpireTokens(tokenIds: string[]) {
|
||||||
const pool = await createConnectionPool();
|
const pool = await createConnectionPool();
|
||||||
const result = await pool.query(sql`
|
const result = await pool.any(psql`
|
||||||
UPDATE "organization_access_tokens"
|
UPDATE "organization_access_tokens"
|
||||||
SET "expires_at"=NOW()
|
SET "expires_at" = NOW()
|
||||||
WHERE id IN (${sql.join(tokenIds, sql`, `)}) AND organization_id=${organization.id}
|
WHERE id IN (${psql.join(tokenIds, psql`, `)}) AND organization_id = ${organization.id}
|
||||||
|
RETURNING
|
||||||
|
"id"
|
||||||
`);
|
`);
|
||||||
await pool.end();
|
await pool.end();
|
||||||
expect(result.rowCount).toBe(tokenIds.length);
|
expect(result.length).toBe(tokenIds.length);
|
||||||
for (const id of tokenIds) {
|
for (const id of tokenIds) {
|
||||||
await purgeOrganizationAccessTokenById(id);
|
await purgeOrganizationAccessTokenById(id);
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +397,7 @@ export function initSeed() {
|
||||||
async setNativeFederation(enabled: boolean) {
|
async setNativeFederation(enabled: boolean) {
|
||||||
const pool = await createConnectionPool();
|
const pool = await createConnectionPool();
|
||||||
|
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
UPDATE projects SET native_federation = ${enabled} WHERE id = ${project.id}
|
UPDATE projects SET native_federation = ${enabled} WHERE id = ${project.id}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import { buildASTSchema, parse } from 'graphql';
|
import { buildASTSchema, parse } from 'graphql';
|
||||||
import { createLogger } from 'graphql-yoga';
|
import { createLogger } from 'graphql-yoga';
|
||||||
import { sql } from 'slonik';
|
|
||||||
import { pollFor } from 'testkit/flow';
|
import { pollFor } from 'testkit/flow';
|
||||||
import { initSeed } from 'testkit/seed';
|
import { initSeed } from 'testkit/seed';
|
||||||
import { getServiceHost } from 'testkit/utils';
|
import { getServiceHost } from 'testkit/utils';
|
||||||
|
import z from 'zod';
|
||||||
import { createHive } from '@graphql-hive/core';
|
import { createHive } from '@graphql-hive/core';
|
||||||
import { clickHouseInsert, clickHouseQuery } from '../../testkit/clickhouse';
|
import { psql } from '@hive/postgres';
|
||||||
|
import { clickHouseInsert } from '../../testkit/clickhouse';
|
||||||
import { graphql } from '../../testkit/gql';
|
import { graphql } from '../../testkit/gql';
|
||||||
import { execute } from '../../testkit/graphql';
|
import { execute } from '../../testkit/graphql';
|
||||||
|
|
||||||
|
|
@ -2056,12 +2057,20 @@ test('activeAppDeployments works for > 1000 records with a date filter (neverUse
|
||||||
);
|
);
|
||||||
|
|
||||||
// insert into postgres
|
// insert into postgres
|
||||||
const result = await conn.pool.query(sql`
|
const result = await conn.pool
|
||||||
|
.any(
|
||||||
|
psql`
|
||||||
INSERT INTO app_deployments ("target_id", "name", "version", "activated_at")
|
INSERT INTO app_deployments ("target_id", "name", "version", "activated_at")
|
||||||
SELECT * FROM ${sql.unnest(appDeploymentRows, ['uuid', 'text', 'text', 'timestamptz'])}
|
SELECT * FROM ${psql.unnest(appDeploymentRows, ['uuid', 'text', 'text', 'timestamptz'])}
|
||||||
RETURNING "id", "target_id", "name", "version"
|
RETURNING "id", "target_id", "name", "version"
|
||||||
`);
|
`,
|
||||||
expect(result.rowCount).toBe(1200);
|
)
|
||||||
|
.then(
|
||||||
|
z.array(
|
||||||
|
z.object({ id: z.string(), target_id: z.string(), name: z.string(), version: z.string() }),
|
||||||
|
).parse,
|
||||||
|
);
|
||||||
|
expect(result.length).toBe(1200);
|
||||||
|
|
||||||
// insert into clickhouse and activate
|
// insert into clickhouse and activate
|
||||||
const query = `INSERT INTO app_deployments (
|
const query = `INSERT INTO app_deployments (
|
||||||
|
|
@ -2071,7 +2080,7 @@ test('activeAppDeployments works for > 1000 records with a date filter (neverUse
|
||||||
,"app_version"
|
,"app_version"
|
||||||
,"is_active"
|
,"is_active"
|
||||||
) VALUES
|
) VALUES
|
||||||
${result.rows
|
${result
|
||||||
.map(
|
.map(
|
||||||
r => `(
|
r => `(
|
||||||
'${r['target_id']}'
|
'${r['target_id']}'
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,28 @@
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { sql, type CommonQueryMethods } from 'slonik';
|
|
||||||
/* eslint-disable no-process-env */
|
/* eslint-disable no-process-env */
|
||||||
import { ProjectType } from 'testkit/gql/graphql';
|
import { ProjectType } from 'testkit/gql/graphql';
|
||||||
import { test } from 'vitest';
|
import { test } from 'vitest';
|
||||||
|
import z from 'zod';
|
||||||
|
import { psql, type CommonQueryMethods } from '@hive/postgres';
|
||||||
import { initSeed } from '../../../testkit/seed';
|
import { initSeed } from '../../../testkit/seed';
|
||||||
|
|
||||||
async function fetchCoordinates(db: CommonQueryMethods, target: { id: string }) {
|
async function fetchCoordinates(db: CommonQueryMethods, target: { id: string }) {
|
||||||
const result = await db.query<{
|
const result = await db
|
||||||
coordinate: string;
|
.any(
|
||||||
created_in_version_id: string;
|
psql`
|
||||||
deprecated_in_version_id: string | null;
|
|
||||||
}>(sql`
|
|
||||||
SELECT coordinate, created_in_version_id, deprecated_in_version_id
|
SELECT coordinate, created_in_version_id, deprecated_in_version_id
|
||||||
FROM schema_coordinate_status WHERE target_id = ${target.id}
|
FROM schema_coordinate_status WHERE target_id = ${target.id}
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
z.object({
|
||||||
|
coordinate: z.string(),
|
||||||
|
created_in_version_id: z.string(),
|
||||||
|
deprecated_in_version_id: z.string().nullable(),
|
||||||
|
}).parse,
|
||||||
|
);
|
||||||
|
|
||||||
return result.rows;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe.skip('schema cleanup tracker', () => {
|
describe.skip('schema cleanup tracker', () => {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { createPool, sql } from 'slonik';
|
|
||||||
import { graphql } from 'testkit/gql';
|
import { graphql } from 'testkit/gql';
|
||||||
/* eslint-disable no-process-env */
|
/* eslint-disable no-process-env */
|
||||||
import { ProjectType } from 'testkit/gql/graphql';
|
import { ProjectType } from 'testkit/gql/graphql';
|
||||||
import { execute } from 'testkit/graphql';
|
import { execute } from 'testkit/graphql';
|
||||||
import { assertNonNull, getServiceHost } from 'testkit/utils';
|
import { assertNonNull, getServiceHost } from 'testkit/utils';
|
||||||
|
import z from 'zod';
|
||||||
|
import { createPostgresDatabasePool, psql } from '@hive/postgres';
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import { createStorage } from '@hive/storage';
|
import { createStorage } from '@hive/storage';
|
||||||
import { createTarget, publishSchema, updateSchemaComposition } from '../../../testkit/flow';
|
import { createTarget, publishSchema, updateSchemaComposition } from '../../../testkit/flow';
|
||||||
|
|
@ -3820,7 +3821,7 @@ test.concurrent(
|
||||||
);
|
);
|
||||||
|
|
||||||
const insertLegacyVersion = async (
|
const insertLegacyVersion = async (
|
||||||
pool: Awaited<ReturnType<typeof createPool>>,
|
pool: Awaited<ReturnType<typeof createPostgresDatabasePool>>,
|
||||||
args: {
|
args: {
|
||||||
sdl: string;
|
sdl: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
|
@ -3828,7 +3829,9 @@ const insertLegacyVersion = async (
|
||||||
serviceUrl: string;
|
serviceUrl: string;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
const logId = await pool.oneFirst<string>(sql`
|
const logId = await pool
|
||||||
|
.oneFirst(
|
||||||
|
psql`
|
||||||
INSERT INTO schema_log
|
INSERT INTO schema_log
|
||||||
(
|
(
|
||||||
author,
|
author,
|
||||||
|
|
@ -3854,9 +3857,13 @@ const insertLegacyVersion = async (
|
||||||
'PUSH'
|
'PUSH'
|
||||||
)
|
)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(z.string().parse);
|
||||||
|
|
||||||
const versionId = await pool.oneFirst<string>(sql`
|
const versionId = await pool
|
||||||
|
.oneFirst(
|
||||||
|
psql`
|
||||||
INSERT INTO schema_versions
|
INSERT INTO schema_versions
|
||||||
(
|
(
|
||||||
is_composable,
|
is_composable,
|
||||||
|
|
@ -3870,9 +3877,11 @@ const insertLegacyVersion = async (
|
||||||
${logId}
|
${logId}
|
||||||
)
|
)
|
||||||
RETURNING "id"
|
RETURNING "id"
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(z.string().parse);
|
||||||
|
|
||||||
await pool.query(sql`
|
await pool.query(psql`
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
schema_version_to_log
|
schema_version_to_log
|
||||||
(version_id, action_id)
|
(version_id, action_id)
|
||||||
|
|
@ -3886,7 +3895,7 @@ const insertLegacyVersion = async (
|
||||||
test.concurrent(
|
test.concurrent(
|
||||||
'service url change from legacy to new version is displayed correctly',
|
'service url change from legacy to new version is displayed correctly',
|
||||||
async ({ expect }) => {
|
async ({ expect }) => {
|
||||||
let pool: Awaited<ReturnType<typeof createPool>> | undefined;
|
let pool: Awaited<ReturnType<typeof createPostgresDatabasePool>> | undefined;
|
||||||
try {
|
try {
|
||||||
const { createOrg } = await initSeed().createOwner();
|
const { createOrg } = await initSeed().createOwner();
|
||||||
const { createProject } = await createOrg();
|
const { createProject } = await createOrg();
|
||||||
|
|
@ -3899,7 +3908,9 @@ test.concurrent(
|
||||||
// We need to seed a legacy entry in the database
|
// We need to seed a legacy entry in the database
|
||||||
|
|
||||||
const conn = connectionString();
|
const conn = connectionString();
|
||||||
pool = await createPool(conn);
|
pool = await createPostgresDatabasePool({
|
||||||
|
connectionParameters: conn,
|
||||||
|
});
|
||||||
|
|
||||||
const sdl = 'type Query { ping: String! }';
|
const sdl = 'type Query { ping: String! }';
|
||||||
|
|
||||||
|
|
@ -3950,7 +3961,7 @@ test.concurrent(
|
||||||
test.concurrent(
|
test.concurrent(
|
||||||
'service url change from legacy to legacy version is displayed correctly',
|
'service url change from legacy to legacy version is displayed correctly',
|
||||||
async ({ expect }) => {
|
async ({ expect }) => {
|
||||||
let pool: Awaited<ReturnType<typeof createPool>> | undefined;
|
let pool: Awaited<ReturnType<typeof createPostgresDatabasePool>> | undefined;
|
||||||
try {
|
try {
|
||||||
const { createOrg } = await initSeed().createOwner();
|
const { createOrg } = await initSeed().createOwner();
|
||||||
const { createProject } = await createOrg();
|
const { createProject } = await createOrg();
|
||||||
|
|
@ -3963,7 +3974,7 @@ test.concurrent(
|
||||||
// We need to seed a legacy entry in the database
|
// We need to seed a legacy entry in the database
|
||||||
|
|
||||||
const conn = connectionString();
|
const conn = connectionString();
|
||||||
pool = await createPool(conn);
|
pool = await createPostgresDatabasePool({ connectionParameters: conn });
|
||||||
|
|
||||||
const sdl = 'type Query { ping: String! }';
|
const sdl = 'type Query { ping: String! }';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@ import { existsSync, rmSync, writeFileSync } from 'node:fs';
|
||||||
import { createServer } from 'node:http';
|
import { createServer } from 'node:http';
|
||||||
import { tmpdir } from 'node:os';
|
import { tmpdir } from 'node:os';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
import { MaybePromise } from 'slonik/dist/src/types';
|
|
||||||
import { ProjectType } from 'testkit/gql/graphql';
|
import { ProjectType } from 'testkit/gql/graphql';
|
||||||
import { initSeed } from 'testkit/seed';
|
import { initSeed } from 'testkit/seed';
|
||||||
import { getServiceHost } from 'testkit/utils';
|
import { getServiceHost } from 'testkit/utils';
|
||||||
import { execa } from '@esm2cjs/execa';
|
import { execa } from '@esm2cjs/execa';
|
||||||
|
|
||||||
|
type MaybePromise<T> = T | Promise<T>;
|
||||||
|
|
||||||
describe('Apollo Router Integration', () => {
|
describe('Apollo Router Integration', () => {
|
||||||
const getAvailablePort = () =>
|
const getAvailablePort = () =>
|
||||||
new Promise<number>(resolve => {
|
new Promise<number>(resolve => {
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ test('update-retention script skips gracefully when no env vars are set', async
|
||||||
delete process.env.CLICKHOUSE_TTL_HOURLY_MV_TABLES;
|
delete process.env.CLICKHOUSE_TTL_HOURLY_MV_TABLES;
|
||||||
delete process.env.CLICKHOUSE_TTL_MINUTELY_MV_TABLES;
|
delete process.env.CLICKHOUSE_TTL_MINUTELY_MV_TABLES;
|
||||||
|
|
||||||
vi.resetModules();
|
|
||||||
const { updateRetention } = await import(
|
const { updateRetention } = await import(
|
||||||
'../../../packages/migrations/src/scripts/update-retention'
|
'../../../packages/migrations/src/scripts/update-retention'
|
||||||
);
|
);
|
||||||
|
|
|
||||||
3
packages/internal/postgres/README.md
Normal file
3
packages/internal/postgres/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Internal Postgres Client
|
||||||
|
|
||||||
|
This is a lightweight abstraction on top of Slonik, that sets up some things for ease of usage.
|
||||||
16
packages/internal/postgres/package.json
Normal file
16
packages/internal/postgres/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "@hive/postgres",
|
||||||
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": true,
|
||||||
|
"exports": {
|
||||||
|
".": "./src/index.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"slonik": "30.4.4",
|
||||||
|
"slonik-interceptor-query-logging": "46.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@hive/service-common": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
export function createConnectionString(config: {
|
export type PostgresConnectionParamaters = {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
password: string | undefined;
|
password: string | undefined;
|
||||||
user: string;
|
user: string;
|
||||||
db: string;
|
db: string;
|
||||||
ssl: boolean;
|
ssl: boolean;
|
||||||
}) {
|
};
|
||||||
|
|
||||||
|
/** Create a Postgres Connection String */
|
||||||
|
export function createConnectionString(config: PostgresConnectionParamaters) {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const encodedUser = encodeURIComponent(config.user);
|
const encodedUser = encodeURIComponent(config.user);
|
||||||
const encodedPassword =
|
const encodedPassword =
|
||||||
18
packages/internal/postgres/src/index.ts
Normal file
18
packages/internal/postgres/src/index.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
export {
|
||||||
|
PostgresDatabasePool,
|
||||||
|
createPostgresDatabasePool,
|
||||||
|
type CommonQueryMethods,
|
||||||
|
} from './postgres-database-pool';
|
||||||
|
export { type PostgresConnectionParamaters, createConnectionString } from './connection-string';
|
||||||
|
export { psql } from './psql';
|
||||||
|
export {
|
||||||
|
UniqueIntegrityConstraintViolationError,
|
||||||
|
ForeignKeyIntegrityConstraintViolationError,
|
||||||
|
type TaggedTemplateLiteralInvocation,
|
||||||
|
type PrimitiveValueExpression,
|
||||||
|
type SerializableValue,
|
||||||
|
type Interceptor,
|
||||||
|
type Query,
|
||||||
|
type QueryContext,
|
||||||
|
} from 'slonik';
|
||||||
|
export { toDate } from './utils';
|
||||||
246
packages/internal/postgres/src/postgres-database-pool.ts
Normal file
246
packages/internal/postgres/src/postgres-database-pool.ts
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
import {
|
||||||
|
createPool,
|
||||||
|
type DatabasePool,
|
||||||
|
type Interceptor,
|
||||||
|
type PrimitiveValueExpression,
|
||||||
|
type QueryResultRow,
|
||||||
|
type QueryResultRowColumn,
|
||||||
|
type CommonQueryMethods as SlonikCommonQueryMethods,
|
||||||
|
type TaggedTemplateLiteralInvocation,
|
||||||
|
} from 'slonik';
|
||||||
|
import { createQueryLoggingInterceptor } from 'slonik-interceptor-query-logging';
|
||||||
|
import { context, SpanKind, SpanStatusCode, trace } from '@hive/service-common';
|
||||||
|
import { createConnectionString, type PostgresConnectionParamaters } from './connection-string';
|
||||||
|
|
||||||
|
const tracer = trace.getTracer('storage');
|
||||||
|
|
||||||
|
export interface CommonQueryMethods {
|
||||||
|
exists(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<boolean>;
|
||||||
|
any(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<ReadonlyArray<unknown>>;
|
||||||
|
maybeOne(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown>;
|
||||||
|
query(sql: TaggedTemplateLiteralInvocation, values?: PrimitiveValueExpression[]): Promise<void>;
|
||||||
|
oneFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown>;
|
||||||
|
one(sql: TaggedTemplateLiteralInvocation, values?: PrimitiveValueExpression[]): Promise<unknown>;
|
||||||
|
anyFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<ReadonlyArray<unknown>>;
|
||||||
|
maybeOneFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PostgresDatabasePool implements CommonQueryMethods {
|
||||||
|
constructor(private pool: DatabasePool) {}
|
||||||
|
|
||||||
|
/** Retrieve the raw PgPool instance. Refrain from using this API. It only exists for postgraphile workers */
|
||||||
|
getRawPgPool() {
|
||||||
|
return this.pool.pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieve the raw Slonik instance. Refrain from using this API. */
|
||||||
|
getSlonikPool() {
|
||||||
|
return this.pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
async exists(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<boolean> {
|
||||||
|
return this.pool.exists(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async any(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<ReadonlyArray<unknown>> {
|
||||||
|
return this.pool.any<unknown>(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async maybeOne(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return this.pool.maybeOne(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async query(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<void> {
|
||||||
|
await this.pool.query<unknown>(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async oneFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return await this.pool.oneFirst(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async maybeOneFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return await this.pool.maybeOneFirst(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async one(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return await this.pool.one(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async anyFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<ReadonlyArray<unknown>> {
|
||||||
|
return await this.pool.anyFirst(sql, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
async transaction<T = void>(
|
||||||
|
name: string,
|
||||||
|
handler: (methods: CommonQueryMethods) => Promise<T>,
|
||||||
|
): Promise<T> {
|
||||||
|
const span = tracer.startSpan(`PG Transaction: ${name}`, {
|
||||||
|
kind: SpanKind.INTERNAL,
|
||||||
|
});
|
||||||
|
|
||||||
|
return context.with(trace.setSpan(context.active(), span), async () => {
|
||||||
|
return await this.pool.transaction(async methods => {
|
||||||
|
try {
|
||||||
|
return await handler({
|
||||||
|
async exists(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<boolean> {
|
||||||
|
return methods.exists(sql, values);
|
||||||
|
},
|
||||||
|
async any(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<ReadonlyArray<unknown>> {
|
||||||
|
return methods.any<unknown>(sql, values);
|
||||||
|
},
|
||||||
|
async maybeOne(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return methods.maybeOne(sql, values);
|
||||||
|
},
|
||||||
|
async query(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<void> {
|
||||||
|
await methods.query<unknown>(sql, values);
|
||||||
|
},
|
||||||
|
async oneFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return await methods.oneFirst(sql, values);
|
||||||
|
},
|
||||||
|
async maybeOneFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return await methods.maybeOneFirst(sql, values);
|
||||||
|
},
|
||||||
|
async anyFirst(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<ReadonlyArray<unknown>> {
|
||||||
|
return await methods.anyFirst(sql, values);
|
||||||
|
},
|
||||||
|
async one(
|
||||||
|
sql: TaggedTemplateLiteralInvocation,
|
||||||
|
values?: PrimitiveValueExpression[],
|
||||||
|
): Promise<unknown> {
|
||||||
|
return await methods.one(sql, values);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
span.setAttribute('error', 'true');
|
||||||
|
|
||||||
|
if (err instanceof Error) {
|
||||||
|
span.setAttribute('error.type', err.name);
|
||||||
|
span.setAttribute('error.message', err.message);
|
||||||
|
span.setStatus({
|
||||||
|
code: SpanStatusCode.ERROR,
|
||||||
|
message: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
} finally {
|
||||||
|
span.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
end(): Promise<void> {
|
||||||
|
return this.pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbInterceptors: Interceptor[] = [createQueryLoggingInterceptor()];
|
||||||
|
|
||||||
|
export async function createPostgresDatabasePool(args: {
|
||||||
|
connectionParameters: PostgresConnectionParamaters | string;
|
||||||
|
maximumPoolSize?: number;
|
||||||
|
additionalInterceptors?: Interceptor[];
|
||||||
|
statementTimeout?: number;
|
||||||
|
}) {
|
||||||
|
const connectionString =
|
||||||
|
typeof args.connectionParameters === 'string'
|
||||||
|
? args.connectionParameters
|
||||||
|
: createConnectionString(args.connectionParameters);
|
||||||
|
const pool = await createPool(connectionString, {
|
||||||
|
interceptors: dbInterceptors.concat(args.additionalInterceptors ?? []),
|
||||||
|
captureStackTrace: false,
|
||||||
|
maximumPoolSize: args.maximumPoolSize,
|
||||||
|
idleTimeout: 30000,
|
||||||
|
statementTimeout: args.statementTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
function interceptError<K extends Exclude<keyof SlonikCommonQueryMethods, 'transaction'>>(
|
||||||
|
methodName: K,
|
||||||
|
) {
|
||||||
|
const original: SlonikCommonQueryMethods[K] = pool[methodName];
|
||||||
|
|
||||||
|
function interceptor<T extends QueryResultRow>(
|
||||||
|
this: any,
|
||||||
|
sql: TaggedTemplateLiteralInvocation<T>,
|
||||||
|
values?: QueryResultRowColumn[],
|
||||||
|
): any {
|
||||||
|
return (original as any).call(this, sql, values).catch((error: any) => {
|
||||||
|
error.sql = sql.sql;
|
||||||
|
error.values = sql.values || values;
|
||||||
|
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pool[methodName] = interceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
interceptError('one');
|
||||||
|
interceptError('many');
|
||||||
|
|
||||||
|
return new PostgresDatabasePool(pool);
|
||||||
|
}
|
||||||
3
packages/internal/postgres/src/psql.ts
Normal file
3
packages/internal/postgres/src/psql.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { createSqlTag } from 'slonik';
|
||||||
|
|
||||||
|
export const psql = createSqlTag();
|
||||||
5
packages/internal/postgres/src/utils.ts
Normal file
5
packages/internal/postgres/src/utils.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { psql } from './psql';
|
||||||
|
|
||||||
|
export function toDate(date: Date) {
|
||||||
|
return psql`to_timestamp(${date.getTime() / 1000})`;
|
||||||
|
}
|
||||||
|
|
@ -13,10 +13,12 @@
|
||||||
"db:init": "pnpm db:create && pnpm migration:run",
|
"db:init": "pnpm db:create && pnpm migration:run",
|
||||||
"db:migrator": "tsx src/index.ts",
|
"db:migrator": "tsx src/index.ts",
|
||||||
"migration:run": "pnpm db:migrator up",
|
"migration:run": "pnpm db:migrator up",
|
||||||
"test": "WATCH=0 tsup-node --config ../../configs/tsup/dev.config.node.ts ./test/root.ts"
|
"test": "WATCH=0 tsup-node --config ../../configs/tsup/dev.config.node.ts ./test/root.ts",
|
||||||
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-hive/core": "workspace:*",
|
"@graphql-hive/core": "workspace:*",
|
||||||
|
"@hive/postgres": "workspace:*",
|
||||||
"@hive/service-common": "workspace:*",
|
"@hive/service-common": "workspace:*",
|
||||||
"@types/bcryptjs": "2.4.6",
|
"@types/bcryptjs": "2.4.6",
|
||||||
"@types/node": "24.10.9",
|
"@types/node": "24.10.9",
|
||||||
|
|
@ -30,7 +32,6 @@
|
||||||
"graphql": "16.9.0",
|
"graphql": "16.9.0",
|
||||||
"p-limit": "6.2.0",
|
"p-limit": "6.2.0",
|
||||||
"pg-promise": "11.10.2",
|
"pg-promise": "11.10.2",
|
||||||
"slonik": "30.4.4",
|
|
||||||
"tslib": "2.8.1",
|
"tslib": "2.8.1",
|
||||||
"tsx": "4.19.2",
|
"tsx": "4.19.2",
|
||||||
"typescript": "5.7.3",
|
"typescript": "5.7.3",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-03-05T19-06-23.initial.sql',
|
name: '2021-03-05T19-06-23.initial.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--initial (up)
|
--initial (up)
|
||||||
-- Extensions
|
-- Extensions
|
||||||
CREATE EXTENSION
|
CREATE EXTENSION
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-03-08T11-02-26.urls.sql',
|
name: '2021-03-08T11-02-26.urls.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--urls (up)
|
--urls (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
projects
|
projects
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-03-09T10-30-35.roles.sql',
|
name: '2021-03-09T10-30-35.roles.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--roles (up)
|
--roles (up)
|
||||||
CREATE TYPE
|
CREATE TYPE
|
||||||
user_role AS ENUM('ADMIN', 'MEMBER');
|
user_role AS ENUM('ADMIN', 'MEMBER');
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-03-09T14-02-34.activities.sql',
|
name: '2021-03-09T14-02-34.activities.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--activities (up)
|
--activities (up)
|
||||||
CREATE TABLE
|
CREATE TABLE
|
||||||
activities (
|
activities (
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-03-15T19-32-01.commit-project-id.sql',
|
name: '2021-03-15T19-32-01.commit-project-id.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--commit-project-id (up)
|
--commit-project-id (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
commits
|
commits
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-04-20T11-30-30.tokens.sql',
|
name: '2021-04-20T11-30-30.tokens.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--tokens (up)
|
--tokens (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
tokens
|
tokens
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-04-30T07-01-57.token-per-target.sql',
|
name: '2021-04-30T07-01-57.token-per-target.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--token-per-target (up)
|
--token-per-target (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
tokens
|
tokens
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-04-30T11-47-26.validation.sql',
|
name: '2021-04-30T11-47-26.validation.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--validation (up)
|
--validation (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
targets
|
targets
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-04-30T18-30-00.persisted-operations.sql',
|
name: '2021-04-30T18-30-00.persisted-operations.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--persisted_operations (up)
|
--persisted_operations (up)
|
||||||
CREATE TYPE
|
CREATE TYPE
|
||||||
operation_kind AS ENUM('query', 'mutation', 'subscription');
|
operation_kind AS ENUM('query', 'mutation', 'subscription');
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-05-07T07-28-07.token-last-used-at.sql',
|
name: '2021-05-07T07-28-07.token-last-used-at.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--token-last-used-at (up)
|
--token-last-used-at (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
tokens
|
tokens
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-06-11T10-46-24.slack-integration.sql',
|
name: '2021-06-11T10-46-24.slack-integration.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--slack-integration (up)
|
--slack-integration (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-06-11T15-38-28.alerts.sql',
|
name: '2021-06-11T15-38-28.alerts.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--alerts (up)
|
--alerts (up)
|
||||||
CREATE TYPE
|
CREATE TYPE
|
||||||
alert_channel_type AS ENUM('SLACK', 'WEBHOOK');
|
alert_channel_type AS ENUM('SLACK', 'WEBHOOK');
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-08-18T13-20-45.urls.sql',
|
name: '2021-08-18T13-20-45.urls.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--urls (up)
|
--urls (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
version_commit
|
version_commit
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021-08-27T14-19-48.non-unique-emails.sql',
|
name: '2021-08-27T14-19-48.non-unique-emails.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--non-unique-emails (up)
|
--non-unique-emails (up)
|
||||||
DROP INDEX
|
DROP INDEX
|
||||||
email_idx;
|
email_idx;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021.09.17T14.45.36.token-deleted.sql',
|
name: '2021.09.17T14.45.36.token-deleted.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
tokens
|
tokens
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021.10.07T12.11.13.access-scopes.sql',
|
name: '2021.10.07T12.11.13.access-scopes.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
-- Adds scopes to tokens
|
-- Adds scopes to tokens
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
tokens
|
tokens
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021.11.22T11.23.44.base-schema.sql',
|
name: '2021.11.22T11.23.44.base-schema.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
-- Adds a base schema column in target table and versions table
|
-- Adds a base schema column in target table and versions table
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
targets
|
targets
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2021.12.20T14.05.30.commits-with-targets.sql',
|
name: '2021.12.20T14.05.30.commits-with-targets.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--creates and fills a target_id column on commits
|
--creates and fills a target_id column on commits
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
commits
|
commits
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.01.21T12.34.46.validation-targets.sql',
|
name: '2022.01.21T12.34.46.validation-targets.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE
|
CREATE TABLE
|
||||||
target_validation (
|
target_validation (
|
||||||
target_id UUID NOT NULL REFERENCES targets (id) ON DELETE CASCADE,
|
target_id UUID NOT NULL REFERENCES targets (id) ON DELETE CASCADE,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.03.28T10.31.26.github-integration.sql',
|
name: '2022.03.28T10.31.26.github-integration.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--slack-integration (up)
|
--slack-integration (up)
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.04.15T14.24.17.hash-tokens.sql',
|
name: '2022.04.15T14.24.17.hash-tokens.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
tokens
|
tokens
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.05.03T15.58.13.org_rate_limits.sql',
|
name: '2022.05.03T15.58.13.org_rate_limits.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.05.04T11.01.22.billing_plans.sql',
|
name: '2022.05.04T11.01.22.billing_plans.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE
|
CREATE TABLE
|
||||||
organizations_billing (
|
organizations_billing (
|
||||||
organization_id UUID NOT NULL REFERENCES organizations (id) ON DELETE CASCADE, -- org id
|
organization_id UUID NOT NULL REFERENCES organizations (id) ON DELETE CASCADE, -- org id
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.05.05T08.05.35.commits-metadata.sql',
|
name: '2022.05.05T08.05.35.commits-metadata.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
commits
|
commits
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.07.07T12.15.10.no-schema-pushes-limit.sql',
|
name: '2022.07.07T12.15.10.no-schema-pushes-limit.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
DROP COLUMN
|
DROP COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.07.11T10.09.41.get-started-wizard.sql',
|
name: '2022.07.11T10.09.41.get-started-wizard.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
-- Tracks feature discovery progress
|
-- Tracks feature discovery progress
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.07.11T20.09.37.migrate-pro-hobby-retention.sql',
|
name: '2022.07.11T20.09.37.migrate-pro-hobby-retention.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
-- Update Hobby with 3d to 7d
|
-- Update Hobby with 3d to 7d
|
||||||
UPDATE
|
UPDATE
|
||||||
organizations
|
organizations
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.07.18T10.10.44.target-validation-client-exclusion.sql',
|
name: '2022.07.18T10.10.44.target-validation-client-exclusion.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
targets
|
targets
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.08.25T09.59.16.multiple-invitation-codes.sql',
|
name: '2022.08.25T09.59.16.multiple-invitation-codes.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
DROP COLUMN
|
DROP COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.08.26T06.23.24.add-supertokens-id.sql',
|
name: '2022.08.26T06.23.24.add-supertokens-id.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
users
|
users
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.09.14T16.09.43.external-projects.sql',
|
name: '2022.09.14T16.09.43.external-projects.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
projects
|
projects
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.10.20T08.00.46.oidc-integrations.sql',
|
name: '2022.10.20T08.00.46.oidc-integrations.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE IF NOT EXISTS
|
CREATE TABLE IF NOT EXISTS
|
||||||
"oidc_integrations" (
|
"oidc_integrations" (
|
||||||
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.11.07T09.30.47.user-table-varchar-to-text.sql',
|
name: '2022.11.07T09.30.47.user-table-varchar-to-text.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
"users"
|
"users"
|
||||||
ALTER COLUMN
|
ALTER COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.12.03T09.12.28.organization-transfer.sql',
|
name: '2022.12.03T09.12.28.organization-transfer.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2022.12.20T09.20.36.oidc-columns.sql',
|
name: '2022.12.20T09.20.36.oidc-columns.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
"oidc_integrations"
|
"oidc_integrations"
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.01.04T17.00.23.hobby-7-by-default.sql',
|
name: '2023.01.04T17.00.23.hobby-7-by-default.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
-- Update Hobby with 3d to 7d - personal orgs were created with the default value of 3d
|
-- Update Hobby with 3d to 7d - personal orgs were created with the default value of 3d
|
||||||
UPDATE
|
UPDATE
|
||||||
organizations
|
organizations
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.01.12T17.00.23.cdn-tokens.sql',
|
name: '2023.01.12T17.00.23.cdn-tokens.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE
|
CREATE TABLE
|
||||||
"cdn_access_tokens" (
|
"cdn_access_tokens" (
|
||||||
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ type Cursor = {
|
||||||
lastCreatedAt: string;
|
lastCreatedAt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const run: MigrationExecutor['run'] = async ({ connection, sql }) => {
|
const run: MigrationExecutor['run'] = async ({ connection, psql }) => {
|
||||||
// eslint-disable-next-line no-process-env
|
// eslint-disable-next-line no-process-env
|
||||||
const eenv = shouldRunModel.parse(process.env);
|
const eenv = shouldRunModel.parse(process.env);
|
||||||
const shouldRun = eenv.RUN_S3_LEGACY_CDN_KEY_IMPORT === '1';
|
const shouldRun = eenv.RUN_S3_LEGACY_CDN_KEY_IMPORT === '1';
|
||||||
|
|
@ -71,7 +71,7 @@ const run: MigrationExecutor['run'] = async ({ connection, sql }) => {
|
||||||
// Also all this code runs inside a database transaction.
|
// Also all this code runs inside a database transaction.
|
||||||
// This will block any other writes to the table.
|
// This will block any other writes to the table.
|
||||||
// As the table should not be heavily in use when this is being run, it does not really matter.
|
// As the table should not be heavily in use when this is being run, it does not really matter.
|
||||||
const query = sql`
|
const query = psql`
|
||||||
SELECT
|
SELECT
|
||||||
"id"
|
"id"
|
||||||
, to_json("created_at") as "created_at_cursor"
|
, to_json("created_at") as "created_at_cursor"
|
||||||
|
|
@ -79,12 +79,12 @@ const run: MigrationExecutor['run'] = async ({ connection, sql }) => {
|
||||||
"targets"
|
"targets"
|
||||||
${
|
${
|
||||||
cursor
|
cursor
|
||||||
? sql`
|
? psql`
|
||||||
WHERE
|
WHERE
|
||||||
("created_at" = ${cursor.lastCreatedAt} AND "id" > ${cursor.lastId})
|
("created_at" = ${cursor.lastCreatedAt} AND "id" > ${cursor.lastId})
|
||||||
OR "created_at" > ${cursor.lastCreatedAt}
|
OR "created_at" > ${cursor.lastCreatedAt}
|
||||||
`
|
`
|
||||||
: sql``
|
: psql``
|
||||||
}
|
}
|
||||||
ORDER BY
|
ORDER BY
|
||||||
"created_at" ASC
|
"created_at" ASC
|
||||||
|
|
@ -93,8 +93,8 @@ const run: MigrationExecutor['run'] = async ({ connection, sql }) => {
|
||||||
200
|
200
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const items = await connection.query(query);
|
const items = await connection.any(query);
|
||||||
return TargetsModel.parse(items.rows);
|
return TargetsModel.parse(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastCursor: null | Cursor = null;
|
let lastCursor: null | Cursor = null;
|
||||||
|
|
@ -120,7 +120,7 @@ const run: MigrationExecutor['run'] = async ({ connection, sql }) => {
|
||||||
throw new Error(`Unexpected Status for storing key. (status=${response.status})`);
|
throw new Error(`Unexpected Status for storing key. (status=${response.status})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = sql`
|
const query = psql`
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
"cdn_access_tokens"
|
"cdn_access_tokens"
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.01.18T11.03.41.registry-v2.sql',
|
name: '2023.01.18T11.03.41.registry-v2.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
--
|
--
|
||||||
CREATE INDEX
|
CREATE INDEX
|
||||||
IF NOT EXISTS version_commit_cid_vid_idx ON version_commit (commit_id, version_id);
|
IF NOT EXISTS version_commit_cid_vid_idx ON version_commit (commit_id, version_id);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.02.22T09.27.02.delete-personal-org.sql',
|
name: '2023.02.22T09.27.02.delete-personal-org.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
-- Find and delete all organizations of type PERSONAL that have no projects
|
-- Find and delete all organizations of type PERSONAL that have no projects
|
||||||
DELETE FROM
|
DELETE FROM
|
||||||
organizations AS o
|
organizations AS o
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.03.14T12.14.23.schema-policy.sql',
|
name: '2023.03.14T12.14.23.schema-policy.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TYPE
|
CREATE TYPE
|
||||||
schema_policy_resource AS ENUM('ORGANIZATION', 'PROJECT');
|
schema_policy_resource AS ENUM('ORGANIZATION', 'PROJECT');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.03.29T11.42.44.feature-flags.sql',
|
name: '2023.03.29T11.42.44.feature-flags.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
organizations
|
organizations
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.04.03T12.51.36.schema-versions-meta.sql',
|
name: '2023.04.03T12.51.36.schema-versions-meta.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE
|
CREATE TABLE
|
||||||
"schema_version_changes" (
|
"schema_version_changes" (
|
||||||
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4 (),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.05.08T12.23.45.clean-invalid-schema-version-changes.sql',
|
name: '2023.05.08T12.23.45.clean-invalid-schema-version-changes.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
DELETE
|
DELETE
|
||||||
FROM
|
FROM
|
||||||
"schema_version_changes" "svc"
|
"schema_version_changes" "svc"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.05.12T08.29.06.store-supergraph-on-schema-versions.sql',
|
name: '2023.05.12T08.29.06.store-supergraph-on-schema-versions.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_versions"
|
ALTER TABLE "schema_versions"
|
||||||
ADD COLUMN "supergraph_sdl" text
|
ADD COLUMN "supergraph_sdl" text
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.06.01T09.07.53.create_collections.sql',
|
name: '2023.06.01T09.07.53.create_collections.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE "document_collections" (
|
CREATE TABLE "document_collections" (
|
||||||
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||||
"title" text NOT NULL,
|
"title" text NOT NULL,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.06.06T11.26.04.schema-checks.sql',
|
name: '2023.06.06T11.26.04.schema-checks.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE "schema_checks" (
|
CREATE TABLE "schema_checks" (
|
||||||
"id" uuid PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4()
|
"id" uuid PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4()
|
||||||
, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.07.10T11.26.04.schema-checks-manual-approval.sql',
|
name: '2023.07.10T11.26.04.schema-checks-manual-approval.sql',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_checks"
|
ALTER TABLE "schema_checks"
|
||||||
ADD COLUMN "github_check_run_id" bigint
|
ADD COLUMN "github_check_run_id" bigint
|
||||||
, ADD COLUMN "is_manually_approved" boolean
|
, ADD COLUMN "is_manually_approved" boolean
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.07.27T11.44.36.graphql-endpoint.ts',
|
name: '2023.07.27T11.44.36.graphql-endpoint.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "targets"
|
ALTER TABLE "targets"
|
||||||
ADD COLUMN "graphql_endpoint_url" text
|
ADD COLUMN "graphql_endpoint_url" text
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.08.01T11.44.36.schema-checks-expires-at.ts',
|
name: '2023.08.01T11.44.36.schema-checks-expires-at.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_checks"
|
ALTER TABLE "schema_checks"
|
||||||
ADD COLUMN "expires_at" TIMESTAMP WITH TIME ZONE
|
ADD COLUMN "expires_at" TIMESTAMP WITH TIME ZONE
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.09.01T09.54.00.zendesk-support.ts',
|
name: '2023.09.01T09.54.00.zendesk-support.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "users" ADD COLUMN "zendesk_user_id" TEXT UNIQUE DEFAULT NULL;
|
ALTER TABLE "users" ADD COLUMN "zendesk_user_id" TEXT UNIQUE DEFAULT NULL;
|
||||||
CREATE INDEX "users_by_zendesk_user_id" ON "users" ("zendesk_user_id" ASC);
|
CREATE INDEX "users_by_zendesk_user_id" ON "users" ("zendesk_user_id" ASC);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.09.25T15.23.00.github-check-with-project-name.ts',
|
name: '2023.09.25T15.23.00.github-check-with-project-name.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "projects" ADD COLUMN "github_check_with_project_name" BOOLEAN;
|
ALTER TABLE "projects" ADD COLUMN "github_check_with_project_name" BOOLEAN;
|
||||||
UPDATE "projects" SET "github_check_with_project_name" = FALSE WHERE "github_check_with_project_name" IS NULL;
|
UPDATE "projects" SET "github_check_with_project_name" = FALSE WHERE "github_check_with_project_name" IS NULL;
|
||||||
ALTER TABLE "projects"
|
ALTER TABLE "projects"
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,6 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.09.28T14.14.14.native-fed-v2.ts',
|
name: '2023.09.28T14.14.14.native-fed-v2.ts',
|
||||||
run: ({ sql }) => sql`ALTER TABLE "projects" ADD COLUMN native_federation BOOLEAN DEFAULT FALSE;`,
|
run: ({ psql }) =>
|
||||||
|
psql`ALTER TABLE "projects" ADD COLUMN native_federation BOOLEAN DEFAULT FALSE;`,
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.08.03T11.44.36.schema-checks-github-repository.ts',
|
name: '2023.08.03T11.44.36.schema-checks-github-repository.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_checks"
|
ALTER TABLE "schema_checks"
|
||||||
ADD COLUMN "github_repository" text
|
ADD COLUMN "github_repository" text
|
||||||
, ADD COLUMN "github_sha" text
|
, ADD COLUMN "github_sha" text
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2023.10.26T12.44.36.schema-checks-filters-index.ts',
|
name: '2023.10.26T12.44.36.schema-checks-filters-index.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'schema_checks_connection_pagination_with_changes',
|
name: 'schema_checks_connection_pagination_with_changes',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "schema_checks_connection_pagination_with_changes" ON "schema_checks" (
|
CREATE INDEX CONCURRENTLY "schema_checks_connection_pagination_with_changes" ON "schema_checks" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
@ -20,7 +20,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'schema_checks_connection_pagination_with_no_success',
|
name: 'schema_checks_connection_pagination_with_no_success',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "schema_checks_connection_pagination_with_no_success" ON "schema_checks" (
|
CREATE INDEX CONCURRENTLY "schema_checks_connection_pagination_with_no_success" ON "schema_checks" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
@ -33,7 +33,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'schema_checks_connection_pagination_with_no_success_and_changes',
|
name: 'schema_checks_connection_pagination_with_no_success_and_changes',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "schema_checks_connection_pagination_with_no_success_and_changes" ON "schema_checks" (
|
CREATE INDEX CONCURRENTLY "schema_checks_connection_pagination_with_no_success_and_changes" ON "schema_checks" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.10.30T00-00-00.drop-persisted-operations.ts',
|
name: '2023.10.30T00-00-00.drop-persisted-operations.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
DROP TABLE IF EXISTS "persisted_operations";
|
DROP TABLE IF EXISTS "persisted_operations";
|
||||||
DROP TYPE IF EXISTS "operation_kind";
|
DROP TYPE IF EXISTS "operation_kind";
|
||||||
`,
|
`,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2023.10.25T14.41.41.schema-checks-dedup.ts',
|
name: '2023.10.25T14.41.41.schema-checks-dedup.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'create sdl_store and alter schema_checks',
|
name: 'create sdl_store and alter schema_checks',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE TABLE "sdl_store" (
|
CREATE TABLE "sdl_store" (
|
||||||
"id" text PRIMARY KEY NOT NULL,
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
"sdl" text NOT NULL
|
"sdl" text NOT NULL
|
||||||
|
|
@ -25,25 +25,25 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create sdl_store_unique_id index',
|
name: 'Create sdl_store_unique_id index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE UNIQUE INDEX sdl_store_unique_id ON "sdl_store" ("id");
|
CREATE UNIQUE INDEX sdl_store_unique_id ON "sdl_store" ("id");
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create schema_check_by_schema_sdl_store_id index',
|
name: 'Create schema_check_by_schema_sdl_store_id index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "schema_check_by_schema_sdl_store_id" ON "schema_checks" ("schema_sdl_store_id" ASC)
|
CREATE INDEX CONCURRENTLY "schema_check_by_schema_sdl_store_id" ON "schema_checks" ("schema_sdl_store_id" ASC)
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create schema_check_by_supergraph_sdl_store_id index',
|
name: 'Create schema_check_by_supergraph_sdl_store_id index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "schema_check_by_supergraph_sdl_store_id" ON "schema_checks" ("supergraph_sdl_store_id" ASC)
|
CREATE INDEX CONCURRENTLY "schema_check_by_supergraph_sdl_store_id" ON "schema_checks" ("supergraph_sdl_store_id" ASC)
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create schema_check_by_composite_schema_sdl_store_id index',
|
name: 'Create schema_check_by_composite_schema_sdl_store_id index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "schema_check_by_composite_schema_sdl_store_id" ON "schema_checks" ("composite_schema_sdl_store_id" ASC);
|
CREATE INDEX CONCURRENTLY "schema_check_by_composite_schema_sdl_store_id" ON "schema_checks" ("composite_schema_sdl_store_id" ASC);
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2023.11.09T00.00.00.schema-check-approval.ts',
|
name: '2023.11.09T00.00.00.schema-check-approval.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE "schema_change_approvals" (
|
CREATE TABLE "schema_change_approvals" (
|
||||||
"target_id" UUID NOT NULL REFERENCES "targets" ("id") ON DELETE CASCADE,
|
"target_id" UUID NOT NULL REFERENCES "targets" ("id") ON DELETE CASCADE,
|
||||||
"context_id" text NOT NULL,
|
"context_id" text NOT NULL,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2023.11.20T10-00-00.organization-member-roles.ts',
|
name: '2023.11.20T10-00-00.organization-member-roles.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'Create organization_roles and alter organization_member table',
|
name: 'Create organization_roles and alter organization_member table',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE TABLE organization_member_roles (
|
CREATE TABLE organization_member_roles (
|
||||||
"id" uuid NOT NULL UNIQUE DEFAULT uuid_generate_v4(),
|
"id" uuid NOT NULL UNIQUE DEFAULT uuid_generate_v4(),
|
||||||
"organization_id" uuid NOT NULL REFERENCES "organizations" ("id") ON DELETE CASCADE,
|
"organization_id" uuid NOT NULL REFERENCES "organizations" ("id") ON DELETE CASCADE,
|
||||||
|
|
@ -26,7 +26,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create Admin role',
|
name: 'Create Admin role',
|
||||||
query: sql`
|
query: psql`
|
||||||
INSERT INTO organization_member_roles
|
INSERT INTO organization_member_roles
|
||||||
(
|
(
|
||||||
organization_id,
|
organization_id,
|
||||||
|
|
@ -68,7 +68,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create Contributor role',
|
name: 'Create Contributor role',
|
||||||
query: sql`
|
query: psql`
|
||||||
INSERT INTO organization_member_roles
|
INSERT INTO organization_member_roles
|
||||||
(
|
(
|
||||||
organization_id,
|
organization_id,
|
||||||
|
|
@ -104,7 +104,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create Viewer role',
|
name: 'Create Viewer role',
|
||||||
query: sql`
|
query: psql`
|
||||||
INSERT INTO organization_member_roles
|
INSERT INTO organization_member_roles
|
||||||
(
|
(
|
||||||
organization_id,
|
organization_id,
|
||||||
|
|
@ -133,7 +133,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Assign roles to users with matching scopes',
|
name: 'Assign roles to users with matching scopes',
|
||||||
query: sql`
|
query: psql`
|
||||||
UPDATE organization_member
|
UPDATE organization_member
|
||||||
SET role_id = (
|
SET role_id = (
|
||||||
SELECT id
|
SELECT id
|
||||||
|
|
@ -150,7 +150,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Migrate organization_invitations table to use Viewer role',
|
name: 'Migrate organization_invitations table to use Viewer role',
|
||||||
query: sql`
|
query: psql`
|
||||||
ALTER TABLE organization_invitations ADD COLUMN "role_id" uuid REFERENCES "organization_member_roles" ("id");
|
ALTER TABLE organization_invitations ADD COLUMN "role_id" uuid REFERENCES "organization_member_roles" ("id");
|
||||||
|
|
||||||
UPDATE organization_invitations
|
UPDATE organization_invitations
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2024.01.08T10-00-00.schema-version-diff-schema-version-id',
|
name: '2024.01.08T10-00-00.schema-version-diff-schema-version-id',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'add diff_schema_version_id column',
|
name: 'add diff_schema_version_id column',
|
||||||
query: sql`
|
query: psql`
|
||||||
ALTER TABLE "schema_versions"
|
ALTER TABLE "schema_versions"
|
||||||
ADD COLUMN IF NOT EXISTS "diff_schema_version_id" uuid REFERENCES "schema_versions" ("id")
|
ADD COLUMN IF NOT EXISTS "diff_schema_version_id" uuid REFERENCES "schema_versions" ("id")
|
||||||
, ADD COLUMN IF NOT EXISTS "record_version" text
|
, ADD COLUMN IF NOT EXISTS "record_version" text
|
||||||
|
|
@ -15,7 +15,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'create schema_versions_cursor_pagination index',
|
name: 'create schema_versions_cursor_pagination index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_cursor_pagination" ON "schema_versions" (
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_cursor_pagination" ON "schema_versions" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
@ -25,7 +25,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'create schema_versions_cursor_pagination index',
|
name: 'create schema_versions_cursor_pagination index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_cursor_pagination_composable" ON "schema_versions" (
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_cursor_pagination_composable" ON "schema_versions" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.01.26T00.00.00.contracts.ts',
|
name: '2024.01.26T00.00.00.contracts.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_versions"
|
ALTER TABLE "schema_versions"
|
||||||
ADD COLUMN "tags" text[]
|
ADD COLUMN "tags" text[]
|
||||||
, ADD COLUMN "has_contract_composition_errors" boolean
|
, ADD COLUMN "has_contract_composition_errors" boolean
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2024.01.26T00.00.01.schema-check-pagination-index-update',
|
name: '2024.01.26T00.00.01.schema-check-pagination-index-update',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'create index schema_checks_connection_pagination_with_changes_new',
|
name: 'create index schema_checks_connection_pagination_with_changes_new',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_connection_pagination_with_changes_new" ON "schema_checks" (
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_connection_pagination_with_changes_new" ON "schema_checks" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
@ -21,7 +21,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'create index schema_checks_connection_pagination_with_no_success_and_changes_new',
|
name: 'create index schema_checks_connection_pagination_with_no_success_and_changes_new',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_connection_pagination_with_no_success_and_changes_new" ON "schema_checks" (
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_connection_pagination_with_no_success_and_changes_new" ON "schema_checks" (
|
||||||
"target_id" ASC
|
"target_id" ASC
|
||||||
, "created_at" DESC
|
, "created_at" DESC
|
||||||
|
|
@ -39,19 +39,19 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'drop index schema_checks_connection_pagination_with_changes',
|
name: 'drop index schema_checks_connection_pagination_with_changes',
|
||||||
query: sql`
|
query: psql`
|
||||||
DROP INDEX CONCURRENTLY IF EXISTS "schema_checks_connection_pagination_with_changes";
|
DROP INDEX CONCURRENTLY IF EXISTS "schema_checks_connection_pagination_with_changes";
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'drop index schema_checks_connection_pagination_with_no_success_and_changes',
|
name: 'drop index schema_checks_connection_pagination_with_no_success_and_changes',
|
||||||
query: sql`
|
query: psql`
|
||||||
DROP INDEX CONCURRENTLY IF EXISTS "schema_checks_connection_pagination_with_no_success_and_changes";
|
DROP INDEX CONCURRENTLY IF EXISTS "schema_checks_connection_pagination_with_no_success_and_changes";
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'create index contract_checks_supergraph_sdl_store_id index',
|
name: 'create index contract_checks_supergraph_sdl_store_id index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "contract_checks_supergraph_sdl_store_id" ON "contract_checks" (
|
CREATE INDEX CONCURRENTLY "contract_checks_supergraph_sdl_store_id" ON "contract_checks" (
|
||||||
"supergraph_sdl_store_id" ASC
|
"supergraph_sdl_store_id" ASC
|
||||||
);
|
);
|
||||||
|
|
@ -59,7 +59,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'create index contract_checks_composite_schema_sdl_store_id',
|
name: 'create index contract_checks_composite_schema_sdl_store_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY "contract_checks_composite_schema_sdl_store_id" ON "contract_checks" (
|
CREATE INDEX CONCURRENTLY "contract_checks_composite_schema_sdl_store_id" ON "contract_checks" (
|
||||||
"composite_schema_sdl_store_id" ASC
|
"composite_schema_sdl_store_id" ASC
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2024.02.19T00.00.01.schema-check-store-breaking-change-metadata.ts',
|
name: '2024.02.19T00.00.01.schema-check-store-breaking-change-metadata.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_checks"
|
ALTER TABLE "schema_checks"
|
||||||
ADD COLUMN IF NOT EXISTS "conditional_breaking_change_metadata" JSONB
|
ADD COLUMN IF NOT EXISTS "conditional_breaking_change_metadata" JSONB
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.04.09T10.10.00.check-approval-comment.ts',
|
name: '2024.04.09T10.10.00.check-approval-comment.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_checks" ADD COLUMN IF NOT EXISTS "manual_approval_comment" text;
|
ALTER TABLE "schema_checks" ADD COLUMN IF NOT EXISTS "manual_approval_comment" text;
|
||||||
`,
|
`,
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.06.11T10-10-00.ms-teams-webhook.ts',
|
name: '2024.06.11T10-10-00.ms-teams-webhook.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TYPE alert_channel_type ADD VALUE 'MSTEAMS_WEBHOOK';
|
ALTER TYPE alert_channel_type ADD VALUE 'MSTEAMS_WEBHOOK';
|
||||||
`,
|
`,
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.07.16T13-44-00.oidc-only-access.ts',
|
name: '2024.07.16T13-44-00.oidc-only-access.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "oidc_integrations"
|
ALTER TABLE "oidc_integrations"
|
||||||
ADD COLUMN "oidc_user_access_only" BOOLEAN NOT NULL DEFAULT TRUE;
|
ADD COLUMN "oidc_user_access_only" BOOLEAN NOT NULL DEFAULT TRUE;
|
||||||
`,
|
`,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.07.17T00-00-00.app-deployments.ts',
|
name: '2024.07.17T00-00-00.app-deployments.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE IF NOT EXISTS "app_deployments" (
|
CREATE TABLE IF NOT EXISTS "app_deployments" (
|
||||||
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
"target_id" UUID NOT NULL REFERENCES "targets" ("id") ON DELETE CASCADE,
|
"target_id" UUID NOT NULL REFERENCES "targets" ("id") ON DELETE CASCADE,
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,15 @@ import {
|
||||||
isScalarType,
|
isScalarType,
|
||||||
isUnionType,
|
isUnionType,
|
||||||
} from 'graphql';
|
} from 'graphql';
|
||||||
import { sql, type CommonQueryMethods } from 'slonik';
|
import z from 'zod';
|
||||||
|
import { psql, type CommonQueryMethods } from '@hive/postgres';
|
||||||
import { env } from '../environment';
|
import { env } from '../environment';
|
||||||
import type { MigrationExecutor } from '../pg-migrator';
|
import type { MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.07.23T09.36.00.schema-cleanup-tracker.ts',
|
name: '2024.07.23T09.36.00.schema-cleanup-tracker.ts',
|
||||||
async run({ connection }) {
|
async run({ connection }) {
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
CREATE TABLE IF NOT EXISTS "schema_coordinate_status" (
|
CREATE TABLE IF NOT EXISTS "schema_coordinate_status" (
|
||||||
coordinate text NOT NULL,
|
coordinate text NOT NULL,
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
|
@ -48,9 +49,13 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schemaVersionsTotal = await connection.oneFirst<number>(sql`
|
const schemaVersionsTotal = await connection
|
||||||
|
.oneFirst(
|
||||||
|
psql`
|
||||||
SELECT count(*) as total FROM schema_versions
|
SELECT count(*) as total FROM schema_versions
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(z.number().parse);
|
||||||
console.log(`Found ${schemaVersionsTotal} schema versions`);
|
console.log(`Found ${schemaVersionsTotal} schema versions`);
|
||||||
|
|
||||||
if (schemaVersionsTotal > 1000) {
|
if (schemaVersionsTotal > 1000) {
|
||||||
|
|
@ -93,24 +98,24 @@ function diffSchemaCoordinates(
|
||||||
|
|
||||||
export async function schemaCoordinateStatusMigration(connection: CommonQueryMethods) {
|
export async function schemaCoordinateStatusMigration(connection: CommonQueryMethods) {
|
||||||
// Fetch targets
|
// Fetch targets
|
||||||
const targetResult = await connection.query<{ id: string }>(sql`
|
const targetResult = await connection
|
||||||
|
.any(
|
||||||
|
psql`
|
||||||
SELECT id FROM targets WHERE ID NOT IN (SELECT target_id FROM schema_coordinate_status)
|
SELECT id FROM targets WHERE ID NOT IN (SELECT target_id FROM schema_coordinate_status)
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(z.array(z.object({ id: z.string() })).parse);
|
||||||
|
|
||||||
console.log(`Found ${targetResult.rowCount} targets`);
|
console.log(`Found ${targetResult.length} targets`);
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for await (const target of targetResult.rows) {
|
for await (const target of targetResult) {
|
||||||
try {
|
try {
|
||||||
console.log(`Processing target (${i++}/${targetResult.rowCount}) - ${target.id}`);
|
console.log(`Processing target (${i++}/${targetResult.length}) - ${target.id}`);
|
||||||
|
|
||||||
const latestSchema = await connection.maybeOne<{
|
const latestSchema = await connection
|
||||||
id: string;
|
.maybeOne(
|
||||||
created_at: number;
|
psql`
|
||||||
is_composable: boolean;
|
|
||||||
sdl?: string;
|
|
||||||
previous_schema_version_id?: string;
|
|
||||||
}>(sql`
|
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
created_at,
|
created_at,
|
||||||
|
|
@ -121,7 +126,19 @@ export async function schemaCoordinateStatusMigration(connection: CommonQueryMet
|
||||||
WHERE target_id = ${target.id} AND is_composable = true
|
WHERE target_id = ${target.id} AND is_composable = true
|
||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
created_at: z.number(),
|
||||||
|
is_composable: z.boolean(),
|
||||||
|
sdl: z.string().nullable(),
|
||||||
|
previous_schema_version_id: z.string().nullable(),
|
||||||
|
})
|
||||||
|
.nullable().parse,
|
||||||
|
);
|
||||||
|
|
||||||
if (!latestSchema) {
|
if (!latestSchema) {
|
||||||
console.log('[SKIPPING] No latest composable schema found for target %s', target.id);
|
console.log('[SKIPPING] No latest composable schema found for target %s', target.id);
|
||||||
|
|
@ -270,10 +287,10 @@ async function insertRemainingCoordinates(
|
||||||
console.log(
|
console.log(
|
||||||
`Adding remaining ${targetCoordinates.coordinates.size} coordinates for target ${targetId}`,
|
`Adding remaining ${targetCoordinates.coordinates.size} coordinates for target ${targetId}`,
|
||||||
);
|
);
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
INSERT INTO schema_coordinate_status
|
INSERT INTO schema_coordinate_status
|
||||||
( target_id, coordinate, created_at, created_in_version_id )
|
( target_id, coordinate, created_at, created_in_version_id )
|
||||||
SELECT * FROM ${sql.unnest(
|
SELECT * FROM ${psql.unnest(
|
||||||
Array.from(targetCoordinates.coordinates).map(coordinate => [
|
Array.from(targetCoordinates.coordinates).map(coordinate => [
|
||||||
targetId,
|
targetId,
|
||||||
coordinate,
|
coordinate,
|
||||||
|
|
@ -290,10 +307,10 @@ async function insertRemainingCoordinates(
|
||||||
console.log(
|
console.log(
|
||||||
`Deprecating remaining ${remainingDeprecated.size} coordinates for target ${targetId}`,
|
`Deprecating remaining ${remainingDeprecated.size} coordinates for target ${targetId}`,
|
||||||
);
|
);
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
INSERT INTO schema_coordinate_status
|
INSERT INTO schema_coordinate_status
|
||||||
( target_id, coordinate, created_at, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
( target_id, coordinate, created_at, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
||||||
SELECT * FROM ${sql.unnest(
|
SELECT * FROM ${psql.unnest(
|
||||||
Array.from(remainingDeprecated).map(coordinate => [
|
Array.from(remainingDeprecated).map(coordinate => [
|
||||||
targetId,
|
targetId,
|
||||||
coordinate,
|
coordinate,
|
||||||
|
|
@ -343,13 +360,9 @@ async function processVersion(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const versionBefore = await connection.maybeOne<{
|
const versionBefore = await connection
|
||||||
id: string;
|
.maybeOne(
|
||||||
sdl?: string;
|
psql`
|
||||||
previous_schema_version_id?: string;
|
|
||||||
created_at: number;
|
|
||||||
is_composable: boolean;
|
|
||||||
}>(sql`
|
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
composite_schema_sdl as sdl,
|
composite_schema_sdl as sdl,
|
||||||
|
|
@ -358,7 +371,19 @@ async function processVersion(
|
||||||
is_composable
|
is_composable
|
||||||
FROM schema_versions
|
FROM schema_versions
|
||||||
WHERE id = ${previousVersionId} AND target_id = ${targetId}
|
WHERE id = ${previousVersionId} AND target_id = ${targetId}
|
||||||
`);
|
`,
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
created_at: z.number(),
|
||||||
|
is_composable: z.boolean(),
|
||||||
|
sdl: z.string().nullable(),
|
||||||
|
previous_schema_version_id: z.string().nullable(),
|
||||||
|
})
|
||||||
|
.nullable().parse,
|
||||||
|
);
|
||||||
|
|
||||||
if (!versionBefore) {
|
if (!versionBefore) {
|
||||||
console.error(
|
console.error(
|
||||||
|
|
@ -440,10 +465,10 @@ async function processVersion(
|
||||||
|
|
||||||
if (added.length) {
|
if (added.length) {
|
||||||
console.log(`Adding ${added.length} coordinates for target ${targetId}`);
|
console.log(`Adding ${added.length} coordinates for target ${targetId}`);
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
INSERT INTO schema_coordinate_status
|
INSERT INTO schema_coordinate_status
|
||||||
( target_id, coordinate, created_at, created_in_version_id )
|
( target_id, coordinate, created_at, created_in_version_id )
|
||||||
SELECT * FROM ${sql.unnest(
|
SELECT * FROM ${psql.unnest(
|
||||||
added.map(coordinate => [targetId, coordinate, datePG, after.versionId]),
|
added.map(coordinate => [targetId, coordinate, datePG, after.versionId]),
|
||||||
['uuid', 'text', 'date', 'uuid'],
|
['uuid', 'text', 'date', 'uuid'],
|
||||||
)}
|
)}
|
||||||
|
|
@ -456,10 +481,10 @@ async function processVersion(
|
||||||
if (deprecated.length) {
|
if (deprecated.length) {
|
||||||
console.log(`deprecating ${deprecated.length} coordinates for target ${targetId}`);
|
console.log(`deprecating ${deprecated.length} coordinates for target ${targetId}`);
|
||||||
|
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
INSERT INTO schema_coordinate_status
|
INSERT INTO schema_coordinate_status
|
||||||
( target_id, coordinate, created_at, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
( target_id, coordinate, created_at, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
||||||
SELECT * FROM ${sql.unnest(
|
SELECT * FROM ${psql.unnest(
|
||||||
deprecated.map(coordinate => [
|
deprecated.map(coordinate => [
|
||||||
targetId,
|
targetId,
|
||||||
coordinate,
|
coordinate,
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2024.12.23T00-00-00.improve-version-index.ts',
|
name: '2024.12.23T00-00-00.improve-version-index.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: `create "schema_log"."action" with "created_at" sort index`,
|
name: `create "schema_log"."action" with "created_at" sort index`,
|
||||||
query: sql`CREATE INDEX CONCURRENTLY idx_schema_log_action_created ON schema_log(action, created_at DESC);`,
|
query: psql`CREATE INDEX CONCURRENTLY idx_schema_log_action_created ON schema_log(action, created_at DESC);`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `create "schema_log"."action" + "service_name" index`,
|
name: `create "schema_log"."action" + "service_name" index`,
|
||||||
query: sql`CREATE INDEX CONCURRENTLY idx_schema_log_action_service ON schema_log(action, lower(service_name));`,
|
query: psql`CREATE INDEX CONCURRENTLY idx_schema_log_action_service ON schema_log(action, lower(service_name));`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2024.12.24T00-00-00.improve-version-index-2.ts',
|
name: '2024.12.24T00-00-00.improve-version-index-2.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: `create "schema_version_changes"."schema_version_id" lookup index`,
|
name: `create "schema_version_changes"."schema_version_id" lookup index`,
|
||||||
query: sql`CREATE INDEX CONCURRENTLY idx_schema_version_changes_id ON schema_version_changes(schema_version_id);`,
|
query: psql`CREATE INDEX CONCURRENTLY idx_schema_version_changes_id ON schema_version_changes(schema_version_id);`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2024.12.27T00.00.00.create-preflight-scripts.ts',
|
name: '2024.12.27T00.00.00.create-preflight-scripts.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE IF NOT EXISTS "document_preflight_scripts" (
|
CREATE TABLE IF NOT EXISTS "document_preflight_scripts" (
|
||||||
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||||
"source_code" text NOT NULL,
|
"source_code" text NOT NULL,
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2025.01.02T00-00-00.cascade-deletion-indices.ts',
|
name: '2025.01.02T00-00-00.cascade-deletion-indices.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'index schema_checks_manual_approval_user_id',
|
name: 'index schema_checks_manual_approval_user_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_manual_approval_user_id"
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_manual_approval_user_id"
|
||||||
ON "schema_checks"("manual_approval_user_id")
|
ON "schema_checks"("manual_approval_user_id")
|
||||||
WHERE "manual_approval_user_id" is not null
|
WHERE "manual_approval_user_id" is not null
|
||||||
|
|
@ -18,106 +18,106 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index organization_member_user_id',
|
name: 'index organization_member_user_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organization_member_user_id"
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organization_member_user_id"
|
||||||
ON "organization_member"("user_id")
|
ON "organization_member"("user_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index organization_member_organization_id',
|
name: 'index organization_member_organization_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organization_member_organization_id"
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organization_member_organization_id"
|
||||||
ON "organization_member"("organization_id")
|
ON "organization_member"("organization_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index organization_member_roles_organization_id',
|
name: 'index organization_member_roles_organization_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organization_member_roles_organization_id"
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organization_member_roles_organization_id"
|
||||||
ON "organization_member_roles"("organization_id")
|
ON "organization_member_roles"("organization_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index projects_org_id',
|
name: 'index projects_org_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "projects_org_id" ON "projects"("org_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "projects_org_id" ON "projects"("org_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index targets_project_id',
|
name: 'index targets_project_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "targets_project_id" ON "targets"("project_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "targets_project_id" ON "targets"("project_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_versions_target_id',
|
name: 'index schema_versions_target_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_target_id" ON "schema_versions"("target_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_target_id" ON "schema_versions"("target_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_checks_target_id',
|
name: 'index schema_checks_target_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_target_id" ON "schema_checks"("target_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_target_id" ON "schema_checks"("target_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_log_target_id',
|
name: 'index schema_log_target_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_log_target_id" ON "schema_log"("target_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_log_target_id" ON "schema_log"("target_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_log_project_id',
|
name: 'index schema_log_project_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_log_project_id" ON "schema_log"("project_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_log_project_id" ON "schema_log"("project_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index contract_versions_schema_version_id',
|
name: 'index contract_versions_schema_version_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "contract_versions_schema_version_id" ON "contract_versions"("schema_version_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "contract_versions_schema_version_id" ON "contract_versions"("schema_version_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_version_to_log_action_id',
|
name: 'index schema_version_to_log_action_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_version_to_log_action_id" ON "schema_version_to_log"("action_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_version_to_log_action_id" ON "schema_version_to_log"("action_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_version_to_log_version_id',
|
name: 'index schema_version_to_log_version_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_version_to_log_version_id" ON "schema_version_to_log"("version_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_version_to_log_version_id" ON "schema_version_to_log"("version_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index contract_schema_change_approvals_schema_change_id',
|
name: 'index contract_schema_change_approvals_schema_change_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "contract_schema_change_approvals_schema_change_id" ON "contract_schema_change_approvals"("schema_change_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "contract_schema_change_approvals_schema_change_id" ON "contract_schema_change_approvals"("schema_change_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_checks_schema_version_id',
|
name: 'index schema_checks_schema_version_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_schema_version_id" ON "schema_checks"("schema_version_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_checks_schema_version_id" ON "schema_checks"("schema_version_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index schema_versions_diff_schema_version_id',
|
name: 'index schema_versions_diff_schema_version_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_diff_schema_version_id" ON "schema_versions"("diff_schema_version_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "schema_versions_diff_schema_version_id" ON "schema_versions"("diff_schema_version_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index organizations_ownership_transfer_user_id',
|
name: 'index organizations_ownership_transfer_user_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organizations_ownership_transfer_user_id" ON "organizations"("ownership_transfer_user_id")
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "organizations_ownership_transfer_user_id" ON "organizations"("ownership_transfer_user_id")
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'index users_supertoken_user_id',
|
name: 'index users_supertoken_user_id',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "users_supertoken_user_id_missing"
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "users_supertoken_user_id_missing"
|
||||||
ON "users"("supertoken_user_id")
|
ON "users"("supertoken_user_id")
|
||||||
WHERE 'supertoken_user_id' IS NULL
|
WHERE 'supertoken_user_id' IS NULL
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ export default {
|
||||||
// we do not run this in a transaction as each user processing delete takes around 300ms.
|
// we do not run this in a transaction as each user processing delete takes around 300ms.
|
||||||
// and we do not want to mess with live traffic.
|
// and we do not want to mess with live traffic.
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
async run({ sql, connection }) {
|
async run({ psql, connection }) {
|
||||||
const userIds = await connection
|
const userIds = await connection
|
||||||
.anyFirst(
|
.anyFirst(
|
||||||
sql`
|
psql`
|
||||||
SELECT
|
SELECT
|
||||||
"id"
|
"id"
|
||||||
FROM
|
FROM
|
||||||
|
|
@ -32,7 +32,7 @@ export default {
|
||||||
`processing userId="${userId}" (${counter.toPrecision().padStart(padAmount, '0')}/${total})`,
|
`processing userId="${userId}" (${counter.toPrecision().padStart(padAmount, '0')}/${total})`,
|
||||||
);
|
);
|
||||||
// ON DELETE SET null constraint is missing, so we need to first update it manually
|
// ON DELETE SET null constraint is missing, so we need to first update it manually
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
UPDATE
|
UPDATE
|
||||||
"organizations"
|
"organizations"
|
||||||
SET
|
SET
|
||||||
|
|
@ -41,14 +41,14 @@ export default {
|
||||||
"ownership_transfer_user_id" = ${userId}
|
"ownership_transfer_user_id" = ${userId}
|
||||||
`);
|
`);
|
||||||
// Delete the organizations of these users
|
// Delete the organizations of these users
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
DELETE
|
DELETE
|
||||||
FROM
|
FROM
|
||||||
"organizations"
|
"organizations"
|
||||||
WHERE
|
WHERE
|
||||||
"user_id" = ${userId}
|
"user_id" = ${userId}
|
||||||
`);
|
`);
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
DELETE
|
DELETE
|
||||||
FROM
|
FROM
|
||||||
"users"
|
"users"
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ const QUERY_RESULT = z.array(
|
||||||
export default {
|
export default {
|
||||||
name: '2025.01.09T00-00-00.legacy-member-scopes.ts',
|
name: '2025.01.09T00-00-00.legacy-member-scopes.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
async run({ sql, connection }) {
|
async run({ psql, connection }) {
|
||||||
const queryResult = await connection.query(sql`
|
const queryResult = await connection.any(psql`
|
||||||
SELECT
|
SELECT
|
||||||
organization_id as "organizationId",
|
organization_id as "organizationId",
|
||||||
sorted_scopes as "sortedScopes",
|
sorted_scopes as "sortedScopes",
|
||||||
|
|
@ -49,7 +49,7 @@ export default {
|
||||||
ORDER BY organization_id;
|
ORDER BY organization_id;
|
||||||
`);
|
`);
|
||||||
|
|
||||||
if (queryResult.rowCount === 0) {
|
if (queryResult.length === 0) {
|
||||||
console.log('No members without role_id found.');
|
console.log('No members without role_id found.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ export default {
|
||||||
// rows are sorted by organization_id
|
// rows are sorted by organization_id
|
||||||
// and grouped by scopes
|
// and grouped by scopes
|
||||||
// so we can process them in order
|
// so we can process them in order
|
||||||
const rows = QUERY_RESULT.parse(queryResult.rows);
|
const rows = QUERY_RESULT.parse(queryResult);
|
||||||
|
|
||||||
let counter = 1;
|
let counter = 1;
|
||||||
let previousOrganizationId: string | null = null;
|
let previousOrganizationId: string | null = null;
|
||||||
|
|
@ -70,12 +70,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`processing organization_id="${row.organizationId}" (${counter}) with ${row.userIds.length} users | ${index + 1}/${queryResult.rowCount}`,
|
`processing organization_id="${row.organizationId}" (${counter}) with ${row.userIds.length} users | ${index + 1}/${queryResult.length}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const startedAt = Date.now();
|
const startedAt = Date.now();
|
||||||
|
|
||||||
await connection.query(sql`
|
await connection.query(psql`
|
||||||
WITH new_role AS (
|
WITH new_role AS (
|
||||||
INSERT INTO organization_member_roles (
|
INSERT INTO organization_member_roles (
|
||||||
organization_id, name, description, scopes
|
organization_id, name, description, scopes
|
||||||
|
|
@ -84,13 +84,13 @@ export default {
|
||||||
${row.organizationId},
|
${row.organizationId},
|
||||||
'Auto Role ' || substring(uuid_generate_v4()::text FROM 1 FOR 8),
|
'Auto Role ' || substring(uuid_generate_v4()::text FROM 1 FOR 8),
|
||||||
'Auto generated role to assign to members without a role',
|
'Auto generated role to assign to members without a role',
|
||||||
${sql.array(row.sortedScopes, 'text')}
|
${psql.array(row.sortedScopes, 'text')}
|
||||||
)
|
)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
)
|
)
|
||||||
UPDATE organization_member
|
UPDATE organization_member
|
||||||
SET role_id = (SELECT id FROM new_role)
|
SET role_id = (SELECT id FROM new_role)
|
||||||
WHERE organization_id = ${row.organizationId} AND user_id = ANY(${sql.array(row.userIds, 'uuid')})
|
WHERE organization_id = ${row.organizationId} AND user_id = ANY(${psql.array(row.userIds, 'uuid')})
|
||||||
`);
|
`);
|
||||||
|
|
||||||
console.log(`finished after ${Date.now() - startedAt}ms`);
|
console.log(`finished after ${Date.now() - startedAt}ms`);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2025.01.10T00.00.00.breaking-changes-request-count.ts',
|
name: '2025.01.10T00.00.00.breaking-changes-request-count.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TYPE
|
CREATE TYPE
|
||||||
breaking_change_formula AS ENUM('PERCENTAGE', 'REQUEST_COUNT');
|
breaking_change_formula AS ENUM('PERCENTAGE', 'REQUEST_COUNT');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ export default {
|
||||||
name: '2025.01.13T10-08-00.default-role.ts',
|
name: '2025.01.13T10-08-00.default-role.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
// Adds a default role to OIDC integration and set index on "oidc_integrations"."default_role_id"
|
// Adds a default role to OIDC integration and set index on "oidc_integrations"."default_role_id"
|
||||||
run: ({ sql }) => [
|
run: ({ psql }) => [
|
||||||
{
|
{
|
||||||
name: 'Add a column',
|
name: 'Add a column',
|
||||||
query: sql`
|
query: psql`
|
||||||
ALTER TABLE "oidc_integrations"
|
ALTER TABLE "oidc_integrations"
|
||||||
ADD COLUMN IF NOT EXISTS "default_role_id" UUID REFERENCES organization_member_roles(id)
|
ADD COLUMN IF NOT EXISTS "default_role_id" UUID REFERENCES organization_member_roles(id)
|
||||||
ON DELETE SET NULL;
|
ON DELETE SET NULL;
|
||||||
|
|
@ -15,7 +15,7 @@ export default {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Create an index',
|
name: 'Create an index',
|
||||||
query: sql`
|
query: psql`
|
||||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "oidc_integrations_default_role_id_idx"
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS "oidc_integrations_default_role_id_idx"
|
||||||
ON "oidc_integrations"("default_role_id")
|
ON "oidc_integrations"("default_role_id")
|
||||||
WHERE "default_role_id" is not null;
|
WHERE "default_role_id" is not null;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2025.01.17T10-08-00.drop-activities.ts',
|
name: '2025.01.17T10-08-00.drop-activities.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
DROP TABLE IF EXISTS "activities";
|
DROP TABLE IF EXISTS "activities";
|
||||||
`,
|
`,
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2025.01.20T00-00-00.legacy-registry-model-removal.ts',
|
name: '2025.01.20T00-00-00.legacy-registry-model-removal.ts',
|
||||||
|
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE projects DROP COLUMN IF EXISTS legacy_registry_model;
|
ALTER TABLE projects DROP COLUMN IF EXISTS legacy_registry_model;
|
||||||
`,
|
`,
|
||||||
} satisfies MigrationExecutor;
|
} satisfies MigrationExecutor;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2025-01-30T00-00-00.granular-member-role-permissions.ts',
|
name: '2025-01-30T00-00-00.granular-member-role-permissions.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "organization_member_roles"
|
ALTER TABLE "organization_member_roles"
|
||||||
ALTER "scopes" DROP NOT NULL
|
ALTER "scopes" DROP NOT NULL
|
||||||
, ADD COLUMN "permissions" text[]
|
, ADD COLUMN "permissions" text[]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2025.02.14T00.00.00.schema-versions-metadata.ts',
|
name: '2025.02.14T00.00.00.schema-versions-metadata.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_versions"
|
ALTER TABLE "schema_versions"
|
||||||
ADD COLUMN "schema_metadata" JSONB DEFAULT NULL
|
ADD COLUMN "schema_metadata" JSONB DEFAULT NULL
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { type MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2025.02.20T00-00-00.organization-access-tokens.ts',
|
name: '2025.02.20T00-00-00.organization-access-tokens.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
CREATE TABLE IF NOT EXISTS "organization_access_tokens" (
|
CREATE TABLE IF NOT EXISTS "organization_access_tokens" (
|
||||||
"id" UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4()
|
"id" UUID PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4()
|
||||||
, "organization_id" UUID NOT NULL REFERENCES "organizations" ("id") ON DELETE CASCADE
|
, "organization_id" UUID NOT NULL REFERENCES "organizations" ("id") ON DELETE CASCADE
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: '2025.02.21T00.00.00.schema-versions-metadata-attributes.ts',
|
name: '2025.02.21T00.00.00.schema-versions-metadata-attributes.ts',
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE "schema_versions"
|
ALTER TABLE "schema_versions"
|
||||||
ADD COLUMN "metadata_attributes" JSONB DEFAULT NULL
|
ADD COLUMN "metadata_attributes" JSONB DEFAULT NULL
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import type { MigrationExecutor } from '../pg-migrator';
|
||||||
export default {
|
export default {
|
||||||
name: '2025.03.20T00-00-00.dangerous_breaking.ts',
|
name: '2025.03.20T00-00-00.dangerous_breaking.ts',
|
||||||
noTransaction: true,
|
noTransaction: true,
|
||||||
run: ({ sql }) => sql`
|
run: ({ psql }) => psql`
|
||||||
ALTER TABLE
|
ALTER TABLE
|
||||||
targets
|
targets
|
||||||
ADD COLUMN
|
ADD COLUMN
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue