mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Creation and deprecation status of schema coordinates - schema age filter (part 1) (#5224)
This commit is contained in:
parent
b651e890c2
commit
8020419437
34 changed files with 2707 additions and 204 deletions
|
|
@ -130,6 +130,7 @@ module.exports = {
|
||||||
'prefer-destructuring': 'off',
|
'prefer-destructuring': 'off',
|
||||||
'prefer-const': 'off',
|
'prefer-const': 'off',
|
||||||
'no-useless-escape': 'off',
|
'no-useless-escape': 'off',
|
||||||
|
'no-inner-declarations': 'off',
|
||||||
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
"slonik": "30.4.4",
|
"slonik": "30.4.4",
|
||||||
"strip-ansi": "7.1.0",
|
"strip-ansi": "7.1.0",
|
||||||
"tslib": "2.6.3",
|
"tslib": "2.6.3",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.3",
|
||||||
"zod": "3.23.8"
|
"zod": "3.23.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,15 @@ export function initSeed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
async createDbConnection() {
|
||||||
|
const pool = await createConnectionPool();
|
||||||
|
return {
|
||||||
|
pool,
|
||||||
|
[Symbol.asyncDispose]: async () => {
|
||||||
|
await pool.end();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
authenticate: authenticate,
|
authenticate: authenticate,
|
||||||
generateEmail: () => userEmail(generateUnique()),
|
generateEmail: () => userEmail(generateUnique()),
|
||||||
async createOwner() {
|
async createOwner() {
|
||||||
|
|
|
||||||
991
integration-tests/tests/api/schema/cleanup-tracker.spec.ts
Normal file
991
integration-tests/tests/api/schema/cleanup-tracker.spec.ts
Normal file
|
|
@ -0,0 +1,991 @@
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import { sql, type CommonQueryMethods } from 'slonik';
|
||||||
|
/* eslint-disable no-process-env */
|
||||||
|
import { ProjectType, TargetAccessScope } from 'testkit/gql/graphql';
|
||||||
|
import { test } from 'vitest';
|
||||||
|
import { initSeed } from '../../../testkit/seed';
|
||||||
|
|
||||||
|
async function fetchCoordinates(db: CommonQueryMethods, target: { id: string }) {
|
||||||
|
const result = await db.query<{
|
||||||
|
coordinate: string;
|
||||||
|
created_in_version_id: string;
|
||||||
|
deprecated_in_version_id: string | null;
|
||||||
|
}>(sql`
|
||||||
|
SELECT coordinate, created_in_version_id, deprecated_in_version_id
|
||||||
|
FROM schema_coordinate_status WHERE target_id = ${target.id}
|
||||||
|
`);
|
||||||
|
|
||||||
|
return result.rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('schema cleanup tracker', () => {
|
||||||
|
test.concurrent('single', async ({ expect }) => {
|
||||||
|
const { publishSchema, target, createDbConnection } = await prepare();
|
||||||
|
// This API is soooooooooooo awkward xD
|
||||||
|
await using db = await createDbConnection();
|
||||||
|
|
||||||
|
const ver1 = await publishSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hello',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver2 = await publishSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hello',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hi',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await publishSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hello',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'Query.hi',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver4 = await publishSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hello',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hi',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver5 = await publishSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String @deprecated(reason: "no longer needed")
|
||||||
|
bye: String
|
||||||
|
goodbye: String
|
||||||
|
hi: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hello',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.bye',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.goodbye',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hi',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await publishSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
bye: String
|
||||||
|
hi: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hello',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.bye',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'Query.goodbye',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.hi',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.concurrent('federation', async ({ expect }) => {
|
||||||
|
const { publishSchema, deleteSchema, target, createDbConnection } = await prepare(
|
||||||
|
ProjectType.Federation,
|
||||||
|
);
|
||||||
|
await using db = await createDbConnection();
|
||||||
|
|
||||||
|
const serviceFoo = {
|
||||||
|
name: 'foo',
|
||||||
|
url: 'https://api.com/foo',
|
||||||
|
};
|
||||||
|
|
||||||
|
const serviceBar = {
|
||||||
|
name: 'bar',
|
||||||
|
url: 'https://api.com/bar',
|
||||||
|
};
|
||||||
|
|
||||||
|
const ver1 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
user(id: ID!): User
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(fields: "id") {
|
||||||
|
id: ID!
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceFoo,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver2 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
users: User
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(fields: "id") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await deleteSchema(serviceBar.name);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver4 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
users: User
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(fields: "id") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver5 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
users: User @deprecated(reason: "no longer needed")
|
||||||
|
randomUser: User
|
||||||
|
admin: User
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(fields: "id") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.randomUser',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.admin',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
users: User
|
||||||
|
admin: User
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(fields: "id") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'Query.randomUser',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.admin',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.concurrent('stitching', async ({ expect }) => {
|
||||||
|
const { publishSchema, deleteSchema, target, createDbConnection } = await prepare(
|
||||||
|
ProjectType.Stitching,
|
||||||
|
);
|
||||||
|
await using db = await createDbConnection();
|
||||||
|
|
||||||
|
const serviceFoo = {
|
||||||
|
name: 'foo',
|
||||||
|
url: 'https://api.com/foo',
|
||||||
|
};
|
||||||
|
|
||||||
|
const serviceBar = {
|
||||||
|
name: 'bar',
|
||||||
|
url: 'https://api.com/bar',
|
||||||
|
};
|
||||||
|
|
||||||
|
const ver1 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
user(id: ID!): User @merge
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(selectionSet: "{ id }") {
|
||||||
|
id: ID!
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceFoo,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver2 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
users: User
|
||||||
|
user(id: ID!): User @merge
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(selectionSet: "{ id }") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await deleteSchema(serviceBar.name);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver2,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver4 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
users: User
|
||||||
|
user(id: ID!): User @merge
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(selectionSet: "{ id }") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ver5 = await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
users: User @deprecated(reason: "no longer needed")
|
||||||
|
randomUser: User
|
||||||
|
admin: User
|
||||||
|
user(id: ID!): User @merge
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(selectionSet: "{ id }") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.randomUser',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.admin',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await publishSchema(
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
users: User
|
||||||
|
admin: User
|
||||||
|
user(id: ID!): User @merge
|
||||||
|
}
|
||||||
|
|
||||||
|
type User @key(selectionSet: "{ id }") {
|
||||||
|
id: ID!
|
||||||
|
pictureUrl: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
serviceBar,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(fetchCoordinates(db.pool, target)).resolves.toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
// foo
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.user.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.id',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.name',
|
||||||
|
created_in_version_id: ver1,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
// bar
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.users',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
coordinate: 'Query.randomUser',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'Query.admin',
|
||||||
|
created_in_version_id: ver5,
|
||||||
|
deprecated_in_version_id: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
coordinate: 'User.pictureUrl',
|
||||||
|
created_in_version_id: ver4,
|
||||||
|
deprecated_in_version_id: ver5,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function prepare(projectType: ProjectType = ProjectType.Single) {
|
||||||
|
const { createOwner, createDbConnection } = initSeed();
|
||||||
|
const { createOrg } = await createOwner();
|
||||||
|
const { createProject, organization } = await createOrg();
|
||||||
|
const { createToken, project, target } = await createProject(projectType);
|
||||||
|
const token = await createToken({
|
||||||
|
targetScopes: [TargetAccessScope.RegistryRead, TargetAccessScope.RegistryWrite],
|
||||||
|
projectScopes: [],
|
||||||
|
organizationScopes: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
createDbConnection,
|
||||||
|
async publishSchema(
|
||||||
|
sdl: string,
|
||||||
|
service?: {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const result = await token
|
||||||
|
.publishSchema({ sdl, service: service?.name, url: service?.url })
|
||||||
|
.then(r => r.expectNoGraphQLErrors());
|
||||||
|
|
||||||
|
if (result.schemaPublish.__typename !== 'SchemaPublishSuccess') {
|
||||||
|
console.log(JSON.stringify(result.schemaPublish, null, 2));
|
||||||
|
throw new Error(`Expected schemaPublish success, got ${result.schemaPublish.__typename}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.schemaPublish.valid) {
|
||||||
|
throw new Error('Expected schema to be valid');
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = await token.fetchLatestValidSchema();
|
||||||
|
const versionId = version.latestValidVersion?.id;
|
||||||
|
|
||||||
|
if (!versionId) {
|
||||||
|
throw new Error('Expected version id to be defined');
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionId;
|
||||||
|
},
|
||||||
|
async deleteSchema(serviceName: string) {
|
||||||
|
const result = await token.deleteSchema(serviceName).then(r => r.expectNoGraphQLErrors());
|
||||||
|
|
||||||
|
if (result.schemaDelete.__typename !== 'SchemaDeleteSuccess') {
|
||||||
|
throw new Error(`Expected schemaDelete success, got ${result.schemaDelete.__typename}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.schemaDelete.valid) {
|
||||||
|
throw new Error('Expected schema to be valid');
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = await token.fetchLatestValidSchema();
|
||||||
|
const versionId = version.latestValidVersion?.id;
|
||||||
|
|
||||||
|
if (!versionId) {
|
||||||
|
throw new Error('Expected version id to be defined');
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionId;
|
||||||
|
},
|
||||||
|
organization,
|
||||||
|
project,
|
||||||
|
target,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -100,7 +100,7 @@
|
||||||
"turbo": "1.13.4",
|
"turbo": "1.13.4",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.3",
|
||||||
"vite-tsconfig-paths": "4.3.2",
|
"vite-tsconfig-paths": "4.3.2",
|
||||||
"vitest": "1.6.0"
|
"vitest": "2.0.3"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
"graphql": "16.9.0",
|
"graphql": "16.9.0",
|
||||||
"graphql-ws": "5.16.0",
|
"graphql-ws": "5.16.0",
|
||||||
"nock": "14.0.0-beta.7",
|
"nock": "14.0.0-beta.7",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.3",
|
||||||
"ws": "8.18.0"
|
"ws": "8.18.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ test('should not interrupt the process', async () => {
|
||||||
|
|
||||||
test('should capture client name and version headers', async () => {
|
test('should capture client name and version headers', async () => {
|
||||||
const clean = handleProcess();
|
const clean = handleProcess();
|
||||||
const fetchSpy = vi.fn<[RequestInfo | URL, options: RequestInit | undefined]>(async () =>
|
const fetchSpy = vi.fn(async (_input: string | URL | globalThis.Request, _init?: RequestInit) =>
|
||||||
Response.json({}, { status: 200 }),
|
Response.json({}, { status: 200 }),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
"graphql": "16.9.0",
|
"graphql": "16.9.0",
|
||||||
"nock": "14.0.0-beta.7",
|
"nock": "14.0.0-beta.7",
|
||||||
"tslib": "2.6.3",
|
"tslib": "2.6.3",
|
||||||
"vitest": "1.6.0"
|
"vitest": "2.0.3"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "https://registry.npmjs.org",
|
"registry": "https://registry.npmjs.org",
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
"graphql-ws": "5.16.0",
|
"graphql-ws": "5.16.0",
|
||||||
"graphql-yoga": "5.6.0",
|
"graphql-yoga": "5.6.0",
|
||||||
"nock": "14.0.0-beta.7",
|
"nock": "14.0.0-beta.7",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.3",
|
||||||
"ws": "8.18.0"
|
"ws": "8.18.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ test('should not interrupt the process', async () => {
|
||||||
}, 1_000);
|
}, 1_000);
|
||||||
|
|
||||||
test('should capture client name and version headers', async () => {
|
test('should capture client name and version headers', async () => {
|
||||||
const fetchSpy = vi.fn<[RequestInfo | URL, options: RequestInit | undefined]>(async () =>
|
const fetchSpy = vi.fn(async (_input: string | URL | globalThis.Request, _init?: RequestInit) =>
|
||||||
Response.json({}, { status: 200 }),
|
Response.json({}, { status: 200 }),
|
||||||
);
|
);
|
||||||
const clean = handleProcess();
|
const clean = handleProcess();
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
"copyfiles": "2.4.1",
|
"copyfiles": "2.4.1",
|
||||||
"dotenv": "16.4.5",
|
"dotenv": "16.4.5",
|
||||||
"got": "14.4.1",
|
"got": "14.4.1",
|
||||||
|
"graphql": "16.9.0",
|
||||||
"p-limit": "4.0.0",
|
"p-limit": "4.0.0",
|
||||||
"pg-promise": "11.9.0",
|
"pg-promise": "11.9.0",
|
||||||
"slonik": "30.4.4",
|
"slonik": "30.4.4",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,496 @@
|
||||||
|
import {
|
||||||
|
buildSchema,
|
||||||
|
GraphQLFieldMap,
|
||||||
|
GraphQLSchema,
|
||||||
|
isEnumType,
|
||||||
|
isInputObjectType,
|
||||||
|
isInterfaceType,
|
||||||
|
isIntrospectionType,
|
||||||
|
isObjectType,
|
||||||
|
isScalarType,
|
||||||
|
isUnionType,
|
||||||
|
} from 'graphql';
|
||||||
|
import { sql, type CommonQueryMethods } from 'slonik';
|
||||||
|
import { env } from '../environment';
|
||||||
|
import type { MigrationExecutor } from '../pg-migrator';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: '2024.07.23T09.36.00.schema-cleanup-tracker.ts',
|
||||||
|
async run({ connection }) {
|
||||||
|
await connection.query(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS "schema_coordinate_status" (
|
||||||
|
coordinate text NOT NULL,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
created_in_version_id UUID NOT NULL REFERENCES "schema_versions" ("id") ON DELETE CASCADE,
|
||||||
|
deprecated_at TIMESTAMPTZ,
|
||||||
|
deprecated_in_version_id UUID REFERENCES "schema_versions" ("id") ON DELETE CASCADE,
|
||||||
|
"target_id" UUID NOT NULL REFERENCES "targets" ("id") ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY (coordinate, target_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_schema_coordinate_status_by_target_timestamp
|
||||||
|
ON schema_coordinate_status(
|
||||||
|
target_id,
|
||||||
|
created_at,
|
||||||
|
deprecated_at
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_schema_coordinate_status_by_target_coordinate_timestamp
|
||||||
|
ON schema_coordinate_status(
|
||||||
|
target_id,
|
||||||
|
coordinate,
|
||||||
|
created_at,
|
||||||
|
deprecated_at
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
if (env.isHiveCloud) {
|
||||||
|
console.log('Skipping schema coordinate status migration for hive cloud');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const schemaVersionsTotal = await connection.oneFirst<number>(sql`
|
||||||
|
SELECT count(*) as total FROM schema_versions
|
||||||
|
`);
|
||||||
|
console.log(`Found ${schemaVersionsTotal} schema versions`);
|
||||||
|
|
||||||
|
if (schemaVersionsTotal > 1000) {
|
||||||
|
console.warn(
|
||||||
|
`[WARN] There are more than 1000 schema versions (${schemaVersionsTotal}). Skipping a data backfill.`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await schemaCoordinateStatusMigration(connection);
|
||||||
|
},
|
||||||
|
} satisfies MigrationExecutor;
|
||||||
|
|
||||||
|
type SchemaCoordinatesDiffResult = {
|
||||||
|
/**
|
||||||
|
* Coordinates that are in incoming but not in existing (including deprecated ones)
|
||||||
|
*/
|
||||||
|
added: Set<string>;
|
||||||
|
/**
|
||||||
|
* Coordinates that are deprecated in incoming, but were not deprecated in existing or non-existent
|
||||||
|
*/
|
||||||
|
deprecated: Set<string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function diffSchemaCoordinates(
|
||||||
|
existingSchema: GraphQLSchema,
|
||||||
|
incomingSchema: GraphQLSchema,
|
||||||
|
): SchemaCoordinatesDiffResult {
|
||||||
|
const before = getSchemaCoordinates(existingSchema);
|
||||||
|
const after = getSchemaCoordinates(incomingSchema);
|
||||||
|
|
||||||
|
const added = after.coordinates.difference(before.coordinates);
|
||||||
|
const deprecated = after.deprecated.difference(before.deprecated);
|
||||||
|
|
||||||
|
return {
|
||||||
|
added,
|
||||||
|
deprecated,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function schemaCoordinateStatusMigration(connection: CommonQueryMethods) {
|
||||||
|
// Fetch targets
|
||||||
|
const targetResult = await connection.query<{ id: string }>(sql`
|
||||||
|
SELECT id FROM targets WHERE ID NOT IN (SELECT target_id FROM schema_coordinate_status)
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log(`Found ${targetResult.rowCount} targets`);
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for await (const target of targetResult.rows) {
|
||||||
|
try {
|
||||||
|
console.log(`Processing target (${i++}/${targetResult.rowCount}) - ${target.id}`);
|
||||||
|
|
||||||
|
const latestSchema = await connection.maybeOne<{
|
||||||
|
id: string;
|
||||||
|
created_at: number;
|
||||||
|
is_composable: boolean;
|
||||||
|
sdl?: string;
|
||||||
|
previous_schema_version_id?: string;
|
||||||
|
}>(sql`
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
created_at,
|
||||||
|
is_composable,
|
||||||
|
previous_schema_version_id,
|
||||||
|
composite_schema_sdl as sdl
|
||||||
|
FROM schema_versions
|
||||||
|
WHERE target_id = ${target.id} AND is_composable = true
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT 1
|
||||||
|
`);
|
||||||
|
|
||||||
|
if (!latestSchema) {
|
||||||
|
console.log('[SKIPPING] No latest composable schema found for target %s', target.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!latestSchema.sdl) {
|
||||||
|
console.warn(
|
||||||
|
`[SKIPPING] No latest, composable schema with non-empty sdl found for target ${target.id}.`,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const schema = buildSchema(latestSchema.sdl, {
|
||||||
|
assumeValid: true,
|
||||||
|
assumeValidSDL: true,
|
||||||
|
});
|
||||||
|
const targetCoordinates = getSchemaCoordinates(schema);
|
||||||
|
|
||||||
|
// The idea here is to
|
||||||
|
// 1. start from the latest composable version.
|
||||||
|
// 2. create a list of coordinates that are in the latest version, all and deprecated.
|
||||||
|
// 3. navigate to the previous version and compare the coordinates.
|
||||||
|
// 4. if a coordinate is added, upsert it into the schema_coordinate_status and remove it from the list.
|
||||||
|
// 5. if a coordinate is deprecated, upsert it into the schema_coordinate_status and remove it from the list of deprecated coordinates.
|
||||||
|
// 6. if the list of coordinates is empty, stop the process.
|
||||||
|
// 7. if the previous version is not composable, skip it and continue with the next previous version.
|
||||||
|
// 8. if the previous version is not found, insert all remaining coordinates and stop the process. This step might create incorrect dates!
|
||||||
|
await processVersion(1, connection, targetCoordinates, target.id, {
|
||||||
|
schema,
|
||||||
|
versionId: latestSchema.id,
|
||||||
|
createdAt: latestSchema.created_at,
|
||||||
|
previousVersionId: latestSchema.previous_schema_version_id ?? null,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing target ${target.id}`);
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSchemaCoordinates(schema: GraphQLSchema): {
|
||||||
|
coordinates: Set<string>;
|
||||||
|
deprecated: Set<string>;
|
||||||
|
} {
|
||||||
|
const coordinates = new Set<string>();
|
||||||
|
const deprecated = new Set<string>();
|
||||||
|
|
||||||
|
const typeMap = schema.getTypeMap();
|
||||||
|
|
||||||
|
for (const typeName in typeMap) {
|
||||||
|
const typeDefinition = typeMap[typeName];
|
||||||
|
|
||||||
|
if (isIntrospectionType(typeDefinition)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
coordinates.add(typeName);
|
||||||
|
|
||||||
|
if (isObjectType(typeDefinition) || isInterfaceType(typeDefinition)) {
|
||||||
|
visitSchemaCoordinatesOfGraphQLFieldMap(
|
||||||
|
typeName,
|
||||||
|
typeDefinition.getFields(),
|
||||||
|
coordinates,
|
||||||
|
deprecated,
|
||||||
|
);
|
||||||
|
} else if (isInputObjectType(typeDefinition)) {
|
||||||
|
const fieldMap = typeDefinition.getFields();
|
||||||
|
for (const fieldName in fieldMap) {
|
||||||
|
const fieldDefinition = fieldMap[fieldName];
|
||||||
|
|
||||||
|
coordinates.add(`${typeName}.${fieldName}`);
|
||||||
|
if (fieldDefinition.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${fieldName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isUnionType(typeDefinition)) {
|
||||||
|
for (const member of typeDefinition.getTypes()) {
|
||||||
|
coordinates.add(`${typeName}.${member.name}`);
|
||||||
|
}
|
||||||
|
} else if (isEnumType(typeDefinition)) {
|
||||||
|
const values = typeDefinition.getValues();
|
||||||
|
for (const value of values) {
|
||||||
|
coordinates.add(`${typeName}.${value.name}`);
|
||||||
|
if (value.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${value.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isScalarType(typeDefinition)) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported type kind ${typeName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
coordinates,
|
||||||
|
deprecated,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visitSchemaCoordinatesOfGraphQLFieldMap(
|
||||||
|
typeName: string,
|
||||||
|
fieldMap: GraphQLFieldMap<any, any>,
|
||||||
|
coordinates: Set<string>,
|
||||||
|
deprecated: Set<string>,
|
||||||
|
) {
|
||||||
|
for (const fieldName in fieldMap) {
|
||||||
|
const fieldDefinition = fieldMap[fieldName];
|
||||||
|
|
||||||
|
coordinates.add(`${typeName}.${fieldName}`);
|
||||||
|
if (fieldDefinition.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${fieldName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const arg of fieldDefinition.args) {
|
||||||
|
coordinates.add(`${typeName}.${fieldName}.${arg.name}`);
|
||||||
|
if (arg.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${fieldName}.${arg.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function insertRemainingCoordinates(
|
||||||
|
connection: CommonQueryMethods,
|
||||||
|
targetId: string,
|
||||||
|
targetCoordinates: {
|
||||||
|
coordinates: Set<string>;
|
||||||
|
deprecated: Set<string>;
|
||||||
|
},
|
||||||
|
versionId: string,
|
||||||
|
createdAt: number,
|
||||||
|
) {
|
||||||
|
if (targetCoordinates.coordinates.size === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pgDate = new Date(createdAt).toISOString();
|
||||||
|
|
||||||
|
// Deprecated only the coordinates that are still in the queue
|
||||||
|
const remainingDeprecated = targetCoordinates.deprecated.intersection(
|
||||||
|
targetCoordinates.coordinates,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Adding remaining ${targetCoordinates.coordinates.size} coordinates for target ${targetId}`,
|
||||||
|
);
|
||||||
|
await connection.query(sql`
|
||||||
|
INSERT INTO schema_coordinate_status
|
||||||
|
( target_id, coordinate, created_at, created_in_version_id )
|
||||||
|
SELECT * FROM ${sql.unnest(
|
||||||
|
Array.from(targetCoordinates.coordinates).map(coordinate => [
|
||||||
|
targetId,
|
||||||
|
coordinate,
|
||||||
|
pgDate,
|
||||||
|
versionId,
|
||||||
|
]),
|
||||||
|
['uuid', 'text', 'date', 'uuid'],
|
||||||
|
)}
|
||||||
|
ON CONFLICT (target_id, coordinate)
|
||||||
|
DO UPDATE SET created_at = ${pgDate}, created_in_version_id = ${versionId}
|
||||||
|
`);
|
||||||
|
|
||||||
|
if (remainingDeprecated.size) {
|
||||||
|
console.log(
|
||||||
|
`Deprecating remaining ${remainingDeprecated.size} coordinates for target ${targetId}`,
|
||||||
|
);
|
||||||
|
await connection.query(sql`
|
||||||
|
INSERT INTO schema_coordinate_status
|
||||||
|
( target_id, coordinate, created_at, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
||||||
|
SELECT * FROM ${sql.unnest(
|
||||||
|
Array.from(remainingDeprecated).map(coordinate => [
|
||||||
|
targetId,
|
||||||
|
coordinate,
|
||||||
|
pgDate,
|
||||||
|
versionId,
|
||||||
|
pgDate,
|
||||||
|
versionId,
|
||||||
|
]),
|
||||||
|
['uuid', 'text', 'date', 'uuid', 'date', 'uuid'],
|
||||||
|
)}
|
||||||
|
ON CONFLICT (target_id, coordinate)
|
||||||
|
DO UPDATE SET deprecated_at = ${pgDate}, deprecated_in_version_id = ${versionId}
|
||||||
|
`);
|
||||||
|
// there will be a conflict, because we are going from deprecated to added order.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processVersion(
|
||||||
|
depth: number,
|
||||||
|
connection: CommonQueryMethods,
|
||||||
|
targetCoordinates: {
|
||||||
|
coordinates: Set<string>;
|
||||||
|
deprecated: Set<string>;
|
||||||
|
},
|
||||||
|
targetId: string,
|
||||||
|
after: {
|
||||||
|
schema: GraphQLSchema;
|
||||||
|
versionId: string;
|
||||||
|
createdAt: number;
|
||||||
|
previousVersionId: string | null;
|
||||||
|
},
|
||||||
|
): Promise<void> {
|
||||||
|
console.log(`Processing target %s at depth %s - version`, targetId, depth, after.versionId);
|
||||||
|
const previousVersionId = after.previousVersionId;
|
||||||
|
if (!previousVersionId) {
|
||||||
|
// Seems like there is no previous version.
|
||||||
|
console.log(
|
||||||
|
`[END] No previous version found. Inserting all remaining coordinates for ${targetId}`,
|
||||||
|
);
|
||||||
|
await insertRemainingCoordinates(
|
||||||
|
connection,
|
||||||
|
targetId,
|
||||||
|
targetCoordinates,
|
||||||
|
after.versionId,
|
||||||
|
after.createdAt,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionBefore = await connection.maybeOne<{
|
||||||
|
id: string;
|
||||||
|
sdl?: string;
|
||||||
|
previous_schema_version_id?: string;
|
||||||
|
created_at: number;
|
||||||
|
is_composable: boolean;
|
||||||
|
}>(sql`
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
composite_schema_sdl as sdl,
|
||||||
|
previous_schema_version_id,
|
||||||
|
created_at,
|
||||||
|
is_composable
|
||||||
|
FROM schema_versions
|
||||||
|
WHERE id = ${previousVersionId} AND target_id = ${targetId}
|
||||||
|
`);
|
||||||
|
|
||||||
|
if (!versionBefore) {
|
||||||
|
console.error(
|
||||||
|
`[ERROR] No schema found for version ${previousVersionId}. Inserting all remaining coordinates for ${targetId}`,
|
||||||
|
);
|
||||||
|
await insertRemainingCoordinates(
|
||||||
|
connection,
|
||||||
|
targetId,
|
||||||
|
targetCoordinates,
|
||||||
|
after.versionId,
|
||||||
|
after.createdAt,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!versionBefore.is_composable) {
|
||||||
|
// Skip non-composable schemas and continue with the previous version.
|
||||||
|
return processVersion(depth + 1, connection, targetCoordinates, targetId, {
|
||||||
|
schema: after.schema,
|
||||||
|
versionId: after.versionId,
|
||||||
|
createdAt: after.createdAt,
|
||||||
|
previousVersionId: versionBefore.previous_schema_version_id ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!versionBefore.sdl) {
|
||||||
|
console.error(
|
||||||
|
`[ERROR] No SDL found for version ${previousVersionId}. Inserting all remaining coordinates for ${targetId}`,
|
||||||
|
);
|
||||||
|
await insertRemainingCoordinates(
|
||||||
|
connection,
|
||||||
|
targetId,
|
||||||
|
targetCoordinates,
|
||||||
|
after.versionId,
|
||||||
|
after.createdAt,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const before: {
|
||||||
|
schema: GraphQLSchema;
|
||||||
|
versionId: string;
|
||||||
|
createdAt: number;
|
||||||
|
previousVersionId: string | null;
|
||||||
|
} = {
|
||||||
|
schema: buildSchema(versionBefore.sdl, {
|
||||||
|
assumeValid: true,
|
||||||
|
assumeValidSDL: true,
|
||||||
|
}),
|
||||||
|
versionId: versionBefore.id,
|
||||||
|
createdAt: versionBefore.created_at,
|
||||||
|
previousVersionId: versionBefore.previous_schema_version_id ?? null,
|
||||||
|
};
|
||||||
|
const diff = diffSchemaCoordinates(before.schema, after.schema);
|
||||||
|
|
||||||
|
// We don't have to track undeprecated or deleted coordinates
|
||||||
|
// as we only want to represent the current state of the schema.
|
||||||
|
const added: string[] = [];
|
||||||
|
const deprecated: string[] = [];
|
||||||
|
const deleteAdded = new Set<string>();
|
||||||
|
const deleteDeprecated = new Set<string>();
|
||||||
|
|
||||||
|
for (const coordinate of diff.added) {
|
||||||
|
if (targetCoordinates.coordinates.has(coordinate)) {
|
||||||
|
added.push(coordinate);
|
||||||
|
// We found a schema version that added a coordinate, so we don't have to look further
|
||||||
|
deleteAdded.add(coordinate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const coordinate of diff.deprecated) {
|
||||||
|
if (targetCoordinates.deprecated.has(coordinate)) {
|
||||||
|
deprecated.push(coordinate);
|
||||||
|
deleteDeprecated.add(coordinate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const datePG = new Date(after.createdAt).toISOString();
|
||||||
|
|
||||||
|
if (added.length) {
|
||||||
|
console.log(`Adding ${added.length} coordinates for target ${targetId}`);
|
||||||
|
await connection.query(sql`
|
||||||
|
INSERT INTO schema_coordinate_status
|
||||||
|
( target_id, coordinate, created_at, created_in_version_id )
|
||||||
|
SELECT * FROM ${sql.unnest(
|
||||||
|
added.map(coordinate => [targetId, coordinate, datePG, after.versionId]),
|
||||||
|
['uuid', 'text', 'date', 'uuid'],
|
||||||
|
)}
|
||||||
|
ON CONFLICT (target_id, coordinate)
|
||||||
|
DO UPDATE SET created_at = ${datePG}, created_in_version_id = ${after.versionId}
|
||||||
|
`);
|
||||||
|
// there will be a conflict, because we are going from deprecated to added order.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecated.length) {
|
||||||
|
console.log(`deprecating ${deprecated.length} coordinates for target ${targetId}`);
|
||||||
|
|
||||||
|
await connection.query(sql`
|
||||||
|
INSERT INTO schema_coordinate_status
|
||||||
|
( target_id, coordinate, created_at, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
||||||
|
SELECT * FROM ${sql.unnest(
|
||||||
|
deprecated.map(coordinate => [
|
||||||
|
targetId,
|
||||||
|
coordinate,
|
||||||
|
datePG,
|
||||||
|
after.versionId,
|
||||||
|
datePG,
|
||||||
|
after.versionId,
|
||||||
|
]),
|
||||||
|
['uuid', 'text', 'date', 'uuid', 'date', 'uuid'],
|
||||||
|
)}
|
||||||
|
ON CONFLICT (target_id, coordinate)
|
||||||
|
DO UPDATE SET deprecated_at = ${datePG}, deprecated_in_version_id = ${after.versionId}
|
||||||
|
`);
|
||||||
|
// there will be a conflict, because we are going from deprecated to added order.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove coordinates that were added in this diff.
|
||||||
|
// We don't need to look for them in previous versions.
|
||||||
|
for (const coordinate of deleteAdded) {
|
||||||
|
targetCoordinates.coordinates.delete(coordinate);
|
||||||
|
}
|
||||||
|
// Remove coordinates that were deprecated in this diff.
|
||||||
|
// To avoid marking them as deprecated later on.
|
||||||
|
for (const coordinate of deleteDeprecated) {
|
||||||
|
targetCoordinates.deprecated.delete(coordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleteAdded.size) {
|
||||||
|
console.log(`Deleted ${deleteAdded.size} coordinates from the stack`);
|
||||||
|
console.log(`Coordinates in queue: ${targetCoordinates.coordinates.size}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return processVersion(depth + 1, connection, targetCoordinates, targetId, before);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
import { createPool } from 'slonik';
|
import { createPool } from 'slonik';
|
||||||
|
import { schemaCoordinateStatusMigration } from './actions/2024.07.23T09.36.00.schema-cleanup-tracker';
|
||||||
import { migrateClickHouse } from './clickhouse';
|
import { migrateClickHouse } from './clickhouse';
|
||||||
import { createConnectionString } from './connection-string';
|
import { createConnectionString } from './connection-string';
|
||||||
import { env } from './environment';
|
import { env } from './environment';
|
||||||
|
|
@ -13,9 +14,21 @@ const slonik = await createPool(createConnectionString(env.postgres), {
|
||||||
// This is used by production build of this package.
|
// This is used by production build of this package.
|
||||||
// We are building a "cli" out of the package, so we need a workaround to pass the command to run.
|
// We are building a "cli" out of the package, so we need a workaround to pass the command to run.
|
||||||
|
|
||||||
console.log('Running the UP migrations');
|
// This is only used for GraphQL Hive Cloud to perform a long running migration.
|
||||||
|
// eslint-disable-next-line no-process-env
|
||||||
|
if (process.env.SCHEMA_COORDINATE_STATUS_MIGRATION === '1') {
|
||||||
|
try {
|
||||||
|
console.log('Running the SCHEMA_COORDINATE_STATUS_MIGRATION');
|
||||||
|
await schemaCoordinateStatusMigration(slonik);
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log('Running the UP migrations');
|
||||||
await runPGMigrations({ slonik });
|
await runPGMigrations({ slonik });
|
||||||
if (env.clickhouse) {
|
if (env.clickhouse) {
|
||||||
await migrateClickHouse(env.isClickHouseMigrator, env.isHiveCloud, env.clickhouse);
|
await migrateClickHouse(env.isClickHouseMigrator, env.isHiveCloud, env.clickhouse);
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ import migration_2024_04_09T10_10_00_check_approval_comment from './actions/2024
|
||||||
import migration_2024_06_11T10_10_00_ms_teams_webhook from './actions/2024.06.11T10-10-00.ms-teams-webhook';
|
import migration_2024_06_11T10_10_00_ms_teams_webhook from './actions/2024.06.11T10-10-00.ms-teams-webhook';
|
||||||
import migration_2024_07_16T13_44_00_oidc_only_access from './actions/2024.07.16T13-44-00.oidc-only-access';
|
import migration_2024_07_16T13_44_00_oidc_only_access from './actions/2024.07.16T13-44-00.oidc-only-access';
|
||||||
import migration_2024_07_17T00_00_00_app_deployments from './actions/2024.07.17T00-00-00.app-deployments';
|
import migration_2024_07_17T00_00_00_app_deployments from './actions/2024.07.17T00-00-00.app-deployments';
|
||||||
|
import migration_2024_07_23T_09_36_00_schema_cleanup_tracker from './actions/2024.07.23T09.36.00.schema-cleanup-tracker';
|
||||||
import { runMigrations } from './pg-migrator';
|
import { runMigrations } from './pg-migrator';
|
||||||
|
|
||||||
export const runPGMigrations = (args: { slonik: DatabasePool; runTo?: string }) =>
|
export const runPGMigrations = (args: { slonik: DatabasePool; runTo?: string }) =>
|
||||||
|
|
@ -140,5 +141,6 @@ export const runPGMigrations = (args: { slonik: DatabasePool; runTo?: string })
|
||||||
migration_2024_06_11T10_10_00_ms_teams_webhook,
|
migration_2024_06_11T10_10_00_ms_teams_webhook,
|
||||||
migration_2024_07_16T13_44_00_oidc_only_access,
|
migration_2024_07_16T13_44_00_oidc_only_access,
|
||||||
migration_2024_07_17T00_00_00_app_deployments,
|
migration_2024_07_17T00_00_00_app_deployments,
|
||||||
|
migration_2024_07_23T_09_36_00_schema_cleanup_tracker,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
import assert from 'node:assert';
|
||||||
|
import { describe, test } from 'node:test';
|
||||||
|
import { sql } from 'slonik';
|
||||||
|
import { createStorage } from '../../services/storage/src/index';
|
||||||
|
import { initMigrationTestingEnvironment } from './utils/testkit';
|
||||||
|
|
||||||
|
await describe('migration: schema-cleanup-tracker', async () => {
|
||||||
|
await test('schema coordinates backfill', async () => {
|
||||||
|
const { db, runTo, complete, done, seed, connectionString } =
|
||||||
|
await initMigrationTestingEnvironment();
|
||||||
|
const storage = await createStorage(connectionString, 1);
|
||||||
|
try {
|
||||||
|
// Run migrations all the way to the point before the one we are testing
|
||||||
|
await runTo('2024.07.17T00-00-00.app-deployments.ts');
|
||||||
|
|
||||||
|
// Seed the database with some data (schema_sdl, supergraph_sdl, composite_schema_sdl)
|
||||||
|
const admin = await seed.user({
|
||||||
|
user: {
|
||||||
|
name: 'test1',
|
||||||
|
email: 'test1@test.com',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const organization = await seed.organization({
|
||||||
|
organization: {
|
||||||
|
name: 'org-1',
|
||||||
|
},
|
||||||
|
user: admin,
|
||||||
|
});
|
||||||
|
|
||||||
|
const project = await seed.project({
|
||||||
|
project: {
|
||||||
|
name: 'project-1',
|
||||||
|
type: 'SINGLE',
|
||||||
|
},
|
||||||
|
organization,
|
||||||
|
});
|
||||||
|
|
||||||
|
const target = await seed.target({
|
||||||
|
target: {
|
||||||
|
name: 'target-1',
|
||||||
|
},
|
||||||
|
project,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function createVersion(
|
||||||
|
schema: string,
|
||||||
|
previousSchemaVersionId: string | null,
|
||||||
|
): Promise<string> {
|
||||||
|
const logId = await db.oneFirst<string>(sql`
|
||||||
|
INSERT INTO schema_log
|
||||||
|
(
|
||||||
|
author,
|
||||||
|
service_name,
|
||||||
|
service_url,
|
||||||
|
commit,
|
||||||
|
sdl,
|
||||||
|
project_id,
|
||||||
|
target_id,
|
||||||
|
metadata,
|
||||||
|
action
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
${'Kamil'},
|
||||||
|
${null},
|
||||||
|
${null},
|
||||||
|
${'random'},
|
||||||
|
${schema},
|
||||||
|
${project.id},
|
||||||
|
${target.id},
|
||||||
|
${null},
|
||||||
|
'PUSH'
|
||||||
|
)
|
||||||
|
RETURNING id
|
||||||
|
`);
|
||||||
|
|
||||||
|
const versionId = await db.oneFirst<string>(sql`
|
||||||
|
INSERT INTO schema_versions
|
||||||
|
(
|
||||||
|
record_version,
|
||||||
|
is_composable,
|
||||||
|
target_id,
|
||||||
|
action_id,
|
||||||
|
base_schema,
|
||||||
|
has_persisted_schema_changes,
|
||||||
|
previous_schema_version_id,
|
||||||
|
diff_schema_version_id,
|
||||||
|
composite_schema_sdl,
|
||||||
|
supergraph_sdl,
|
||||||
|
schema_composition_errors,
|
||||||
|
github_repository,
|
||||||
|
github_sha,
|
||||||
|
tags,
|
||||||
|
has_contract_composition_errors,
|
||||||
|
conditional_breaking_change_metadata
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
(
|
||||||
|
'2024-01-10',
|
||||||
|
${true},
|
||||||
|
${target.id},
|
||||||
|
${logId},
|
||||||
|
${null},
|
||||||
|
${true},
|
||||||
|
${previousSchemaVersionId},
|
||||||
|
${previousSchemaVersionId},
|
||||||
|
${schema},
|
||||||
|
${null},
|
||||||
|
${null},
|
||||||
|
${null},
|
||||||
|
${null},
|
||||||
|
${null},
|
||||||
|
${false},
|
||||||
|
${null}
|
||||||
|
)
|
||||||
|
RETURNING id
|
||||||
|
`);
|
||||||
|
|
||||||
|
return versionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const schemas = [
|
||||||
|
// [0]
|
||||||
|
// first
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
// [1]
|
||||||
|
// second
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
// [2]
|
||||||
|
// third
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
// [3]
|
||||||
|
// fourth
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
// [4]
|
||||||
|
// fifth
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String @deprecated(reason: "no longer needed")
|
||||||
|
bye: String
|
||||||
|
goodbye: String
|
||||||
|
hi: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
// [5]
|
||||||
|
// sixth
|
||||||
|
/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
bye: String
|
||||||
|
hi: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
|
||||||
|
// insert schema versions
|
||||||
|
let previousSchemaVersionId: string | null = null;
|
||||||
|
for await (const schema of schemas) {
|
||||||
|
const versionId = await createVersion(schema, previousSchemaVersionId);
|
||||||
|
previousSchemaVersionId = versionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the remaining migrations
|
||||||
|
await complete();
|
||||||
|
|
||||||
|
// check that coordinates are correct
|
||||||
|
|
||||||
|
const versions = await db.manyFirst<string>(sql`
|
||||||
|
SELECT id FROM schema_versions WHERE target_id = ${target.id} ORDER BY created_at ASC
|
||||||
|
`);
|
||||||
|
|
||||||
|
const coordinates = await db.many<{
|
||||||
|
coordinate: string;
|
||||||
|
created_in_version_id: string;
|
||||||
|
deprecated_in_version_id: string | null;
|
||||||
|
}>(sql`
|
||||||
|
SELECT * FROM schema_coordinate_status WHERE target_id = ${target.id}
|
||||||
|
`);
|
||||||
|
|
||||||
|
assert.strictEqual(versions.length, 6);
|
||||||
|
|
||||||
|
const queryType = coordinates.find(c => c.coordinate === 'Query');
|
||||||
|
const helloField = coordinates.find(c => c.coordinate === 'Query.hello');
|
||||||
|
const hiField = coordinates.find(c => c.coordinate === 'Query.hi');
|
||||||
|
const byeField = coordinates.find(c => c.coordinate === 'Query.bye');
|
||||||
|
const goodbyeField = coordinates.find(c => c.coordinate === 'Query.goodbye');
|
||||||
|
|
||||||
|
assert.ok(queryType, 'Query type not found');
|
||||||
|
assert.ok(helloField, 'Query.hello field not found');
|
||||||
|
assert.ok(hiField, 'Query.hi field not found');
|
||||||
|
assert.ok(byeField, 'Query.bye field not found');
|
||||||
|
|
||||||
|
// Query
|
||||||
|
// was create in the first version
|
||||||
|
// never deprecated
|
||||||
|
assert.strictEqual(queryType.created_in_version_id, versions[0]);
|
||||||
|
assert.strictEqual(queryType.deprecated_in_version_id, null);
|
||||||
|
|
||||||
|
// Query.hello
|
||||||
|
// was created in the first version,
|
||||||
|
// deprecated in fifth
|
||||||
|
// undeprecated in the sixth
|
||||||
|
assert.strictEqual(helloField.created_in_version_id, versions[0]);
|
||||||
|
assert.strictEqual(helloField.deprecated_in_version_id, null);
|
||||||
|
|
||||||
|
// Query.hi
|
||||||
|
// was created in the second version
|
||||||
|
// removed in the third
|
||||||
|
// added back in the fourth
|
||||||
|
// deprecated in the fifth
|
||||||
|
assert.strictEqual(hiField.created_in_version_id, versions[3]);
|
||||||
|
assert.strictEqual(hiField.deprecated_in_version_id, versions[4]);
|
||||||
|
|
||||||
|
// Query.bye
|
||||||
|
// was created in the fifth version
|
||||||
|
assert.strictEqual(byeField.created_in_version_id, versions[4]);
|
||||||
|
|
||||||
|
// Query.goodbye
|
||||||
|
// was created in the fifth version
|
||||||
|
// removed in the sixth
|
||||||
|
assert.ok(!goodbyeField, 'Query.goodbye field should not be found');
|
||||||
|
} finally {
|
||||||
|
await done();
|
||||||
|
await storage.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -2,3 +2,4 @@ import './2023.02.22T09.27.02.delete-personal-org.test';
|
||||||
import './2023.09.25T15.23.00.github-check-with-project-name.test';
|
import './2023.09.25T15.23.00.github-check-with-project-name.test';
|
||||||
import './2023.11.20T10-00-00.organization-member-roles.test';
|
import './2023.11.20T10-00-00.organization-member-roles.test';
|
||||||
import './2024.01.26T00.00.01.schema-check-purging.test';
|
import './2024.01.26T00.00.01.schema-check-purging.test';
|
||||||
|
import './2024.07.23T09.36.00.schema-cleanup-tracker.test';
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
"slonik": "30.4.4",
|
"slonik": "30.4.4",
|
||||||
"supertokens-node": "15.2.1",
|
"supertokens-node": "15.2.1",
|
||||||
"tslib": "2.6.3",
|
"tslib": "2.6.3",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.3",
|
||||||
"zod": "3.23.8",
|
"zod": "3.23.8",
|
||||||
"zod-validation-error": "3.3.0"
|
"zod-validation-error": "3.3.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,371 @@
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import { buildSchema } from 'graphql';
|
||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
import { diffSchemaCoordinates } from './inspector';
|
||||||
|
|
||||||
|
describe('diffSchemaCoordinates', () => {
|
||||||
|
test('should return empty arrays when schemas are equal', () => {
|
||||||
|
const schema = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(schema, schema);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {},
|
||||||
|
deleted: Set {},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('field becomes deprecated', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
goodbye: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String @deprecated
|
||||||
|
goodbye: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {},
|
||||||
|
deleted: Set {},
|
||||||
|
deprecated: Set {
|
||||||
|
Query.hello,
|
||||||
|
},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('added field is deprecated', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String @deprecated
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {
|
||||||
|
Query.hi,
|
||||||
|
},
|
||||||
|
deleted: Set {},
|
||||||
|
deprecated: Set {
|
||||||
|
Query.hi,
|
||||||
|
},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('field is deleted', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
goodbye: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hi: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {
|
||||||
|
Query.hi,
|
||||||
|
},
|
||||||
|
deleted: Set {
|
||||||
|
Query.goodbye,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('deprecated field is deleted', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
goodbye: String @deprecated
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {},
|
||||||
|
deleted: Set {
|
||||||
|
Query.goodbye,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('deprecated field is undeprecated', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String @deprecated
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
hi: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {},
|
||||||
|
deleted: Set {},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {
|
||||||
|
Query.hi,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('deprecated field is undeprecated, undeprecated field is deprecated', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String @deprecated(reason: "no longer needed")
|
||||||
|
bye: String
|
||||||
|
goodbye: String
|
||||||
|
hi: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
bye: String
|
||||||
|
hi: String @deprecated(reason: "no longer needed")
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {},
|
||||||
|
deleted: Set {
|
||||||
|
Query.goodbye,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {
|
||||||
|
Query.hello,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('removed a deprecated field', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
goodbye: String @deprecated
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {},
|
||||||
|
deleted: Set {
|
||||||
|
Query.goodbye,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('added and removed an argument on deprecated and non-deprecated fields', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello(lang: String): String
|
||||||
|
hi: String @deprecated
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String @deprecated
|
||||||
|
hi(lang: String): String
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {
|
||||||
|
Query.hi.lang,
|
||||||
|
},
|
||||||
|
deleted: Set {
|
||||||
|
Query.hello.lang,
|
||||||
|
},
|
||||||
|
deprecated: Set {
|
||||||
|
Query.hello,
|
||||||
|
},
|
||||||
|
undeprecated: Set {
|
||||||
|
Query.hi,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('added removed enum members', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
enum Role {
|
||||||
|
ADMIN
|
||||||
|
USER
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
enum Role {
|
||||||
|
ANONYMOUS
|
||||||
|
USER
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {
|
||||||
|
Role.ANONYMOUS,
|
||||||
|
},
|
||||||
|
deleted: Set {
|
||||||
|
Role.ADMIN,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('added removed union members', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
union Account = Admin | User
|
||||||
|
type Admin {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
type User {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
union Account = Anonymous | User
|
||||||
|
type Anonymous {
|
||||||
|
ip: String
|
||||||
|
}
|
||||||
|
type User {
|
||||||
|
id: ID
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {
|
||||||
|
Account.Anonymous,
|
||||||
|
Anonymous,
|
||||||
|
Anonymous.ip,
|
||||||
|
},
|
||||||
|
deleted: Set {
|
||||||
|
Account.Admin,
|
||||||
|
Admin,
|
||||||
|
Admin.id,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('added removed scalars', () => {
|
||||||
|
const before = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
scalar GOODBYE
|
||||||
|
`);
|
||||||
|
const after = buildSchema(/* GraphQL */ `
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
scalar HELLO
|
||||||
|
`);
|
||||||
|
|
||||||
|
const result = diffSchemaCoordinates(before, after);
|
||||||
|
|
||||||
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
added: Set {
|
||||||
|
HELLO,
|
||||||
|
},
|
||||||
|
deleted: Set {
|
||||||
|
GOODBYE,
|
||||||
|
},
|
||||||
|
deprecated: Set {},
|
||||||
|
undeprecated: Set {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,8 +1,18 @@
|
||||||
import { type GraphQLSchema } from 'graphql';
|
import {
|
||||||
|
GraphQLFieldMap,
|
||||||
|
isEnumType,
|
||||||
|
isInputObjectType,
|
||||||
|
isInterfaceType,
|
||||||
|
isIntrospectionType,
|
||||||
|
isObjectType,
|
||||||
|
isScalarType,
|
||||||
|
isUnionType,
|
||||||
|
type GraphQLSchema,
|
||||||
|
} from 'graphql';
|
||||||
import { Injectable, Scope } from 'graphql-modules';
|
import { Injectable, Scope } from 'graphql-modules';
|
||||||
import { Change, ChangeType, diff } from '@graphql-inspector/core';
|
import { Change, ChangeType, diff } from '@graphql-inspector/core';
|
||||||
import { traceFn } from '@hive/service-common';
|
import { traceFn } from '@hive/service-common';
|
||||||
import { HiveSchemaChangeModel, SchemaChangeType } from '@hive/storage';
|
import { HiveSchemaChangeModel } from '@hive/storage';
|
||||||
import { Logger } from '../../shared/providers/logger';
|
import { Logger } from '../../shared/providers/logger';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
|
@ -21,7 +31,7 @@ export class Inspector {
|
||||||
'hive.diff.changes.count': result.length,
|
'hive.diff.changes.count': result.length,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
async diff(existing: GraphQLSchema, incoming: GraphQLSchema): Promise<Array<SchemaChangeType>> {
|
async diff(existing: GraphQLSchema, incoming: GraphQLSchema) {
|
||||||
this.logger.debug('Comparing Schemas');
|
this.logger.debug('Comparing Schemas');
|
||||||
|
|
||||||
const changes = await diff(existing, incoming);
|
const changes = await diff(existing, incoming);
|
||||||
|
|
@ -120,3 +130,130 @@ function matchChange<R, T extends ChangeType>(
|
||||||
return pattern[change.type]?.(change);
|
return pattern[change.type]?.(change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SchemaCoordinatesDiffResult = {
|
||||||
|
/**
|
||||||
|
* Coordinates that are in incoming but not in existing (including deprecated ones)
|
||||||
|
*/
|
||||||
|
added: Set<string>;
|
||||||
|
/**
|
||||||
|
* Coordinates that are in existing but not in incoming (including deprecated ones)
|
||||||
|
*/
|
||||||
|
deleted: Set<string>;
|
||||||
|
/**
|
||||||
|
* Coordinates that are deprecated in incoming, but were not deprecated in existing or non-existent
|
||||||
|
*/
|
||||||
|
deprecated: Set<string>;
|
||||||
|
/**
|
||||||
|
* Coordinates that exists in incoming and are not deprecated in incoming, but were deprecated in existing
|
||||||
|
*/
|
||||||
|
undeprecated: Set<string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function diffSchemaCoordinates(
|
||||||
|
existingSchema: GraphQLSchema | null,
|
||||||
|
incomingSchema: GraphQLSchema,
|
||||||
|
): SchemaCoordinatesDiffResult {
|
||||||
|
const before = existingSchema
|
||||||
|
? getSchemaCoordinates(existingSchema)
|
||||||
|
: { coordinates: new Set<string>(), deprecated: new Set<string>() };
|
||||||
|
const after = getSchemaCoordinates(incomingSchema);
|
||||||
|
|
||||||
|
const added = after.coordinates.difference(before.coordinates);
|
||||||
|
const deleted = before.coordinates.difference(after.coordinates);
|
||||||
|
const deprecated = after.deprecated.difference(before.deprecated);
|
||||||
|
const undeprecated = before.deprecated
|
||||||
|
.difference(after.deprecated)
|
||||||
|
.intersection(after.coordinates);
|
||||||
|
|
||||||
|
return {
|
||||||
|
added,
|
||||||
|
deleted,
|
||||||
|
deprecated,
|
||||||
|
undeprecated,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSchemaCoordinates(schema: GraphQLSchema): {
|
||||||
|
coordinates: Set<string>;
|
||||||
|
deprecated: Set<string>;
|
||||||
|
} {
|
||||||
|
const coordinates = new Set<string>();
|
||||||
|
const deprecated = new Set<string>();
|
||||||
|
|
||||||
|
const typeMap = schema.getTypeMap();
|
||||||
|
|
||||||
|
for (const typeName in typeMap) {
|
||||||
|
const typeDefinition = typeMap[typeName];
|
||||||
|
|
||||||
|
if (isIntrospectionType(typeDefinition)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
coordinates.add(typeName);
|
||||||
|
|
||||||
|
if (isObjectType(typeDefinition) || isInterfaceType(typeDefinition)) {
|
||||||
|
visitSchemaCoordinatesOfGraphQLFieldMap(
|
||||||
|
typeName,
|
||||||
|
typeDefinition.getFields(),
|
||||||
|
coordinates,
|
||||||
|
deprecated,
|
||||||
|
);
|
||||||
|
} else if (isInputObjectType(typeDefinition)) {
|
||||||
|
const fieldMap = typeDefinition.getFields();
|
||||||
|
for (const fieldName in fieldMap) {
|
||||||
|
const fieldDefinition = fieldMap[fieldName];
|
||||||
|
|
||||||
|
coordinates.add(`${typeName}.${fieldName}`);
|
||||||
|
if (fieldDefinition.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${fieldName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isUnionType(typeDefinition)) {
|
||||||
|
coordinates.add(typeName);
|
||||||
|
for (const member of typeDefinition.getTypes()) {
|
||||||
|
coordinates.add(`${typeName}.${member.name}`);
|
||||||
|
}
|
||||||
|
} else if (isEnumType(typeDefinition)) {
|
||||||
|
const values = typeDefinition.getValues();
|
||||||
|
for (const value of values) {
|
||||||
|
coordinates.add(`${typeName}.${value.name}`);
|
||||||
|
if (value.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${value.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isScalarType(typeDefinition)) {
|
||||||
|
coordinates.add(typeName);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported type kind ${typeName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
coordinates,
|
||||||
|
deprecated,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visitSchemaCoordinatesOfGraphQLFieldMap(
|
||||||
|
typeName: string,
|
||||||
|
fieldMap: GraphQLFieldMap<any, any>,
|
||||||
|
coordinates: Set<string>,
|
||||||
|
deprecated: Set<string>,
|
||||||
|
) {
|
||||||
|
for (const fieldName in fieldMap) {
|
||||||
|
const fieldDefinition = fieldMap[fieldName];
|
||||||
|
|
||||||
|
coordinates.add(`${typeName}.${fieldName}`);
|
||||||
|
if (fieldDefinition.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${fieldName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const arg of fieldDefinition.args) {
|
||||||
|
coordinates.add(`${typeName}.${fieldName}.${arg.name}`);
|
||||||
|
if (arg.deprecationReason) {
|
||||||
|
deprecated.add(`${typeName}.${fieldName}.${arg.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,11 @@ export class CompositeLegacyModel {
|
||||||
messages,
|
messages,
|
||||||
changes,
|
changes,
|
||||||
breakingChanges: breakingChanges ?? null,
|
breakingChanges: breakingChanges ?? null,
|
||||||
|
coordinatesDiff:
|
||||||
|
diffCheck.result?.coordinatesDiff ??
|
||||||
|
diffCheck.reason?.coordinatesDiff ??
|
||||||
|
diffCheck.data?.coordinatesDiff ??
|
||||||
|
null,
|
||||||
compositionErrors,
|
compositionErrors,
|
||||||
schema: incoming,
|
schema: incoming,
|
||||||
schemas,
|
schemas,
|
||||||
|
|
@ -372,6 +377,7 @@ export class CompositeLegacyModel {
|
||||||
code: PublishFailureReasonCode.BreakingChanges,
|
code: PublishFailureReasonCode.BreakingChanges,
|
||||||
changes: diffCheck.reason.all ?? [],
|
changes: diffCheck.reason.all ?? [],
|
||||||
breakingChanges: diffCheck.reason.breaking ?? [],
|
breakingChanges: diffCheck.reason.breaking ?? [],
|
||||||
|
coordinatesDiff: diffCheck.reason?.coordinatesDiff ?? null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,11 @@ export class CompositeModel {
|
||||||
composable: compositionCheck.status === 'completed',
|
composable: compositionCheck.status === 'completed',
|
||||||
initial: latestVersion === null,
|
initial: latestVersion === null,
|
||||||
changes: diffCheck.result?.all ?? diffCheck.reason?.all ?? null,
|
changes: diffCheck.result?.all ?? diffCheck.reason?.all ?? null,
|
||||||
|
coordinatesDiff:
|
||||||
|
diffCheck.result?.coordinatesDiff ??
|
||||||
|
diffCheck.reason?.coordinatesDiff ??
|
||||||
|
diffCheck.data?.coordinatesDiff ??
|
||||||
|
null,
|
||||||
messages,
|
messages,
|
||||||
breakingChanges: null,
|
breakingChanges: null,
|
||||||
compositionErrors: compositionCheck.reason?.errors ?? null,
|
compositionErrors: compositionCheck.reason?.errors ?? null,
|
||||||
|
|
@ -688,6 +693,11 @@ export class CompositeModel {
|
||||||
...composablePartial,
|
...composablePartial,
|
||||||
changes,
|
changes,
|
||||||
breakingChanges,
|
breakingChanges,
|
||||||
|
coordinatesDiff:
|
||||||
|
diffCheck.result?.coordinatesDiff ??
|
||||||
|
diffCheck.reason?.coordinatesDiff ??
|
||||||
|
diffCheck.data?.coordinatesDiff ??
|
||||||
|
null,
|
||||||
compositionErrors: compositionCheck.reason?.errors ?? [],
|
compositionErrors: compositionCheck.reason?.errors ?? [],
|
||||||
supergraph: compositionCheck.result?.supergraph ?? null,
|
supergraph: compositionCheck.result?.supergraph ?? null,
|
||||||
tags: compositionCheck.result?.tags ?? null,
|
tags: compositionCheck.result?.tags ?? null,
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,15 @@ import { PushedCompositeSchema, SingleSchema } from 'packages/services/api/src/s
|
||||||
import type { CheckPolicyResponse } from '@hive/policy';
|
import type { CheckPolicyResponse } from '@hive/policy';
|
||||||
import { CompositionFailureError } from '@hive/schema';
|
import { CompositionFailureError } from '@hive/schema';
|
||||||
import type { SchemaChangeType, SchemaCompositionError } from '@hive/storage';
|
import type { SchemaChangeType, SchemaCompositionError } from '@hive/storage';
|
||||||
import { type Contract, type ValidContractVersion } from '../contracts';
|
import type { Contract, ValidContractVersion } from '../contracts';
|
||||||
import {
|
import type { SchemaCoordinatesDiffResult } from '../inspector';
|
||||||
|
import type {
|
||||||
ContractCompositionResult,
|
ContractCompositionResult,
|
||||||
ContractCompositionSuccess,
|
ContractCompositionSuccess,
|
||||||
|
RegistryChecks,
|
||||||
SchemaDiffResult,
|
SchemaDiffResult,
|
||||||
SchemaDiffSkip,
|
SchemaDiffSkip,
|
||||||
SchemaDiffSuccess,
|
SchemaDiffSuccess,
|
||||||
type RegistryChecks,
|
|
||||||
} from '../registry-checks';
|
} from '../registry-checks';
|
||||||
|
|
||||||
export const SchemaPublishConclusion = {
|
export const SchemaPublishConclusion = {
|
||||||
|
|
@ -207,6 +208,7 @@ export type SchemaPublishFailureReason =
|
||||||
code: (typeof PublishFailureReasonCode)['BreakingChanges'];
|
code: (typeof PublishFailureReasonCode)['BreakingChanges'];
|
||||||
breakingChanges: Array<SchemaChangeType>;
|
breakingChanges: Array<SchemaChangeType>;
|
||||||
changes: Array<SchemaChangeType>;
|
changes: Array<SchemaChangeType>;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ContractResult = {
|
type ContractResult = {
|
||||||
|
|
@ -223,6 +225,7 @@ type SchemaPublishSuccess = {
|
||||||
state: {
|
state: {
|
||||||
composable: boolean;
|
composable: boolean;
|
||||||
initial: boolean;
|
initial: boolean;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
changes: Array<SchemaChangeType> | null;
|
changes: Array<SchemaChangeType> | null;
|
||||||
messages: string[] | null;
|
messages: string[] | null;
|
||||||
breakingChanges: Array<{
|
breakingChanges: Array<{
|
||||||
|
|
@ -277,6 +280,7 @@ export type SchemaDeleteSuccess = {
|
||||||
schemas: PushedCompositeSchema[];
|
schemas: PushedCompositeSchema[];
|
||||||
breakingChanges: Array<SchemaChangeType> | null;
|
breakingChanges: Array<SchemaChangeType> | null;
|
||||||
compositionErrors: Array<SchemaCompositionError> | null;
|
compositionErrors: Array<SchemaCompositionError> | null;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
supergraph: string | null;
|
supergraph: string | null;
|
||||||
tags: null | Array<string>;
|
tags: null | Array<string>;
|
||||||
contracts: null | Array<ContractResult>;
|
contracts: null | Array<ContractResult>;
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,11 @@ export class SingleLegacyModel {
|
||||||
messages,
|
messages,
|
||||||
changes,
|
changes,
|
||||||
breakingChanges: breakingChanges ?? null,
|
breakingChanges: breakingChanges ?? null,
|
||||||
|
coordinatesDiff:
|
||||||
|
diffCheck.result?.coordinatesDiff ??
|
||||||
|
diffCheck.reason?.coordinatesDiff ??
|
||||||
|
diffCheck.data?.coordinatesDiff ??
|
||||||
|
null,
|
||||||
compositionErrors,
|
compositionErrors,
|
||||||
schema: incoming,
|
schema: incoming,
|
||||||
schemas,
|
schemas,
|
||||||
|
|
@ -304,6 +309,7 @@ export class SingleLegacyModel {
|
||||||
code: PublishFailureReasonCode.BreakingChanges,
|
code: PublishFailureReasonCode.BreakingChanges,
|
||||||
changes: diffCheck.reason.all ?? [],
|
changes: diffCheck.reason.all ?? [],
|
||||||
breakingChanges: diffCheck.reason.breaking ?? [],
|
breakingChanges: diffCheck.reason.breaking ?? [],
|
||||||
|
coordinatesDiff: diffCheck.reason?.coordinatesDiff ?? null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,11 @@ export class SingleModel {
|
||||||
changes: diffCheck.result?.all ?? diffCheck.reason?.all ?? null,
|
changes: diffCheck.result?.all ?? diffCheck.reason?.all ?? null,
|
||||||
messages,
|
messages,
|
||||||
breakingChanges: null,
|
breakingChanges: null,
|
||||||
|
coordinatesDiff:
|
||||||
|
diffCheck.result?.coordinatesDiff ??
|
||||||
|
diffCheck.reason?.coordinatesDiff ??
|
||||||
|
diffCheck.data?.coordinatesDiff ??
|
||||||
|
null,
|
||||||
compositionErrors: compositionCheck.reason?.errors ?? null,
|
compositionErrors: compositionCheck.reason?.errors ?? null,
|
||||||
schema: incoming,
|
schema: incoming,
|
||||||
schemas,
|
schemas,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import type {
|
||||||
SingleSchema,
|
SingleSchema,
|
||||||
} from './../../../shared/entities';
|
} from './../../../shared/entities';
|
||||||
import { Logger } from './../../shared/providers/logger';
|
import { Logger } from './../../shared/providers/logger';
|
||||||
import { Inspector } from './inspector';
|
import { diffSchemaCoordinates, Inspector, SchemaCoordinatesDiffResult } from './inspector';
|
||||||
import { SchemaCheckWarning } from './models/shared';
|
import { SchemaCheckWarning } from './models/shared';
|
||||||
import { extendWithBase, isCompositeSchema, SchemaHelper } from './schema-helper';
|
import { extendWithBase, isCompositeSchema, SchemaHelper } from './schema-helper';
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ export type ConditionalBreakingChangeDiffConfig = {
|
||||||
|
|
||||||
// The reason why I'm using `result` and `reason` instead of just `data` for both:
|
// The reason why I'm using `result` and `reason` instead of just `data` for both:
|
||||||
// https://bit.ly/hive-check-result-data
|
// https://bit.ly/hive-check-result-data
|
||||||
export type CheckResult<C = unknown, F = unknown> =
|
export type CheckResult<C = unknown, F = unknown, S = unknown> =
|
||||||
| {
|
| {
|
||||||
status: 'completed';
|
status: 'completed';
|
||||||
result: C;
|
result: C;
|
||||||
|
|
@ -48,6 +48,7 @@ export type CheckResult<C = unknown, F = unknown> =
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
status: 'skipped';
|
status: 'skipped';
|
||||||
|
data?: S;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Schemas = [SingleSchema] | PushedCompositeSchema[];
|
type Schemas = [SingleSchema] | PushedCompositeSchema[];
|
||||||
|
|
@ -134,6 +135,7 @@ type SchemaDiffFailure = {
|
||||||
breaking: Array<SchemaChangeType> | null;
|
breaking: Array<SchemaChangeType> | null;
|
||||||
safe: Array<SchemaChangeType> | null;
|
safe: Array<SchemaChangeType> | null;
|
||||||
all: Array<SchemaChangeType> | null;
|
all: Array<SchemaChangeType> | null;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
};
|
};
|
||||||
result?: never;
|
result?: never;
|
||||||
};
|
};
|
||||||
|
|
@ -144,6 +146,7 @@ export type SchemaDiffSuccess = {
|
||||||
breaking: Array<SchemaChangeType> | null;
|
breaking: Array<SchemaChangeType> | null;
|
||||||
safe: Array<SchemaChangeType> | null;
|
safe: Array<SchemaChangeType> | null;
|
||||||
all: Array<SchemaChangeType> | null;
|
all: Array<SchemaChangeType> | null;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
};
|
};
|
||||||
reason?: never;
|
reason?: never;
|
||||||
};
|
};
|
||||||
|
|
@ -412,32 +415,39 @@ export class RegistryChecks {
|
||||||
/** Settings for fetching conditional breaking changes. */
|
/** Settings for fetching conditional breaking changes. */
|
||||||
conditionalBreakingChangeConfig: null | ConditionalBreakingChangeDiffConfig;
|
conditionalBreakingChangeConfig: null | ConditionalBreakingChangeDiffConfig;
|
||||||
}) {
|
}) {
|
||||||
if (args.existingSdl == null || args.incomingSdl == null) {
|
let existingSchema: GraphQLSchema | null = null;
|
||||||
this.logger.debug('Skip diff check due to either existing or incoming SDL being absent.');
|
let incomingSchema: GraphQLSchema | null = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
existingSchema = args.existingSdl
|
||||||
|
? buildSortedSchemaFromSchemaObject(
|
||||||
|
this.helper.createSchemaObject({
|
||||||
|
sdl: args.existingSdl,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
incomingSchema = args.incomingSdl
|
||||||
|
? buildSortedSchemaFromSchemaObject(
|
||||||
|
this.helper.createSchemaObject({
|
||||||
|
sdl: args.incomingSdl,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('Failed to build schema for diff. Skip diff check.');
|
||||||
return {
|
return {
|
||||||
status: 'skipped',
|
status: 'skipped',
|
||||||
} satisfies CheckResult;
|
} satisfies CheckResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
let existingSchema: GraphQLSchema;
|
if (existingSchema === null || incomingSchema === null) {
|
||||||
let incomingSchema: GraphQLSchema;
|
this.logger.debug('Skip diff check due to either existing or incoming SDL being absent.');
|
||||||
|
|
||||||
try {
|
|
||||||
existingSchema = buildSortedSchemaFromSchemaObject(
|
|
||||||
this.helper.createSchemaObject({
|
|
||||||
sdl: args.existingSdl,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
incomingSchema = buildSortedSchemaFromSchemaObject(
|
|
||||||
this.helper.createSchemaObject({
|
|
||||||
sdl: args.incomingSdl,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Failed to build schema for diff. Skip diff check.');
|
|
||||||
return {
|
return {
|
||||||
status: 'skipped',
|
status: 'skipped',
|
||||||
|
data: {
|
||||||
|
coordinatesDiff: incomingSchema ? diffSchemaCoordinates(null, incomingSchema) : null,
|
||||||
|
},
|
||||||
} satisfies CheckResult;
|
} satisfies CheckResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -511,6 +521,8 @@ export class RegistryChecks {
|
||||||
const safeChanges: Array<SchemaChangeType> = [];
|
const safeChanges: Array<SchemaChangeType> = [];
|
||||||
const breakingChanges: Array<SchemaChangeType> = [];
|
const breakingChanges: Array<SchemaChangeType> = [];
|
||||||
|
|
||||||
|
const coordinatesDiff = diffSchemaCoordinates(existingSchema, incomingSchema);
|
||||||
|
|
||||||
for (const change of inspectorChanges) {
|
for (const change of inspectorChanges) {
|
||||||
if (change.criticality === CriticalityLevel.Breaking) {
|
if (change.criticality === CriticalityLevel.Breaking) {
|
||||||
if (change.isSafeBasedOnUsage === true) {
|
if (change.isSafeBasedOnUsage === true) {
|
||||||
|
|
@ -549,6 +561,7 @@ export class RegistryChecks {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
coordinatesDiff,
|
||||||
},
|
},
|
||||||
} satisfies SchemaDiffFailure;
|
} satisfies SchemaDiffFailure;
|
||||||
}
|
}
|
||||||
|
|
@ -568,6 +581,7 @@ export class RegistryChecks {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
coordinatesDiff,
|
||||||
},
|
},
|
||||||
} satisfies SchemaDiffSuccess;
|
} satisfies SchemaDiffSuccess;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import { TargetManager } from '../../target/providers/target-manager';
|
||||||
import { BreakingSchemaChangeUsageHelper } from './breaking-schema-changes-helper';
|
import { BreakingSchemaChangeUsageHelper } from './breaking-schema-changes-helper';
|
||||||
import { SCHEMA_MODULE_CONFIG, type SchemaModuleConfig } from './config';
|
import { SCHEMA_MODULE_CONFIG, type SchemaModuleConfig } from './config';
|
||||||
import { Contracts } from './contracts';
|
import { Contracts } from './contracts';
|
||||||
|
import type { SchemaCoordinatesDiffResult } from './inspector';
|
||||||
import { FederationOrchestrator } from './orchestrators/federation';
|
import { FederationOrchestrator } from './orchestrators/federation';
|
||||||
import { SingleOrchestrator } from './orchestrators/single';
|
import { SingleOrchestrator } from './orchestrators/single';
|
||||||
import { StitchingOrchestrator } from './orchestrators/stitching';
|
import { StitchingOrchestrator } from './orchestrators/stitching';
|
||||||
|
|
@ -427,6 +428,7 @@ export class SchemaManager {
|
||||||
projectType: ProjectType;
|
projectType: ProjectType;
|
||||||
actionFn(): Promise<void>;
|
actionFn(): Promise<void>;
|
||||||
changes: Array<SchemaChangeType>;
|
changes: Array<SchemaChangeType>;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
previousSchemaVersion: string | null;
|
previousSchemaVersion: string | null;
|
||||||
diffSchemaVersionId: string | null;
|
diffSchemaVersionId: string | null;
|
||||||
github: null | {
|
github: null | {
|
||||||
|
|
@ -460,13 +462,18 @@ export class SchemaManager {
|
||||||
) {
|
) {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
'Creating a new version (input=%o)',
|
'Creating a new version (input=%o)',
|
||||||
lodash.omit(input, [
|
lodash.pick(input, [
|
||||||
'schema',
|
'commit',
|
||||||
'actionFn',
|
'author',
|
||||||
'changes',
|
'valid',
|
||||||
'compositeSchemaSDL',
|
'service',
|
||||||
'supergraphSDL',
|
'logIds',
|
||||||
'schemaCompositionErrors',
|
'url',
|
||||||
|
'projectType',
|
||||||
|
'previousSchemaVersion',
|
||||||
|
'diffSchemaVersionId',
|
||||||
|
'github',
|
||||||
|
'conditionalBreakingChangeMetadata',
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1028,7 +1028,14 @@ export class SchemaPublisher {
|
||||||
);
|
);
|
||||||
|
|
||||||
const token = this.authManager.ensureApiToken();
|
const token = this.authManager.ensureApiToken();
|
||||||
const contracts = await this.contracts.getActiveContractsByTargetId({ targetId: input.target });
|
const [contracts, latestVersion] = await Promise.all([
|
||||||
|
this.contracts.getActiveContractsByTargetId({ targetId: input.target }),
|
||||||
|
this.schemaManager.getMaybeLatestVersion({
|
||||||
|
organization: input.organization,
|
||||||
|
project: input.project,
|
||||||
|
target: input.target,
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
const checksum = createHash('md5')
|
const checksum = createHash('md5')
|
||||||
.update(
|
.update(
|
||||||
|
|
@ -1042,6 +1049,10 @@ export class SchemaPublisher {
|
||||||
contractId: contract.id,
|
contractId: contract.id,
|
||||||
contractName: contract.contractName,
|
contractName: contract.contractName,
|
||||||
})),
|
})),
|
||||||
|
// We include the latest version ID to avoid caching a schema publication that targets different versions.
|
||||||
|
// When deleting a schema, and publishing it again, the latest version ID will be different.
|
||||||
|
// If we don't include it, the cache will return the previous result.
|
||||||
|
latestVersionId: latestVersion?.id,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.update(token)
|
.update(token)
|
||||||
|
|
@ -1335,6 +1346,7 @@ export class SchemaPublisher {
|
||||||
composable: deleteResult.state.composable,
|
composable: deleteResult.state.composable,
|
||||||
diffSchemaVersionId,
|
diffSchemaVersionId,
|
||||||
changes: deleteResult.state.changes,
|
changes: deleteResult.state.changes,
|
||||||
|
coordinatesDiff: deleteResult.state.coordinatesDiff,
|
||||||
contracts:
|
contracts:
|
||||||
deleteResult.state.contracts?.map(contract => ({
|
deleteResult.state.contracts?.map(contract => ({
|
||||||
contractId: contract.contractId,
|
contractId: contract.contractId,
|
||||||
|
|
@ -1909,6 +1921,7 @@ export class SchemaPublisher {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changes,
|
changes,
|
||||||
|
coordinatesDiff: publishResult.state.coordinatesDiff,
|
||||||
diffSchemaVersionId,
|
diffSchemaVersionId,
|
||||||
previousSchemaVersion: latestVersion?.version ?? null,
|
previousSchemaVersion: latestVersion?.version ?? null,
|
||||||
conditionalBreakingChangeMetadata: await this.getConditionalBreakingChangeMetadata({
|
conditionalBreakingChangeMetadata: await this.getConditionalBreakingChangeMetadata({
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import type { OrganizationAccessScope } from '../../auth/providers/organization-
|
||||||
import type { ProjectAccessScope } from '../../auth/providers/project-access';
|
import type { ProjectAccessScope } from '../../auth/providers/project-access';
|
||||||
import type { TargetAccessScope } from '../../auth/providers/target-access';
|
import type { TargetAccessScope } from '../../auth/providers/target-access';
|
||||||
import type { Contracts } from '../../schema/providers/contracts';
|
import type { Contracts } from '../../schema/providers/contracts';
|
||||||
|
import type { SchemaCoordinatesDiffResult } from '../../schema/providers/inspector';
|
||||||
|
|
||||||
export interface OrganizationSelector {
|
export interface OrganizationSelector {
|
||||||
organization: string;
|
organization: string;
|
||||||
|
|
@ -442,6 +443,7 @@ export interface Storage {
|
||||||
diffSchemaVersionId: string | null;
|
diffSchemaVersionId: string | null;
|
||||||
conditionalBreakingChangeMetadata: null | ConditionalBreakingChangeMetadata;
|
conditionalBreakingChangeMetadata: null | ConditionalBreakingChangeMetadata;
|
||||||
contracts: null | Array<CreateContractVersionInput>;
|
contracts: null | Array<CreateContractVersionInput>;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
} & TargetSelector &
|
} & TargetSelector &
|
||||||
(
|
(
|
||||||
| {
|
| {
|
||||||
|
|
@ -480,6 +482,7 @@ export interface Storage {
|
||||||
};
|
};
|
||||||
contracts: null | Array<CreateContractVersionInput>;
|
contracts: null | Array<CreateContractVersionInput>;
|
||||||
conditionalBreakingChangeMetadata: null | ConditionalBreakingChangeMetadata;
|
conditionalBreakingChangeMetadata: null | ConditionalBreakingChangeMetadata;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult | null;
|
||||||
} & TargetSelector) &
|
} & TargetSelector) &
|
||||||
(
|
(
|
||||||
| {
|
| {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
"itty-router": "4.2.2",
|
"itty-router": "4.2.2",
|
||||||
"toucan-js": "3.4.0",
|
"toucan-js": "3.4.0",
|
||||||
"undici": "6.19.2",
|
"undici": "6.19.2",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.3",
|
||||||
"workers-loki-logger": "0.1.15",
|
"workers-loki-logger": "0.1.15",
|
||||||
"zod": "3.23.8"
|
"zod": "3.23.8"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -271,6 +271,15 @@ export interface schema_checks {
|
||||||
updated_at: Date;
|
updated_at: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface schema_coordinate_status {
|
||||||
|
coordinate: string;
|
||||||
|
created_at: Date;
|
||||||
|
created_in_version_id: string;
|
||||||
|
deprecated_at: Date | null;
|
||||||
|
deprecated_in_version_id: string | null;
|
||||||
|
target_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface schema_log {
|
export interface schema_log {
|
||||||
action: string;
|
action: string;
|
||||||
author: string;
|
author: string;
|
||||||
|
|
@ -418,6 +427,7 @@ export interface DBTables {
|
||||||
projects: projects;
|
projects: projects;
|
||||||
schema_change_approvals: schema_change_approvals;
|
schema_change_approvals: schema_change_approvals;
|
||||||
schema_checks: schema_checks;
|
schema_checks: schema_checks;
|
||||||
|
schema_coordinate_status: schema_coordinate_status;
|
||||||
schema_log: schema_log;
|
schema_log: schema_log;
|
||||||
schema_policy_config: schema_policy_config;
|
schema_policy_config: schema_policy_config;
|
||||||
schema_version_changes: schema_version_changes;
|
schema_version_changes: schema_version_changes;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import type {
|
||||||
} from '@hive/api';
|
} from '@hive/api';
|
||||||
import { context, SpanKind, SpanStatusCode, trace } from '@hive/service-common';
|
import { context, SpanKind, SpanStatusCode, trace } from '@hive/service-common';
|
||||||
import { batch } from '@theguild/buddy';
|
import { batch } from '@theguild/buddy';
|
||||||
|
import type { SchemaCoordinatesDiffResult } from '../../api/src/modules/schema/providers/inspector';
|
||||||
import {
|
import {
|
||||||
createSDLHash,
|
createSDLHash,
|
||||||
OrganizationMemberRoleModel,
|
OrganizationMemberRoleModel,
|
||||||
|
|
@ -2644,6 +2645,14 @@ export async function createStorage(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.coordinatesDiff) {
|
||||||
|
await updateSchemaCoordinateStatus(trx, {
|
||||||
|
targetId: args.target,
|
||||||
|
versionId: newVersion.id,
|
||||||
|
coordinatesDiff: args.coordinatesDiff,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (const contract of args.contracts ?? []) {
|
for (const contract of args.contracts ?? []) {
|
||||||
const schemaVersionContractId = await insertSchemaVersionContract(trx, {
|
const schemaVersionContractId = await insertSchemaVersionContract(trx, {
|
||||||
schemaVersionId: newVersion.id,
|
schemaVersionId: newVersion.id,
|
||||||
|
|
@ -2756,6 +2765,14 @@ export async function createStorage(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.coordinatesDiff) {
|
||||||
|
await updateSchemaCoordinateStatus(trx, {
|
||||||
|
targetId: input.target,
|
||||||
|
versionId: version.id,
|
||||||
|
coordinatesDiff: input.coordinatesDiff,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await input.actionFn();
|
await input.actionFn();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -5137,6 +5154,80 @@ async function insertSchemaVersionContract(
|
||||||
return zod.string().parse(id);
|
return zod.string().parse(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateSchemaCoordinateStatus(
|
||||||
|
trx: DatabaseTransactionConnection,
|
||||||
|
args: {
|
||||||
|
targetId: string;
|
||||||
|
versionId: string;
|
||||||
|
coordinatesDiff: SchemaCoordinatesDiffResult;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const actions: Promise<unknown>[] = [];
|
||||||
|
|
||||||
|
if (args.coordinatesDiff.deleted) {
|
||||||
|
actions.push(
|
||||||
|
trx.query(sql`/* schema_coordinate_status_deleted */
|
||||||
|
DELETE FROM schema_coordinate_status
|
||||||
|
WHERE
|
||||||
|
target_id = ${args.targetId}
|
||||||
|
AND
|
||||||
|
coordinate = ANY(${sql.array(Array.from(args.coordinatesDiff.deleted), 'text')})
|
||||||
|
AND
|
||||||
|
created_at <= NOW()
|
||||||
|
`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.coordinatesDiff.added) {
|
||||||
|
actions.push(
|
||||||
|
trx.query(sql`/* schema_coordinate_status_inserted */
|
||||||
|
INSERT INTO schema_coordinate_status
|
||||||
|
( target_id, coordinate, created_in_version_id, deprecated_at, deprecated_in_version_id )
|
||||||
|
SELECT * FROM ${sql.unnest(
|
||||||
|
Array.from(args.coordinatesDiff.added).map(coordinate => {
|
||||||
|
const isDeprecatedAsWell = args.coordinatesDiff.deprecated.has(coordinate);
|
||||||
|
return [
|
||||||
|
args.targetId,
|
||||||
|
coordinate,
|
||||||
|
args.versionId,
|
||||||
|
// if it's added and deprecated at the same time
|
||||||
|
isDeprecatedAsWell ? 'NOW()' : null,
|
||||||
|
isDeprecatedAsWell ? args.versionId : null,
|
||||||
|
];
|
||||||
|
}),
|
||||||
|
['uuid', 'text', 'uuid', 'date', 'uuid'],
|
||||||
|
)}
|
||||||
|
`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.coordinatesDiff.undeprecated) {
|
||||||
|
actions.push(
|
||||||
|
trx.query(sql`/* schema_coordinate_status_undeprecated */
|
||||||
|
UPDATE schema_coordinate_status
|
||||||
|
SET deprecated_at = NULL, deprecated_in_version_id = NULL
|
||||||
|
WHERE
|
||||||
|
target_id = ${args.targetId}
|
||||||
|
AND
|
||||||
|
coordinate = ANY(${sql.array(Array.from(args.coordinatesDiff.undeprecated), 'text')})
|
||||||
|
`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(actions);
|
||||||
|
|
||||||
|
if (args.coordinatesDiff.deprecated) {
|
||||||
|
await trx.query(sql`/* schema_coordinate_status_deprecated */
|
||||||
|
UPDATE schema_coordinate_status
|
||||||
|
SET deprecated_at = NOW(), deprecated_in_version_id = ${args.versionId}
|
||||||
|
WHERE
|
||||||
|
target_id = ${args.targetId}
|
||||||
|
AND
|
||||||
|
coordinate = ANY(${sql.array(Array.from(args.coordinatesDiff.deprecated), 'text')})
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Small helper utility for jsonifying a nullable object.
|
* Small helper utility for jsonifying a nullable object.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import {
|
||||||
DiffEditor as MonacoDiffEditor,
|
DiffEditor as MonacoDiffEditor,
|
||||||
Editor as MonacoEditor,
|
Editor as MonacoEditor,
|
||||||
} from '@monaco-editor/react';
|
} from '@monaco-editor/react';
|
||||||
import pkg from '../../package.json' assert { type: 'json' };
|
import pkg from '../../package.json' with { type: 'json' };
|
||||||
|
|
||||||
loader.config({
|
loader.config({
|
||||||
paths: {
|
paths: {
|
||||||
|
|
|
||||||
375
pnpm-lock.yaml
375
pnpm-lock.yaml
|
|
@ -159,7 +159,7 @@ importers:
|
||||||
version: 0.18.1(prettier@3.3.3)
|
version: 0.18.1(prettier@3.3.3)
|
||||||
prettier-plugin-tailwindcss:
|
prettier-plugin-tailwindcss:
|
||||||
specifier: 0.6.5
|
specifier: 0.6.5
|
||||||
version: 0.6.5(@ianvs/prettier-plugin-sort-imports@4.2.1(prettier@3.3.3))(prettier@3.3.3)
|
version: 0.6.5(@ianvs/prettier-plugin-sort-imports@4.3.1(prettier@3.3.3))(prettier@3.3.3)
|
||||||
pretty-quick:
|
pretty-quick:
|
||||||
specifier: 4.0.0
|
specifier: 4.0.0
|
||||||
version: 4.0.0(prettier@3.3.3)
|
version: 4.0.0(prettier@3.3.3)
|
||||||
|
|
@ -185,8 +185,8 @@ importers:
|
||||||
specifier: 4.3.2
|
specifier: 4.3.2
|
||||||
version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
|
|
||||||
deployment:
|
deployment:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -333,8 +333,8 @@ importers:
|
||||||
specifier: 2.6.3
|
specifier: 2.6.3
|
||||||
version: 2.6.3
|
version: 2.6.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
zod:
|
zod:
|
||||||
specifier: 3.23.8
|
specifier: 3.23.8
|
||||||
version: 3.23.8
|
version: 3.23.8
|
||||||
|
|
@ -367,8 +367,8 @@ importers:
|
||||||
specifier: 14.0.0-beta.7
|
specifier: 14.0.0-beta.7
|
||||||
version: 14.0.0-beta.7
|
version: 14.0.0-beta.7
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
ws:
|
ws:
|
||||||
specifier: 8.18.0
|
specifier: 8.18.0
|
||||||
version: 8.18.0
|
version: 8.18.0
|
||||||
|
|
@ -496,8 +496,8 @@ importers:
|
||||||
specifier: 2.6.3
|
specifier: 2.6.3
|
||||||
version: 2.6.3
|
version: 2.6.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
publishDirectory: dist
|
publishDirectory: dist
|
||||||
|
|
||||||
packages/libraries/envelop:
|
packages/libraries/envelop:
|
||||||
|
|
@ -573,8 +573,8 @@ importers:
|
||||||
specifier: 14.0.0-beta.7
|
specifier: 14.0.0-beta.7
|
||||||
version: 14.0.0-beta.7
|
version: 14.0.0-beta.7
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
ws:
|
ws:
|
||||||
specifier: 8.18.0
|
specifier: 8.18.0
|
||||||
version: 8.18.0
|
version: 8.18.0
|
||||||
|
|
@ -612,6 +612,9 @@ importers:
|
||||||
got:
|
got:
|
||||||
specifier: 14.4.1
|
specifier: 14.4.1
|
||||||
version: 14.4.1(patch_hash=b6pwqmrs3qqykctltsasvrfwti)
|
version: 14.4.1(patch_hash=b6pwqmrs3qqykctltsasvrfwti)
|
||||||
|
graphql:
|
||||||
|
specifier: 16.9.0
|
||||||
|
version: 16.9.0
|
||||||
p-limit:
|
p-limit:
|
||||||
specifier: 4.0.0
|
specifier: 4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
|
|
@ -800,8 +803,8 @@ importers:
|
||||||
specifier: 2.6.3
|
specifier: 2.6.3
|
||||||
version: 2.6.3
|
version: 2.6.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
zod:
|
zod:
|
||||||
specifier: 3.23.8
|
specifier: 3.23.8
|
||||||
version: 3.23.8
|
version: 3.23.8
|
||||||
|
|
@ -833,8 +836,8 @@ importers:
|
||||||
specifier: 6.19.2
|
specifier: 6.19.2
|
||||||
version: 6.19.2
|
version: 6.19.2
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 1.6.0
|
specifier: 2.0.3
|
||||||
version: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
version: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
workers-loki-logger:
|
workers-loki-logger:
|
||||||
specifier: 0.1.15
|
specifier: 0.1.15
|
||||||
version: 0.1.15
|
version: 0.1.15
|
||||||
|
|
@ -1744,7 +1747,7 @@ importers:
|
||||||
version: 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
version: 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
||||||
'@storybook/addon-interactions':
|
'@storybook/addon-interactions':
|
||||||
specifier: 8.2.2
|
specifier: 8.2.2
|
||||||
version: 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
version: 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
||||||
'@storybook/addon-links':
|
'@storybook/addon-links':
|
||||||
specifier: 8.2.2
|
specifier: 8.2.2
|
||||||
version: 8.2.2(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
version: 8.2.2(react@18.3.1)(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
||||||
|
|
@ -4021,6 +4024,7 @@ packages:
|
||||||
|
|
||||||
'@fastify/vite@6.0.7':
|
'@fastify/vite@6.0.7':
|
||||||
resolution: {integrity: sha512-+dRo9KUkvmbqdmBskG02SwigWl06Mwkw8SBDK1zTNH6vd4DyXbRvI7RmJEmBkLouSU81KTzy1+OzwHSffqSD6w==}
|
resolution: {integrity: sha512-+dRo9KUkvmbqdmBskG02SwigWl06Mwkw8SBDK1zTNH6vd4DyXbRvI7RmJEmBkLouSU81KTzy1+OzwHSffqSD6w==}
|
||||||
|
bundledDependencies: []
|
||||||
|
|
||||||
'@floating-ui/core@1.2.6':
|
'@floating-ui/core@1.2.6':
|
||||||
resolution: {integrity: sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg==}
|
resolution: {integrity: sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg==}
|
||||||
|
|
@ -4735,6 +4739,15 @@ packages:
|
||||||
'@vue/compiler-sfc':
|
'@vue/compiler-sfc':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@ianvs/prettier-plugin-sort-imports@4.3.1':
|
||||||
|
resolution: {integrity: sha512-ZHwbyjkANZOjaBm3ZosADD2OUYGFzQGxfy67HmGZU94mHqe7g1LCMA7YYKB1Cq+UTPCBqlAYapY0KXAjKEw8Sg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@vue/compiler-sfc': 2.7.x || 3.x
|
||||||
|
prettier: 2 || 3
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vue/compiler-sfc':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@inquirer/confirm@3.1.8':
|
'@inquirer/confirm@3.1.8':
|
||||||
resolution: {integrity: sha512-f3INZ+ca4dQdn+MQiq1yP/mOIR/Oc8BLRYuDh6ciToWd6z4W8yArfzjBCMQ0BPY8PcJKwZxGIt8Z6yNT32eSTw==}
|
resolution: {integrity: sha512-f3INZ+ca4dQdn+MQiq1yP/mOIR/Oc8BLRYuDh6ciToWd6z4W8yArfzjBCMQ0BPY8PcJKwZxGIt8Z6yNT32eSTw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -4820,10 +4833,6 @@ packages:
|
||||||
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
|
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
'@jridgewell/set-array@1.1.2':
|
|
||||||
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
|
|
||||||
engines: {node: '>=6.0.0'}
|
|
||||||
|
|
||||||
'@jridgewell/set-array@1.2.1':
|
'@jridgewell/set-array@1.2.1':
|
||||||
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
|
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
@ -8150,18 +8159,30 @@ packages:
|
||||||
'@vitest/expect@1.6.0':
|
'@vitest/expect@1.6.0':
|
||||||
resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
|
resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
|
||||||
|
|
||||||
'@vitest/runner@1.6.0':
|
'@vitest/expect@2.0.3':
|
||||||
resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==}
|
resolution: {integrity: sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==}
|
||||||
|
|
||||||
'@vitest/snapshot@1.6.0':
|
'@vitest/pretty-format@2.0.3':
|
||||||
resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==}
|
resolution: {integrity: sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==}
|
||||||
|
|
||||||
|
'@vitest/runner@2.0.3':
|
||||||
|
resolution: {integrity: sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==}
|
||||||
|
|
||||||
|
'@vitest/snapshot@2.0.3':
|
||||||
|
resolution: {integrity: sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==}
|
||||||
|
|
||||||
'@vitest/spy@1.6.0':
|
'@vitest/spy@1.6.0':
|
||||||
resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==}
|
resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==}
|
||||||
|
|
||||||
|
'@vitest/spy@2.0.3':
|
||||||
|
resolution: {integrity: sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==}
|
||||||
|
|
||||||
'@vitest/utils@1.6.0':
|
'@vitest/utils@1.6.0':
|
||||||
resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
|
resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
|
||||||
|
|
||||||
|
'@vitest/utils@2.0.3':
|
||||||
|
resolution: {integrity: sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==}
|
||||||
|
|
||||||
'@webassemblyjs/ast@1.12.1':
|
'@webassemblyjs/ast@1.12.1':
|
||||||
resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==}
|
resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==}
|
||||||
|
|
||||||
|
|
@ -8518,6 +8539,10 @@ packages:
|
||||||
assertion-error@1.1.0:
|
assertion-error@1.1.0:
|
||||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
||||||
|
|
||||||
|
assertion-error@2.0.1:
|
||||||
|
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
ast-types-flow@0.0.8:
|
ast-types-flow@0.0.8:
|
||||||
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
|
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
|
||||||
|
|
||||||
|
|
@ -8880,6 +8905,10 @@ packages:
|
||||||
resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==}
|
resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
chai@5.1.1:
|
||||||
|
resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
chalk@2.3.0:
|
chalk@2.3.0:
|
||||||
resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==}
|
resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
@ -8936,6 +8965,10 @@ packages:
|
||||||
check-error@1.0.3:
|
check-error@1.0.3:
|
||||||
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
|
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
|
||||||
|
|
||||||
|
check-error@2.1.1:
|
||||||
|
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
|
||||||
|
engines: {node: '>= 16'}
|
||||||
|
|
||||||
check-more-types@2.24.0:
|
check-more-types@2.24.0:
|
||||||
resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==}
|
resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
@ -9628,6 +9661,10 @@ packages:
|
||||||
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
|
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
deep-eql@5.0.2:
|
||||||
|
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
deep-equal@2.1.0:
|
deep-equal@2.1.0:
|
||||||
resolution: {integrity: sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA==}
|
resolution: {integrity: sha512-2pxgvWu3Alv1PoWEyVg7HS8YhGlUFUV7N5oOvfL6d+7xAmLSemMwv/c8Zv/i9KFzxV5Kt5CAvQc70fLwVuf4UA==}
|
||||||
|
|
||||||
|
|
@ -11848,9 +11885,6 @@ packages:
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
js-tokens@8.0.3:
|
|
||||||
resolution: {integrity: sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==}
|
|
||||||
|
|
||||||
js-yaml@3.14.1:
|
js-yaml@3.14.1:
|
||||||
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
|
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -11953,9 +11987,6 @@ packages:
|
||||||
resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==}
|
resolution: {integrity: sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
|
||||||
jsonc-parser@3.2.0:
|
|
||||||
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
|
|
||||||
|
|
||||||
jsonfile@4.0.0:
|
jsonfile@4.0.0:
|
||||||
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
|
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
|
||||||
|
|
||||||
|
|
@ -12159,10 +12190,6 @@ packages:
|
||||||
resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==}
|
resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==}
|
||||||
engines: {node: '>=4.0.0'}
|
engines: {node: '>=4.0.0'}
|
||||||
|
|
||||||
local-pkg@0.5.0:
|
|
||||||
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
|
|
||||||
localforage@1.10.0:
|
localforage@1.10.0:
|
||||||
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
|
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
|
||||||
|
|
||||||
|
|
@ -12262,6 +12289,9 @@ packages:
|
||||||
loupe@2.3.7:
|
loupe@2.3.7:
|
||||||
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
|
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
|
||||||
|
|
||||||
|
loupe@3.1.1:
|
||||||
|
resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==}
|
||||||
|
|
||||||
lower-case-first@2.0.2:
|
lower-case-first@2.0.2:
|
||||||
resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==}
|
resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==}
|
||||||
|
|
||||||
|
|
@ -12321,6 +12351,9 @@ packages:
|
||||||
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
|
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
magic-string@0.30.10:
|
||||||
|
resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
|
||||||
|
|
||||||
magic-string@0.30.5:
|
magic-string@0.30.5:
|
||||||
resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==}
|
resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
@ -12940,9 +12973,6 @@ packages:
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
mlly@1.4.2:
|
|
||||||
resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==}
|
|
||||||
|
|
||||||
mnemonist@0.39.6:
|
mnemonist@0.39.6:
|
||||||
resolution: {integrity: sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==}
|
resolution: {integrity: sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==}
|
||||||
|
|
||||||
|
|
@ -13419,10 +13449,6 @@ packages:
|
||||||
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
|
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
|
||||||
p-limit@5.0.0:
|
|
||||||
resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==}
|
|
||||||
engines: {node: '>=18'}
|
|
||||||
|
|
||||||
p-limit@6.1.0:
|
p-limit@6.1.0:
|
||||||
resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==}
|
resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
@ -13626,9 +13652,16 @@ packages:
|
||||||
pathe@1.1.1:
|
pathe@1.1.1:
|
||||||
resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==}
|
resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==}
|
||||||
|
|
||||||
|
pathe@1.1.2:
|
||||||
|
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
|
||||||
|
|
||||||
pathval@1.1.1:
|
pathval@1.1.1:
|
||||||
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
||||||
|
|
||||||
|
pathval@2.0.0:
|
||||||
|
resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
|
||||||
|
engines: {node: '>= 14.16'}
|
||||||
|
|
||||||
pend@1.2.0:
|
pend@1.2.0:
|
||||||
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
|
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
|
||||||
|
|
||||||
|
|
@ -13768,9 +13801,6 @@ packages:
|
||||||
resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
|
resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
pkg-types@1.0.3:
|
|
||||||
resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
|
|
||||||
|
|
||||||
pluralize@8.0.0:
|
pluralize@8.0.0:
|
||||||
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
|
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
@ -15228,8 +15258,8 @@ packages:
|
||||||
std-env@3.3.3:
|
std-env@3.3.3:
|
||||||
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
|
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
|
||||||
|
|
||||||
std-env@3.6.0:
|
std-env@3.7.0:
|
||||||
resolution: {integrity: sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==}
|
resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
|
||||||
|
|
||||||
storybook@8.2.2:
|
storybook@8.2.2:
|
||||||
resolution: {integrity: sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==}
|
resolution: {integrity: sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==}
|
||||||
|
|
@ -15338,9 +15368,6 @@ packages:
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
strip-literal@2.0.0:
|
|
||||||
resolution: {integrity: sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==}
|
|
||||||
|
|
||||||
stripe@14.25.0:
|
stripe@14.25.0:
|
||||||
resolution: {integrity: sha512-wQS3GNMofCXwH8TSje8E1SE8zr6ODiGtHQgPtO95p9Mb4FhKC9jvXR2NUTpZ9ZINlckJcFidCmaTFV4P6vsb9g==}
|
resolution: {integrity: sha512-wQS3GNMofCXwH8TSje8E1SE8zr6ODiGtHQgPtO95p9Mb4FhKC9jvXR2NUTpZ9ZINlckJcFidCmaTFV4P6vsb9g==}
|
||||||
engines: {node: '>=12.*'}
|
engines: {node: '>=12.*'}
|
||||||
|
|
@ -15580,17 +15607,25 @@ packages:
|
||||||
tiny-warning@1.0.3:
|
tiny-warning@1.0.3:
|
||||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||||
|
|
||||||
tinybench@2.5.1:
|
tinybench@2.8.0:
|
||||||
resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==}
|
resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
|
||||||
|
|
||||||
tinypool@0.8.3:
|
tinypool@1.0.0:
|
||||||
resolution: {integrity: sha512-Ud7uepAklqRH1bvwy22ynrliC7Dljz7Tm8M/0RBUW+YRa4YHhZ6e4PpgE+fu1zr/WqB1kbeuVrdfeuyIBpy4tw==}
|
resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
|
||||||
|
tinyrainbow@1.2.0:
|
||||||
|
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
tinyspy@2.2.0:
|
tinyspy@2.2.0:
|
||||||
resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==}
|
resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
|
tinyspy@3.0.0:
|
||||||
|
resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
title-case@3.0.3:
|
title-case@3.0.3:
|
||||||
resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==}
|
resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==}
|
||||||
|
|
||||||
|
|
@ -15901,9 +15936,6 @@ packages:
|
||||||
uc.micro@2.1.0:
|
uc.micro@2.1.0:
|
||||||
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
|
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
|
||||||
|
|
||||||
ufo@1.3.0:
|
|
||||||
resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==}
|
|
||||||
|
|
||||||
uglify-js@3.17.4:
|
uglify-js@3.17.4:
|
||||||
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
|
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
|
|
@ -16225,8 +16257,8 @@ packages:
|
||||||
vfile@6.0.1:
|
vfile@6.0.1:
|
||||||
resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
|
resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
|
||||||
|
|
||||||
vite-node@1.6.0:
|
vite-node@2.0.3:
|
||||||
resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==}
|
resolution: {integrity: sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
|
@ -16266,15 +16298,15 @@ packages:
|
||||||
terser:
|
terser:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
vitest@1.6.0:
|
vitest@2.0.3:
|
||||||
resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
|
resolution: {integrity: sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@edge-runtime/vm': '*'
|
'@edge-runtime/vm': '*'
|
||||||
'@types/node': ^18.0.0 || >=20.0.0
|
'@types/node': ^18.0.0 || >=20.0.0
|
||||||
'@vitest/browser': 1.6.0
|
'@vitest/browser': 2.0.3
|
||||||
'@vitest/ui': 1.6.0
|
'@vitest/ui': 2.0.3
|
||||||
happy-dom: '*'
|
happy-dom: '*'
|
||||||
jsdom: '*'
|
jsdom: '*'
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
|
|
@ -18015,19 +18047,19 @@ snapshots:
|
||||||
'@babel/helper-module-transforms@7.23.3(@babel/core@7.22.9)':
|
'@babel/helper-module-transforms@7.23.3(@babel/core@7.22.9)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.22.9
|
'@babel/core': 7.22.9
|
||||||
'@babel/helper-environment-visitor': 7.22.20
|
'@babel/helper-environment-visitor': 7.24.7
|
||||||
'@babel/helper-module-imports': 7.22.15
|
'@babel/helper-module-imports': 7.22.15
|
||||||
'@babel/helper-simple-access': 7.22.5
|
'@babel/helper-simple-access': 7.22.5
|
||||||
'@babel/helper-split-export-declaration': 7.22.6
|
'@babel/helper-split-export-declaration': 7.24.7
|
||||||
'@babel/helper-validator-identifier': 7.24.7
|
'@babel/helper-validator-identifier': 7.24.7
|
||||||
|
|
||||||
'@babel/helper-module-transforms@7.23.3(@babel/core@7.24.0)':
|
'@babel/helper-module-transforms@7.23.3(@babel/core@7.24.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.24.0
|
'@babel/core': 7.24.0
|
||||||
'@babel/helper-environment-visitor': 7.22.20
|
'@babel/helper-environment-visitor': 7.24.7
|
||||||
'@babel/helper-module-imports': 7.22.15
|
'@babel/helper-module-imports': 7.22.15
|
||||||
'@babel/helper-simple-access': 7.22.5
|
'@babel/helper-simple-access': 7.22.5
|
||||||
'@babel/helper-split-export-declaration': 7.22.6
|
'@babel/helper-split-export-declaration': 7.24.7
|
||||||
'@babel/helper-validator-identifier': 7.24.7
|
'@babel/helper-validator-identifier': 7.24.7
|
||||||
|
|
||||||
'@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)':
|
'@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)':
|
||||||
|
|
@ -18821,7 +18853,7 @@ snapshots:
|
||||||
'@babel/template@7.24.0':
|
'@babel/template@7.24.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.24.2
|
'@babel/code-frame': 7.24.2
|
||||||
'@babel/parser': 7.24.5
|
'@babel/parser': 7.24.7
|
||||||
'@babel/types': 7.24.7
|
'@babel/types': 7.24.7
|
||||||
|
|
||||||
'@babel/template@7.24.7':
|
'@babel/template@7.24.7':
|
||||||
|
|
@ -18848,12 +18880,12 @@ snapshots:
|
||||||
'@babel/traverse@7.24.5':
|
'@babel/traverse@7.24.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.24.2
|
'@babel/code-frame': 7.24.2
|
||||||
'@babel/generator': 7.24.5
|
'@babel/generator': 7.24.7
|
||||||
'@babel/helper-environment-visitor': 7.22.20
|
'@babel/helper-environment-visitor': 7.22.20
|
||||||
'@babel/helper-function-name': 7.23.0
|
'@babel/helper-function-name': 7.23.0
|
||||||
'@babel/helper-hoist-variables': 7.22.5
|
'@babel/helper-hoist-variables': 7.22.5
|
||||||
'@babel/helper-split-export-declaration': 7.24.5
|
'@babel/helper-split-export-declaration': 7.24.5
|
||||||
'@babel/parser': 7.24.5
|
'@babel/parser': 7.24.7
|
||||||
'@babel/types': 7.24.7
|
'@babel/types': 7.24.7
|
||||||
debug: 4.3.5(supports-color@8.1.1)
|
debug: 4.3.5(supports-color@8.1.1)
|
||||||
globals: 11.12.0
|
globals: 11.12.0
|
||||||
|
|
@ -20933,15 +20965,28 @@ snapshots:
|
||||||
'@ianvs/prettier-plugin-sort-imports@4.2.1(prettier@3.3.3)':
|
'@ianvs/prettier-plugin-sort-imports@4.2.1(prettier@3.3.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.24.7
|
'@babel/core': 7.24.7
|
||||||
'@babel/generator': 7.23.6
|
'@babel/generator': 7.24.7
|
||||||
'@babel/parser': 7.24.0
|
'@babel/parser': 7.24.7
|
||||||
'@babel/traverse': 7.24.0
|
'@babel/traverse': 7.24.7
|
||||||
'@babel/types': 7.24.7
|
'@babel/types': 7.24.7
|
||||||
prettier: 3.3.3
|
prettier: 3.3.3
|
||||||
semver: 7.6.2
|
semver: 7.6.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@ianvs/prettier-plugin-sort-imports@4.3.1(prettier@3.3.3)':
|
||||||
|
dependencies:
|
||||||
|
'@babel/core': 7.24.7
|
||||||
|
'@babel/generator': 7.24.7
|
||||||
|
'@babel/parser': 7.24.7
|
||||||
|
'@babel/traverse': 7.24.7
|
||||||
|
'@babel/types': 7.24.7
|
||||||
|
prettier: 3.3.3
|
||||||
|
semver: 7.6.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@inquirer/confirm@3.1.8':
|
'@inquirer/confirm@3.1.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@inquirer/core': 8.2.1
|
'@inquirer/core': 8.2.1
|
||||||
|
|
@ -21046,9 +21091,9 @@ snapshots:
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.3':
|
'@jridgewell/gen-mapping@0.3.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/set-array': 1.1.2
|
'@jridgewell/set-array': 1.2.1
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
'@jridgewell/trace-mapping': 0.3.20
|
'@jridgewell/trace-mapping': 0.3.25
|
||||||
|
|
||||||
'@jridgewell/gen-mapping@0.3.5':
|
'@jridgewell/gen-mapping@0.3.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -21058,8 +21103,6 @@ snapshots:
|
||||||
|
|
||||||
'@jridgewell/resolve-uri@3.1.1': {}
|
'@jridgewell/resolve-uri@3.1.1': {}
|
||||||
|
|
||||||
'@jridgewell/set-array@1.1.2': {}
|
|
||||||
|
|
||||||
'@jridgewell/set-array@1.2.1': {}
|
'@jridgewell/set-array@1.2.1': {}
|
||||||
|
|
||||||
'@jridgewell/source-map@0.3.6':
|
'@jridgewell/source-map@0.3.6':
|
||||||
|
|
@ -24213,11 +24256,11 @@ snapshots:
|
||||||
'@storybook/global': 5.0.0
|
'@storybook/global': 5.0.0
|
||||||
storybook: 8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7))
|
storybook: 8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7))
|
||||||
|
|
||||||
'@storybook/addon-interactions@8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))':
|
'@storybook/addon-interactions@8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@storybook/global': 5.0.0
|
'@storybook/global': 5.0.0
|
||||||
'@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
'@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
||||||
'@storybook/test': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
'@storybook/test': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
||||||
polished: 4.2.2
|
polished: 4.2.2
|
||||||
storybook: 8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7))
|
storybook: 8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7))
|
||||||
ts-dedent: 2.2.0
|
ts-dedent: 2.2.0
|
||||||
|
|
@ -24411,12 +24454,12 @@ snapshots:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.5.3
|
typescript: 5.5.3
|
||||||
|
|
||||||
'@storybook/test@8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))':
|
'@storybook/test@8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))(vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@storybook/csf': 0.1.11
|
'@storybook/csf': 0.1.11
|
||||||
'@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
'@storybook/instrumenter': 8.2.2(storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)))
|
||||||
'@testing-library/dom': 10.1.0
|
'@testing-library/dom': 10.1.0
|
||||||
'@testing-library/jest-dom': 6.4.5(vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
'@testing-library/jest-dom': 6.4.5(vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))
|
||||||
'@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0)
|
'@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0)
|
||||||
'@vitest/expect': 1.6.0
|
'@vitest/expect': 1.6.0
|
||||||
'@vitest/spy': 1.6.0
|
'@vitest/spy': 1.6.0
|
||||||
|
|
@ -24581,7 +24624,7 @@ snapshots:
|
||||||
lz-string: 1.5.0
|
lz-string: 1.5.0
|
||||||
pretty-format: 27.5.1
|
pretty-format: 27.5.1
|
||||||
|
|
||||||
'@testing-library/jest-dom@6.4.5(vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))':
|
'@testing-library/jest-dom@6.4.5(vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@adobe/css-tools': 4.3.3
|
'@adobe/css-tools': 4.3.3
|
||||||
'@babel/runtime': 7.24.7
|
'@babel/runtime': 7.24.7
|
||||||
|
|
@ -24592,7 +24635,7 @@ snapshots:
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
redent: 3.0.0
|
redent: 3.0.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vitest: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
vitest: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
|
|
||||||
'@testing-library/user-event@14.5.2(@testing-library/dom@10.1.0)':
|
'@testing-library/user-event@14.5.2(@testing-library/dom@10.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -24655,8 +24698,8 @@ snapshots:
|
||||||
'@typescript-eslint/parser': 7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3)
|
'@typescript-eslint/parser': 7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3)
|
||||||
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
||||||
eslint-config-prettier: 9.1.0(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-config-prettier: 9.1.0(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
eslint-plugin-jsonc: 2.11.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-plugin-jsonc: 2.11.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
eslint-plugin-mdx: 3.0.0(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-plugin-mdx: 3.0.0(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
|
|
@ -24776,7 +24819,7 @@ snapshots:
|
||||||
|
|
||||||
'@types/babel__template@7.4.1':
|
'@types/babel__template@7.4.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.24.5
|
'@babel/parser': 7.24.7
|
||||||
'@babel/types': 7.24.7
|
'@babel/types': 7.24.7
|
||||||
|
|
||||||
'@types/babel__traverse@7.18.3':
|
'@types/babel__traverse@7.18.3':
|
||||||
|
|
@ -25300,22 +25343,36 @@ snapshots:
|
||||||
'@vitest/utils': 1.6.0
|
'@vitest/utils': 1.6.0
|
||||||
chai: 4.4.1
|
chai: 4.4.1
|
||||||
|
|
||||||
'@vitest/runner@1.6.0':
|
'@vitest/expect@2.0.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/utils': 1.6.0
|
'@vitest/spy': 2.0.3
|
||||||
p-limit: 5.0.0
|
'@vitest/utils': 2.0.3
|
||||||
pathe: 1.1.1
|
chai: 5.1.1
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
'@vitest/snapshot@1.6.0':
|
'@vitest/pretty-format@2.0.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
magic-string: 0.30.5
|
tinyrainbow: 1.2.0
|
||||||
pathe: 1.1.1
|
|
||||||
pretty-format: 29.7.0
|
'@vitest/runner@2.0.3':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/utils': 2.0.3
|
||||||
|
pathe: 1.1.2
|
||||||
|
|
||||||
|
'@vitest/snapshot@2.0.3':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/pretty-format': 2.0.3
|
||||||
|
magic-string: 0.30.10
|
||||||
|
pathe: 1.1.2
|
||||||
|
|
||||||
'@vitest/spy@1.6.0':
|
'@vitest/spy@1.6.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
tinyspy: 2.2.0
|
tinyspy: 2.2.0
|
||||||
|
|
||||||
|
'@vitest/spy@2.0.3':
|
||||||
|
dependencies:
|
||||||
|
tinyspy: 3.0.0
|
||||||
|
|
||||||
'@vitest/utils@1.6.0':
|
'@vitest/utils@1.6.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
diff-sequences: 29.6.3
|
diff-sequences: 29.6.3
|
||||||
|
|
@ -25323,6 +25380,13 @@ snapshots:
|
||||||
loupe: 2.3.7
|
loupe: 2.3.7
|
||||||
pretty-format: 29.7.0
|
pretty-format: 29.7.0
|
||||||
|
|
||||||
|
'@vitest/utils@2.0.3':
|
||||||
|
dependencies:
|
||||||
|
'@vitest/pretty-format': 2.0.3
|
||||||
|
estree-walker: 3.0.3
|
||||||
|
loupe: 3.1.1
|
||||||
|
tinyrainbow: 1.2.0
|
||||||
|
|
||||||
'@webassemblyjs/ast@1.12.1':
|
'@webassemblyjs/ast@1.12.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@webassemblyjs/helper-numbers': 1.11.6
|
'@webassemblyjs/helper-numbers': 1.11.6
|
||||||
|
|
@ -25716,6 +25780,8 @@ snapshots:
|
||||||
|
|
||||||
assertion-error@1.1.0: {}
|
assertion-error@1.1.0: {}
|
||||||
|
|
||||||
|
assertion-error@2.0.1: {}
|
||||||
|
|
||||||
ast-types-flow@0.0.8: {}
|
ast-types-flow@0.0.8: {}
|
||||||
|
|
||||||
ast-types@0.16.1:
|
ast-types@0.16.1:
|
||||||
|
|
@ -26187,6 +26253,14 @@ snapshots:
|
||||||
pathval: 1.1.1
|
pathval: 1.1.1
|
||||||
type-detect: 4.0.8
|
type-detect: 4.0.8
|
||||||
|
|
||||||
|
chai@5.1.1:
|
||||||
|
dependencies:
|
||||||
|
assertion-error: 2.0.1
|
||||||
|
check-error: 2.1.1
|
||||||
|
deep-eql: 5.0.2
|
||||||
|
loupe: 3.1.1
|
||||||
|
pathval: 2.0.0
|
||||||
|
|
||||||
chalk@2.3.0:
|
chalk@2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 3.2.1
|
ansi-styles: 3.2.1
|
||||||
|
|
@ -26261,6 +26335,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
get-func-name: 2.0.2
|
get-func-name: 2.0.2
|
||||||
|
|
||||||
|
check-error@2.1.1: {}
|
||||||
|
|
||||||
check-more-types@2.24.0: {}
|
check-more-types@2.24.0: {}
|
||||||
|
|
||||||
cheerio-select@1.6.0:
|
cheerio-select@1.6.0:
|
||||||
|
|
@ -27037,6 +27113,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
type-detect: 4.0.8
|
type-detect: 4.0.8
|
||||||
|
|
||||||
|
deep-eql@5.0.2: {}
|
||||||
|
|
||||||
deep-equal@2.1.0:
|
deep-equal@2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.5
|
call-bind: 1.0.5
|
||||||
|
|
@ -27564,13 +27642,13 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)):
|
eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.5(supports-color@8.1.1)
|
debug: 4.3.5(supports-color@8.1.1)
|
||||||
enhanced-resolve: 5.17.0
|
enhanced-resolve: 5.17.0
|
||||||
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
||||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.7.5
|
get-tsconfig: 4.7.5
|
||||||
is-core-module: 2.13.1
|
is-core-module: 2.13.1
|
||||||
|
|
@ -27601,14 +27679,14 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.8.0(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)):
|
eslint-module-utils@2.8.0(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7(supports-color@8.1.1)
|
debug: 3.2.7(supports-color@8.1.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/parser': 7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3)
|
'@typescript-eslint/parser': 7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3)
|
||||||
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -27624,7 +27702,7 @@ snapshots:
|
||||||
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
||||||
eslint-compat-utils: 0.1.2(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-compat-utils: 0.1.2(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
|
|
||||||
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)):
|
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)):
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes: 3.1.7
|
array-includes: 3.1.7
|
||||||
array.prototype.findlastindex: 1.2.3
|
array.prototype.findlastindex: 1.2.3
|
||||||
|
|
@ -27634,7 +27712,7 @@ snapshots:
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
eslint: 8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.1(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))(typescript@5.5.3))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva)))(eslint@8.57.0(patch_hash=fjbpfrtrjd6idngyeqxnwopfva))
|
||||||
hasown: 2.0.0
|
hasown: 2.0.0
|
||||||
is-core-module: 2.13.1
|
is-core-module: 2.13.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
@ -29803,8 +29881,6 @@ snapshots:
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
js-tokens@8.0.3: {}
|
|
||||||
|
|
||||||
js-yaml@3.14.1:
|
js-yaml@3.14.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse: 1.0.10
|
argparse: 1.0.10
|
||||||
|
|
@ -29923,8 +29999,6 @@ snapshots:
|
||||||
espree: 9.6.1
|
espree: 9.6.1
|
||||||
semver: 7.6.2
|
semver: 7.6.2
|
||||||
|
|
||||||
jsonc-parser@3.2.0: {}
|
|
||||||
|
|
||||||
jsonfile@4.0.0:
|
jsonfile@4.0.0:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
|
@ -30171,11 +30245,6 @@ snapshots:
|
||||||
emojis-list: 3.0.0
|
emojis-list: 3.0.0
|
||||||
json5: 1.0.2
|
json5: 1.0.2
|
||||||
|
|
||||||
local-pkg@0.5.0:
|
|
||||||
dependencies:
|
|
||||||
mlly: 1.4.2
|
|
||||||
pkg-types: 1.0.3
|
|
||||||
|
|
||||||
localforage@1.10.0:
|
localforage@1.10.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
lie: 3.1.1
|
lie: 3.1.1
|
||||||
|
|
@ -30265,6 +30334,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
get-func-name: 2.0.2
|
get-func-name: 2.0.2
|
||||||
|
|
||||||
|
loupe@3.1.1:
|
||||||
|
dependencies:
|
||||||
|
get-func-name: 2.0.2
|
||||||
|
|
||||||
lower-case-first@2.0.2:
|
lower-case-first@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.6.3
|
tslib: 2.6.3
|
||||||
|
|
@ -30314,6 +30387,10 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
|
||||||
|
magic-string@0.30.10:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
|
||||||
magic-string@0.30.5:
|
magic-string@0.30.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
|
@ -31534,13 +31611,6 @@ snapshots:
|
||||||
|
|
||||||
mkdirp@3.0.1: {}
|
mkdirp@3.0.1: {}
|
||||||
|
|
||||||
mlly@1.4.2:
|
|
||||||
dependencies:
|
|
||||||
acorn: 8.12.0
|
|
||||||
pathe: 1.1.1
|
|
||||||
pkg-types: 1.0.3
|
|
||||||
ufo: 1.3.0
|
|
||||||
|
|
||||||
mnemonist@0.39.6:
|
mnemonist@0.39.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
obliterator: 2.0.4
|
obliterator: 2.0.4
|
||||||
|
|
@ -32106,10 +32176,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
yocto-queue: 1.0.0
|
yocto-queue: 1.0.0
|
||||||
|
|
||||||
p-limit@5.0.0:
|
|
||||||
dependencies:
|
|
||||||
yocto-queue: 1.0.0
|
|
||||||
|
|
||||||
p-limit@6.1.0:
|
p-limit@6.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
yocto-queue: 1.1.1
|
yocto-queue: 1.1.1
|
||||||
|
|
@ -32346,8 +32412,12 @@ snapshots:
|
||||||
|
|
||||||
pathe@1.1.1: {}
|
pathe@1.1.1: {}
|
||||||
|
|
||||||
|
pathe@1.1.2: {}
|
||||||
|
|
||||||
pathval@1.1.1: {}
|
pathval@1.1.1: {}
|
||||||
|
|
||||||
|
pathval@2.0.0: {}
|
||||||
|
|
||||||
pend@1.2.0: {}
|
pend@1.2.0: {}
|
||||||
|
|
||||||
performance-now@2.1.0: {}
|
performance-now@2.1.0: {}
|
||||||
|
|
@ -32516,12 +32586,6 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
find-up: 6.3.0
|
find-up: 6.3.0
|
||||||
|
|
||||||
pkg-types@1.0.3:
|
|
||||||
dependencies:
|
|
||||||
jsonc-parser: 3.2.0
|
|
||||||
mlly: 1.4.2
|
|
||||||
pathe: 1.1.1
|
|
||||||
|
|
||||||
pluralize@8.0.0: {}
|
pluralize@8.0.0: {}
|
||||||
|
|
||||||
polished@4.2.2:
|
polished@4.2.2:
|
||||||
|
|
@ -32786,11 +32850,11 @@ snapshots:
|
||||||
sql-formatter: 15.0.2
|
sql-formatter: 15.0.2
|
||||||
tslib: 2.6.3
|
tslib: 2.6.3
|
||||||
|
|
||||||
prettier-plugin-tailwindcss@0.6.5(@ianvs/prettier-plugin-sort-imports@4.2.1(prettier@3.3.3))(prettier@3.3.3):
|
prettier-plugin-tailwindcss@0.6.5(@ianvs/prettier-plugin-sort-imports@4.3.1(prettier@3.3.3))(prettier@3.3.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
prettier: 3.3.3
|
prettier: 3.3.3
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@ianvs/prettier-plugin-sort-imports': 4.2.1(prettier@3.3.3)
|
'@ianvs/prettier-plugin-sort-imports': 4.3.1(prettier@3.3.3)
|
||||||
|
|
||||||
prettier@2.8.8: {}
|
prettier@2.8.8: {}
|
||||||
|
|
||||||
|
|
@ -34117,7 +34181,7 @@ snapshots:
|
||||||
|
|
||||||
std-env@3.3.3: {}
|
std-env@3.3.3: {}
|
||||||
|
|
||||||
std-env@3.6.0: {}
|
std-env@3.7.0: {}
|
||||||
|
|
||||||
storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)):
|
storybook@8.2.2(@babel/preset-env@7.24.5(@babel/core@7.24.7)):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -34270,10 +34334,6 @@ snapshots:
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
strip-literal@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
js-tokens: 8.0.3
|
|
||||||
|
|
||||||
stripe@14.25.0:
|
stripe@14.25.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.14.10
|
'@types/node': 20.14.10
|
||||||
|
|
@ -34571,12 +34631,16 @@ snapshots:
|
||||||
|
|
||||||
tiny-warning@1.0.3: {}
|
tiny-warning@1.0.3: {}
|
||||||
|
|
||||||
tinybench@2.5.1: {}
|
tinybench@2.8.0: {}
|
||||||
|
|
||||||
tinypool@0.8.3: {}
|
tinypool@1.0.0: {}
|
||||||
|
|
||||||
|
tinyrainbow@1.2.0: {}
|
||||||
|
|
||||||
tinyspy@2.2.0: {}
|
tinyspy@2.2.0: {}
|
||||||
|
|
||||||
|
tinyspy@3.0.0: {}
|
||||||
|
|
||||||
title-case@3.0.3:
|
title-case@3.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.6.3
|
tslib: 2.6.3
|
||||||
|
|
@ -34870,8 +34934,6 @@ snapshots:
|
||||||
|
|
||||||
uc.micro@2.1.0: {}
|
uc.micro@2.1.0: {}
|
||||||
|
|
||||||
ufo@1.3.0: {}
|
|
||||||
|
|
||||||
uglify-js@3.17.4: {}
|
uglify-js@3.17.4: {}
|
||||||
|
|
||||||
unbox-primitive@1.0.2:
|
unbox-primitive@1.0.2:
|
||||||
|
|
@ -35252,12 +35314,12 @@ snapshots:
|
||||||
unist-util-stringify-position: 4.0.0
|
unist-util-stringify-position: 4.0.0
|
||||||
vfile-message: 4.0.2
|
vfile-message: 4.0.2
|
||||||
|
|
||||||
vite-node@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1):
|
vite-node@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
cac: 6.7.14
|
cac: 6.7.14
|
||||||
debug: 4.3.5(supports-color@8.1.1)
|
debug: 4.3.5(supports-color@8.1.1)
|
||||||
pathe: 1.1.1
|
pathe: 1.1.2
|
||||||
picocolors: 1.0.1
|
tinyrainbow: 1.2.0
|
||||||
vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/node'
|
- '@types/node'
|
||||||
|
|
@ -35291,27 +35353,26 @@ snapshots:
|
||||||
less: 4.2.0
|
less: 4.2.0
|
||||||
terser: 5.31.1
|
terser: 5.31.1
|
||||||
|
|
||||||
vitest@1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1):
|
vitest@2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/expect': 1.6.0
|
'@ampproject/remapping': 2.3.0
|
||||||
'@vitest/runner': 1.6.0
|
'@vitest/expect': 2.0.3
|
||||||
'@vitest/snapshot': 1.6.0
|
'@vitest/pretty-format': 2.0.3
|
||||||
'@vitest/spy': 1.6.0
|
'@vitest/runner': 2.0.3
|
||||||
'@vitest/utils': 1.6.0
|
'@vitest/snapshot': 2.0.3
|
||||||
acorn-walk: 8.3.2
|
'@vitest/spy': 2.0.3
|
||||||
chai: 4.4.1
|
'@vitest/utils': 2.0.3
|
||||||
|
chai: 5.1.1
|
||||||
debug: 4.3.5(supports-color@8.1.1)
|
debug: 4.3.5(supports-color@8.1.1)
|
||||||
execa: 8.0.1
|
execa: 8.0.1
|
||||||
local-pkg: 0.5.0
|
magic-string: 0.30.10
|
||||||
magic-string: 0.30.5
|
pathe: 1.1.2
|
||||||
pathe: 1.1.1
|
std-env: 3.7.0
|
||||||
picocolors: 1.0.1
|
tinybench: 2.8.0
|
||||||
std-env: 3.6.0
|
tinypool: 1.0.0
|
||||||
strip-literal: 2.0.0
|
tinyrainbow: 1.2.0
|
||||||
tinybench: 2.5.1
|
|
||||||
tinypool: 0.8.3
|
|
||||||
vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
vite-node: 1.6.0(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
vite-node: 2.0.3(@types/node@20.14.10)(less@4.2.0)(terser@5.31.1)
|
||||||
why-is-node-running: 2.2.2
|
why-is-node-running: 2.2.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 20.14.10
|
'@types/node': 20.14.10
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,12 @@ const { plugins, ...prettierConfig } = require('@theguild/prettier-config');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...prettierConfig,
|
...prettierConfig,
|
||||||
importOrderParserPlugins: ['importAssertions', ...prettierConfig.importOrderParserPlugins],
|
importOrderParserPlugins: [
|
||||||
|
'importAssertions',
|
||||||
|
// `using` keyword
|
||||||
|
'explicitResourceManagement',
|
||||||
|
...prettierConfig.importOrderParserPlugins,
|
||||||
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
'prettier-plugin-sql',
|
'prettier-plugin-sql',
|
||||||
...plugins,
|
...plugins,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue