mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
chore: extract shared tsconfig, move display-status to core, add i18n tests
- Add `@sofa/tsconfig` package with a shared `base.json` (target, lib, strict, moduleResolution, etc.) and migrate all packages/apps to `"extends": "@sofa/tsconfig/base.json"` to eliminate duplicated compiler options - Move `display-status.ts` (and its `DisplayStatus` type + `getDisplayStatus` fn) from `@sofa/api` to `@sofa/core`; remove the `./display-status` export from `@sofa/api` and update all import sites in `discovery.ts` and `tracking.ts` - Add `packages/core/test/display-status.test.ts`: 15 tests covering `ONGOING_TMDB_STATUSES` and all `getDisplayStatus` branches (movie, TV watchlist/in_progress/caught_up/completed, edge cases) - Add `packages/i18n/vitest.config.ts` and two new test files: `date-buckets.test.ts` and `format.test.ts` covering date bucketing and locale formatting utilities
This commit is contained in:
@@ -7,8 +7,7 @@
|
||||
"./contract": "./src/contract.ts",
|
||||
"./schemas": "./src/schemas.ts",
|
||||
"./errors": "./src/errors.ts",
|
||||
"./utils": "./src/utils.ts",
|
||||
"./display-status": "./src/display-status.ts"
|
||||
"./utils": "./src/utils.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "oxlint",
|
||||
@@ -21,6 +20,7 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"better-auth": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/bun": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"check-types": "tsc --noEmit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/bun": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"./credits": "./src/credits.ts",
|
||||
"./cron": "./src/cron.ts",
|
||||
"./discovery": "./src/discovery.ts",
|
||||
"./display-status": "./src/display-status.ts",
|
||||
"./export": "./src/export.ts",
|
||||
"./image-cache": "./src/image-cache.ts",
|
||||
"./imports": "./src/imports/index.ts",
|
||||
@@ -49,6 +50,7 @@
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/adm-zip": "0.5.8",
|
||||
"@types/bun": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { DisplayStatus } from "@sofa/api/display-status";
|
||||
import {
|
||||
getAllTrackedTitleIds,
|
||||
getAvailabilityByTitleIds,
|
||||
@@ -25,6 +24,7 @@ import {
|
||||
} from "@sofa/db/queries/discovery";
|
||||
import { tmdbImageUrl } from "@sofa/tmdb/image";
|
||||
|
||||
import type { DisplayStatus } from "./display-status";
|
||||
import { getDisplayStatusesByTitleIds } from "./tracking";
|
||||
|
||||
function formatLocalDate(d: Date): string {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { DisplayStatus } from "@sofa/api/display-status";
|
||||
import { getDisplayStatus } from "@sofa/api/display-status";
|
||||
import { getTitlesByIds } from "@sofa/db/queries/discovery";
|
||||
import { getTitleById } from "@sofa/db/queries/title";
|
||||
import {
|
||||
@@ -25,6 +23,9 @@ import {
|
||||
upsertTitleStatus,
|
||||
} from "@sofa/db/queries/tracking";
|
||||
|
||||
import type { DisplayStatus } from "./display-status";
|
||||
import { getDisplayStatus } from "./display-status";
|
||||
|
||||
export function setTitleStatus(
|
||||
userId: string,
|
||||
titleId: string,
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { ONGOING_TMDB_STATUSES, getDisplayStatus } from "../src/display-status";
|
||||
|
||||
describe("ONGOING_TMDB_STATUSES", () => {
|
||||
test("contains expected values", () => {
|
||||
expect(ONGOING_TMDB_STATUSES).toContain("Returning Series");
|
||||
expect(ONGOING_TMDB_STATUSES).toContain("In Production");
|
||||
expect(ONGOING_TMDB_STATUSES).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getDisplayStatus", () => {
|
||||
// -- Movies --
|
||||
|
||||
test("movie with watchlist status returns in_watchlist", () => {
|
||||
expect(getDisplayStatus("watchlist", "movie", null, null)).toBe("in_watchlist");
|
||||
});
|
||||
|
||||
test("movie with completed status returns completed", () => {
|
||||
expect(getDisplayStatus("completed", "movie", null, null)).toBe("completed");
|
||||
});
|
||||
|
||||
test("movie with in_progress status returns in_watchlist", () => {
|
||||
// Movies don't have an "in_progress" concept — falls through to in_watchlist
|
||||
expect(getDisplayStatus("in_progress", "movie", null, null)).toBe("in_watchlist");
|
||||
});
|
||||
|
||||
// -- TV: watchlist --
|
||||
|
||||
test("TV with watchlist status returns in_watchlist", () => {
|
||||
expect(getDisplayStatus("watchlist", "tv", "Returning Series", null)).toBe("in_watchlist");
|
||||
});
|
||||
|
||||
// -- TV: in_progress, no/partial progress --
|
||||
|
||||
test("TV in_progress with no progress data returns watching", () => {
|
||||
expect(getDisplayStatus("in_progress", "tv", "Returning Series", null)).toBe("watching");
|
||||
});
|
||||
|
||||
test("TV in_progress with partial progress returns watching", () => {
|
||||
expect(
|
||||
getDisplayStatus("in_progress", "tv", "Returning Series", { watched: 3, total: 10 }),
|
||||
).toBe("watching");
|
||||
});
|
||||
|
||||
test("TV in_progress with zero total returns watching", () => {
|
||||
expect(getDisplayStatus("in_progress", "tv", "Ended", { watched: 0, total: 0 })).toBe(
|
||||
"watching",
|
||||
);
|
||||
});
|
||||
|
||||
// -- TV: in_progress, all watched, ongoing --
|
||||
|
||||
test("TV in_progress, all watched, Returning Series returns caught_up", () => {
|
||||
expect(
|
||||
getDisplayStatus("in_progress", "tv", "Returning Series", { watched: 10, total: 10 }),
|
||||
).toBe("caught_up");
|
||||
});
|
||||
|
||||
test("TV in_progress, all watched, In Production returns caught_up", () => {
|
||||
expect(getDisplayStatus("in_progress", "tv", "In Production", { watched: 10, total: 10 })).toBe(
|
||||
"caught_up",
|
||||
);
|
||||
});
|
||||
|
||||
// -- TV: in_progress, all watched, ended --
|
||||
|
||||
test("TV in_progress, all watched, Ended returns completed", () => {
|
||||
expect(getDisplayStatus("in_progress", "tv", "Ended", { watched: 10, total: 10 })).toBe(
|
||||
"completed",
|
||||
);
|
||||
});
|
||||
|
||||
test("TV in_progress, all watched, Canceled returns completed", () => {
|
||||
expect(getDisplayStatus("in_progress", "tv", "Canceled", { watched: 5, total: 5 })).toBe(
|
||||
"completed",
|
||||
);
|
||||
});
|
||||
|
||||
test("TV in_progress, all watched, null tmdbStatus returns completed", () => {
|
||||
expect(getDisplayStatus("in_progress", "tv", null, { watched: 10, total: 10 })).toBe(
|
||||
"completed",
|
||||
);
|
||||
});
|
||||
|
||||
// -- Edge cases --
|
||||
|
||||
test("TV in_progress, watched exceeds total still returns caught_up/completed", () => {
|
||||
// watched > total shouldn't happen, but if it does, treat as all-watched
|
||||
expect(
|
||||
getDisplayStatus("in_progress", "tv", "Returning Series", { watched: 15, total: 10 }),
|
||||
).toBe("caught_up");
|
||||
expect(getDisplayStatus("in_progress", "tv", "Ended", { watched: 15, total: 10 })).toBe(
|
||||
"completed",
|
||||
);
|
||||
});
|
||||
|
||||
test("TV completed status returns in_watchlist (no special handling)", () => {
|
||||
// "completed" stored status on TV falls through the movie branch check
|
||||
// titleType !== "movie" so it doesn't enter that branch, and storedStatus !== "watchlist"
|
||||
// so it falls to the episode progress check → no progress → "watching"
|
||||
expect(getDisplayStatus("completed", "tv", "Ended", null)).toBe("watching");
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src", "test"]
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"drizzle-orm": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/bun": "catalog:",
|
||||
"drizzle-kit": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"lint": "oxlint",
|
||||
"format": "oxfmt --config ../../.oxfmtrc.json",
|
||||
"format:check": "oxfmt --check --config ../../.oxfmtrc.json",
|
||||
"check-types": "tsc --noEmit"
|
||||
"check-types": "tsc --noEmit",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lingui/core": "catalog:",
|
||||
@@ -24,8 +25,10 @@
|
||||
"@lingui/cli": "catalog:",
|
||||
"@lingui/conf": "catalog:",
|
||||
"@lingui/format-po": "catalog:",
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/bun": "catalog:",
|
||||
"react": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
"typescript": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
|
||||
vi.mock("../src/index", () => ({
|
||||
i18n: {
|
||||
locale: "en",
|
||||
_: (descriptor: { id?: string; message?: string } | string) => {
|
||||
if (typeof descriptor === "string") return descriptor;
|
||||
return descriptor.message ?? descriptor.id ?? "";
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@lingui/core/macro", () => ({
|
||||
msg: (strings: TemplateStringsArray, ...values: unknown[]) => ({
|
||||
id: String.raw(strings, ...values),
|
||||
message: String.raw(strings, ...values),
|
||||
}),
|
||||
}));
|
||||
|
||||
import { formatLocalDate, groupByDateBucket } from "../src/date-buckets";
|
||||
|
||||
describe("formatLocalDate", () => {
|
||||
test("formats a date as YYYY-MM-DD", () => {
|
||||
expect(formatLocalDate(new Date(2024, 0, 5))).toBe("2024-01-05");
|
||||
});
|
||||
|
||||
test("pads single-digit month and day", () => {
|
||||
expect(formatLocalDate(new Date(2024, 2, 3))).toBe("2024-03-03");
|
||||
});
|
||||
|
||||
test("handles December correctly", () => {
|
||||
expect(formatLocalDate(new Date(2024, 11, 31))).toBe("2024-12-31");
|
||||
});
|
||||
});
|
||||
|
||||
describe("groupByDateBucket", () => {
|
||||
// Pin "today" to a Wednesday: 2024-06-12
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2024-06-12T10:00:00"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test("empty array returns empty result", () => {
|
||||
expect(groupByDateBucket([])).toEqual([]);
|
||||
});
|
||||
|
||||
test("item on today goes to 'today' bucket", () => {
|
||||
const result = groupByDateBucket([{ date: "2024-06-12" }]);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].key).toBe("today");
|
||||
expect(result[0].items).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("item on tomorrow goes to 'tomorrow' bucket", () => {
|
||||
const result = groupByDateBucket([{ date: "2024-06-13" }]);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].key).toBe("tomorrow");
|
||||
});
|
||||
|
||||
test("item within 6 days goes to 'this_week' bucket", () => {
|
||||
// Today is June 12 (Wed), end of week = June 18 (Tue)
|
||||
const result = groupByDateBucket([{ date: "2024-06-17" }]);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].key).toBe("this_week");
|
||||
});
|
||||
|
||||
test("item 7-13 days out goes to 'next_week' bucket", () => {
|
||||
// End of week = June 18, next week ends June 25
|
||||
const result = groupByDateBucket([{ date: "2024-06-22" }]);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].key).toBe("next_week");
|
||||
});
|
||||
|
||||
test("item 30+ days out goes to month bucket", () => {
|
||||
const result = groupByDateBucket([{ date: "2024-08-15" }]);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].key).toBe("month_2024-08");
|
||||
});
|
||||
|
||||
test("multiple items in same bucket are grouped together", () => {
|
||||
const result = groupByDateBucket([
|
||||
{ date: "2024-06-12", name: "a" },
|
||||
{ date: "2024-06-12", name: "b" },
|
||||
]);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].key).toBe("today");
|
||||
expect(result[0].items).toHaveLength(2);
|
||||
});
|
||||
|
||||
test("items across multiple buckets are ordered by first appearance", () => {
|
||||
const result = groupByDateBucket([
|
||||
{ date: "2024-06-13" }, // tomorrow
|
||||
{ date: "2024-06-12" }, // today
|
||||
{ date: "2024-08-01" }, // month
|
||||
]);
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result[0].key).toBe("tomorrow");
|
||||
expect(result[1].key).toBe("today");
|
||||
expect(result[2].key).toBe("month_2024-08");
|
||||
});
|
||||
|
||||
test("bucket labels are populated", () => {
|
||||
const result = groupByDateBucket([{ date: "2024-06-12" }, { date: "2024-06-13" }]);
|
||||
expect(result[0].label).toBeTruthy();
|
||||
expect(result[1].label).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
|
||||
vi.mock("../src/index", () => ({
|
||||
i18n: { locale: "en" },
|
||||
}));
|
||||
|
||||
import {
|
||||
formatBytes,
|
||||
formatDate,
|
||||
formatNumber,
|
||||
formatRelativeTime,
|
||||
formatShortDate,
|
||||
} from "../src/format";
|
||||
|
||||
describe("formatDate", () => {
|
||||
test("formats a Date object", () => {
|
||||
const result = formatDate(new Date("2024-06-15T12:00:00Z"));
|
||||
expect(result).toContain("2024");
|
||||
expect(result).toContain("15");
|
||||
});
|
||||
|
||||
test("formats date-only ISO string in UTC to avoid off-by-one", () => {
|
||||
// "1990-05-15" is parsed as UTC midnight — formatting in UTC prevents
|
||||
// users west of UTC from seeing May 14 instead of May 15
|
||||
const result = formatDate("1990-05-15");
|
||||
expect(result).toContain("15");
|
||||
expect(result).toContain("1990");
|
||||
});
|
||||
|
||||
test("respects custom options", () => {
|
||||
const result = formatDate("2024-06-15", { month: "short" });
|
||||
expect(result).toContain("Jun");
|
||||
});
|
||||
|
||||
test("does not force UTC when a timeZone option is provided", () => {
|
||||
const result = formatDate("2024-06-15", { timeZone: "America/New_York" });
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
test("formats a full ISO datetime string (not date-only)", () => {
|
||||
const result = formatDate("2024-06-15T18:30:00Z");
|
||||
expect(result).toContain("2024");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatShortDate", () => {
|
||||
test("formats with short month", () => {
|
||||
// Use a local Date to avoid UTC-to-local day shift
|
||||
const result = formatShortDate(new Date(2024, 0, 3));
|
||||
expect(result).toContain("Jan");
|
||||
expect(result).toContain("3");
|
||||
expect(result).toContain("2024");
|
||||
});
|
||||
|
||||
test("accepts a Date object", () => {
|
||||
const result = formatShortDate(new Date(2024, 11, 25));
|
||||
expect(result).toContain("Dec");
|
||||
expect(result).toContain("25");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatRelativeTime", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2024-06-15T12:00:00Z"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test("seconds ago", () => {
|
||||
const result = formatRelativeTime("2024-06-15T11:59:30Z");
|
||||
expect(result).toContain("30 seconds ago");
|
||||
});
|
||||
|
||||
test("minutes ago", () => {
|
||||
const result = formatRelativeTime("2024-06-15T11:55:00Z");
|
||||
expect(result).toContain("5 minutes ago");
|
||||
});
|
||||
|
||||
test("hours ago", () => {
|
||||
const result = formatRelativeTime("2024-06-15T09:00:00Z");
|
||||
expect(result).toContain("3 hours ago");
|
||||
});
|
||||
|
||||
test("days ago", () => {
|
||||
const result = formatRelativeTime("2024-06-10T12:00:00Z");
|
||||
expect(result).toContain("5 days ago");
|
||||
});
|
||||
|
||||
test("months ago", () => {
|
||||
const result = formatRelativeTime("2024-03-15T12:00:00Z");
|
||||
expect(result).toContain("3 months ago");
|
||||
});
|
||||
|
||||
test("years ago", () => {
|
||||
const result = formatRelativeTime("2022-06-15T12:00:00Z");
|
||||
expect(result).toContain("2 years ago");
|
||||
});
|
||||
|
||||
test("future seconds", () => {
|
||||
const result = formatRelativeTime("2024-06-15T12:00:45Z");
|
||||
expect(result).toContain("in 45 seconds");
|
||||
});
|
||||
|
||||
test("future days", () => {
|
||||
const result = formatRelativeTime("2024-06-20T12:00:00Z");
|
||||
expect(result).toContain("in 5 days");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatNumber", () => {
|
||||
test("formats a number", () => {
|
||||
expect(formatNumber(1234)).toBe("1,234");
|
||||
});
|
||||
|
||||
test("respects options", () => {
|
||||
const result = formatNumber(0.5, { style: "percent" });
|
||||
expect(result).toBe("50%");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatBytes", () => {
|
||||
test("zero bytes", () => {
|
||||
expect(formatBytes(0)).toBe("0 B");
|
||||
});
|
||||
|
||||
test("bytes", () => {
|
||||
expect(formatBytes(512)).toBe("512 B");
|
||||
});
|
||||
|
||||
test("kilobytes", () => {
|
||||
expect(formatBytes(1024)).toBe("1 KB");
|
||||
});
|
||||
|
||||
test("megabytes", () => {
|
||||
expect(formatBytes(1024 * 1024)).toBe("1 MB");
|
||||
});
|
||||
|
||||
test("gigabytes", () => {
|
||||
expect(formatBytes(1024 * 1024 * 1024)).toBe("1 GB");
|
||||
});
|
||||
|
||||
test("fractional megabytes", () => {
|
||||
expect(formatBytes(1536 * 1024)).toBe("1.5 MB");
|
||||
});
|
||||
});
|
||||
@@ -1,15 +1,7 @@
|
||||
{
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"types": ["bun"]
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src", "test"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { defineProject } from "vitest/config";
|
||||
|
||||
export default defineProject({
|
||||
test: {
|
||||
include: ["test/**/*.test.ts"],
|
||||
},
|
||||
});
|
||||
@@ -17,6 +17,7 @@
|
||||
"pino-pretty": "13.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/bun": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"drizzle-orm": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/better-sqlite3": "7.6.13",
|
||||
"typescript": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"openapi-fetch": "0.17.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sofa/tsconfig": "workspace:*",
|
||||
"@types/bun": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["esnext"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["bun"]
|
||||
},
|
||||
"extends": "@sofa/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "https://www.schemastore.org/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"lib": ["ESNext"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"isolatedModules": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"types": ["bun"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@sofa/tsconfig",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./base.json": "./base.json"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user