Use explicit ts specifiers for declarations

Restore explicit .ts relative specifiers in source and enable rewriteRelativeImportExtensions so emitted JS uses .js while declarations keep explicit .ts specifiers. Add a NodeNext declaration-consumer gate to prevent extensionless declaration regressions.
This commit is contained in:
Tianyi Cui
2026-06-22 06:11:00 +08:00
parent 94e7355449
commit 07f4047ff0
56 changed files with 323 additions and 147 deletions

2
vendor/README.md vendored
View File

@@ -33,7 +33,7 @@ Keep this log exhaustive — every divergence from upstream must be listed.
1. **`hmr/src/index.ts`**: removed the `./locales/en-US.yml` / `./locales/zh-CN.yml` imports, the `.i18n({...})` call on the `Config` schema, and the `src/locales/` directory. Rationale: those imports require a runtime YAML loader hook (`@cordisjs/unyaml`) that we do not vendor; the i18n texts only localize config descriptions.
2. **All `package.json` files**: regenerated — added `private: true`, added precise `files` entries for bundled runtime files and `lib/types/**/*.d.ts` / `.d.ts.map`, preserved `src` in `files` only for packages whose previous file list already shipped it, added a `./src/*` export where missing, pointed declaration metadata at `lib/types`, and removed upstream `devDependencies`/`scripts`/`repository` fields. Dependency and peer-dependency ranges preserved, except `hmr` declares `esbuild` as a direct dev dependency because its source imports the `BuildFailure` type and pnpm's strict workspace resolution requires the owner package to name that dependency.
3. **All `tsconfig.json` files**: regenerated to extend the repo-root `tsconfig.base.json`, emit TypeScript intermediates to `lib/types`, and declare project references.
4. **Vendored TypeScript source internal specifiers**: changed local relative imports/exports from explicit `.ts` / `.js` specifiers to extensionless specifiers so generated `.js` and `.d.ts` intermediates are extensionless and no declaration postprocess is needed. This includes `loader/src/config/isolate.ts` changing `declare module './entry.ts'` to `declare module './entry'`.
4. **Vendored TypeScript source internal specifiers**: changed local relative imports/exports from upstream's specifier shape to explicit `.ts` specifiers so TypeScript rewrites emitted JS to `.js` while declarations keep explicit, NodeNext-safe `.ts` specifiers. This includes `loader/src/config/isolate.ts` using `declare module './entry.ts'`.
5. **`schemastery/tsdown.config.ts` and `logger-console/tsdown.config.ts`**: ours, not upstream files — per-package build-shape overrides (dual ESM+CJS output; separate node/browser entries) for the repo-root tsdown build. They read the JS emitted under `lib/types` and then write the publish runtime entries under `lib/`. Like the regenerated tsconfigs, they are not part of the upstream sync surface.
## Sync procedure

View File

