style: format code with biome linter across multiple packages

This commit is contained in:
2025-09-30 14:47:22 +07:00
parent d28c9520ee
commit 065ebe1625
13 changed files with 2171 additions and 684 deletions

View File

@@ -1,41 +1,41 @@
{
"name": "@nontara/server",
"main": "index.ts",
"type": "module",
"scripts": {
"build": "tsdown",
"check-types": "tsc -b",
"compile": "bun build --compile --minify --sourcemap --bytecode ./src/main.ts --outfile server",
"dev": "bun run --watch src/main.ts",
"start": "bun run dist/main.js",
"db:local": "turso dev --db-file local.db",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"auth:generate": "bunx --bun @better-auth/cli generate --config ./src/lib/auth.ts --output ./src/db/schema/auth.ts",
"auth:migrate": "bunx --bun @better-auth/cli migrate --config ./src/lib/auth.ts"
},
"dependencies": {
"@hono/trpc-server": "^0.4.0",
"@libsql/client": "^0.15.9",
"@nontara/language-codes": "workspace:*",
"@trpc/client": "^11.5.0",
"@trpc/server": "^11.5.0",
"better-auth": "^1.3.10",
"consola": "^3.4.2",
"dotenv": "^17.2.1",
"drizzle-orm": "^0.44.5",
"fluent-ffmpeg": "^2.1.3",
"hono": "^4.8.2",
"zod": "^4.0.2"
},
"devDependencies": {
"@better-auth/cli": "^1.3.11",
"@types/bun": "^1.2.6",
"@types/fluent-ffmpeg": "^2.1.27",
"drizzle-kit": "^0.31.5",
"tsdown": "^0.15.1",
"typescript": "^5.8.2"
}
}
"name": "@nontara/server",
"main": "index.ts",
"type": "module",
"scripts": {
"build": "tsdown",
"check-types": "tsc -b",
"compile": "bun build --compile --minify --sourcemap --bytecode ./src/main.ts --outfile server",
"dev": "bun run --watch src/main.ts",
"start": "bun run dist/main.js",
"db:local": "turso dev --db-file local.db",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"auth:generate": "bunx --bun @better-auth/cli generate --config ./src/lib/auth.ts --output ./src/db/schema/auth.ts",
"auth:migrate": "bunx --bun @better-auth/cli migrate --config ./src/lib/auth.ts"
},
"dependencies": {
"@hono/trpc-server": "^0.4.0",
"@libsql/client": "^0.15.9",
"@nontara/language-codes": "workspace:*",
"@trpc/client": "^11.5.0",
"@trpc/server": "^11.5.0",
"better-auth": "^1.3.10",
"consola": "^3.4.2",
"dotenv": "^17.2.1",
"drizzle-orm": "^0.44.5",
"fluent-ffmpeg": "^2.1.3",
"hono": "^4.8.2",
"zod": "^4.0.2"
},
"devDependencies": {
"@better-auth/cli": "^1.3.11",
"@types/bun": "^1.2.6",
"@types/fluent-ffmpeg": "^2.1.27",
"drizzle-kit": "^0.31.5",
"tsdown": "^0.15.1",
"typescript": "^5.8.2"
}
}

View File

@@ -1,6 +1,9 @@
import { drizzle } from "drizzle-orm/bun-sqlite";
import * as schema from "./schema";
export const database = drizzle(process.env.DATABASE_FILENAME ?? "database.db", {
schema: schema,
});
export const database = drizzle(
process.env.DATABASE_FILENAME ?? "database.db",
{
schema: schema,
},
);

View File

