vendor: support native TypeScript source loading

This commit is contained in:
imccyu
2026-07-28 23:03:23 +08:00
parent eb38a365dc
commit 5ea161fa68
23 changed files with 77 additions and 72 deletions

1
vendor/README.md vendored
View File

@@ -38,6 +38,7 @@ Keep this log exhaustive — every divergence from upstream must be listed.
6. **`cordis/src/fiber.ts` lifecycle hardening**: locally closes three reentrant disposal gaps. An effect's owner-list wrapper is registered before its setup body runs, so an unload begun from inside setup awaits setup and every collected cleanup; synchronous setup failure removes the wrapper and rolls back collected cleanup. Async cleanup stays owner-visible until quiescence, and Cordis's internal effect composition joins an already-running cleanup while repeated public disposer calls retain their upstream single-shot result. Effect creation is rejected while the owner is `UNLOADING` (while `PENDING` and `LOADING` remain legal), preventing cleanup-time registrations from escaping the unload snapshot. Child fibers register and receive their parent-owned disposer before `internal/plugin` publication, resolve dependency declarations added by that notification before activation, drain effects attached while pending, skip plugin execution when reentrant disposal invalidates the load epoch before its first checkpoint, and contain teardown-notification failures per observer so one callback cannot starve peers or interrupt ownership cleanup.
7. **`cordis/src/*.ts` JSDoc enrichment**: added `@param`/`@returns` tags and contract documentation (disposal semantics, waterfall veto, bail conditions, error cases) across the public plugin-author surface — `Context` (class, statics, and the `Context` interface properties incl. `root`), `EventsService`, `Fiber`, `RegistryService`, `ReflectService`, `Service`, `LoggerService` and their `declare module './context.ts'` overloads. Comment-only; no code changes. Motivation: the website API-reference generator renders these docs and hard-errors on undocumented members. Retire this entry when the enrichment is upstreamed to the fork.
8. **`include/src/index.ts` hot-reload hardening**: `refresh()` awaits the full read-and-update and catches failures (logging a warning and keeping the last good entry tree) instead of rethrowing — upstream's throw escaped `@cordisjs/plugin-hmr`'s async watcher callback as an unhandled rejection, so one bad `cordis.yml` edit killed a live app. `read()` rejects a non-array parse result (an empty or mid-write truncated file parses to `undefined`, which upstream later crashed on) and commits `content`/`data` only on success, so reverting an edit to the exact last good content reads as "unchanged". `refresh()` and the `internal/update` listener re-apply `config.patches` before `root.update()`, matching initial load; upstream applied patches only in `[Service.init]`, so any config hot-reload silently reverted overlay-patched entries and removed inserted ones. `applyPatches` deep-copies via `structuredClone` instead of mutating the cached parse (repeated application converges; removing a patch reverts), and the veto-style `internal/update` listener persists the incoming config itself (`Fiber.update` only assigns behind `next()`), so later re-reads use the new patches. `[Service.init]` falls back to `initial` only on `ENOENT`; an existing-but-invalid file fails loud with its real parse error instead of "config file not found" (or a silent overwrite). Covered by `packages/ui/app-boot/tests/config-reload.spec.ts`.
9. **Vendored Node-compatible TypeScript**: marked erased imports explicitly across `cordis`, `loader`, `include`, `hmr`, and `schemastery` so Node's native TypeScript transform does not request types as runtime exports. Schemastery's source uses an ESM default export and its package declares `type: module`; its built ESM/CJS entries retain explicit `.mjs`/`.cjs` extensions.
## Sync procedure

View File

@@ -1,8 +1,8 @@
import { Dict } from 'cosmokit'
import type { Dict } from 'cosmokit'
import { EventsService } from './events.ts'
import { LoggerService } from './logger.ts'
import { ReflectService } from './reflect.ts'
import { InjectKey, RegistryService } from './registry.ts'
import { RegistryService, type InjectKey } from './registry.ts'
import { getTraceable, symbols } from './utils.ts'
import { Fiber } from './fiber.ts'