@@ -1,10 +1,10 @@
import { Dict } from 'cosmokit'
import { EventsService } from './events'
import { LoggerService } from './logger'
import { ReflectService } from './reflect'
import { InjectKey, RegistryService } from './registry'
import { getTraceable, symbols } from './utils'
import { Fiber } from './fiber'
import { EventsService } from './events.ts'
import { LoggerService } from './logger.ts'
import { ReflectService } from './reflect.ts'
import { InjectKey, RegistryService } from './registry.ts'
import { getTraceable, symbols } from './utils.ts'
import { Fiber } from './fiber.ts'
/**
* Public shape of a Cordis context.

View File

@@ -1,7 +1,7 @@
import { defineProperty, Promisify } from 'cosmokit'
import { Context } from './context'
import { Fiber, FiberState } from './fiber'
import { DisposableList, symbols } from './utils'
import { Context } from './context.ts'
import { Fiber, FiberState } from './fiber.ts'
import { DisposableList, symbols } from './utils.ts'
/** Return whether an event result should stop a bail-style dispatch. */
export function isBailed(value: any) {
@@ -25,7 +25,7 @@ export type ThisType<F> = F extends (this: infer T, ...args: any) => any ? T : n
*/
export type DispatchMode = 'emit' | 'parallel' | 'serial' | 'bail' | 'waterfall'
declare module './context' {
declare module './context.ts' {
export interface Context {
/* eslint-disable max-len */
parallel<K extends keyof Events>(name: K, ...args: Parameters<Events[K]>): Promise<void>

View File

@@ -1,11 +1,11 @@
import { Awaitable, defineProperty, Dict, isNullable } from 'cosmokit'
import { Context } from './context'
import { Plugin } from './registry'
import { buildOuterStack, composeError, DisposableList, getTraceable, isConstructor, isObject, symbols } from './utils'
import { Impl } from './reflect'
import { Context } from './context.ts'
import { 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'
declare module './context' {
declare module './context.ts' {
export interface Context extends Pick<Fiber, 'effect'> {
fiber: Fiber
}

View File

@@ -1,14 +1,14 @@
/** Core context type and root context implementation. */
export * from './context'
export * from './context.ts'
/** Event bus, dispatch modes, and event augmentation types. */
export * from './events'
export * from './events.ts'
/** Plugin fiber lifecycle, effects, and config validation helpers. */
export * from './fiber'
export * from './fiber.ts'
/** Logger facade, logger service, message, exporter, and formatting types. */
export * from './logger'
export * from './logger.ts'
/** Plugin registry, dependency injection, and plugin entrypoint types. */
export * from './registry'
export * from './registry.ts'
/** Base service class and service lifecycle symbols. */
export * from './service'
export * from './service.ts'
/** Shared internal helpers used by context, services, and plugin fibers. */
export * from './utils'
export * from './utils.ts'

View File

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

View File

@@ -1,9 +1,9 @@
import { defineProperty, Dict, isNullable } from 'cosmokit'
import { Context } from './context'
import { getTraceable, symbols, withProps } from './utils'
import { Fiber, FiberState } from './fiber'
import { Context } from './context.ts'
import { getTraceable, symbols, withProps } from './utils.ts'
import { Fiber, FiberState } from './fiber.ts'
declare module './context' {
declare module './context.ts' {
interface Context {
get<K extends string & keyof this>(name: K, strict?: boolean): undefined | this[K]
get(name: string, strict?: boolean): any

View File

@@ -1,8 +1,8 @@
import { defineProperty, Dict } from 'cosmokit'
import { StandardSchemaV1 } from '@standard-schema/spec'
import { Context } from './context'
import { Fiber } from './fiber'
import { buildOuterStack, DisposableList, symbols, withProps } from './utils'
import { Context } from './context.ts'
import { Fiber } from './fiber.ts'
import { buildOuterStack, DisposableList, symbols, withProps } from './utils.ts'
function isApplicable(object: Plugin) {
return object && typeof object === 'object' && typeof object.apply === 'function'
@@ -140,7 +140,7 @@ type GetPluginConfig<P> =
? S
: GetPluginParameters<P>[0]
declare module './context' {
declare module './context.ts' {
export interface Context {
inject(deps: Inject, callback: Plugin.Function<void>): Fiber & PromiseLike<Fiber>
plugin<P extends Plugin>(plugin: P, ...args: Spread<GetPluginConfig<P>>): Fiber & PromiseLike<Fiber>

View File

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

View File

@@ -1,5 +1,5 @@
import { defineProperty } from 'cosmokit'
import type { Context, Service } from '.'
import type { Context, Service } from './index.ts'
/** Ordered collection of disposable values with O(1) deletion by value. */
export class DisposableList<T extends WeakKey> {

View File

@@ -1,4 +1,4 @@
import { isNullable } from './misc'
import { isNullable } from './misc.ts'
/** Return true when every item in `array2` is present in `array1`. */
export function contain(array1: readonly any[], array2: readonly any[]) {

View File

@@ -1,10 +1,10 @@
/** Array set and normalization helpers. */
export * from './array'
export * from './array.ts'
/** Runtime type, binary, clone, and equality helpers. */
export * from './types'
export * from './types.ts'
/** Shared utility types and object helpers. */
export * from './misc'
export * from './misc.ts'
/** String case, path, and property formatting helpers. */
export * from './string'
export * from './string.ts'
/** Time constants, parsing, and formatting helpers. */
export * from './time'
export * from './time.ts'

View File

@@ -1,4 +1,4 @@
import { isNullable } from './misc'
import { isNullable } from './misc.ts'
type GlobalConstructorNames = keyof {
[K in keyof typeof globalThis as typeof globalThis[K] extends abstract new (...args: any) => any ? K : never]: K

View File

@@ -4,7 +4,7 @@ import { ModuleJob, ModuleLoader, ResolveResult } from '@cordisjs/plugin-loader'
import type { Include } from '@cordisjs/plugin-include'
import { ChokidarOptions, FSWatcher, watch } from 'chokidar'
import { relative, resolve } from 'node:path'
import { handleError } from './error'
import { handleError } from './error.ts'
import type {} from '@cordisjs/plugin-timer'
import { fileURLToPath, pathToFileURL } from 'node:url'
import { createRequire } from 'node:module'

View File

@@ -1,9 +1,9 @@
import { Context, Fiber, Inject } from 'cordis'
import { deepEqual, isNullable } from 'cosmokit'
import { Loader } from '../index'
import { EntryGroup } from './group'
import { EntryTree } from './tree'
import { evaluate, interpolate } from './utils'
import { Loader } from '../index.ts'
import { EntryGroup } from './group.ts'
import { EntryTree } from './tree.ts'
import { evaluate, interpolate } from './utils.ts'
/** Serialized plugin entry options stored in loader config files. */
export interface EntryOptions {

View File

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

View File

@@ -1,8 +1,8 @@
import { Context } from 'cordis'
import { Dict } from 'cosmokit'
import { Entry } from './entry'
import { Entry } from './entry.ts'
declare module './entry' {
declare module './entry.ts' {
interface EntryOptions {
intercept?: Dict | null
isolate?: Dict<true | string> | null

View File

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

View File

@@ -1,22 +1,22 @@
import { Context, Inject, Service } from 'cordis'
import { defineProperty, Dict, isNullable } from 'cosmokit'
import { ModuleLoader } from './internal'
import { Entry, EntryOptions } from './config/entry'
import isolate from './config/isolate'
import { EntryTree } from './config/tree'
import { ModuleLoader } from './internal.ts'
import { Entry, EntryOptions } from './config/entry.ts'
import isolate from './config/isolate.ts'
import { EntryTree } from './config/tree.ts'
/** Re-export entry node APIs. */
export * from './config/entry'
export * from './config/entry.ts'
/** Re-export nested entry group APIs. */
export * from './config/group'
export * from './config/group.ts'
/** Re-export service isolation helpers. */
export * from './config/isolate'
export * from './config/isolate.ts'
/** Re-export entry tree persistence APIs. */
export * from './config/tree'
export * from './config/tree.ts'
/** Re-export loader config expression helpers. */
export * from './config/utils'
export * from './config/utils.ts'
/** Re-export Node internal module loader compatibility types. */
export * from './internal'
export * from './internal.ts'
declare module 'cordis' {
interface Events {

View File

@@ -1,8 +1,8 @@
import { Message } from 'cordis'
import { ConsoleExporter as Base } from './shared'
import { ConsoleExporter as Base } from './shared.ts'
/** Re-export shared console exporter config and base implementation. */
export * from './shared'
export * from './shared.ts'
/** Browser console exporter that dispatches to native console methods. */
export class ConsoleExporter extends Base {

View File

@@ -1,10 +1,10 @@
import { Formatter } from 'cordis'
import { inspect } from 'node:util'
import supportsColor from 'supports-color'
import { ConsoleExporter as Base } from './shared'
import { ConsoleExporter as Base } from './shared.ts'
/** Re-export shared console exporter config and base implementation. */
export * from './shared'
export * from './shared.ts'
const inspectFormatter: Formatter = (value, target) => {
return inspect(value, { colors: !!target.colors, depth: Infinity, compact: true, breakLength: Infinity })