@@ -1,77 +1,77 @@
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const user = sqliteTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: integer("email_verified", { mode: "boolean" })
.default(false)
.notNull(),
image: text("image"),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.$onUpdate(() => new Date())
.notNull(),
username: text("username").unique(),
displayUsername: text("display_username"),
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: integer("email_verified", { mode: "boolean" })
.default(false)
.notNull(),
image: text("image"),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.$onUpdate(() => new Date())
.notNull(),
username: text("username").unique(),
displayUsername: text("display_username"),
});
export const session = sqliteTable("session", {
id: text("id").primaryKey(),
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
token: text("token").notNull().unique(),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$onUpdate(() => new Date())
.notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
id: text("id").primaryKey(),
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
token: text("token").notNull().unique(),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$onUpdate(() => new Date())
.notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
});
export const account = sqliteTable("account", {
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: integer("access_token_expires_at", {
mode: "timestamp",
}),
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
mode: "timestamp",
}),
scope: text("scope"),
password: text("password"),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$onUpdate(() => new Date())
.notNull(),
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: integer("access_token_expires_at", {
mode: "timestamp",
}),
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
mode: "timestamp",
}),
scope: text("scope"),
password: text("password"),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$onUpdate(() => new Date())
.notNull(),
});
export const verification = sqliteTable("verification", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.$onUpdate(() => new Date())
.notNull(),
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
createdAt: integer("created_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.notNull(),
updatedAt: integer("updated_at", { mode: "timestamp" })
.$defaultFn(() => new Date())
.$onUpdate(() => new Date())
.notNull(),
});

View File

@@ -1,12 +1,19 @@
import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";
import {
integer,
sqliteTable,
text,
uniqueIndex,
} from "drizzle-orm/sqlite-core";
import type { LibraryType } from "./enums";
export const libraryFolders = sqliteTable(
"library_folders",
{
id: integer("id").primaryKey().$defaultFn(() => {
return Math.floor(100000 + Math.random() * 99999);
}),
id: integer("id")
.primaryKey()
.$defaultFn(() => {
return Math.floor(100000 + Math.random() * 99999);
}),
name: text("name").notNull(), // "Movies", "TV Shows"
type: text("type").$type<LibraryType>().notNull(), // "MOVIE" | "SERIES"
path: text("path").notNull(), // absolute/mount path

View File

@@ -1,9 +1,4 @@
import {
index,
integer,
sqliteTable,
text,
} from "drizzle-orm/sqlite-core";
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
// ----- PEOPLE (base table for actors, directors, crew, etc.) -----
export const people = sqliteTable(
@@ -36,4 +31,4 @@ export const people = sqliteTable(
index("idx_people_tmdb").on(t.tmdbId),
index("idx_people_imdb").on(t.imdbId),
],
);
);

View File

@@ -1,15 +1,15 @@
{
"name": "@nontora/tmdb-metadata",
"module": "index.ts",
"devDependencies": {
"@types/bun": "latest",
"@nontara/server": "workspace:*"
},
"peerDependencies": {
"typescript": "^5"
},
"type": "module",
"dependencies": {
"tmdb-ts": "^2.0.2"
}
}
"name": "@nontora/tmdb-metadata",
"module": "index.ts",
"devDependencies": {
"@types/bun": "latest",
"@nontara/server": "workspace:*"
},
"peerDependencies": {
"typescript": "^5"
},
"type": "module",
"dependencies": {
"tmdb-ts": "^2.0.2"
}
}

View File

@@ -1,29 +1,29 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}

View File

@@ -1,29 +1,29 @@
{
"name": "nontara",
"private": true,
"type": "module",
"workspaces": [
"apps/*",
"packages/*",
"extensions/*"
],
"scripts": {
"check": "biome check --write .",
"dev": "turbo dev",
"build": "turbo build",
"check-types": "turbo check-types",
"dev:native": "turbo -F native dev",
"dev:web": "turbo -F web dev",
"dev:server": "turbo -F server dev",
"db:push": "turbo -F server db:push",
"db:studio": "turbo -F server db:studio",
"db:generate": "turbo -F server db:generate",
"db:migrate": "turbo -F server db:migrate"
},
"dependencies": {},
"devDependencies": {
"turbo": "^2.5.4",
"@biomejs/biome": "^2.2.0"
},
"packageManager": "bun@1.2.22"
"name": "nontara",
"private": true,
"type": "module",
"workspaces": [
"apps/*",
"packages/*",
"extensions/*"
],
"scripts": {
"check": "biome check --write .",
"dev": "turbo dev",
"build": "turbo build",
"check-types": "turbo check-types",
"dev:native": "turbo -F native dev",
"dev:web": "turbo -F web dev",
"dev:server": "turbo -F server dev",
"db:push": "turbo -F server db:push",
"db:studio": "turbo -F server db:studio",
"db:generate": "turbo -F server db:generate",
"db:migrate": "turbo -F server db:migrate"
},
"dependencies": {},
"devDependencies": {
"turbo": "^2.5.4",
"@biomejs/biome": "^2.2.0"
},
"packageManager": "bun@1.2.22"
}

