feat: add versioned migrations and kysely query layer
This commit is contained in:
@@ -1,8 +1,41 @@
|
|||||||
export function runMigrations(): Promise<void> {
|
import { join, sep } from 'node:path';
|
||||||
console.log('No migrations configured in Phase 01');
|
import { runner } from 'node-pg-migrate';
|
||||||
return Promise.resolve();
|
import { loadEnvironment } from '../../../libs/configuration/src';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the `backend/migrations` directory relative to this file's own
|
||||||
|
* location rather than `process.cwd()`, so migrations run identically from
|
||||||
|
* the compiled `dist/apps/api/src/migration.js` (production/deploy) and from
|
||||||
|
* the TypeScript source at `apps/api/src/migration.ts` (ts-jest integration
|
||||||
|
* tests), even though those two locations sit at different directory depths
|
||||||
|
* relative to the `backend/` package root.
|
||||||
|
*/
|
||||||
|
function resolveMigrationsDir(): string {
|
||||||
|
const segments = __dirname.split(sep);
|
||||||
|
const distIndex = segments.lastIndexOf('dist');
|
||||||
|
const backendRoot =
|
||||||
|
distIndex !== -1
|
||||||
|
? segments.slice(0, distIndex).join(sep)
|
||||||
|
: segments.slice(0, -3).join(sep);
|
||||||
|
return join(backendRoot, 'migrations');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function runMigrations(): Promise<void> {
|
||||||
|
const env = loadEnvironment(process.env);
|
||||||
|
await runner({
|
||||||
|
databaseUrl: env.databaseUrl,
|
||||||
|
dir: resolveMigrationsDir(),
|
||||||
|
direction: 'up',
|
||||||
|
count: Infinity,
|
||||||
|
migrationsTable: 'pgmigrations',
|
||||||
|
checkOrder: true,
|
||||||
|
log: (message: string) => console.log(message),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
void runMigrations();
|
void runMigrations().catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exitCode = 1;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
10
backend/jest-integration.json
Normal file
10
backend/jest-integration.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"moduleFileExtensions": ["js", "json", "ts"],
|
||||||
|
"rootDir": ".",
|
||||||
|
"testEnvironment": "node",
|
||||||
|
"testRegex": ".*\\.integration-spec\\.ts$",
|
||||||
|
"testPathIgnorePatterns": ["<rootDir>/node_modules/", "<rootDir>/dist/"],
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
}
|
||||||
|
}
|
||||||
2
backend/libs/database/src/index.ts
Normal file
2
backend/libs/database/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './schema';
|
||||||
|
export * from './kysely.module';
|
||||||
22
backend/libs/database/src/kysely.module.ts
Normal file
22
backend/libs/database/src/kysely.module.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { Kysely, PostgresDialect } from 'kysely';
|
||||||
|
import type { Pool } from 'pg';
|
||||||
|
import { PostgresModule } from '../../infrastructure/src';
|
||||||
|
import { POSTGRES_POOL } from '../../infrastructure/src';
|
||||||
|
import type { Database } from './schema';
|
||||||
|
|
||||||
|
export const KYSELY_DB = Symbol('KYSELY_DB');
|
||||||
|
|
||||||
|
export const kyselyDbProvider = {
|
||||||
|
provide: KYSELY_DB,
|
||||||
|
inject: [POSTGRES_POOL],
|
||||||
|
useFactory: (pool: Pool) =>
|
||||||
|
new Kysely<Database>({ dialect: new PostgresDialect({ pool }) }),
|
||||||
|
};
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [PostgresModule],
|
||||||
|
providers: [kyselyDbProvider],
|
||||||
|
exports: [kyselyDbProvider],
|
||||||
|
})
|
||||||
|
export class DatabaseModule {}
|
||||||
105
backend/libs/database/src/schema.ts
Normal file
105
backend/libs/database/src/schema.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import type { ColumnType, Generated } from 'kysely';
|
||||||
|
|
||||||
|
export interface UsersTable {
|
||||||
|
id: Generated<string>;
|
||||||
|
external_subject_id: string;
|
||||||
|
display_name: string;
|
||||||
|
email: string;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserPreferencesTable {
|
||||||
|
user_id: string;
|
||||||
|
preferred_pace: string | null;
|
||||||
|
preferred_budget_level: string | null;
|
||||||
|
max_walking_distance_km: number | null;
|
||||||
|
preferred_start_time: string | null;
|
||||||
|
child_friendly_preferred: boolean;
|
||||||
|
interests: string[];
|
||||||
|
notes: string | null;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TripsTable {
|
||||||
|
id: Generated<string>;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
owner_id: string;
|
||||||
|
start_date: string | null;
|
||||||
|
end_date: string | null;
|
||||||
|
status: string;
|
||||||
|
planning_stage: string | null;
|
||||||
|
currency: string;
|
||||||
|
version: Generated<number>;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TripSettingsTable {
|
||||||
|
trip_id: string;
|
||||||
|
web_research_enabled: boolean;
|
||||||
|
periodic_agent_review_enabled: boolean;
|
||||||
|
notification_email_enabled: boolean;
|
||||||
|
notification_push_enabled: boolean;
|
||||||
|
default_research_depth: string | null;
|
||||||
|
default_planning_style: string | null;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TripMembersTable {
|
||||||
|
id: Generated<string>;
|
||||||
|
trip_id: string;
|
||||||
|
user_id: string;
|
||||||
|
role: string;
|
||||||
|
status: string;
|
||||||
|
joined_at: ColumnType<Date, string | undefined, string> | null;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TripInvitationsTable {
|
||||||
|
id: Generated<string>;
|
||||||
|
trip_id: string;
|
||||||
|
email: string;
|
||||||
|
invited_by_user_id: string;
|
||||||
|
token_hash: string;
|
||||||
|
expires_at: ColumnType<Date, string, string>;
|
||||||
|
accepted_at: ColumnType<Date, string | undefined, string> | null;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TravelersTable {
|
||||||
|
id: Generated<string>;
|
||||||
|
trip_id: string;
|
||||||
|
linked_user_id: string | null;
|
||||||
|
display_name: string;
|
||||||
|
traveler_type: string;
|
||||||
|
created_by_user_id: string;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TripPreferenceOverridesTable {
|
||||||
|
id: Generated<string>;
|
||||||
|
trip_id: string;
|
||||||
|
user_id: string | null;
|
||||||
|
traveler_id: string | null;
|
||||||
|
overrides: unknown;
|
||||||
|
created_at: ColumnType<Date, string | undefined, never>;
|
||||||
|
updated_at: ColumnType<Date, string | undefined, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Database {
|
||||||
|
users: UsersTable;
|
||||||
|
user_preferences: UserPreferencesTable;
|
||||||
|
trips: TripsTable;
|
||||||
|
trip_settings: TripSettingsTable;
|
||||||
|
trip_members: TripMembersTable;
|
||||||
|
trip_invitations: TripInvitationsTable;
|
||||||
|
travelers: TravelersTable;
|
||||||
|
trip_preference_overrides: TripPreferenceOverridesTable;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Pool } from 'pg';
|
||||||
|
import { runMigrations } from '../../../apps/api/src/migration';
|
||||||
|
|
||||||
|
describe('runMigrations (integration)', () => {
|
||||||
|
it('applies all pending migrations idempotently against a real database', async () => {
|
||||||
|
await runMigrations();
|
||||||
|
await runMigrations(); // must be safe to run twice
|
||||||
|
|
||||||
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
||||||
|
try {
|
||||||
|
const tables = await pool.query<{ table_name: string }>(
|
||||||
|
`select table_name from information_schema.tables where table_schema = 'public'`,
|
||||||
|
);
|
||||||
|
const names = tables.rows.map((r) => r.table_name);
|
||||||
|
for (const expected of [
|
||||||
|
'users',
|
||||||
|
'user_preferences',
|
||||||
|
'trips',
|
||||||
|
'trip_settings',
|
||||||
|
'trip_members',
|
||||||
|
'trip_invitations',
|
||||||
|
'travelers',
|
||||||
|
'trip_preference_overrides',
|
||||||
|
]) {
|
||||||
|
expect(names).toContain(expected);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
16
backend/migrations/1700000001000_create-users.cjs
Normal file
16
backend/migrations/1700000001000_create-users.cjs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createExtension('pgcrypto', { ifNotExists: true });
|
||||||
|
pgm.createTable('users', {
|
||||||
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
||||||
|
external_subject_id: { type: 'text', notNull: true },
|
||||||
|
display_name: { type: 'text', notNull: true },
|
||||||
|
email: { type: 'text', notNull: true },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
pgm.addConstraint('users', 'users_external_subject_id_key', 'UNIQUE(external_subject_id)');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('users');
|
||||||
|
};
|
||||||
24
backend/migrations/1700000002000_create-user-preferences.cjs
Normal file
24
backend/migrations/1700000002000_create-user-preferences.cjs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('user_preferences', {
|
||||||
|
user_id: {
|
||||||
|
type: 'uuid',
|
||||||
|
primaryKey: true,
|
||||||
|
notNull: true,
|
||||||
|
references: 'users(id)',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
},
|
||||||
|
preferred_pace: { type: 'text' },
|
||||||
|
preferred_budget_level: { type: 'text' },
|
||||||
|
max_walking_distance_km: { type: 'numeric' },
|
||||||
|
preferred_start_time: { type: 'text' },
|
||||||
|
child_friendly_preferred: { type: 'boolean', notNull: true, default: false },
|
||||||
|
interests: { type: 'text[]', notNull: true, default: '{}' },
|
||||||
|
notes: { type: 'text' },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('user_preferences');
|
||||||
|
};
|
||||||
26
backend/migrations/1700000003000_create-trips.cjs
Normal file
26
backend/migrations/1700000003000_create-trips.cjs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('trips', {
|
||||||
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
||||||
|
name: { type: 'text', notNull: true },
|
||||||
|
description: { type: 'text' },
|
||||||
|
owner_id: { type: 'uuid', notNull: true, references: 'users(id)' },
|
||||||
|
start_date: { type: 'date' },
|
||||||
|
end_date: { type: 'date' },
|
||||||
|
status: { type: 'text', notNull: true, default: 'DRAFT' },
|
||||||
|
planning_stage: { type: 'text' },
|
||||||
|
currency: { type: 'text', notNull: true, default: 'EUR' },
|
||||||
|
version: { type: 'integer', notNull: true, default: 1 },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
pgm.addConstraint(
|
||||||
|
'trips',
|
||||||
|
'trips_status_check',
|
||||||
|
"CHECK (status IN ('DRAFT','PLANNING','BOOKING','UPCOMING','ACTIVE','COMPLETED','ARCHIVED'))",
|
||||||
|
);
|
||||||
|
pgm.createIndex('trips', 'owner_id');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('trips');
|
||||||
|
};
|
||||||
23
backend/migrations/1700000004000_create-trip-settings.cjs
Normal file
23
backend/migrations/1700000004000_create-trip-settings.cjs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('trip_settings', {
|
||||||
|
trip_id: {
|
||||||
|
type: 'uuid',
|
||||||
|
primaryKey: true,
|
||||||
|
notNull: true,
|
||||||
|
references: 'trips(id)',
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
},
|
||||||
|
web_research_enabled: { type: 'boolean', notNull: true, default: false },
|
||||||
|
periodic_agent_review_enabled: { type: 'boolean', notNull: true, default: false },
|
||||||
|
notification_email_enabled: { type: 'boolean', notNull: true, default: true },
|
||||||
|
notification_push_enabled: { type: 'boolean', notNull: true, default: true },
|
||||||
|
default_research_depth: { type: 'text' },
|
||||||
|
default_planning_style: { type: 'text' },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('trip_settings');
|
||||||
|
};
|
||||||
25
backend/migrations/1700000005000_create-trip-members.cjs
Normal file
25
backend/migrations/1700000005000_create-trip-members.cjs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('trip_members', {
|
||||||
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
||||||
|
trip_id: { type: 'uuid', notNull: true, references: 'trips(id)', onDelete: 'CASCADE' },
|
||||||
|
user_id: { type: 'uuid', notNull: true, references: 'users(id)' },
|
||||||
|
role: { type: 'text', notNull: true },
|
||||||
|
status: { type: 'text', notNull: true },
|
||||||
|
joined_at: { type: 'timestamptz' },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
pgm.addConstraint('trip_members', 'trip_members_trip_user_key', 'UNIQUE(trip_id, user_id)');
|
||||||
|
pgm.addConstraint('trip_members', 'trip_members_role_check', "CHECK (role IN ('OWNER','MEMBER'))");
|
||||||
|
pgm.addConstraint(
|
||||||
|
'trip_members',
|
||||||
|
'trip_members_status_check',
|
||||||
|
"CHECK (status IN ('INVITED','ACTIVE','DECLINED'))",
|
||||||
|
);
|
||||||
|
pgm.createIndex('trip_members', 'trip_id');
|
||||||
|
pgm.createIndex('trip_members', 'user_id');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('trip_members');
|
||||||
|
};
|
||||||
20
backend/migrations/1700000006000_create-trip-invitations.cjs
Normal file
20
backend/migrations/1700000006000_create-trip-invitations.cjs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('trip_invitations', {
|
||||||
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
||||||
|
trip_id: { type: 'uuid', notNull: true, references: 'trips(id)', onDelete: 'CASCADE' },
|
||||||
|
email: { type: 'text', notNull: true },
|
||||||
|
invited_by_user_id: { type: 'uuid', notNull: true, references: 'users(id)' },
|
||||||
|
token_hash: { type: 'text', notNull: true },
|
||||||
|
expires_at: { type: 'timestamptz', notNull: true },
|
||||||
|
accepted_at: { type: 'timestamptz' },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
pgm.addConstraint('trip_invitations', 'trip_invitations_token_hash_key', 'UNIQUE(token_hash)');
|
||||||
|
pgm.createIndex('trip_invitations', 'trip_id');
|
||||||
|
pgm.sql('CREATE INDEX trip_invitations_lower_email_idx ON trip_invitations (lower(email))');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('trip_invitations');
|
||||||
|
};
|
||||||
22
backend/migrations/1700000007000_create-travelers.cjs
Normal file
22
backend/migrations/1700000007000_create-travelers.cjs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('travelers', {
|
||||||
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
||||||
|
trip_id: { type: 'uuid', notNull: true, references: 'trips(id)', onDelete: 'CASCADE' },
|
||||||
|
linked_user_id: { type: 'uuid', references: 'users(id)' },
|
||||||
|
display_name: { type: 'text', notNull: true },
|
||||||
|
traveler_type: { type: 'text', notNull: true },
|
||||||
|
created_by_user_id: { type: 'uuid', notNull: true, references: 'users(id)' },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
pgm.addConstraint(
|
||||||
|
'travelers',
|
||||||
|
'travelers_traveler_type_check',
|
||||||
|
"CHECK (traveler_type IN ('ADULT','CHILD','INFANT'))",
|
||||||
|
);
|
||||||
|
pgm.createIndex('travelers', 'trip_id');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('travelers');
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
exports.up = (pgm) => {
|
||||||
|
pgm.createTable('trip_preference_overrides', {
|
||||||
|
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
|
||||||
|
trip_id: { type: 'uuid', notNull: true, references: 'trips(id)', onDelete: 'CASCADE' },
|
||||||
|
user_id: { type: 'uuid', references: 'users(id)' },
|
||||||
|
traveler_id: { type: 'uuid', references: 'travelers(id)', onDelete: 'CASCADE' },
|
||||||
|
overrides: { type: 'jsonb', notNull: true, default: '{}' },
|
||||||
|
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
|
||||||
|
});
|
||||||
|
pgm.addConstraint(
|
||||||
|
'trip_preference_overrides',
|
||||||
|
'trip_preference_overrides_subject_check',
|
||||||
|
'CHECK (num_nonnulls(user_id, traveler_id) = 1)',
|
||||||
|
);
|
||||||
|
pgm.createIndex('trip_preference_overrides', ['trip_id', 'user_id'], {
|
||||||
|
unique: true,
|
||||||
|
where: 'user_id IS NOT NULL',
|
||||||
|
name: 'trip_pref_overrides_trip_user_uq',
|
||||||
|
});
|
||||||
|
pgm.createIndex('trip_preference_overrides', ['trip_id', 'traveler_id'], {
|
||||||
|
unique: true,
|
||||||
|
where: 'traveler_id IS NOT NULL',
|
||||||
|
name: 'trip_pref_overrides_trip_traveler_uq',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = (pgm) => {
|
||||||
|
pgm.dropTable('trip_preference_overrides');
|
||||||
|
};
|
||||||
@@ -20,13 +20,16 @@
|
|||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:cov": "jest --coverage",
|
"test:cov": "jest --coverage",
|
||||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
"test:e2e": "jest --config ./apps/api/test/jest-e2e.json"
|
"test:e2e": "jest --config ./apps/api/test/jest-e2e.json",
|
||||||
|
"test:integration": "jest --config jest-integration.json --runInBand"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nestjs/common": "^11.0.1",
|
"@nestjs/common": "^11.0.1",
|
||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
"ioredis": "^6.0.0",
|
"ioredis": "^6.0.0",
|
||||||
|
"kysely": "^0.29.5",
|
||||||
|
"node-pg-migrate": "^7.9.1",
|
||||||
"pg": "^8.23.0",
|
"pg": "^8.23.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ COPY --from=build /app/node_modules ./node_modules
|
|||||||
COPY --from=build /app/backend/node_modules ./backend/node_modules
|
COPY --from=build /app/backend/node_modules ./backend/node_modules
|
||||||
COPY --from=build /app/backend/package.json ./backend/package.json
|
COPY --from=build /app/backend/package.json ./backend/package.json
|
||||||
COPY --from=build /app/backend/dist ./backend/dist
|
COPY --from=build /app/backend/dist ./backend/dist
|
||||||
|
COPY --from=build /app/backend/migrations ./backend/migrations
|
||||||
USER node
|
USER node
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
CMD ["node", "backend/dist/apps/api/src/main.js"]
|
CMD ["node", "backend/dist/apps/api/src/main.js"]
|
||||||
|
|||||||
160
pnpm-lock.yaml
generated
160
pnpm-lock.yaml
generated
@@ -26,6 +26,12 @@ importers:
|
|||||||
ioredis:
|
ioredis:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
|
kysely:
|
||||||
|
specifier: ^0.29.5
|
||||||
|
version: 0.29.5
|
||||||
|
node-pg-migrate:
|
||||||
|
specifier: ^7.9.1
|
||||||
|
version: 7.9.1(@types/pg@8.21.0)(pg@8.23.0)
|
||||||
pg:
|
pg:
|
||||||
specifier: ^8.23.0
|
specifier: ^8.23.0
|
||||||
version: 8.23.0
|
version: 8.23.0
|
||||||
@@ -68,13 +74,13 @@ importers:
|
|||||||
version: 7.2.1
|
version: 7.2.1
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.18.0
|
specifier: ^9.18.0
|
||||||
version: 9.39.5
|
version: 9.39.5(jiti@2.7.0)
|
||||||
eslint-config-prettier:
|
eslint-config-prettier:
|
||||||
specifier: ^10.0.1
|
specifier: ^10.0.1
|
||||||
version: 10.1.8(eslint@9.39.5)
|
version: 10.1.8(eslint@9.39.5(jiti@2.7.0))
|
||||||
eslint-plugin-prettier:
|
eslint-plugin-prettier:
|
||||||
specifier: ^5.2.2
|
specifier: ^5.2.2
|
||||||
version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.5))(eslint@9.39.5)(prettier@3.9.6)
|
version: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))(prettier@3.9.6)
|
||||||
globals:
|
globals:
|
||||||
specifier: ^17.0.0
|
specifier: ^17.0.0
|
||||||
version: 17.11.0
|
version: 17.11.0
|
||||||
@@ -107,7 +113,7 @@ importers:
|
|||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
typescript-eslint:
|
typescript-eslint:
|
||||||
specifier: ^8.20.0
|
specifier: ^8.20.0
|
||||||
version: 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
version: 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -141,7 +147,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
'@angular/build':
|
'@angular/build':
|
||||||
specifier: ^21.2.6
|
specifier: ^21.2.6
|
||||||
version: 21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)))(yaml@2.9.0)
|
version: 21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(jiti@2.7.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)))(yaml@2.9.0)
|
||||||
'@angular/cli':
|
'@angular/cli':
|
||||||
specifier: ^21.2.6
|
specifier: ^21.2.6
|
||||||
version: 21.2.21(@types/node@24.13.3)(chokidar@5.0.0)
|
version: 21.2.21(@types/node@24.13.3)(chokidar@5.0.0)
|
||||||
@@ -159,7 +165,7 @@ importers:
|
|||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
vitest:
|
vitest:
|
||||||
specifier: ^4.0.8
|
specifier: ^4.0.8
|
||||||
version: 4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
version: 4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -1031,6 +1037,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
'@isaacs/cliui@9.0.0':
|
||||||
|
resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
'@isaacs/fs-minipass@4.0.1':
|
'@isaacs/fs-minipass@4.0.1':
|
||||||
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
|
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -3085,6 +3095,12 @@ packages:
|
|||||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
glob@11.0.3:
|
||||||
|
resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==}
|
||||||
|
engines: {node: 20 || >=22}
|
||||||
|
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
glob@13.0.6:
|
glob@13.0.6:
|
||||||
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
|
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
|
||||||
engines: {node: 18 || 20 || >=22}
|
engines: {node: 18 || 20 || >=22}
|
||||||
@@ -3307,6 +3323,10 @@ packages:
|
|||||||
jackspeak@3.4.3:
|
jackspeak@3.4.3:
|
||||||
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
||||||
|
|
||||||
|
jackspeak@4.2.3:
|
||||||
|
resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==}
|
||||||
|
engines: {node: 20 || >=22}
|
||||||
|
|
||||||
jest-changed-files@30.4.1:
|
jest-changed-files@30.4.1:
|
||||||
resolution: {integrity: sha512-IuctmYrxi21iOSOaIXpJWalHyPAsVv0GeBHKDn8C1CA4W5htHn7INL+wdnL4Bo0+olEndvAFkmb++tIQJG+vvg==}
|
resolution: {integrity: sha512-IuctmYrxi21iOSOaIXpJWalHyPAsVv0GeBHKDn8C1CA4W5htHn7INL+wdnL4Bo0+olEndvAFkmb++tIQJG+vvg==}
|
||||||
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
|
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||||
@@ -3439,6 +3459,10 @@ packages:
|
|||||||
node-notifier:
|
node-notifier:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
jiti@2.7.0:
|
||||||
|
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
jose@6.2.9:
|
jose@6.2.9:
|
||||||
resolution: {integrity: sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==}
|
resolution: {integrity: sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==}
|
||||||
|
|
||||||
@@ -3507,6 +3531,10 @@ packages:
|
|||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
|
|
||||||
|
kysely@0.29.5:
|
||||||
|
resolution: {integrity: sha512-ooa+eSbBNPTo3MycPEuW5jdrxQdQwdtB3LC3h43FiXQbIry5tR0C5lDG7eealK0E4D7XjrnOP5DIUg/LyjRMYQ==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
leven@3.1.0:
|
leven@3.1.0:
|
||||||
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -3764,6 +3792,17 @@ packages:
|
|||||||
node-int64@0.4.0:
|
node-int64@0.4.0:
|
||||||
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
||||||
|
|
||||||
|
node-pg-migrate@7.9.1:
|
||||||
|
resolution: {integrity: sha512-6z4OSN27ye8aYdX9ZU7NN2PTI5pOp34hTr+22Ej12djIYECq++gT7LPLZVOQXEeVCBOZQLqf87kC3Y36G434OQ==}
|
||||||
|
engines: {node: '>=18.19.0'}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@types/pg': '>=6.0.0 <9.0.0'
|
||||||
|
pg: '>=4.3.0 <9.0.0'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/pg':
|
||||||
|
optional: true
|
||||||
|
|
||||||
node-releases@2.0.53:
|
node-releases@2.0.53:
|
||||||
resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==}
|
resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -5115,7 +5154,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- chokidar
|
- chokidar
|
||||||
|
|
||||||
'@angular/build@21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)))(yaml@2.9.0)':
|
'@angular/build@21.2.21(@angular/compiler-cli@21.2.20(@angular/compiler@21.2.20)(typescript@5.9.3))(@angular/compiler@21.2.20)(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(@angular/platform-browser@21.2.20(@angular/common@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)))(@angular/service-worker@21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2))(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.13.3)(chokidar@5.0.0)(jiti@2.7.0)(postcss@8.5.26)(terser@5.50.0)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)))(yaml@2.9.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ampproject/remapping': 2.3.0
|
'@ampproject/remapping': 2.3.0
|
||||||
'@angular-devkit/architect': 0.2102.21(chokidar@5.0.0)
|
'@angular-devkit/architect': 0.2102.21(chokidar@5.0.0)
|
||||||
@@ -5125,7 +5164,7 @@ snapshots:
|
|||||||
'@babel/helper-annotate-as-pure': 7.27.3
|
'@babel/helper-annotate-as-pure': 7.27.3
|
||||||
'@babel/helper-split-export-declaration': 7.24.7
|
'@babel/helper-split-export-declaration': 7.24.7
|
||||||
'@inquirer/confirm': 5.1.21(@types/node@24.13.3)
|
'@inquirer/confirm': 5.1.21(@types/node@24.13.3)
|
||||||
'@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
'@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
||||||
beasties: 0.4.1
|
beasties: 0.4.1
|
||||||
browserslist: 4.28.8
|
browserslist: 4.28.8
|
||||||
esbuild: 0.28.1
|
esbuild: 0.28.1
|
||||||
@@ -5146,7 +5185,7 @@ snapshots:
|
|||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
undici: 7.29.0
|
undici: 7.29.0
|
||||||
vite: 7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
||||||
watchpack: 2.5.1
|
watchpack: 2.5.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)
|
'@angular/core': 21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2)
|
||||||
@@ -5154,7 +5193,7 @@ snapshots:
|
|||||||
'@angular/service-worker': 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2)
|
'@angular/service-worker': 21.2.20(@angular/core@21.2.20(@angular/compiler@21.2.20)(rxjs@7.8.2))(rxjs@7.8.2)
|
||||||
lmdb: 3.5.1
|
lmdb: 3.5.1
|
||||||
postcss: 8.5.26
|
postcss: 8.5.26
|
||||||
vitest: 4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
vitest: 4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@emnapi/core'
|
- '@emnapi/core'
|
||||||
- '@emnapi/runtime'
|
- '@emnapi/runtime'
|
||||||
@@ -5606,9 +5645,9 @@ snapshots:
|
|||||||
'@esbuild/win32-x64@0.28.1':
|
'@esbuild/win32-x64@0.28.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5)':
|
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.12.2': {}
|
'@eslint-community/regexpp@4.12.2': {}
|
||||||
@@ -5832,6 +5871,8 @@ snapshots:
|
|||||||
wrap-ansi: 8.1.0
|
wrap-ansi: 8.1.0
|
||||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||||
|
|
||||||
|
'@isaacs/cliui@9.0.0': {}
|
||||||
|
|
||||||
'@isaacs/fs-minipass@4.0.1':
|
'@isaacs/fs-minipass@4.0.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
minipass: 7.1.3
|
minipass: 7.1.3
|
||||||
@@ -6756,15 +6797,15 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/yargs-parser': 21.0.3
|
'@types/yargs-parser': 21.0.3
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)':
|
'@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.12.2
|
'@eslint-community/regexpp': 4.12.2
|
||||||
'@typescript-eslint/parser': 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
'@typescript-eslint/scope-manager': 8.67.0
|
'@typescript-eslint/scope-manager': 8.67.0
|
||||||
'@typescript-eslint/type-utils': 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/type-utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
'@typescript-eslint/utils': 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.67.0
|
'@typescript-eslint/visitor-keys': 8.67.0
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
ignore: 7.0.6
|
ignore: 7.0.6
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||||
@@ -6772,14 +6813,14 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.67.0(eslint@9.39.5)(typescript@5.9.3)':
|
'@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.67.0
|
'@typescript-eslint/scope-manager': 8.67.0
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.67.0
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.67.0
|
'@typescript-eslint/visitor-keys': 8.67.0
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -6802,13 +6843,13 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.67.0(eslint@9.39.5)(typescript@5.9.3)':
|
'@typescript-eslint/type-utils@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.67.0
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
||||||
'@typescript-eslint/utils': 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -6831,13 +6872,13 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.67.0(eslint@9.39.5)(typescript@5.9.3)':
|
'@typescript-eslint/utils@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
|
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0))
|
||||||
'@typescript-eslint/scope-manager': 8.67.0
|
'@typescript-eslint/scope-manager': 8.67.0
|
||||||
'@typescript-eslint/types': 8.67.0
|
'@typescript-eslint/types': 8.67.0
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -6919,9 +6960,9 @@ snapshots:
|
|||||||
'@unrs/resolver-binding-win32-x64-msvc@1.12.2':
|
'@unrs/resolver-binding-win32-x64-msvc@1.12.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))':
|
'@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
||||||
|
|
||||||
'@vitest/expect@4.1.10':
|
'@vitest/expect@4.1.10':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6932,13 +6973,13 @@ snapshots:
|
|||||||
chai: 6.2.2
|
chai: 6.2.2
|
||||||
tinyrainbow: 3.1.1
|
tinyrainbow: 3.1.1
|
||||||
|
|
||||||
'@vitest/mocker@4.1.10(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))':
|
'@vitest/mocker@4.1.10(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/spy': 4.1.10
|
'@vitest/spy': 4.1.10
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
||||||
|
|
||||||
'@vitest/pretty-format@4.1.10':
|
'@vitest/pretty-format@4.1.10':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7668,19 +7709,19 @@ snapshots:
|
|||||||
|
|
||||||
escape-string-regexp@4.0.0: {}
|
escape-string-regexp@4.0.0: {}
|
||||||
|
|
||||||
eslint-config-prettier@10.1.8(eslint@9.39.5):
|
eslint-config-prettier@10.1.8(eslint@9.39.5(jiti@2.7.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
|
|
||||||
eslint-plugin-prettier@5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.5))(eslint@9.39.5)(prettier@3.9.6):
|
eslint-plugin-prettier@5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))(prettier@3.9.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
prettier: 3.9.6
|
prettier: 3.9.6
|
||||||
prettier-linter-helpers: 1.0.1
|
prettier-linter-helpers: 1.0.1
|
||||||
synckit: 0.11.13
|
synckit: 0.11.13
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/eslint': 9.6.1
|
'@types/eslint': 9.6.1
|
||||||
eslint-config-prettier: 10.1.8(eslint@9.39.5)
|
eslint-config-prettier: 10.1.8(eslint@9.39.5(jiti@2.7.0))
|
||||||
|
|
||||||
eslint-scope@5.1.1:
|
eslint-scope@5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7698,9 +7739,9 @@ snapshots:
|
|||||||
|
|
||||||
eslint-visitor-keys@5.0.1: {}
|
eslint-visitor-keys@5.0.1: {}
|
||||||
|
|
||||||
eslint@9.39.5:
|
eslint@9.39.5(jiti@2.7.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
|
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0))
|
||||||
'@eslint-community/regexpp': 4.12.2
|
'@eslint-community/regexpp': 4.12.2
|
||||||
'@eslint/config-array': 0.21.2
|
'@eslint/config-array': 0.21.2
|
||||||
'@eslint/config-helpers': 0.4.2
|
'@eslint/config-helpers': 0.4.2
|
||||||
@@ -7734,6 +7775,8 @@ snapshots:
|
|||||||
minimatch: 3.1.5
|
minimatch: 3.1.5
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
optionator: 0.9.4
|
optionator: 0.9.4
|
||||||
|
optionalDependencies:
|
||||||
|
jiti: 2.7.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -8010,6 +8053,15 @@ snapshots:
|
|||||||
package-json-from-dist: 1.0.1
|
package-json-from-dist: 1.0.1
|
||||||
path-scurry: 1.11.1
|
path-scurry: 1.11.1
|
||||||
|
|
||||||
|
glob@11.0.3:
|
||||||
|
dependencies:
|
||||||
|
foreground-child: 3.3.1
|
||||||
|
jackspeak: 4.2.3
|
||||||
|
minimatch: 10.2.6
|
||||||
|
minipass: 7.1.3
|
||||||
|
package-json-from-dist: 1.0.1
|
||||||
|
path-scurry: 2.0.2
|
||||||
|
|
||||||
glob@13.0.6:
|
glob@13.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
minimatch: 10.2.6
|
minimatch: 10.2.6
|
||||||
@@ -8226,6 +8278,10 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@pkgjs/parseargs': 0.11.0
|
'@pkgjs/parseargs': 0.11.0
|
||||||
|
|
||||||
|
jackspeak@4.2.3:
|
||||||
|
dependencies:
|
||||||
|
'@isaacs/cliui': 9.0.0
|
||||||
|
|
||||||
jest-changed-files@30.4.1:
|
jest-changed-files@30.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
execa: 5.1.1
|
execa: 5.1.1
|
||||||
@@ -8544,6 +8600,9 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- ts-node
|
- ts-node
|
||||||
|
|
||||||
|
jiti@2.7.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
jose@6.2.9: {}
|
jose@6.2.9: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
@@ -8616,6 +8675,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
json-buffer: 3.0.1
|
json-buffer: 3.0.1
|
||||||
|
|
||||||
|
kysely@0.29.5: {}
|
||||||
|
|
||||||
leven@3.1.0: {}
|
leven@3.1.0: {}
|
||||||
|
|
||||||
levn@0.4.1:
|
levn@0.4.1:
|
||||||
@@ -8887,6 +8948,14 @@ snapshots:
|
|||||||
|
|
||||||
node-int64@0.4.0: {}
|
node-int64@0.4.0: {}
|
||||||
|
|
||||||
|
node-pg-migrate@7.9.1(@types/pg@8.21.0)(pg@8.23.0):
|
||||||
|
dependencies:
|
||||||
|
glob: 11.0.3
|
||||||
|
pg: 8.23.0
|
||||||
|
yargs: 17.7.3
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/pg': 8.21.0
|
||||||
|
|
||||||
node-releases@2.0.53: {}
|
node-releases@2.0.53: {}
|
||||||
|
|
||||||
nopt@9.0.0:
|
nopt@9.0.0:
|
||||||
@@ -9776,13 +9845,13 @@ snapshots:
|
|||||||
|
|
||||||
typedarray@0.0.6: {}
|
typedarray@0.0.6: {}
|
||||||
|
|
||||||
typescript-eslint@8.67.0(eslint@9.39.5)(typescript@5.9.3):
|
typescript-eslint@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5)(typescript@5.9.3))(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
'@typescript-eslint/parser': 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.67.0(typescript@5.9.3)
|
||||||
'@typescript-eslint/utils': 8.67.0(eslint@9.39.5)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)
|
||||||
eslint: 9.39.5
|
eslint: 9.39.5(jiti@2.7.0)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -9859,7 +9928,7 @@ snapshots:
|
|||||||
|
|
||||||
vary@1.1.2: {}
|
vary@1.1.2: {}
|
||||||
|
|
||||||
vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0):
|
vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.28.1
|
esbuild: 0.28.1
|
||||||
fdir: 6.5.0(picomatch@4.0.4)
|
fdir: 6.5.0(picomatch@4.0.4)
|
||||||
@@ -9870,14 +9939,15 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 24.13.3
|
'@types/node': 24.13.3
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
jiti: 2.7.0
|
||||||
sass: 1.97.3
|
sass: 1.97.3
|
||||||
terser: 5.50.0
|
terser: 5.50.0
|
||||||
yaml: 2.9.0
|
yaml: 2.9.0
|
||||||
|
|
||||||
vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)):
|
vitest@4.1.10(@types/node@24.13.3)(jsdom@28.1.0(@noble/hashes@1.8.0))(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/expect': 4.1.10
|
'@vitest/expect': 4.1.10
|
||||||
'@vitest/mocker': 4.1.10(vite@7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
'@vitest/mocker': 4.1.10(vite@7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0))
|
||||||
'@vitest/pretty-format': 4.1.10
|
'@vitest/pretty-format': 4.1.10
|
||||||
'@vitest/runner': 4.1.10
|
'@vitest/runner': 4.1.10
|
||||||
'@vitest/snapshot': 4.1.10
|
'@vitest/snapshot': 4.1.10
|
||||||
@@ -9894,7 +9964,7 @@ snapshots:
|
|||||||
tinyexec: 1.3.0
|
tinyexec: 1.3.0
|
||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
tinyrainbow: 3.1.1
|
tinyrainbow: 3.1.1
|
||||||
vite: 7.3.6(@types/node@24.13.3)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
vite: 7.3.6(@types/node@24.13.3)(jiti@2.7.0)(sass@1.97.3)(terser@5.50.0)(yaml@2.9.0)
|
||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 24.13.3
|
'@types/node': 24.13.3
|
||||||
|
|||||||
Reference in New Issue
Block a user