diff --git a/src/core/Dispatcher.ts b/src/core/Dispatcher.ts index 5b4bd1d..198b69a 100644 --- a/src/core/Dispatcher.ts +++ b/src/core/Dispatcher.ts @@ -102,6 +102,10 @@ type Implementations< Specs extends Specifications > = {[K in NeedKeys]: ImpType} +export interface ReflectedTypeInfo { + reflectedType5: string +} + // The builder interface that lets us assemble narrowly-typed Implementations: interface ImplementationBuilder< Signatures extends GenSigs, @@ -135,7 +139,7 @@ interface ImplementationBuilder< Specs & {[K in NewKeys]: DepCheck} > - ship(): Implementations & { reflectedType5: string } + ship(info?: ReflectedTypeInfo): Implementations & ReflectedTypeInfo } // And a function that actually provides the builder interface: @@ -187,9 +191,8 @@ function impBuilder< Specs & {[K in NewKeys]: DepCheck} > }, - ship() { - return (sofar as - Implementations & { reflectedType5: string }) + ship(info?: ReflectedTypeInfo) { + return { ...sofar, ...info } } } } diff --git a/tools/reflectTypes.mjs b/tools/reflectTypes.mjs index 4ffa0ad..89c6af6 100644 --- a/tools/reflectTypes.mjs +++ b/tools/reflectTypes.mjs @@ -11,44 +11,38 @@ const files = (await readdirSync(buildDir, { recursive: true })) .map(file => join(buildDir, file)) for (const file of files) { - reflectType(file, { debug: true }) + reflectType5(file, { debug: true }) } -function reflectType(srcFile, options = { debug: false }) { +function reflectType5(srcFile, options = { debug: false }) { log(`Reflecting file "${relative(__dirname, srcFile)}"`) const defFile = srcFile.replace(/.js$/, '.d.ts') const src = String(readFileSync(srcFile)) const defs = String(readFileSync(defFile)) - if (src.includes('.reflectedType5')) { - log(' Source file already contains reflected types and will be ignored') + const typeDefMatches = defs.matchAll(/: ({(?:(?!\n}).)+\n}) & (?:(?!ReflectedTypeInfo).)+ReflectedTypeInfo/gs) + if (!typeDefMatches) { + log('No ReflectedTypeInfo found.') return } - const matches = Array.from(src.matchAll(/[^\n](export +)?const +([\w$]+) += +implementations\b/g)) + const typeDefs = Array.from(typeDefMatches).map(def => def[1]) + log(` ${typeDefs.length} ReflectedTypeInfo found`) - if (matches.length === 0) { - log(` No implementations found`) - return + let index = 0 + const srcReflected = src.replaceAll(/(\s*)\.ship\(\)/g, () => { + const def = typeDefs[index] + index++ + return `.ship({ reflectedType5: \`${def}\` })` + }) + log(` ReflectedTypeInfo injected in ${index} occurrences of .ship()`) + + if (index !== typeDefs.length) { + log(' WARNING: not all ReflectedTypeInfo occurrences could be injected') } - for (const match of matches) { - const name = match[2] - log(` Found an implementations definition: "${name}"`) - - const def = new RegExp(`export declare const ${name}: {(?:(?!\n}).)+\n}`, 's').exec(defs) - - if (def) { - log(` Injected type definitions for "${name}"`) - - const srcReflected = `${src}\n${name}.reflectedType5 = \`${def}\`\n` - - writeFileSync(srcFile, srcReflected) - } else { - log(` No type definitions found for "${name}"`) - } - } + writeFileSync(srcFile, srcReflected) function log(...args) { if (options.debug) {