View File

@@ -1,132 +1,132 @@
import { type Language, languages } from "./language-list";
/**
* Valid language code types that can be used for filtering
*/
export type LanguageCodeType = "1" | "2" | "2T" | "2B" | "3" | 1 | 2 | 3;
/**
* Valid criteria for searching languages
*/
export type LanguageCriteria = keyof Language;
// Re-export the Language interface for convenience
export type { Language } from "./language-list";
/**
* Returns all available languages
* @returns Array of all language objects
* @example
* ```typescript
* const allLangs = allLanguages();
* console.log(allLangs.length); // 184
* ```
*/
export function allLanguages(): readonly Language[] {
return languages;
}
/**
* Checks if a language exists based on given criteria and value
* @param criteria - The property to search by (e.g., 'name', '1', '2', etc.)
* @param value - The value to search for
* @returns True if language exists, false otherwise
* @example
* ```typescript
* const exists = hasLanguage('1', 'en'); // true
* const notExists = hasLanguage('name', 'Klingon'); // false
* ```
*/
export function hasLanguage(
criteria: LanguageCriteria,
value: string,
): boolean {
return findBy(criteria, value) !== undefined;
}
/**
* Gets all language codes of a specific type
* @param type - The code type to retrieve ('1', '2', '2T', '2B', '3', or numeric equivalents)
* @returns Array of language codes, or undefined if invalid type
* @example
* ```typescript
* const iso6391Codes = getCodes('1'); // ['ab', 'aa', 'af', ...]
* const iso6392Codes = getCodes('2'); // ['abk', 'aar', 'afr', ...]
* ```
*/
export function getCodes(type: LanguageCodeType): string[] | undefined {
if (!isValidType(type)) {
return undefined;
}
const stringType = String(type) as keyof Language;
return languages.map((language: Language) => language[stringType]);
}
/**
* Gets all language names (English or local)
* @param useLocal - If true, returns local names; if false, returns English names
* @returns Array of language names
* @example
* ```typescript
* const englishNames = getNames(false); // ['Abkhaz', 'Afar', 'Afrikaans', ...]
* const localNames = getNames(true); // ['Аҧсуа', 'Afaraf', 'Afrikaans', ...]
* ```
*/
export function getNames(useLocal = false): string[] {
return languages.map((language: Language) =>
useLocal ? language.local : language.name,
);
}
/**
* Finds a language by specific criteria and value
* @param criteria - The property to search by
* @param value - The value to search for
* @returns The matching language object, or undefined if not found
* @example
* ```typescript
* const english = findBy('1', 'en');
* // { name: 'English', local: 'English', '1': 'en', '2': 'eng', ... }
*
* const spanish = findBy('name', 'Spanish');
* // { name: 'Spanish', local: 'Español', '1': 'es', '2': 'spa', ... }
* ```
*/
export function findBy(
criteria: LanguageCriteria,
value: string,
): Language | undefined {
return languages.find((language: Language) => language[criteria] === value);
}
/**
* Validates if the given type is a valid language code type
* @param type - The type to validate
* @returns True if valid, false otherwise
* @internal
*/
function isValidType(type: unknown): type is LanguageCodeType {
const validTypes: (string | number)[] = [1, 2, 3, "1", "2", "2B", "2T", "3"];
return validTypes.includes(type as string | number);
}
/**
* Main API object containing all language utility functions
* @deprecated Use named exports instead
*/
export const langs = {
/** @deprecated Use allLanguages() instead */
all: allLanguages,
/** @deprecated Use hasLanguage() instead */
has: hasLanguage,
/** @deprecated Use getCodes() instead */
codes: getCodes,
/** @deprecated Use getNames() instead */
names: getNames,
/** @deprecated Use findBy() instead */
where: findBy,
} as const;
// Default export for backward compatibility
export default langs;
import { type Language, languages } from "./language-list";
/**
* Valid language code types that can be used for filtering
*/
export type LanguageCodeType = "1" | "2" | "2T" | "2B" | "3" | 1 | 2 | 3;
/**
* Valid criteria for searching languages
*/
export type LanguageCriteria = keyof Language;
// Re-export the Language interface for convenience
export type { Language } from "./language-list";
/**
* Returns all available languages
* @returns Array of all language objects
* @example
* ```typescript
* const allLangs = allLanguages();
* console.log(allLangs.length); // 184
* ```
*/
export function allLanguages(): readonly Language[] {
return languages;
}
/**
* Checks if a language exists based on given criteria and value
* @param criteria - The property to search by (e.g., 'name', '1', '2', etc.)
* @param value - The value to search for
* @returns True if language exists, false otherwise
* @example
* ```typescript
* const exists = hasLanguage('1', 'en'); // true
* const notExists = hasLanguage('name', 'Klingon'); // false
* ```
*/
export function hasLanguage(
criteria: LanguageCriteria,
value: string,
): boolean {
return findBy(criteria, value) !== undefined;
}
/**
* Gets all language codes of a specific type
* @param type - The code type to retrieve ('1', '2', '2T', '2B', '3', or numeric equivalents)
* @returns Array of language codes, or undefined if invalid type
* @example
* ```typescript
* const iso6391Codes = getCodes('1'); // ['ab', 'aa', 'af', ...]
* const iso6392Codes = getCodes('2'); // ['abk', 'aar', 'afr', ...]
* ```
*/
export function getCodes(type: LanguageCodeType): string[] | undefined {
if (!isValidType(type)) {
return undefined;
}
const stringType = String(type) as keyof Language;
return languages.map((language: Language) => language[stringType]);
}
/**
* Gets all language names (English or local)
* @param useLocal - If true, returns local names; if false, returns English names
* @returns Array of language names
* @example
* ```typescript
* const englishNames = getNames(false); // ['Abkhaz', 'Afar', 'Afrikaans', ...]
* const localNames = getNames(true); // ['Аҧсуа', 'Afaraf', 'Afrikaans', ...]
* ```
*/
export function getNames(useLocal = false): string[] {
return languages.map((language: Language) =>
useLocal ? language.local : language.name,
);
}
/**
* Finds a language by specific criteria and value
* @param criteria - The property to search by
* @param value - The value to search for
* @returns The matching language object, or undefined if not found
* @example
* ```typescript
* const english = findBy('1', 'en');
* // { name: 'English', local: 'English', '1': 'en', '2': 'eng', ... }
*
* const spanish = findBy('name', 'Spanish');
* // { name: 'Spanish', local: 'Español', '1': 'es', '2': 'spa', ... }
* ```
*/
export function findBy(
criteria: LanguageCriteria,
value: string,
): Language | undefined {
return languages.find((language: Language) => language[criteria] === value);
}
/**
* Validates if the given type is a valid language code type
* @param type - The type to validate
* @returns True if valid, false otherwise
* @internal
*/
function isValidType(type: unknown): type is LanguageCodeType {
const validTypes: (string | number)[] = [1, 2, 3, "1", "2", "2B", "2T", "3"];
return validTypes.includes(type as string | number);
}
/**
* Main API object containing all language utility functions
* @deprecated Use named exports instead
*/
export const langs = {
/** @deprecated Use allLanguages() instead */
all: allLanguages,
/** @deprecated Use hasLanguage() instead */
has: hasLanguage,
/** @deprecated Use getCodes() instead */
codes: getCodes,
/** @deprecated Use getNames() instead */
names: getNames,
/** @deprecated Use findBy() instead */
where: findBy,
} as const;
// Default export for backward compatibility
export default langs;

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
{
"name": "@nontara/language-codes",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5"
}
}
"name": "@nontara/language-codes",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5"
}
}

