refactor(asr): [PKG-ASR-04] preserve old declarations and add precise runtime types

This commit is contained in:
Harvey Zhao committed 2026-09-13 15:07:04 +08:00
1 parent 0cf2af4840
commit 93208e59e1
24 files changed
+1224 -19

No files matched your search

+2 -1
View File
@@ -2,4 +2,5 @@ node_modules
.DS_Store
yarn.lock
package-lock.json
src
src
tsconfig.json
+19 -4
View File
@@ -63,10 +63,20 @@ HTML, punctuation splitting, replacement, ignored non-string values and the
historical `length=0` behavior. The CJS function has a non-enumerable self `default`
alias for consumers of the 2.0 namespace, while preserving the callable 2.1 form.
Root public declarations have not yet migrated: they describe stop as void and
the callback as void/Promise<void>. PKG-ASR-04 owns exact asynchronous public types,
old assignment consumers, module forms and installed tarball acceptance. Internal
strict TypeScript does not prove that public type migration complete.
Root and `/legacy` declarations intentionally retain the historical factory,
void stop and void/Promise<void> callback. Their NodeNext ESM default import remains
the old namespace type: changing it into a callable default would break legal
namespace substitution. Historical direct-call errors are frozen separately from
legal namespace consumers. Do not silently rewrite these declarations to match
runtime behavior or require a self-default property on old replacement factories.
The additive `/runtime` entry references the same main/ESM implementation, with
`RuntimeOption`, `RuntimeResult` and `RuntimeFactory`: callback text/null/no result
and asynchronous stop are accurate. Its `.d.mts` default export and `.d.cts`/
`.d.ts` export assignment support ESM, raw CommonJS and old Node10 resolution.
Pure type namespaces make all four named runtime types available in every mode.
The root also exports those types for convenient annotations. No runtime code or
version changes are needed for this entry.
From the repository root:
@@ -76,6 +86,11 @@ From the repository root:
published/current core, pause/resume, source switch, stop/restart and destroy.
Set `ARTPLAYER_ASR_ARTIFACT` to an actual main/legacy file to test that artifact.
- `yarn typecheck`: includes the package strict/noUncheckedIndexedAccess project.
- `yarn test:asr-types-package`: packs and installs core/ASR outside the workspace,
checks frozen 2.0/2.1 consumers and candidate declarations in strict compiler
modes, verifies offline frozen reinstall and file hashes, exercises actual
import/require exports, and rejects invalid uses. Historical declaration errors
are explicit expectations and never counted as candidate success.
- `yarn dev artplayer-plugin-asr` and `yarn build artplayer-plugin-asr`: normal
repository development and three-format production builds.
+29
View File
@@ -8,6 +8,35 @@ restart capture; the player's direct Web Audio connection remains alive until
the player is destroyed so that stopping recognition does not silence playback.
Call `art.destroy()` when disposing the player.
## TypeScript
Existing imports keep their historical types, including `stop(): void` and a
`void | Promise<void>` recognition callback. For accurate asynchronous types, use
the additive `/runtime` entry. It loads the same implementation as the root entry:
```ts
import Artplayer from 'artplayer'
import asr from 'artplayer-plugin-asr/runtime'
import type { RuntimeOption } from 'artplayer-plugin-asr/runtime'
const option: RuntimeOption = {
onAudioChunk: async ({ pcm, wav }) => {
// Send one of these buffers to your own recognition service.
void [pcm, wav]
return 'Recognized text.'
},
}
const art = new Artplayer({ container: '#player', url: '/video.mp4' })
const recognition = asr(option)(art)
await recognition.stop()
```
The callback may return text, `null`, or no value, synchronously or asynchronously.
CommonJS TypeScript can use `import asr = require('artplayer-plugin-asr/runtime')`.
The root declaration retains its historical NodeNext ESM namespace shape; use
`/runtime` for a directly callable default import in that mode. This is an opt-in
type entry, and does not require changes to existing JavaScript consumers.
## Maintenance
See [ARCHITECTURE.md](ARCHITECTURE.md) for the current audio flow, public behavior,
+21 -1
View File
@@ -27,11 +27,31 @@
"types": "./types/artplayer-plugin-asr.d.ts",
"import": "./dist/artplayer-plugin-asr.legacy.js",
"require": "./dist/artplayer-plugin-asr.legacy.js"
},
"./runtime": {
"import": {
"types": "./types/runtime.d.mts",
"default": "./dist/artplayer-plugin-asr.mjs"
},
"require": {
"types": "./types/runtime.d.cts",
"default": "./dist/artplayer-plugin-asr.js"
}
}
},
"main": "./dist/artplayer-plugin-asr.js",
"module": "./dist/artplayer-plugin-asr.mjs",
"types": "./types/artplayer-plugin-asr.d.ts",
"legacy": "./dist/artplayer-plugin-asr.legacy.js",
"browserslist": "last 1 Chrome version"
"browserslist": "last 1 Chrome version",
"typesVersions": {
"*": {
"legacy": [
"types/artplayer-plugin-asr.d.ts"
],
"runtime": [
"types/runtime.d.ts"
]
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": { "allowJs": false },
"include": ["src/**/*.ts", "types/**/*.d.ts", "../../types/assets.d.ts"]
"include": ["src/**/*.ts", "types/**/*.d.ts", "types/**/*.d.mts", "types/**/*.d.cts", "../../types/assets.d.ts"]
}
@@ -1,11 +1,11 @@
import type Artplayer from 'artplayer'
interface AudioChunk {
export interface AudioChunk {
pcm: ArrayBuffer
wav: ArrayBuffer
}
interface AsrPluginOption {
export interface AsrPluginOption {
length?: number
interval?: number
sampleRate?: number
@@ -13,13 +13,30 @@ interface AsrPluginOption {
onAudioChunk?: (chunk: AudioChunk) => void | Promise<void>
}
interface AsrPluginInstance {
export interface AsrPluginInstance {
name: 'artplayerPluginAsr'
stop: () => void
hide: () => void
append: (subtitle: string) => void
}
/** Historical factory shape, including void stop and callback results. */
export type Factory = (option?: AsrPluginOption) => (art: Artplayer) => AsrPluginInstance
/** Accurate asynchronous view available through the /runtime entry. */
export interface RuntimeOption extends Omit<AsrPluginOption, 'onAudioChunk'> {
onAudioChunk?: (chunk: AudioChunk) => string | void | null | Promise<string | void | null>
}
export interface RuntimeResult extends Omit<AsrPluginInstance, 'stop'> {
stop: () => Promise<void>
}
export interface RuntimeFactory {
(option?: RuntimeOption): (art: Artplayer) => RuntimeResult
readonly default: RuntimeFactory
}
declare function artplayerPluginAsr(option?: AsrPluginOption): (art: Artplayer) => AsrPluginInstance
export default artplayerPluginAsr
@@ -0,0 +1,11 @@
import type { RuntimeFactory } from './artplayer-plugin-asr.js'
declare const artplayerPluginAsr: RuntimeFactory
// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory.
declare namespace artplayerPluginAsr {
type AudioChunk = import('./artplayer-plugin-asr.js').AudioChunk
type RuntimeFactory = import('./artplayer-plugin-asr.js').RuntimeFactory
type RuntimeOption = import('./artplayer-plugin-asr.js').RuntimeOption
type RuntimeResult = import('./artplayer-plugin-asr.js').RuntimeResult
}
export = artplayerPluginAsr
@@ -0,0 +1,5 @@
import type { RuntimeFactory } from './artplayer-plugin-asr.js'
declare const artplayerPluginAsr: RuntimeFactory
export default artplayerPluginAsr
export type { AudioChunk, RuntimeFactory, RuntimeOption, RuntimeResult } from './artplayer-plugin-asr.js'
+11
View File
@@ -0,0 +1,11 @@
import type { RuntimeFactory } from './artplayer-plugin-asr.js'
declare const artplayerPluginAsr: RuntimeFactory
// eslint-disable-next-line ts/no-redeclare -- Ambient merge exposes types on the CommonJS factory.
declare namespace artplayerPluginAsr {
type AudioChunk = import('./artplayer-plugin-asr.js').AudioChunk
type RuntimeFactory = import('./artplayer-plugin-asr.js').RuntimeFactory
type RuntimeOption = import('./artplayer-plugin-asr.js').RuntimeOption
type RuntimeResult = import('./artplayer-plugin-asr.js').RuntimeResult
}
export = artplayerPluginAsr