View File

@@ -1,4 +1,5 @@
import { defineProperty, Promisify } from 'cosmokit'
import { defineProperty } from 'cosmokit'
import type { Promisify } from 'cosmokit'
import { Context } from './context.ts'
import { Fiber, FiberState } from './fiber.ts'
import { DisposableList, symbols } from './utils.ts'

View File

@@ -1,9 +1,10 @@
import { Awaitable, defineProperty, Dict, isNullable } from 'cosmokit'
import { defineProperty, isNullable } from 'cosmokit'
import type { Awaitable, Dict } from 'cosmokit'
import { Context } from './context.ts'
import { Plugin } from './registry.ts'
import type { Plugin } from './registry.ts'
import { buildOuterStack, composeError, DisposableList, getTraceable, isConstructor, isObject, symbols } from './utils.ts'
import { Impl } from './reflect.ts'
import { StandardSchemaV1 } from '@standard-schema/spec'
import type { Impl } from './reflect.ts'
import type { StandardSchemaV1 } from '@standard-schema/spec'
declare module './context.ts' {
export interface Context extends Pick<Fiber, 'effect'> {

View File

@@ -1,7 +1,7 @@
import { defineProperty, hyphenate } from 'cosmokit'
import { Context } from './context.ts'
import { Fiber } from './fiber.ts'
import { createCallable, joinPrototype, symbols, Tracker } from './utils.ts'
import { createCallable, joinPrototype, symbols, type Tracker } from './utils.ts'
declare module './context.ts' {
interface Intercept {

View File

@@ -1,4 +1,5 @@
import { defineProperty, Dict, isNullable } from 'cosmokit'
import { defineProperty, isNullable } from 'cosmokit'
import type { Dict } from 'cosmokit'
import { Context } from './context.ts'
import { getTraceable, symbols, withProps } from './utils.ts'
import { Fiber, FiberState } from './fiber.ts'

View File

@@ -1,5 +1,6 @@
import { defineProperty, Dict } from 'cosmokit'
import { StandardSchemaV1 } from '@standard-schema/spec'
import { defineProperty } from 'cosmokit'
import type { Dict } from 'cosmokit'
import type { StandardSchemaV1 } from '@standard-schema/spec'
import { Context } from './context.ts'
import { Fiber } from './fiber.ts'
import { buildOuterStack, DisposableList, symbols, withProps } from './utils.ts'

View File

@@ -1,6 +1,6 @@
import { defineProperty } from 'cosmokit'
import { Context } from './context.ts'
import { createCallable, joinPrototype, symbols, Tracker } from './utils.ts'
import { createCallable, joinPrototype, symbols, type Tracker } from './utils.ts'
/**
* Base class for services that expose a named API on `ctx`.

View File

@@ -1,5 +1,5 @@
import { Context } from 'cordis'
import { BuildFailure } from 'esbuild'
import type { BuildFailure } from 'esbuild'
import { codeFrameColumns } from '@babel/code-frame'
import { readFileSync } from 'node:fs'

View File

@@ -1,8 +1,8 @@
import { Context, Inject, Plugin, Service } from 'cordis'
import { Dict } from 'cosmokit'
import { ModuleJob, ModuleLoader, ResolveResult } from '@cordisjs/plugin-loader'
import { Context, Inject, Service, type Plugin } from 'cordis'
import type { Dict } from 'cosmokit'
import { ModuleLoader, type ModuleJob, type ResolveResult } from '@cordisjs/plugin-loader'
import type { Include } from '@cordisjs/plugin-include'
import { ChokidarOptions, FSWatcher, watch } from 'chokidar'
import { FSWatcher, watch, type ChokidarOptions } from 'chokidar'
import { relative, resolve } from 'node:path'
import { handleError } from './error.ts'
import type {} from '@cordisjs/plugin-timer'

View File

@@ -1,4 +1,4 @@
import { EntryOptions, EntryTree, isJsExpr } from '@cordisjs/plugin-loader'
import { EntryTree, isJsExpr, type EntryOptions } from '@cordisjs/plugin-loader'
import { Context, Service } from 'cordis'
import { extname } from 'node:path'
import { access, constants, readFile, rename, writeFile } from 'node:fs/promises'

View File

@@ -1,5 +1,5 @@
import { Context, Service } from 'cordis'
import { Entry, EntryOptions } from './entry.ts'
import { Entry, type EntryOptions } from './entry.ts'
import { EntryTree } from './tree.ts'
/** Runtime owner for a list of child loader entries. */

View File

@@ -1,5 +1,5 @@
import { Context } from 'cordis'
import { Dict } from 'cosmokit'
import type { Dict } from 'cosmokit'
import { Entry } from './entry.ts'
declare module './entry.ts' {

View File

@@ -1,6 +1,6 @@
import { composeError, Context } from 'cordis'
import { Dict, isNonNullable } from 'cosmokit'
import { Entry, EntryOptions } from './entry.ts'
import { isNonNullable, type Dict } from 'cosmokit'
import { Entry, type EntryOptions } from './entry.ts'
import { EntryGroup } from './group.ts'
/** Mutable tree of loader entries. Persistence is supplied by subclasses. */

View File

@@ -1,7 +1,7 @@
import { Context, Inject, Service } from 'cordis'
import { defineProperty, Dict, isNullable } from 'cosmokit'
import { defineProperty, isNullable, type Dict } from 'cosmokit'
import { ModuleLoader } from './internal.ts'
import { Entry, EntryOptions } from './config/entry.ts'
import { Entry, type EntryOptions } from './config/entry.ts'
import isolate from './config/isolate.ts'
import { EntryTree } from './config/tree.ts'

View File

@@ -1,5 +1,5 @@
import { createRequire, LoadHookContext } from 'node:module'
import { Dict } from 'cosmokit'
import { createRequire, type LoadHookContext } from 'node:module'
import type { Dict } from 'cosmokit'
/** Node internal module format names handled by loader hooks. */
export type ModuleFormat = 'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'

View File

@@ -3,6 +3,7 @@
"description": "Type driven schema validator",
"version": "3.18.0",
"private": true,
"type": "module",
"main": "lib/index.cjs",
"module": "lib/index.mjs",
"types": "lib/types/index.d.ts",

View File

@@ -1,4 +1,4 @@
import { Binary, clone, deepEqual, Dict, filterKeys, isNullable, isPlainObject, pick, valueMap } from 'cosmokit'
import { Binary, clone, deepEqual, filterKeys, isNullable, isPlainObject, pick, valueMap, type Dict } from 'cosmokit'
import type { StandardSchemaV1 } from '@standard-schema/spec'
const kSchema = Symbol.for('schemastery')
@@ -899,4 +899,4 @@ defineMethod('intersect', ['list'], ({ list }) => {
defineMethod('transform', ['inner', 'callback', 'preserve'], ({ inner }, isInner) => inner!.toString(isInner))
export = Schema
export default Schema

View File

@@ -1,10 +1,9 @@
import { defineConfig } from 'tsdown'
/**
* schemastery has no `"type": "module"` and publishes dual-format output
* (package.json: main → lib/index.cjs, module → lib/index.mjs). The entry is
* the JS emitted by tsc under lib/types; pin the bundled extensions
* explicitly because the defaults for a CommonJS package would emit .mjs/.js.
* Schemastery publishes dual-format output (package.json: main → lib/index.cjs,
* module → lib/index.mjs). The entry is the JS emitted by tsc under lib/types;
* pin the bundled extensions explicitly so the package retains both formats.
*/
export default defineConfig({
entry: ['lib/types/index.js'],