View File

@@ -1,105 +1,115 @@
/**
* Test file for the lang-codes package
* This file demonstrates the usage and validates the functionality
*/
import {
allLanguages,
hasLanguage,
getCodes,
getNames,
findBy,
type Language,
type LanguageCodeType,
type LanguageCriteria,
langs // Legacy API
} from "./index";
function runTests() {
console.log("🧪 Testing lang-codes package...\n");
// Test 1: allLanguages()
console.log("1⃣ Testing allLanguages()");
const allLangs = allLanguages();
console.log(` ✅ Total languages: ${allLangs.length}`);
console.log(` ✅ First language: ${allLangs[0].name} (${allLangs[0]['1']})`);
console.log();
// Test 2: hasLanguage()
console.log("2⃣ Testing hasLanguage()");
console.log(` ✅ Has English (ISO 639-1): ${hasLanguage('1', 'en')}`);
console.log(` ✅ Has Spanish (name): ${hasLanguage('name', 'Spanish')}`);
console.log(` ✅ Has Klingon (name): ${hasLanguage('name', 'Klingon')}`);
console.log();
// Test 3: getCodes()
console.log("3⃣ Testing getCodes()");
const iso1Codes = getCodes('1');
const iso2Codes = getCodes('2');
const invalidCodes = getCodes('invalid' as LanguageCodeType);
console.log(` ✅ ISO 639-1 codes count: ${iso1Codes?.length}`);
console.log(` ✅ ISO 639-2 codes count: ${iso2Codes?.length}`);
console.log(` ✅ Invalid type returns: ${invalidCodes}`);
console.log(` Sample ISO 639-1 codes: ${iso1Codes?.slice(0, 5).join(', ')}`);
console.log();
// Test 4: getNames()
console.log("4⃣ Testing getNames()");
const englishNames = getNames(false);
const localNames = getNames(true);
console.log(` ✅ English names count: ${englishNames.length}`);
console.log(` ✅ Local names count: ${localNames.length}`);
console.log(` ✅ Sample English names: ${englishNames.slice(0, 3).join(', ')}`);
console.log(` ✅ Sample local names: ${localNames.slice(0, 3).join(', ')}`);
console.log();
// Test 5: findBy()
console.log("5⃣ Testing findBy()");
const english = findBy('1', 'en');
const spanish = findBy('name', 'Spanish');
const french = findBy('local', 'Français');
const notFound = findBy('name', 'Klingon');
console.log(` ✅ English by ISO 639-1: ${english?.name} (${english?.local})`);
console.log(` ✅ Spanish by name: ${spanish?.name} (${spanish?.['1']})`);
console.log(` ✅ French by local name: ${french?.name} (${french?.['1']})`);
console.log(` ✅ Klingon (not found): ${notFound}`);
console.log();
// Test 6: Legacy API
console.log("6⃣ Testing Legacy API");
const legacyAll = langs.all();
const legacyHas = langs.has('1', 'de');
const legacyCodes = langs.codes('2');
const legacyNames = langs.names(false);
const legacyWhere = langs.where('name', 'German');
console.log(` ✅ Legacy all() count: ${legacyAll.length}`);
console.log(` ✅ Legacy has() German: ${legacyHas}`);
console.log(` ✅ Legacy codes() count: ${legacyCodes?.length}`);
console.log(` ✅ Legacy names() count: ${legacyNames.length}`);
console.log(` ✅ Legacy where() German: ${legacyWhere?.name} (${legacyWhere?.['1']})`);
console.log();
// Test 7: Type validation
console.log("7⃣ Testing Type Safety");
const language: Language | undefined = findBy('name', 'English');
if (language) {
// Type-safe access to language properties
const name: string = language.name;
const local: string = language.local;
const iso1: string = language['1'];
const iso2: string = language['2'];
console.log(` ✅ Type-safe access: ${name} (${iso1}) - ${local}`);
}
// Test various code types
const codeTypes: LanguageCodeType[] = ['1', '2', '2B', '2T', '3', 1, 2, 3];
console.log(` ✅ Valid code types: ${codeTypes.join(', ')}`);
console.log();
console.log("🎉 All tests completed successfully!");
}
// Run the tests
runTests();
/**
* Test file for the lang-codes package
* This file demonstrates the usage and validates the functionality
*/
import {
allLanguages,
findBy,
getCodes,
getNames,
hasLanguage,
type Language,
type LanguageCodeType,
type LanguageCriteria,
langs, // Legacy API
} from "./index";
function runTests() {
console.log("🧪 Testing lang-codes package...\n");
// Test 1: allLanguages()
console.log("1⃣ Testing allLanguages()");
const allLangs = allLanguages();
console.log(` ✅ Total languages: ${allLangs.length}`);
console.log(
` ✅ First language: ${allLangs[0].name} (${allLangs[0]["1"]})`,
);
console.log();
// Test 2: hasLanguage()
console.log("2⃣ Testing hasLanguage()");
console.log(` ✅ Has English (ISO 639-1): ${hasLanguage("1", "en")}`);
console.log(` ✅ Has Spanish (name): ${hasLanguage("name", "Spanish")}`);
console.log(` ✅ Has Klingon (name): ${hasLanguage("name", "Klingon")}`);
console.log();
// Test 3: getCodes()
console.log("3⃣ Testing getCodes()");
const iso1Codes = getCodes("1");
const iso2Codes = getCodes("2");
const invalidCodes = getCodes("invalid" as LanguageCodeType);
console.log(` ✅ ISO 639-1 codes count: ${iso1Codes?.length}`);
console.log(` ✅ ISO 639-2 codes count: ${iso2Codes?.length}`);
console.log(` ✅ Invalid type returns: ${invalidCodes}`);
console.log(
` ✅ Sample ISO 639-1 codes: ${iso1Codes?.slice(0, 5).join(", ")}`,
);
console.log();
// Test 4: getNames()
console.log("4⃣ Testing getNames()");
const englishNames = getNames(false);
const localNames = getNames(true);
console.log(` ✅ English names count: ${englishNames.length}`);
console.log(` ✅ Local names count: ${localNames.length}`);
console.log(
` ✅ Sample English names: ${englishNames.slice(0, 3).join(", ")}`,
);
console.log(` ✅ Sample local names: ${localNames.slice(0, 3).join(", ")}`);
console.log();
// Test 5: findBy()
console.log("5⃣ Testing findBy()");
const english = findBy("1", "en");
const spanish = findBy("name", "Spanish");
const french = findBy("local", "Français");
const notFound = findBy("name", "Klingon");
console.log(
` ✅ English by ISO 639-1: ${english?.name} (${english?.local})`,
);
console.log(` ✅ Spanish by name: ${spanish?.name} (${spanish?.["1"]})`);
console.log(` ✅ French by local name: ${french?.name} (${french?.["1"]})`);
console.log(` ✅ Klingon (not found): ${notFound}`);
console.log();
// Test 6: Legacy API
console.log("6⃣ Testing Legacy API");
const legacyAll = langs.all();
const legacyHas = langs.has("1", "de");
const legacyCodes = langs.codes("2");
const legacyNames = langs.names(false);
const legacyWhere = langs.where("name", "German");
console.log(` ✅ Legacy all() count: ${legacyAll.length}`);
console.log(` ✅ Legacy has() German: ${legacyHas}`);
console.log(` ✅ Legacy codes() count: ${legacyCodes?.length}`);
console.log(` ✅ Legacy names() count: ${legacyNames.length}`);
console.log(
` ✅ Legacy where() German: ${legacyWhere?.name} (${legacyWhere?.["1"]})`,
);
console.log();
// Test 7: Type validation
console.log("7⃣ Testing Type Safety");
const language: Language | undefined = findBy("name", "English");
if (language) {
// Type-safe access to language properties
const name: string = language.name;
const local: string = language.local;
const iso1: string = language["1"];
const iso2: string = language["2"];
console.log(` ✅ Type-safe access: ${name} (${iso1}) - ${local}`);
}
// Test various code types
const codeTypes: LanguageCodeType[] = ["1", "2", "2B", "2T", "3", 1, 2, 3];
console.log(` ✅ Valid code types: ${codeTypes.join(", ")}`);
console.log();
console.log("🎉 All tests completed successfully!");
}
// Run the tests
runTests();

View File

@@ -1,29 +1,29 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}