@conorroberts/utils 0.0.113 → 0.0.117
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/migrate.mjs +1 -2
- package/dist/db/migrate.mjs.map +1 -1
- package/dist/db/validate-schema.mjs +1 -2
- package/dist/db/validate-schema.mjs.map +1 -1
- package/dist/env.d.mts +0 -1
- package/dist/env.mjs +2 -3
- package/dist/env.mjs.map +1 -1
- package/dist/images.mjs +1 -2
- package/dist/images.mjs.map +1 -1
- package/dist/oxlint/config.json +36 -3
- package/dist/oxlint/index.d.mts +2 -2
- package/dist/oxlint/index.mjs +67 -181
- package/dist/oxlint/index.mjs.map +1 -1
- package/dist/react.mjs +1 -6
- package/dist/react.mjs.map +1 -1
- package/dist/vscode/settings.json +47 -0
- package/package.json +16 -8
package/dist/db/migrate.mjs
CHANGED
|
@@ -5,7 +5,6 @@ import { drizzle } from "drizzle-orm/planetscale-serverless";
|
|
|
5
5
|
import { migrate } from "drizzle-orm/planetscale-serverless/migrator";
|
|
6
6
|
import { getTableName } from "drizzle-orm/table";
|
|
7
7
|
import { resolve } from "node:path";
|
|
8
|
-
|
|
9
8
|
//#region src/db/migrate.ts
|
|
10
9
|
const escapeIdentifier = (value) => {
|
|
11
10
|
return `\`${value.replaceAll("`", "``")}\``;
|
|
@@ -113,7 +112,7 @@ const runMigrations = async (options) => {
|
|
|
113
112
|
});
|
|
114
113
|
consola.log("[OK] Migrations completed successfully!");
|
|
115
114
|
};
|
|
116
|
-
|
|
117
115
|
//#endregion
|
|
118
116
|
export { runMigrations };
|
|
117
|
+
|
|
119
118
|
//# sourceMappingURL=migrate.mjs.map
|
package/dist/db/migrate.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.mjs","names":[
|
|
1
|
+
{"version":3,"file":"migrate.mjs","names":[],"sources":["../../src/db/migrate.ts"],"sourcesContent":["import { consola } from \"consola\";\nimport { sql } from \"drizzle-orm\";\nimport { DrizzleQueryError } from \"drizzle-orm/errors\";\nimport { drizzle } from \"drizzle-orm/planetscale-serverless\";\nimport { migrate } from \"drizzle-orm/planetscale-serverless/migrator\";\nimport { getTableName } from \"drizzle-orm/table\";\nimport { resolve } from \"node:path\";\nimport type { DrizzleSchema } from \"./types\";\n\ntype SchemaTableName<TSchema extends DrizzleSchema> = TSchema[keyof TSchema][\"_\"][\"name\"];\n\ninterface MigrateConnectionOptions {\n migrationsFolder: string;\n host: string;\n username: string;\n password: string;\n}\n\ninterface MigrateSharedOptions<TSchema extends DrizzleSchema> extends MigrateConnectionOptions {\n deleteOrder?: SchemaTableName<TSchema>[];\n migrationsTable?: string;\n}\n\ntype CleanMigrateOptions<TSchema extends DrizzleSchema> = MigrateSharedOptions<TSchema> & {\n clean: true;\n schema: TSchema;\n};\n\ntype StandardMigrateOptions<TSchema extends DrizzleSchema> = MigrateSharedOptions<TSchema> & {\n clean?: false;\n schema?: TSchema;\n};\n\ntype MigrateOptions<TSchema extends DrizzleSchema = DrizzleSchema> =\n | CleanMigrateOptions<TSchema>\n | StandardMigrateOptions<TSchema>;\n\ninterface DeleteResult {\n table: string;\n rowsDeleted: number;\n success: boolean;\n error?: string;\n}\n\nconst escapeIdentifier = (value: string): string => {\n return `\\`${value.replaceAll(\"`\", \"``\")}\\``;\n};\n\nconst parseError = (error: unknown): string => {\n if (error instanceof DrizzleQueryError) {\n if (error.cause instanceof Error) {\n return error.cause.message;\n }\n\n return error.message;\n }\n\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n};\n\nconst buildDeleteOrder = <TTableName extends string>(tableNames: TTableName[], preferredOrder: TTableName[]) => {\n const seen = new Set<string>();\n const ordered: TTableName[] = [];\n\n for (const tableName of preferredOrder) {\n if (seen.has(tableName)) {\n continue;\n }\n\n seen.add(tableName);\n\n if (tableNames.includes(tableName)) {\n ordered.push(tableName);\n }\n }\n\n for (const tableName of tableNames) {\n if (!seen.has(tableName)) {\n ordered.push(tableName);\n }\n }\n\n return ordered;\n};\n\nconst listSchemaTables = <TSchema extends DrizzleSchema>(schema: TSchema): SchemaTableName<TSchema>[] => {\n const tableNames: Set<SchemaTableName<TSchema>> = new Set();\n const tables = Object.values(schema) as TSchema[keyof TSchema][];\n\n for (const table of tables) {\n const tableName = getTableName(table) as SchemaTableName<TSchema>;\n\n tableNames.add(tableName);\n }\n\n return Array.from(tableNames);\n};\n\nconst deleteTableRows = async (db: ReturnType<typeof drizzle>, tableNames: string[]): Promise<DeleteResult[]> => {\n const results: DeleteResult[] = [];\n\n for (const tableName of tableNames) {\n try {\n const rowsDeleted = await db.$count(sql.raw(tableName));\n\n await db.execute(sql.raw(`DELETE FROM ${tableName}`));\n\n results.push({\n table: tableName,\n rowsDeleted,\n success: true,\n });\n\n const status = rowsDeleted > 0 ? `[OK] Deleted ${rowsDeleted} rows` : \"[SKIP] Empty\";\n consola.log(`${status.padEnd(30)} from ${tableName}`);\n } catch (error) {\n const errorDetails = parseError(error) || String(error);\n\n results.push({\n table: tableName,\n rowsDeleted: 0,\n success: false,\n error: errorDetails,\n });\n\n consola.error(`[FAIL] Failed to delete from ${tableName}: ${errorDetails}`);\n }\n }\n\n return results;\n};\n\nconst dropTables = async (db: ReturnType<typeof drizzle>, tableNames: string[]): Promise<void> => {\n for (const tableName of tableNames) {\n try {\n await db.execute(sql.raw(`DROP TABLE IF EXISTS ${escapeIdentifier(tableName)}`));\n consola.log(`[OK] Dropped table ${tableName}`);\n } catch (error) {\n const errorDetails = parseError(error) || String(error);\n consola.error(`[FAIL] Failed to drop ${tableName}: ${errorDetails}`);\n }\n }\n};\n\nconst cleanDatabase = async (\n db: ReturnType<typeof drizzle>,\n options: CleanMigrateOptions<DrizzleSchema>,\n): Promise<void> => {\n if (process.env.UNSAFE_CONFIRM_DELETE !== \"true\") {\n consola.error('Refusing to clean database. Set UNSAFE_CONFIRM_DELETE=\"true\" to continue.');\n process.exit(1);\n }\n\n const tableNames = listSchemaTables(options.schema);\n const allTableNames = options.migrationsTable ? [...tableNames, options.migrationsTable] : tableNames;\n\n if (allTableNames.length === 0) {\n consola.log(\"Clean requested, but no tables were found in the provided Drizzle schema.\");\n return;\n }\n\n const ordered = buildDeleteOrder(allTableNames, options.deleteOrder ?? []);\n\n consola.warn(\"WARNING: This will delete and drop ALL tables from the database.\");\n consola.log(`Database host: ${db.$client.config.host}`);\n\n consola.log(\"\");\n consola.log(\"Deleting table rows in order...\\n\");\n\n const results = await deleteTableRows(db, ordered);\n\n consola.log(\"\\nDropping tables in order...\\n\");\n await dropTables(db, ordered);\n\n const successCount = results.filter((result) => result.success).length;\n const totalRowsDeleted = results.reduce((sum, result) => sum + result.rowsDeleted, 0);\n\n consola.log(\"\");\n consola.log(\"=\".repeat(60));\n consola.log(\"SUMMARY\");\n consola.log(\"=\".repeat(60));\n consola.log(`Deletion phase: ${successCount} tables processed, ${totalRowsDeleted} rows deleted`);\n consola.success(\"Database is now empty and ready for migrations.\");\n};\n\nconst runMigrations = async <TSchema extends DrizzleSchema>(options: MigrateOptions<TSchema>) => {\n const db = drizzle({\n connection: {\n host: options.host,\n username: options.username,\n password: options.password,\n },\n });\n\n if (options.clean) {\n await cleanDatabase(db, options);\n }\n\n consola.log(\"Running database migrations...\");\n await migrate(db, { migrationsFolder: resolve(options.migrationsFolder), migrationsTable: options.migrationsTable });\n consola.log(\"[OK] Migrations completed successfully!\");\n};\n\nexport { runMigrations };\nexport type { DrizzleSchema, MigrateOptions, SchemaTableName };\n"],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { consola } from "consola";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
|
-
|
|
5
4
|
//#region src/db/validateSchema.ts
|
|
6
5
|
/**
|
|
7
6
|
* Database Schema Validator
|
|
@@ -336,7 +335,7 @@ const validateDatabaseSchema = (options) => {
|
|
|
336
335
|
consola.log("");
|
|
337
336
|
return finalize(1);
|
|
338
337
|
};
|
|
339
|
-
|
|
340
338
|
//#endregion
|
|
341
339
|
export { validateDatabaseSchema };
|
|
340
|
+
|
|
342
341
|
//# sourceMappingURL=validate-schema.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-schema.mjs","names":["entries: JournalEntry[]","issues: ValidationIssue[]","allConstraints: Array<{ table: string; type: string; name: string; length: number }>","parts: string[]"],"sources":["../../src/db/validateSchema.ts"],"sourcesContent":["/**\n * Database Schema Validator\n *\n * This script validates the database schema by analyzing all MySQL table definitions\n * from Drizzle migration metadata and reports any table, column, or constraint names\n * that exceed MySQL's maximum length limits.\n *\n * MySQL Limits:\n * - Table/Column names: 64 characters\n * - Constraint names: 64 characters\n *\n * Usage:\n * - Basic: pnpm -F scripts validate:db-schema\n * - Verbose: pnpm -F scripts validate:db-schema -- --verbose\n *\n * The verbose mode shows all constraint names being checked, sorted by length.\n *\n * This validation runs automatically:\n * - After `pnpm generate` (blocks if violations found)\n * - In CI/CD as part of PR checks\n */\n\nimport { consola } from \"consola\";\nimport { readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\n\ninterface NameLengthIssue {\n type: \"table\" | \"column\" | \"constraint\";\n tableName: string;\n name: string;\n actualLength: number;\n maxLength: number;\n constraintType?: \"foreign_key\" | \"primary_key\" | \"unique\" | \"index\";\n}\n\ninterface IndexWidthIssue {\n type: \"index_width\";\n tableName: string;\n name: string;\n keyType: \"primary_key\" | \"unique\" | \"index\";\n actualBytes: number;\n maxBytes: number;\n columns: string[];\n}\n\ntype ValidationIssue = NameLengthIssue | IndexWidthIssue;\n\ninterface DrizzleSnapshot {\n tables: Record<string, DrizzleTable>;\n}\n\ninterface DrizzleTable {\n name: string;\n columns: Record<string, DrizzleColumn>;\n indexes: Record<string, DrizzleIndex>;\n foreignKeys: Record<string, DrizzleForeignKey>;\n compositePrimaryKeys: Record<string, DrizzlePrimaryKey>;\n uniqueConstraints: Record<string, DrizzleUniqueConstraint>;\n}\n\ninterface DrizzleColumn {\n name: string;\n type: string;\n primaryKey: boolean;\n notNull: boolean;\n autoincrement: boolean;\n}\n\ninterface DrizzleIndex {\n name: string;\n columns: string[];\n isUnique?: boolean;\n}\n\ninterface DrizzleForeignKey {\n name: string;\n tableFrom: string;\n tableTo: string;\n columnsFrom: string[];\n columnsTo: string[];\n}\n\ninterface DrizzlePrimaryKey {\n name: string;\n columns: string[];\n}\n\ninterface DrizzleUniqueConstraint {\n name: string;\n columns: string[];\n}\n\nconst MAX_IDENTIFIER_LENGTH = 64;\nconst MAX_CONSTRAINT_NAME_LENGTH = 64;\nconst MYSQL_MAX_INDEX_BYTES = 3072;\nconst UTF8MB4_BYTES_PER_CHAR = 4;\n\nconst getLatestSnapshot = (metaDir: string): DrizzleSnapshot => {\n const resolvedMetaDir = resolve(metaDir);\n\n // Read the journal to find the latest migration\n const journalPath = join(resolvedMetaDir, \"_journal.json\");\n const parsedJournal = JSON.parse(readFileSync(journalPath, \"utf-8\"));\n\n interface JournalEntry {\n tag: string;\n idx: number;\n }\n\n const entries: JournalEntry[] = parsedJournal.entries;\n const latestEntry = entries[entries.length - 1];\n\n if (!latestEntry) {\n throw new Error(\"No migrations found in journal\");\n }\n\n // Read the latest snapshot\n const snapshotPath = join(resolvedMetaDir, `${latestEntry.idx.toString().padStart(4, \"0\")}_snapshot.json`);\n const parsedSnapshot = JSON.parse(readFileSync(snapshotPath, \"utf-8\"));\n const snapshot: DrizzleSnapshot = parsedSnapshot;\n\n return snapshot;\n};\n\ninterface ValidateDatabaseSchemaOptions {\n metaDir: string;\n verbose?: boolean;\n exitOnComplete?: boolean;\n}\n\nconst getTypeByteLength = (columnType: string): number => {\n const normalizedType = columnType.toLowerCase().trim();\n\n const varcharMatch = normalizedType.match(/^varchar\\((\\d+)\\)$/);\n if (varcharMatch) {\n return Number(varcharMatch[1]) * UTF8MB4_BYTES_PER_CHAR;\n }\n\n const charMatch = normalizedType.match(/^char\\((\\d+)\\)$/);\n if (charMatch) {\n return Number(charMatch[1]) * UTF8MB4_BYTES_PER_CHAR;\n }\n\n const varbinaryMatch = normalizedType.match(/^varbinary\\((\\d+)\\)$/);\n if (varbinaryMatch) {\n return Number(varbinaryMatch[1]);\n }\n\n const binaryMatch = normalizedType.match(/^binary\\((\\d+)\\)$/);\n if (binaryMatch) {\n return Number(binaryMatch[1]);\n }\n\n if (normalizedType.startsWith(\"tinyint\")) return 1;\n if (normalizedType.startsWith(\"smallint\")) return 2;\n if (normalizedType.startsWith(\"mediumint\")) return 3;\n if (normalizedType.startsWith(\"int\")) return 4;\n if (normalizedType.startsWith(\"bigint\")) return 8;\n if (normalizedType.startsWith(\"date\")) return 3;\n if (normalizedType.startsWith(\"datetime\")) return 8;\n if (normalizedType.startsWith(\"timestamp\")) return 4;\n\n if (normalizedType.includes(\"text\") || normalizedType === \"json\" || normalizedType.includes(\"blob\")) {\n return Number.POSITIVE_INFINITY;\n }\n\n return 0;\n};\n\nconst getKeyTypeLabel = (keyType: IndexWidthIssue[\"keyType\"]): string => {\n if (keyType === \"primary_key\") return \"Primary Keys\";\n if (keyType === \"unique\") return \"Unique Indexes\";\n return \"Indexes\";\n};\n\nconst validateDatabaseSchema = (options: ValidateDatabaseSchemaOptions): number => {\n const { metaDir, verbose = false, exitOnComplete = false } = options;\n const issues: ValidationIssue[] = [];\n const allConstraints: Array<{ table: string; type: string; name: string; length: number }> = [];\n const finalize = (exitCode: number): number => {\n if (exitOnComplete) {\n process.exit(exitCode);\n }\n\n return exitCode;\n };\n\n const snapshot = getLatestSnapshot(metaDir);\n const tables = Object.values(snapshot.tables);\n const validateIndexWidth = (\n table: DrizzleTable,\n args: {\n name: string;\n columns: string[];\n keyType: IndexWidthIssue[\"keyType\"];\n },\n ) => {\n const actualBytes = args.columns.reduce((total, columnName) => {\n const column = table.columns[columnName];\n\n if (!column) {\n return total;\n }\n\n return total + getTypeByteLength(column.type);\n }, 0);\n\n if (actualBytes > MYSQL_MAX_INDEX_BYTES || !Number.isFinite(actualBytes)) {\n issues.push({\n type: \"index_width\",\n tableName: table.name,\n name: args.name,\n keyType: args.keyType,\n actualBytes,\n maxBytes: MYSQL_MAX_INDEX_BYTES,\n columns: args.columns,\n });\n }\n };\n\n tables.forEach((table) => {\n // Check table name length\n if (table.name.length > MAX_IDENTIFIER_LENGTH) {\n issues.push({\n type: \"table\",\n tableName: table.name,\n name: table.name,\n actualLength: table.name.length,\n maxLength: MAX_IDENTIFIER_LENGTH,\n });\n }\n\n // Check column name lengths\n Object.values(table.columns).forEach((column) => {\n if (column.name.length > MAX_IDENTIFIER_LENGTH) {\n issues.push({\n type: \"column\",\n tableName: table.name,\n name: column.name,\n actualLength: column.name.length,\n maxLength: MAX_IDENTIFIER_LENGTH,\n });\n }\n });\n\n // Check foreign key constraint names\n Object.values(table.foreignKeys).forEach((fk) => {\n allConstraints.push({ table: table.name, type: \"FK\", name: fk.name, length: fk.name.length });\n if (fk.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: fk.name,\n actualLength: fk.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"foreign_key\",\n });\n }\n });\n\n // Check primary key constraint names\n Object.values(table.compositePrimaryKeys).forEach((pk) => {\n const pkType = pk.columns.length > 1 ? \"PK (composite)\" : \"PK\";\n allConstraints.push({ table: table.name, type: pkType, name: pk.name, length: pk.name.length });\n if (pk.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: pk.name,\n actualLength: pk.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"primary_key\",\n });\n }\n\n validateIndexWidth(table, {\n name: pk.name,\n columns: pk.columns,\n keyType: \"primary_key\",\n });\n });\n\n // Check unique constraint names\n Object.values(table.uniqueConstraints).forEach((unique) => {\n allConstraints.push({ table: table.name, type: \"UNIQUE\", name: unique.name, length: unique.name.length });\n if (unique.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: unique.name,\n actualLength: unique.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"unique\",\n });\n }\n\n validateIndexWidth(table, {\n name: unique.name,\n columns: unique.columns,\n keyType: \"unique\",\n });\n });\n\n // Check index names\n Object.values(table.indexes).forEach((index) => {\n allConstraints.push({ table: table.name, type: \"INDEX\", name: index.name, length: index.name.length });\n if (index.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: index.name,\n actualLength: index.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"index\",\n });\n }\n\n validateIndexWidth(table, {\n name: index.name,\n columns: index.columns,\n keyType: index.isUnique ? \"unique\" : \"index\",\n });\n });\n });\n\n // Verbose mode: show all constraints checked\n if (verbose) {\n consola.box(\"All Constraints Checked\");\n const sortedConstraints = allConstraints.sort((a, b) => b.length - a.length);\n sortedConstraints.forEach((constraint) => {\n const exceeds = constraint.length > MAX_CONSTRAINT_NAME_LENGTH;\n const lengthStr = `[${constraint.length.toString().padStart(2)} chars]`;\n const typeStr = constraint.type.padEnd(15);\n const message = `${lengthStr} ${typeStr} ${constraint.name} (${constraint.table})`;\n if (exceeds) {\n consola.error(message);\n } else {\n consola.success(message);\n }\n });\n consola.log(\"\");\n }\n\n // Print report\n consola.box(\"MySQL Schema Analysis\");\n consola.info(`Maximum identifier length: ${MAX_IDENTIFIER_LENGTH} characters`);\n consola.info(`Maximum constraint name length: ${MAX_CONSTRAINT_NAME_LENGTH} characters`);\n consola.info(`Maximum index key length: ${MYSQL_MAX_INDEX_BYTES} bytes`);\n consola.info(`Analyzed ${tables.length} tables`);\n consola.log(\"\");\n\n // Show table summary\n consola.start(\"Tables analyzed:\");\n tables.forEach((table) => {\n const columnCount = Object.keys(table.columns).length;\n const fkCount = Object.keys(table.foreignKeys).length;\n const pkCount = Object.keys(table.compositePrimaryKeys).length;\n const uniqueCount = Object.keys(table.uniqueConstraints).length;\n const indexCount = Object.keys(table.indexes).length;\n\n const parts: string[] = [];\n parts.push(`${columnCount} columns`);\n if (fkCount > 0) {\n parts.push(`${fkCount} FKs`);\n }\n if (pkCount > 0) {\n parts.push(`${pkCount} PKs`);\n }\n if (uniqueCount > 0) {\n parts.push(`${uniqueCount} unique`);\n }\n if (indexCount > 0) {\n parts.push(`${indexCount} indexes`);\n }\n\n consola.log(` - ${table.name} (${parts.join(\", \")})`);\n });\n consola.log(\"\");\n\n if (issues.length === 0) {\n consola.success(\"No schema validation issues found!\");\n return finalize(0);\n }\n\n consola.warn(`Found ${issues.length} schema validation issue(s):`);\n consola.log(\"\");\n\n const tableIssues = issues.filter((i): i is NameLengthIssue => i.type === \"table\");\n const columnIssues = issues.filter((i): i is NameLengthIssue => i.type === \"column\");\n const constraintIssues = issues.filter((i): i is NameLengthIssue => i.type === \"constraint\");\n const indexWidthIssues = issues.filter((i): i is IndexWidthIssue => i.type === \"index_width\");\n\n if (tableIssues.length > 0) {\n consola.error(\"Table Name Issues:\");\n tableIssues.forEach((issue) => {\n consola.log(\n ` - Table: ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n });\n consola.log(\"\");\n }\n\n if (columnIssues.length > 0) {\n consola.error(\"Column Name Issues:\");\n columnIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.tableName}.${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n });\n consola.log(\"\");\n }\n\n if (constraintIssues.length > 0) {\n consola.error(\"Constraint Name Issues:\");\n const fkIssues = constraintIssues.filter((i) => i.constraintType === \"foreign_key\");\n const pkIssues = constraintIssues.filter((i) => i.constraintType === \"primary_key\");\n const uniqueIssues = constraintIssues.filter((i) => i.constraintType === \"unique\");\n const indexIssues = constraintIssues.filter((i) => i.constraintType === \"index\");\n\n if (fkIssues.length > 0) {\n consola.log(\" Foreign Keys:\");\n fkIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n\n if (pkIssues.length > 0) {\n consola.log(\" Primary Keys:\");\n pkIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n\n if (uniqueIssues.length > 0) {\n consola.log(\" Unique Constraints:\");\n uniqueIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n\n if (indexIssues.length > 0) {\n consola.log(\" Indexes:\");\n indexIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n consola.log(\"\");\n }\n\n if (indexWidthIssues.length > 0) {\n consola.error(\"Index Width Issues:\");\n const primaryKeyWidthIssues = indexWidthIssues.filter((issue) => issue.keyType === \"primary_key\");\n const uniqueWidthIssues = indexWidthIssues.filter((issue) => issue.keyType === \"unique\");\n const indexOnlyWidthIssues = indexWidthIssues.filter((issue) => issue.keyType === \"index\");\n\n for (const issueGroup of [primaryKeyWidthIssues, uniqueWidthIssues, indexOnlyWidthIssues]) {\n if (issueGroup.length === 0) {\n continue;\n }\n\n consola.log(` ${getKeyTypeLabel(issueGroup[0]!.keyType)}:`);\n issueGroup.forEach((issue) => {\n const actualBytes = Number.isFinite(issue.actualBytes) ? issue.actualBytes.toString() : \"unbounded\";\n consola.log(\n ` - ${issue.name} (${actualBytes} bytes, exceeds max by ${\n Number.isFinite(issue.actualBytes) ? issue.actualBytes - issue.maxBytes : \"unknown amount\"\n })`,\n );\n consola.log(` Table: ${issue.tableName}`);\n consola.log(` Columns: ${issue.columns.join(\", \")}`);\n });\n }\n\n consola.log(\"\");\n }\n\n consola.box(\"Summary\");\n consola.info(`Total issues: ${issues.length}`);\n consola.info(` - Table names: ${tableIssues.length}`);\n consola.info(` - Column names: ${columnIssues.length}`);\n consola.info(` - Constraint names: ${constraintIssues.length}`);\n consola.info(` - Index widths: ${indexWidthIssues.length}`);\n if (constraintIssues.length > 0) {\n const fkCount = constraintIssues.filter((i) => i.constraintType === \"foreign_key\").length;\n const pkCount = constraintIssues.filter((i) => i.constraintType === \"primary_key\").length;\n const uniqueCount = constraintIssues.filter((i) => i.constraintType === \"unique\").length;\n const indexCount = constraintIssues.filter((i) => i.constraintType === \"index\").length;\n consola.info(` - Foreign keys: ${fkCount}`);\n consola.info(` - Primary keys: ${pkCount}`);\n consola.info(` - Unique constraints: ${uniqueCount}`);\n consola.info(` - Indexes: ${indexCount}`);\n }\n if (indexWidthIssues.length > 0) {\n const pkWidthCount = indexWidthIssues.filter((i) => i.keyType === \"primary_key\").length;\n const uniqueWidthCount = indexWidthIssues.filter((i) => i.keyType === \"unique\").length;\n const indexWidthCount = indexWidthIssues.filter((i) => i.keyType === \"index\").length;\n consola.info(` - Primary keys: ${pkWidthCount}`);\n consola.info(` - Unique indexes: ${uniqueWidthCount}`);\n consola.info(` - Indexes: ${indexWidthCount}`);\n }\n consola.log(\"\");\n\n // Print actionable feedback\n consola.fail(\"MIGRATION BLOCKED: Schema validation violations detected!\");\n consola.log(\"\");\n consola.start(\"Action required:\");\n consola.log(\"1. Review the issues listed above\");\n consola.log(\"2. Shorten table/column/constraint names where required\");\n consola.log(\"3. Reduce indexed column widths or introduce prefix/hash columns for oversized indexes\");\n consola.log(\"4. Run 'pnpm generate' again after making changes\");\n consola.log(\"5. Run this check with --verbose to see all constraint names\");\n consola.log(\"\");\n\n return finalize(1);\n};\n\nexport { validateDatabaseSchema };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validate-schema.mjs","names":[],"sources":["../../src/db/validateSchema.ts"],"sourcesContent":["/**\n * Database Schema Validator\n *\n * This script validates the database schema by analyzing all MySQL table definitions\n * from Drizzle migration metadata and reports any table, column, or constraint names\n * that exceed MySQL's maximum length limits.\n *\n * MySQL Limits:\n * - Table/Column names: 64 characters\n * - Constraint names: 64 characters\n *\n * Usage:\n * - Basic: pnpm -F scripts validate:db-schema\n * - Verbose: pnpm -F scripts validate:db-schema -- --verbose\n *\n * The verbose mode shows all constraint names being checked, sorted by length.\n *\n * This validation runs automatically:\n * - After `pnpm generate` (blocks if violations found)\n * - In CI/CD as part of PR checks\n */\n\nimport { consola } from \"consola\";\nimport { readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\n\ninterface NameLengthIssue {\n type: \"table\" | \"column\" | \"constraint\";\n tableName: string;\n name: string;\n actualLength: number;\n maxLength: number;\n constraintType?: \"foreign_key\" | \"primary_key\" | \"unique\" | \"index\";\n}\n\ninterface IndexWidthIssue {\n type: \"index_width\";\n tableName: string;\n name: string;\n keyType: \"primary_key\" | \"unique\" | \"index\";\n actualBytes: number;\n maxBytes: number;\n columns: string[];\n}\n\ntype ValidationIssue = NameLengthIssue | IndexWidthIssue;\n\ninterface DrizzleSnapshot {\n tables: Record<string, DrizzleTable>;\n}\n\ninterface DrizzleTable {\n name: string;\n columns: Record<string, DrizzleColumn>;\n indexes: Record<string, DrizzleIndex>;\n foreignKeys: Record<string, DrizzleForeignKey>;\n compositePrimaryKeys: Record<string, DrizzlePrimaryKey>;\n uniqueConstraints: Record<string, DrizzleUniqueConstraint>;\n}\n\ninterface DrizzleColumn {\n name: string;\n type: string;\n primaryKey: boolean;\n notNull: boolean;\n autoincrement: boolean;\n}\n\ninterface DrizzleIndex {\n name: string;\n columns: string[];\n isUnique?: boolean;\n}\n\ninterface DrizzleForeignKey {\n name: string;\n tableFrom: string;\n tableTo: string;\n columnsFrom: string[];\n columnsTo: string[];\n}\n\ninterface DrizzlePrimaryKey {\n name: string;\n columns: string[];\n}\n\ninterface DrizzleUniqueConstraint {\n name: string;\n columns: string[];\n}\n\nconst MAX_IDENTIFIER_LENGTH = 64;\nconst MAX_CONSTRAINT_NAME_LENGTH = 64;\nconst MYSQL_MAX_INDEX_BYTES = 3072;\nconst UTF8MB4_BYTES_PER_CHAR = 4;\n\nconst getLatestSnapshot = (metaDir: string): DrizzleSnapshot => {\n const resolvedMetaDir = resolve(metaDir);\n\n // Read the journal to find the latest migration\n const journalPath = join(resolvedMetaDir, \"_journal.json\");\n const parsedJournal = JSON.parse(readFileSync(journalPath, \"utf-8\"));\n\n interface JournalEntry {\n tag: string;\n idx: number;\n }\n\n const entries: JournalEntry[] = parsedJournal.entries;\n const latestEntry = entries[entries.length - 1];\n\n if (!latestEntry) {\n throw new Error(\"No migrations found in journal\");\n }\n\n // Read the latest snapshot\n const snapshotPath = join(resolvedMetaDir, `${latestEntry.idx.toString().padStart(4, \"0\")}_snapshot.json`);\n const parsedSnapshot = JSON.parse(readFileSync(snapshotPath, \"utf-8\"));\n const snapshot: DrizzleSnapshot = parsedSnapshot;\n\n return snapshot;\n};\n\ninterface ValidateDatabaseSchemaOptions {\n metaDir: string;\n verbose?: boolean;\n exitOnComplete?: boolean;\n}\n\nconst getTypeByteLength = (columnType: string): number => {\n const normalizedType = columnType.toLowerCase().trim();\n\n const varcharMatch = normalizedType.match(/^varchar\\((\\d+)\\)$/);\n if (varcharMatch) {\n return Number(varcharMatch[1]) * UTF8MB4_BYTES_PER_CHAR;\n }\n\n const charMatch = normalizedType.match(/^char\\((\\d+)\\)$/);\n if (charMatch) {\n return Number(charMatch[1]) * UTF8MB4_BYTES_PER_CHAR;\n }\n\n const varbinaryMatch = normalizedType.match(/^varbinary\\((\\d+)\\)$/);\n if (varbinaryMatch) {\n return Number(varbinaryMatch[1]);\n }\n\n const binaryMatch = normalizedType.match(/^binary\\((\\d+)\\)$/);\n if (binaryMatch) {\n return Number(binaryMatch[1]);\n }\n\n if (normalizedType.startsWith(\"tinyint\")) return 1;\n if (normalizedType.startsWith(\"smallint\")) return 2;\n if (normalizedType.startsWith(\"mediumint\")) return 3;\n if (normalizedType.startsWith(\"int\")) return 4;\n if (normalizedType.startsWith(\"bigint\")) return 8;\n if (normalizedType.startsWith(\"date\")) return 3;\n if (normalizedType.startsWith(\"datetime\")) return 8;\n if (normalizedType.startsWith(\"timestamp\")) return 4;\n\n if (normalizedType.includes(\"text\") || normalizedType === \"json\" || normalizedType.includes(\"blob\")) {\n return Number.POSITIVE_INFINITY;\n }\n\n return 0;\n};\n\nconst getKeyTypeLabel = (keyType: IndexWidthIssue[\"keyType\"]): string => {\n if (keyType === \"primary_key\") return \"Primary Keys\";\n if (keyType === \"unique\") return \"Unique Indexes\";\n return \"Indexes\";\n};\n\nconst validateDatabaseSchema = (options: ValidateDatabaseSchemaOptions): number => {\n const { metaDir, verbose = false, exitOnComplete = false } = options;\n const issues: ValidationIssue[] = [];\n const allConstraints: Array<{ table: string; type: string; name: string; length: number }> = [];\n const finalize = (exitCode: number): number => {\n if (exitOnComplete) {\n process.exit(exitCode);\n }\n\n return exitCode;\n };\n\n const snapshot = getLatestSnapshot(metaDir);\n const tables = Object.values(snapshot.tables);\n const validateIndexWidth = (\n table: DrizzleTable,\n args: {\n name: string;\n columns: string[];\n keyType: IndexWidthIssue[\"keyType\"];\n },\n ) => {\n const actualBytes = args.columns.reduce((total, columnName) => {\n const column = table.columns[columnName];\n\n if (!column) {\n return total;\n }\n\n return total + getTypeByteLength(column.type);\n }, 0);\n\n if (actualBytes > MYSQL_MAX_INDEX_BYTES || !Number.isFinite(actualBytes)) {\n issues.push({\n type: \"index_width\",\n tableName: table.name,\n name: args.name,\n keyType: args.keyType,\n actualBytes,\n maxBytes: MYSQL_MAX_INDEX_BYTES,\n columns: args.columns,\n });\n }\n };\n\n tables.forEach((table) => {\n // Check table name length\n if (table.name.length > MAX_IDENTIFIER_LENGTH) {\n issues.push({\n type: \"table\",\n tableName: table.name,\n name: table.name,\n actualLength: table.name.length,\n maxLength: MAX_IDENTIFIER_LENGTH,\n });\n }\n\n // Check column name lengths\n Object.values(table.columns).forEach((column) => {\n if (column.name.length > MAX_IDENTIFIER_LENGTH) {\n issues.push({\n type: \"column\",\n tableName: table.name,\n name: column.name,\n actualLength: column.name.length,\n maxLength: MAX_IDENTIFIER_LENGTH,\n });\n }\n });\n\n // Check foreign key constraint names\n Object.values(table.foreignKeys).forEach((fk) => {\n allConstraints.push({ table: table.name, type: \"FK\", name: fk.name, length: fk.name.length });\n if (fk.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: fk.name,\n actualLength: fk.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"foreign_key\",\n });\n }\n });\n\n // Check primary key constraint names\n Object.values(table.compositePrimaryKeys).forEach((pk) => {\n const pkType = pk.columns.length > 1 ? \"PK (composite)\" : \"PK\";\n allConstraints.push({ table: table.name, type: pkType, name: pk.name, length: pk.name.length });\n if (pk.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: pk.name,\n actualLength: pk.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"primary_key\",\n });\n }\n\n validateIndexWidth(table, {\n name: pk.name,\n columns: pk.columns,\n keyType: \"primary_key\",\n });\n });\n\n // Check unique constraint names\n Object.values(table.uniqueConstraints).forEach((unique) => {\n allConstraints.push({ table: table.name, type: \"UNIQUE\", name: unique.name, length: unique.name.length });\n if (unique.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: unique.name,\n actualLength: unique.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"unique\",\n });\n }\n\n validateIndexWidth(table, {\n name: unique.name,\n columns: unique.columns,\n keyType: \"unique\",\n });\n });\n\n // Check index names\n Object.values(table.indexes).forEach((index) => {\n allConstraints.push({ table: table.name, type: \"INDEX\", name: index.name, length: index.name.length });\n if (index.name.length > MAX_CONSTRAINT_NAME_LENGTH) {\n issues.push({\n type: \"constraint\",\n tableName: table.name,\n name: index.name,\n actualLength: index.name.length,\n maxLength: MAX_CONSTRAINT_NAME_LENGTH,\n constraintType: \"index\",\n });\n }\n\n validateIndexWidth(table, {\n name: index.name,\n columns: index.columns,\n keyType: index.isUnique ? \"unique\" : \"index\",\n });\n });\n });\n\n // Verbose mode: show all constraints checked\n if (verbose) {\n consola.box(\"All Constraints Checked\");\n const sortedConstraints = allConstraints.sort((a, b) => b.length - a.length);\n sortedConstraints.forEach((constraint) => {\n const exceeds = constraint.length > MAX_CONSTRAINT_NAME_LENGTH;\n const lengthStr = `[${constraint.length.toString().padStart(2)} chars]`;\n const typeStr = constraint.type.padEnd(15);\n const message = `${lengthStr} ${typeStr} ${constraint.name} (${constraint.table})`;\n if (exceeds) {\n consola.error(message);\n } else {\n consola.success(message);\n }\n });\n consola.log(\"\");\n }\n\n // Print report\n consola.box(\"MySQL Schema Analysis\");\n consola.info(`Maximum identifier length: ${MAX_IDENTIFIER_LENGTH} characters`);\n consola.info(`Maximum constraint name length: ${MAX_CONSTRAINT_NAME_LENGTH} characters`);\n consola.info(`Maximum index key length: ${MYSQL_MAX_INDEX_BYTES} bytes`);\n consola.info(`Analyzed ${tables.length} tables`);\n consola.log(\"\");\n\n // Show table summary\n consola.start(\"Tables analyzed:\");\n tables.forEach((table) => {\n const columnCount = Object.keys(table.columns).length;\n const fkCount = Object.keys(table.foreignKeys).length;\n const pkCount = Object.keys(table.compositePrimaryKeys).length;\n const uniqueCount = Object.keys(table.uniqueConstraints).length;\n const indexCount = Object.keys(table.indexes).length;\n\n const parts: string[] = [];\n parts.push(`${columnCount} columns`);\n if (fkCount > 0) {\n parts.push(`${fkCount} FKs`);\n }\n if (pkCount > 0) {\n parts.push(`${pkCount} PKs`);\n }\n if (uniqueCount > 0) {\n parts.push(`${uniqueCount} unique`);\n }\n if (indexCount > 0) {\n parts.push(`${indexCount} indexes`);\n }\n\n consola.log(` - ${table.name} (${parts.join(\", \")})`);\n });\n consola.log(\"\");\n\n if (issues.length === 0) {\n consola.success(\"No schema validation issues found!\");\n return finalize(0);\n }\n\n consola.warn(`Found ${issues.length} schema validation issue(s):`);\n consola.log(\"\");\n\n const tableIssues = issues.filter((i): i is NameLengthIssue => i.type === \"table\");\n const columnIssues = issues.filter((i): i is NameLengthIssue => i.type === \"column\");\n const constraintIssues = issues.filter((i): i is NameLengthIssue => i.type === \"constraint\");\n const indexWidthIssues = issues.filter((i): i is IndexWidthIssue => i.type === \"index_width\");\n\n if (tableIssues.length > 0) {\n consola.error(\"Table Name Issues:\");\n tableIssues.forEach((issue) => {\n consola.log(\n ` - Table: ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n });\n consola.log(\"\");\n }\n\n if (columnIssues.length > 0) {\n consola.error(\"Column Name Issues:\");\n columnIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.tableName}.${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n });\n consola.log(\"\");\n }\n\n if (constraintIssues.length > 0) {\n consola.error(\"Constraint Name Issues:\");\n const fkIssues = constraintIssues.filter((i) => i.constraintType === \"foreign_key\");\n const pkIssues = constraintIssues.filter((i) => i.constraintType === \"primary_key\");\n const uniqueIssues = constraintIssues.filter((i) => i.constraintType === \"unique\");\n const indexIssues = constraintIssues.filter((i) => i.constraintType === \"index\");\n\n if (fkIssues.length > 0) {\n consola.log(\" Foreign Keys:\");\n fkIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n\n if (pkIssues.length > 0) {\n consola.log(\" Primary Keys:\");\n pkIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n\n if (uniqueIssues.length > 0) {\n consola.log(\" Unique Constraints:\");\n uniqueIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n\n if (indexIssues.length > 0) {\n consola.log(\" Indexes:\");\n indexIssues.forEach((issue) => {\n consola.log(\n ` - ${issue.name} (${issue.actualLength} chars, exceeds max by ${issue.actualLength - issue.maxLength})`,\n );\n consola.log(` Table: ${issue.tableName}`);\n });\n }\n consola.log(\"\");\n }\n\n if (indexWidthIssues.length > 0) {\n consola.error(\"Index Width Issues:\");\n const primaryKeyWidthIssues = indexWidthIssues.filter((issue) => issue.keyType === \"primary_key\");\n const uniqueWidthIssues = indexWidthIssues.filter((issue) => issue.keyType === \"unique\");\n const indexOnlyWidthIssues = indexWidthIssues.filter((issue) => issue.keyType === \"index\");\n\n for (const issueGroup of [primaryKeyWidthIssues, uniqueWidthIssues, indexOnlyWidthIssues]) {\n if (issueGroup.length === 0) {\n continue;\n }\n\n consola.log(` ${getKeyTypeLabel(issueGroup[0]!.keyType)}:`);\n issueGroup.forEach((issue) => {\n const actualBytes = Number.isFinite(issue.actualBytes) ? issue.actualBytes.toString() : \"unbounded\";\n consola.log(\n ` - ${issue.name} (${actualBytes} bytes, exceeds max by ${\n Number.isFinite(issue.actualBytes) ? issue.actualBytes - issue.maxBytes : \"unknown amount\"\n })`,\n );\n consola.log(` Table: ${issue.tableName}`);\n consola.log(` Columns: ${issue.columns.join(\", \")}`);\n });\n }\n\n consola.log(\"\");\n }\n\n consola.box(\"Summary\");\n consola.info(`Total issues: ${issues.length}`);\n consola.info(` - Table names: ${tableIssues.length}`);\n consola.info(` - Column names: ${columnIssues.length}`);\n consola.info(` - Constraint names: ${constraintIssues.length}`);\n consola.info(` - Index widths: ${indexWidthIssues.length}`);\n if (constraintIssues.length > 0) {\n const fkCount = constraintIssues.filter((i) => i.constraintType === \"foreign_key\").length;\n const pkCount = constraintIssues.filter((i) => i.constraintType === \"primary_key\").length;\n const uniqueCount = constraintIssues.filter((i) => i.constraintType === \"unique\").length;\n const indexCount = constraintIssues.filter((i) => i.constraintType === \"index\").length;\n consola.info(` - Foreign keys: ${fkCount}`);\n consola.info(` - Primary keys: ${pkCount}`);\n consola.info(` - Unique constraints: ${uniqueCount}`);\n consola.info(` - Indexes: ${indexCount}`);\n }\n if (indexWidthIssues.length > 0) {\n const pkWidthCount = indexWidthIssues.filter((i) => i.keyType === \"primary_key\").length;\n const uniqueWidthCount = indexWidthIssues.filter((i) => i.keyType === \"unique\").length;\n const indexWidthCount = indexWidthIssues.filter((i) => i.keyType === \"index\").length;\n consola.info(` - Primary keys: ${pkWidthCount}`);\n consola.info(` - Unique indexes: ${uniqueWidthCount}`);\n consola.info(` - Indexes: ${indexWidthCount}`);\n }\n consola.log(\"\");\n\n // Print actionable feedback\n consola.fail(\"MIGRATION BLOCKED: Schema validation violations detected!\");\n consola.log(\"\");\n consola.start(\"Action required:\");\n consola.log(\"1. Review the issues listed above\");\n consola.log(\"2. Shorten table/column/constraint names where required\");\n consola.log(\"3. Reduce indexed column widths or introduce prefix/hash columns for oversized indexes\");\n consola.log(\"4. Run 'pnpm generate' again after making changes\");\n consola.log(\"5. Run this check with --verbose to see all constraint names\");\n consola.log(\"\");\n\n return finalize(1);\n};\n\nexport { validateDatabaseSchema };\n"],"mappings":"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"}
|
package/dist/env.d.mts
CHANGED
package/dist/env.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { pipe } from "remeda";
|
|
2
2
|
import * as v from "valibot";
|
|
3
|
-
|
|
4
3
|
//#region src/env.ts
|
|
5
4
|
const PUBLIC_ENV_PREFIX = "PUBLIC_";
|
|
6
5
|
/**
|
|
@@ -19,11 +18,11 @@ const createEnv = (args) => {
|
|
|
19
18
|
}
|
|
20
19
|
if (invalidKeys.length > 0) throw new Error(`Invalid environment variable(s): ${invalidKeys.map((e) => `"${e}"`).join(", ")}`);
|
|
21
20
|
return {
|
|
22
|
-
client: pipe(serverEnv, (obj) => Array.from(obj.entries()), (pairs
|
|
21
|
+
client: pipe(serverEnv, (obj) => Array.from(obj.entries()), (pairs) => pairs.filter(([k]) => k.startsWith(PUBLIC_ENV_PREFIX)), (pairs) => Object.fromEntries(pairs)),
|
|
23
22
|
server: Object.fromEntries(serverEnv.entries())
|
|
24
23
|
};
|
|
25
24
|
};
|
|
26
|
-
|
|
27
25
|
//#endregion
|
|
28
26
|
export { createEnv };
|
|
27
|
+
|
|
29
28
|
//# sourceMappingURL=env.mjs.map
|
package/dist/env.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.mjs","names":[
|
|
1
|
+
{"version":3,"file":"env.mjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { pipe } from \"remeda\";\nimport * as v from \"valibot\";\n\nconst PUBLIC_ENV_PREFIX = \"PUBLIC_\" as const;\n\n/**\n * Validates your environment variables against the given Valibot schema;\n * @param args\n * @returns An object containing client environment variables and another containing server environment variables\n */\nexport const createEnv = <\n Schema extends Record<string, v.GenericSchema>,\n Env = {\n [K in keyof Schema]: v.InferOutput<Schema[K]>;\n },\n>(args: {\n schema: Schema;\n // oxlint-disable-next-line no-explicit-any\n env: any;\n}) => {\n const pairs = Object.entries(args.schema);\n const serverEnv = new Map();\n const invalidKeys: string[] = [];\n\n for (const [key, value] of pairs) {\n const result = v.safeParse(value, args.env[key]);\n\n if (!result.success) {\n invalidKeys.push(key);\n }\n\n serverEnv.set(key, result.output);\n }\n\n if (invalidKeys.length > 0) {\n throw new Error(`Invalid environment variable(s): ${invalidKeys.map((e) => `\"${e}\"`).join(\", \")}`);\n }\n\n type ClientEnvKeys = Exclude<\n {\n [K in keyof Env]: K extends `${typeof PUBLIC_ENV_PREFIX}${string}` ? K : never;\n }[keyof Env],\n undefined\n >;\n\n type ClientEnv = {\n [B in ClientEnvKeys]: Env[B];\n };\n\n const clientEnv = pipe(\n serverEnv,\n (obj) => Array.from(obj.entries()),\n (pairs) => pairs.filter(([k]) => k.startsWith(PUBLIC_ENV_PREFIX)),\n (pairs) => Object.fromEntries(pairs),\n ) as ClientEnv;\n\n return {\n client: clientEnv,\n server: Object.fromEntries(serverEnv.entries()) as Env,\n };\n};\n"],"mappings":";;;AAGA,MAAM,oBAAoB;;;;;;AAO1B,MAAa,aAKX,SAII;CACJ,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO;CACzC,MAAM,4BAAY,IAAI,KAAK;CAC3B,MAAM,cAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO;EAChC,MAAM,SAAS,EAAE,UAAU,OAAO,KAAK,IAAI,KAAK;AAEhD,MAAI,CAAC,OAAO,QACV,aAAY,KAAK,IAAI;AAGvB,YAAU,IAAI,KAAK,OAAO,OAAO;;AAGnC,KAAI,YAAY,SAAS,EACvB,OAAM,IAAI,MAAM,oCAAoC,YAAY,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,GAAG;AAqBpG,QAAO;EACL,QARgB,KAChB,YACC,QAAQ,MAAM,KAAK,IAAI,SAAS,CAAC,GACjC,UAAU,MAAM,QAAQ,CAAC,OAAO,EAAE,WAAW,kBAAkB,CAAC,GAChE,UAAU,OAAO,YAAY,MAAM,CACrC;EAIC,QAAQ,OAAO,YAAY,UAAU,SAAS,CAAC;EAChD"}
|
package/dist/images.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { nanoid } from "nanoid";
|
|
2
2
|
import dayjs from "dayjs";
|
|
3
3
|
import { ofetch } from "ofetch";
|
|
4
|
-
|
|
5
4
|
//#region src/images.ts
|
|
6
5
|
var ImageUtils = class {
|
|
7
6
|
blacklist = ["img.clerk.com"];
|
|
@@ -124,7 +123,7 @@ var ImageUtils = class {
|
|
|
124
123
|
}));
|
|
125
124
|
}
|
|
126
125
|
};
|
|
127
|
-
|
|
128
126
|
//#endregion
|
|
129
127
|
export { ImageUtils };
|
|
128
|
+
|
|
130
129
|
//# sourceMappingURL=images.mjs.map
|
package/dist/images.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"images.mjs","names":[],"sources":["../src/images.ts"],"sourcesContent":["import { nanoid } from \"nanoid\";\nimport dayjs from \"dayjs\";\nimport { ofetch } from \"ofetch\";\n\nexport interface OptimizedImageOptions {\n anim?: boolean;\n background?: string;\n blur?: number;\n brightness?: number;\n compression?: \"fast\"; // faster compression = larger file size\n contrast?: number;\n dpr?: number;\n fit?: \"scale-down\" | \"contain\" | \"cover\" | \"crop\" | \"pad\";\n format?: \"webp\" | \"avif\" | \"json\";\n gamma?: number;\n width?: number;\n height?: number;\n metadata?: \"keep\" | \"copyright\" | \"none\";\n quality?: number;\n rotate?: number;\n sharpen?: number;\n}\n\nexport interface CreateImageUrlResponse {\n result: {\n id: string;\n uploadURL: string;\n };\n success: boolean;\n errors: unknown[];\n messages: unknown[];\n}\n\ninterface UploadImageResponse {\n result: {\n id: string;\n filename: string;\n uploaded: string;\n requireSignedURLs: boolean;\n variants: string[];\n };\n success: boolean;\n errors: unknown[];\n messages: unknown[];\n}\n\ninterface CloudflareImagesV1Response {\n result: {\n images: CloudflareImage[];\n };\n success: boolean;\n errors: CloudflareApiError[];\n messages: string[];\n}\n\ninterface CloudflareImage {\n id: string; // Unique image identifier\n filename: string; // Original filename\n uploaded: string; // ISO 8601 date-time string\n requireSignedURLs: boolean;\n variants: string[]; // Array of URLs for the image variants\n meta?: Record<string, any>; // User modifiable key-value store (max 1024 bytes)\n creator?: string | null; // Internal user ID (optional)\n}\n\ninterface CloudflareApiError {\n code: number;\n message: string;\n}\n\nexport class ImageUtils<ImageIds extends Record<string, any>> {\n private blacklist: string[] = [\"img.clerk.com\"];\n private accountId: string;\n private accountHash: string;\n private _imageIds: ImageIds | undefined;\n\n constructor(args: { accountId: string; accountHash: string; blacklist?: string[]; imageIds?: ImageIds }) {\n this.accountId = args.accountId;\n this.accountHash = args.accountHash;\n\n this._imageIds = args.imageIds;\n\n if (args.blacklist) {\n this.blacklist.push(...args.blacklist);\n }\n }\n\n get imageIds() {\n if (!this._imageIds) {\n throw new Error(\"imageIds was not supplied in constructor\");\n }\n\n return this._imageIds;\n }\n\n public url(id: string) {\n return `https://imagedelivery.net/${this.accountHash}/${id}/public`;\n }\n\n private isBlacklisted(url: string) {\n return this.blacklist.some((u) => url.includes(u));\n }\n\n private isProtected(id: string) {\n if (!this._imageIds) {\n return false;\n }\n\n return Object.values(this._imageIds).some((e) => e === id);\n }\n\n /**\n * Will only operate on images that have been uploaded via cloudflare images\n */\n public optimizeUrl(url: string, options: OptimizedImageOptions) {\n if (this.isBlacklisted(url)) {\n return url;\n }\n\n // Final format should look similar to: https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/w=400,sharpen=3\n return url.replace(\"public\", this.createImageOptionsString(options));\n }\n\n public optimizeId(id: string, options: OptimizedImageOptions) {\n return this.optimizeUrl(this.url(id), options);\n }\n\n public createOptionsSearchParams(options: OptimizedImageOptions) {\n const params = new URLSearchParams();\n\n const pairs = Object.entries(options);\n\n for (const [key, val] of pairs) {\n if (val === undefined) {\n continue;\n }\n\n params.set(key, val.toString());\n }\n\n return params;\n }\n\n public createImageOptionsString(options: OptimizedImageOptions) {\n const params = this.createOptionsSearchParams(options);\n\n return Array.from(params.entries())\n .map(([key, val]) => `${key}=${val}`)\n .join(\",\");\n }\n\n public async createUploadUrls(count: number, args: { apiKey: string }) {\n if (count === 0) {\n return [];\n }\n\n const headers = new Headers();\n headers.set(\"Authorization\", `Bearer ${args.apiKey}`);\n\n const urls = await Promise.all(\n Array.from({ length: count }).map(async () => {\n try {\n const form = new FormData();\n const id = nanoid();\n form.append(\"id\", id);\n form.append(\"expiry\", dayjs().add(5, \"minute\").toISOString());\n\n const img = await ofetch<CreateImageUrlResponse>(\n `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v2/direct_upload`,\n { method: \"POST\", headers, body: form },\n );\n\n if (!img.success) {\n throw new Error(\"Error uploading image\");\n }\n\n return { url: img.result.uploadURL, id };\n } catch (e) {\n console.error(\"Error uploading image\");\n throw e;\n }\n }),\n );\n\n return urls;\n }\n\n public async serverUpload(data: Blob, args: { id?: string; apiKey: string }) {\n const formData = new FormData();\n formData.append(\"file\", data);\n formData.append(\"id\", args.id ?? nanoid());\n\n const headers = new Headers();\n headers.set(\"Authorization\", `Bearer ${args.apiKey}`);\n\n const response = await fetch(`https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1`, {\n method: \"POST\",\n headers,\n body: formData,\n });\n\n const json: CloudflareImagesV1Response = await response.json();\n\n return json;\n }\n\n public async upload(url: string, body: FormData) {\n const fetchResponse = await ofetch<UploadImageResponse>(url, {\n method: \"POST\",\n body,\n });\n\n if (!fetchResponse.success) {\n throw new Error(\"Failed to upload image\");\n }\n\n const downloadUrl = fetchResponse.result.variants[0];\n\n if (!downloadUrl) {\n throw new Error(\"Could not find download URL\");\n }\n\n return downloadUrl;\n }\n\n public async delete(id: string, args: { apiKey: string }) {\n if (this.isProtected(id)) {\n return { success: true };\n }\n\n try {\n const headers = new Headers();\n headers.set(\"Authorization\", `Bearer ${args.apiKey}`);\n\n await ofetch(`https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1/${id}`, {\n method: \"POST\",\n headers,\n });\n return { success: true };\n } catch {\n return { success: false };\n }\n }\n\n public async batchUpload(files: { file: File; url: { id: string; value: string } }[]) {\n return await Promise.all(\n files.map(async (e) => {\n const formData = new FormData();\n formData.append(\"file\", e.file);\n\n const downloadUrl = await this.upload(e.url.value, formData);\n\n return {\n url: downloadUrl,\n id: e.url.id,\n };\n }),\n );\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"images.mjs","names":[],"sources":["../src/images.ts"],"sourcesContent":["import { nanoid } from \"nanoid\";\nimport dayjs from \"dayjs\";\nimport { ofetch } from \"ofetch\";\n\nexport interface OptimizedImageOptions {\n anim?: boolean;\n background?: string;\n blur?: number;\n brightness?: number;\n compression?: \"fast\"; // faster compression = larger file size\n contrast?: number;\n dpr?: number;\n fit?: \"scale-down\" | \"contain\" | \"cover\" | \"crop\" | \"pad\";\n format?: \"webp\" | \"avif\" | \"json\";\n gamma?: number;\n width?: number;\n height?: number;\n metadata?: \"keep\" | \"copyright\" | \"none\";\n quality?: number;\n rotate?: number;\n sharpen?: number;\n}\n\nexport interface CreateImageUrlResponse {\n result: {\n id: string;\n uploadURL: string;\n };\n success: boolean;\n errors: unknown[];\n messages: unknown[];\n}\n\ninterface UploadImageResponse {\n result: {\n id: string;\n filename: string;\n uploaded: string;\n requireSignedURLs: boolean;\n variants: string[];\n };\n success: boolean;\n errors: unknown[];\n messages: unknown[];\n}\n\ninterface CloudflareImagesV1Response {\n result: {\n images: CloudflareImage[];\n };\n success: boolean;\n errors: CloudflareApiError[];\n messages: string[];\n}\n\ninterface CloudflareImage {\n id: string; // Unique image identifier\n filename: string; // Original filename\n uploaded: string; // ISO 8601 date-time string\n requireSignedURLs: boolean;\n variants: string[]; // Array of URLs for the image variants\n meta?: Record<string, any>; // User modifiable key-value store (max 1024 bytes)\n creator?: string | null; // Internal user ID (optional)\n}\n\ninterface CloudflareApiError {\n code: number;\n message: string;\n}\n\nexport class ImageUtils<ImageIds extends Record<string, any>> {\n private blacklist: string[] = [\"img.clerk.com\"];\n private accountId: string;\n private accountHash: string;\n private _imageIds: ImageIds | undefined;\n\n constructor(args: { accountId: string; accountHash: string; blacklist?: string[]; imageIds?: ImageIds }) {\n this.accountId = args.accountId;\n this.accountHash = args.accountHash;\n\n this._imageIds = args.imageIds;\n\n if (args.blacklist) {\n this.blacklist.push(...args.blacklist);\n }\n }\n\n get imageIds() {\n if (!this._imageIds) {\n throw new Error(\"imageIds was not supplied in constructor\");\n }\n\n return this._imageIds;\n }\n\n public url(id: string) {\n return `https://imagedelivery.net/${this.accountHash}/${id}/public`;\n }\n\n private isBlacklisted(url: string) {\n return this.blacklist.some((u) => url.includes(u));\n }\n\n private isProtected(id: string) {\n if (!this._imageIds) {\n return false;\n }\n\n return Object.values(this._imageIds).some((e) => e === id);\n }\n\n /**\n * Will only operate on images that have been uploaded via cloudflare images\n */\n public optimizeUrl(url: string, options: OptimizedImageOptions) {\n if (this.isBlacklisted(url)) {\n return url;\n }\n\n // Final format should look similar to: https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/w=400,sharpen=3\n return url.replace(\"public\", this.createImageOptionsString(options));\n }\n\n public optimizeId(id: string, options: OptimizedImageOptions) {\n return this.optimizeUrl(this.url(id), options);\n }\n\n public createOptionsSearchParams(options: OptimizedImageOptions) {\n const params = new URLSearchParams();\n\n const pairs = Object.entries(options);\n\n for (const [key, val] of pairs) {\n if (val === undefined) {\n continue;\n }\n\n params.set(key, val.toString());\n }\n\n return params;\n }\n\n public createImageOptionsString(options: OptimizedImageOptions) {\n const params = this.createOptionsSearchParams(options);\n\n return Array.from(params.entries())\n .map(([key, val]) => `${key}=${val}`)\n .join(\",\");\n }\n\n public async createUploadUrls(count: number, args: { apiKey: string }) {\n if (count === 0) {\n return [];\n }\n\n const headers = new Headers();\n headers.set(\"Authorization\", `Bearer ${args.apiKey}`);\n\n const urls = await Promise.all(\n Array.from({ length: count }).map(async () => {\n try {\n const form = new FormData();\n const id = nanoid();\n form.append(\"id\", id);\n form.append(\"expiry\", dayjs().add(5, \"minute\").toISOString());\n\n const img = await ofetch<CreateImageUrlResponse>(\n `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v2/direct_upload`,\n { method: \"POST\", headers, body: form },\n );\n\n if (!img.success) {\n throw new Error(\"Error uploading image\");\n }\n\n return { url: img.result.uploadURL, id };\n } catch (e) {\n console.error(\"Error uploading image\");\n throw e;\n }\n }),\n );\n\n return urls;\n }\n\n public async serverUpload(data: Blob, args: { id?: string; apiKey: string }) {\n const formData = new FormData();\n formData.append(\"file\", data);\n formData.append(\"id\", args.id ?? nanoid());\n\n const headers = new Headers();\n headers.set(\"Authorization\", `Bearer ${args.apiKey}`);\n\n const response = await fetch(`https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1`, {\n method: \"POST\",\n headers,\n body: formData,\n });\n\n const json: CloudflareImagesV1Response = await response.json();\n\n return json;\n }\n\n public async upload(url: string, body: FormData) {\n const fetchResponse = await ofetch<UploadImageResponse>(url, {\n method: \"POST\",\n body,\n });\n\n if (!fetchResponse.success) {\n throw new Error(\"Failed to upload image\");\n }\n\n const downloadUrl = fetchResponse.result.variants[0];\n\n if (!downloadUrl) {\n throw new Error(\"Could not find download URL\");\n }\n\n return downloadUrl;\n }\n\n public async delete(id: string, args: { apiKey: string }) {\n if (this.isProtected(id)) {\n return { success: true };\n }\n\n try {\n const headers = new Headers();\n headers.set(\"Authorization\", `Bearer ${args.apiKey}`);\n\n await ofetch(`https://api.cloudflare.com/client/v4/accounts/${this.accountId}/images/v1/${id}`, {\n method: \"POST\",\n headers,\n });\n return { success: true };\n } catch {\n return { success: false };\n }\n }\n\n public async batchUpload(files: { file: File; url: { id: string; value: string } }[]) {\n return await Promise.all(\n files.map(async (e) => {\n const formData = new FormData();\n formData.append(\"file\", e.file);\n\n const downloadUrl = await this.upload(e.url.value, formData);\n\n return {\n url: downloadUrl,\n id: e.url.id,\n };\n }),\n );\n }\n}\n"],"mappings":";;;;AAsEA,IAAa,aAAb,MAA8D;CAC5D,YAA8B,CAAC,gBAAgB;CAC/C;CACA;CACA;CAEA,YAAY,MAA6F;AACvG,OAAK,YAAY,KAAK;AACtB,OAAK,cAAc,KAAK;AAExB,OAAK,YAAY,KAAK;AAEtB,MAAI,KAAK,UACP,MAAK,UAAU,KAAK,GAAG,KAAK,UAAU;;CAI1C,IAAI,WAAW;AACb,MAAI,CAAC,KAAK,UACR,OAAM,IAAI,MAAM,2CAA2C;AAG7D,SAAO,KAAK;;CAGd,IAAW,IAAY;AACrB,SAAO,6BAA6B,KAAK,YAAY,GAAG,GAAG;;CAG7D,cAAsB,KAAa;AACjC,SAAO,KAAK,UAAU,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;;CAGpD,YAAoB,IAAY;AAC9B,MAAI,CAAC,KAAK,UACR,QAAO;AAGT,SAAO,OAAO,OAAO,KAAK,UAAU,CAAC,MAAM,MAAM,MAAM,GAAG;;;;;CAM5D,YAAmB,KAAa,SAAgC;AAC9D,MAAI,KAAK,cAAc,IAAI,CACzB,QAAO;AAIT,SAAO,IAAI,QAAQ,UAAU,KAAK,yBAAyB,QAAQ,CAAC;;CAGtE,WAAkB,IAAY,SAAgC;AAC5D,SAAO,KAAK,YAAY,KAAK,IAAI,GAAG,EAAE,QAAQ;;CAGhD,0BAAiC,SAAgC;EAC/D,MAAM,SAAS,IAAI,iBAAiB;EAEpC,MAAM,QAAQ,OAAO,QAAQ,QAAQ;AAErC,OAAK,MAAM,CAAC,KAAK,QAAQ,OAAO;AAC9B,OAAI,QAAQ,KAAA,EACV;AAGF,UAAO,IAAI,KAAK,IAAI,UAAU,CAAC;;AAGjC,SAAO;;CAGT,yBAAgC,SAAgC;EAC9D,MAAM,SAAS,KAAK,0BAA0B,QAAQ;AAEtD,SAAO,MAAM,KAAK,OAAO,SAAS,CAAC,CAChC,KAAK,CAAC,KAAK,SAAS,GAAG,IAAI,GAAG,MAAM,CACpC,KAAK,IAAI;;CAGd,MAAa,iBAAiB,OAAe,MAA0B;AACrE,MAAI,UAAU,EACZ,QAAO,EAAE;EAGX,MAAM,UAAU,IAAI,SAAS;AAC7B,UAAQ,IAAI,iBAAiB,UAAU,KAAK,SAAS;AA2BrD,SAzBa,MAAM,QAAQ,IACzB,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC,CAAC,IAAI,YAAY;AAC5C,OAAI;IACF,MAAM,OAAO,IAAI,UAAU;IAC3B,MAAM,KAAK,QAAQ;AACnB,SAAK,OAAO,MAAM,GAAG;AACrB,SAAK,OAAO,UAAU,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,aAAa,CAAC;IAE7D,MAAM,MAAM,MAAM,OAChB,iDAAiD,KAAK,UAAU,2BAChE;KAAE,QAAQ;KAAQ;KAAS,MAAM;KAAM,CACxC;AAED,QAAI,CAAC,IAAI,QACP,OAAM,IAAI,MAAM,wBAAwB;AAG1C,WAAO;KAAE,KAAK,IAAI,OAAO;KAAW;KAAI;YACjC,GAAG;AACV,YAAQ,MAAM,wBAAwB;AACtC,UAAM;;IAER,CACH;;CAKH,MAAa,aAAa,MAAY,MAAuC;EAC3E,MAAM,WAAW,IAAI,UAAU;AAC/B,WAAS,OAAO,QAAQ,KAAK;AAC7B,WAAS,OAAO,MAAM,KAAK,MAAM,QAAQ,CAAC;EAE1C,MAAM,UAAU,IAAI,SAAS;AAC7B,UAAQ,IAAI,iBAAiB,UAAU,KAAK,SAAS;AAUrD,SAFyC,OANxB,MAAM,MAAM,iDAAiD,KAAK,UAAU,aAAa;GACxG,QAAQ;GACR;GACA,MAAM;GACP,CAAC,EAEsD,MAAM;;CAKhE,MAAa,OAAO,KAAa,MAAgB;EAC/C,MAAM,gBAAgB,MAAM,OAA4B,KAAK;GAC3D,QAAQ;GACR;GACD,CAAC;AAEF,MAAI,CAAC,cAAc,QACjB,OAAM,IAAI,MAAM,yBAAyB;EAG3C,MAAM,cAAc,cAAc,OAAO,SAAS;AAElD,MAAI,CAAC,YACH,OAAM,IAAI,MAAM,8BAA8B;AAGhD,SAAO;;CAGT,MAAa,OAAO,IAAY,MAA0B;AACxD,MAAI,KAAK,YAAY,GAAG,CACtB,QAAO,EAAE,SAAS,MAAM;AAG1B,MAAI;GACF,MAAM,UAAU,IAAI,SAAS;AAC7B,WAAQ,IAAI,iBAAiB,UAAU,KAAK,SAAS;AAErD,SAAM,OAAO,iDAAiD,KAAK,UAAU,aAAa,MAAM;IAC9F,QAAQ;IACR;IACD,CAAC;AACF,UAAO,EAAE,SAAS,MAAM;UAClB;AACN,UAAO,EAAE,SAAS,OAAO;;;CAI7B,MAAa,YAAY,OAA6D;AACpF,SAAO,MAAM,QAAQ,IACnB,MAAM,IAAI,OAAO,MAAM;GACrB,MAAM,WAAW,IAAI,UAAU;AAC/B,YAAS,OAAO,QAAQ,EAAE,KAAK;AAI/B,UAAO;IACL,KAHkB,MAAM,KAAK,OAAO,EAAE,IAAI,OAAO,SAAS;IAI1D,IAAI,EAAE,IAAI;IACX;IACD,CACH"}
|
package/dist/oxlint/config.json
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "../node_modules/oxlint/configuration_schema.json",
|
|
3
|
-
"plugins": [
|
|
3
|
+
"plugins": [
|
|
4
|
+
"import",
|
|
5
|
+
"typescript",
|
|
6
|
+
"unicorn",
|
|
7
|
+
"react",
|
|
8
|
+
"react-perf",
|
|
9
|
+
"oxc",
|
|
10
|
+
"node",
|
|
11
|
+
"promise"
|
|
12
|
+
],
|
|
13
|
+
"jsPlugins": [
|
|
14
|
+
{
|
|
15
|
+
"name": "react-js",
|
|
16
|
+
"specifier": "eslint-plugin-react"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
4
19
|
"env": {
|
|
5
20
|
"browser": true
|
|
6
21
|
},
|
|
@@ -12,7 +27,11 @@
|
|
|
12
27
|
"packages/common/src/oxlint-plugins",
|
|
13
28
|
"**/node_modules"
|
|
14
29
|
],
|
|
15
|
-
"settings": {
|
|
30
|
+
"settings": {
|
|
31
|
+
"react": {
|
|
32
|
+
"version": "19.0"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
16
35
|
"rules": {
|
|
17
36
|
"@typescript-eslint/ban-ts-comment": "error",
|
|
18
37
|
"@typescript-eslint/no-floating-promises": "off",
|
|
@@ -22,9 +41,23 @@
|
|
|
22
41
|
"react/rules-of-hooks": "deny",
|
|
23
42
|
"no-nested-ternary": "deny",
|
|
24
43
|
"react/exhaustive-deps": "deny",
|
|
25
|
-
"react/
|
|
44
|
+
"react-js/function-component-definition": [
|
|
45
|
+
"error",
|
|
46
|
+
{
|
|
47
|
+
"namedComponents": "arrow-function",
|
|
48
|
+
"unnamedComponents": "arrow-function"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"react-js/hook-use-state": "error",
|
|
52
|
+
"react-js/jsx-no-bind": "error",
|
|
53
|
+
"react/jsx-no-constructed-context-values": "error",
|
|
54
|
+
"react-js/jsx-no-leaked-render": "error",
|
|
55
|
+
"react/jsx-no-useless-fragment": "error",
|
|
56
|
+
"react/jsx-pascal-case": "error",
|
|
57
|
+
"react-js/no-unstable-nested-components": "error",
|
|
26
58
|
"typescript/no-floating-promises": "off",
|
|
27
59
|
"no-unused-vars": "warn",
|
|
60
|
+
"react/only-export-components": "error",
|
|
28
61
|
"typescript/no-import-type-side-effects": "deny",
|
|
29
62
|
"@typescript-eslint/consistent-type-imports": "deny",
|
|
30
63
|
"conorroberts/no-inline-components": "error",
|
package/dist/oxlint/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _$_oxlint_plugins0 from "@oxlint/plugins";
|
|
2
2
|
|
|
3
3
|
//#region src/oxlint-plugins/index.d.ts
|
|
4
|
-
declare const plugin:
|
|
4
|
+
declare const plugin: _$_oxlint_plugins0.Plugin;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { plugin as default };
|
|
7
7
|
//# sourceMappingURL=index.d.mts.map
|