feat: Try two different kinds of type reflection #5
@ -102,6 +102,10 @@ type Implementations<
|
|||||||
Specs extends Specifications<Signatures, NeedKeys, NeedList>
|
Specs extends Specifications<Signatures, NeedKeys, NeedList>
|
||||||
> = {[K in NeedKeys]: ImpType<Signatures, K, Specs[K]>}
|
> = {[K in NeedKeys]: ImpType<Signatures, K, Specs[K]>}
|
||||||
|
|
||||||
|
export interface ReflectedTypeInfo {
|
||||||
|
reflectedType5: string
|
||||||
|
}
|
||||||
|
|
||||||
// The builder interface that lets us assemble narrowly-typed Implementations:
|
// The builder interface that lets us assemble narrowly-typed Implementations:
|
||||||
interface ImplementationBuilder<
|
interface ImplementationBuilder<
|
||||||
Signatures extends GenSigs,
|
Signatures extends GenSigs,
|
||||||
@ -135,7 +139,7 @@ interface ImplementationBuilder<
|
|||||||
Specs & {[K in NewKeys]: DepCheck<RD, Signatures>}
|
Specs & {[K in NewKeys]: DepCheck<RD, Signatures>}
|
||||||
>
|
>
|
||||||
|
|
||||||
ship(): Implementations<Signatures, NeedKeys, NeedList, Specs> & { reflectedType5: string }
|
ship(info?: ReflectedTypeInfo): Implementations<Signatures, NeedKeys, NeedList, Specs> & ReflectedTypeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// And a function that actually provides the builder interface:
|
// And a function that actually provides the builder interface:
|
||||||
@ -187,9 +191,8 @@ function impBuilder<
|
|||||||
Specs & {[K in NewKeys]: DepCheck<RD, Signatures, DepKeys>}
|
Specs & {[K in NewKeys]: DepCheck<RD, Signatures, DepKeys>}
|
||||||
>
|
>
|
||||||
},
|
},
|
||||||
ship() {
|
ship(info?: ReflectedTypeInfo) {
|
||||||
return (sofar as
|
return { ...sofar, ...info }
|
||||||
Implementations<Signatures, NeedKeys, NeedList, Specs> & { reflectedType5: string })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,44 +11,38 @@ const files = (await readdirSync(buildDir, { recursive: true }))
|
|||||||
.map(file => join(buildDir, file))
|
.map(file => join(buildDir, file))
|
||||||
|
|
||||||
for (const file of files) {
|
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)}"`)
|
log(`Reflecting file "${relative(__dirname, srcFile)}"`)
|
||||||
|
|
||||||
const defFile = srcFile.replace(/.js$/, '.d.ts')
|
const defFile = srcFile.replace(/.js$/, '.d.ts')
|
||||||
const src = String(readFileSync(srcFile))
|
const src = String(readFileSync(srcFile))
|
||||||
const defs = String(readFileSync(defFile))
|
const defs = String(readFileSync(defFile))
|
||||||
|
|
||||||
if (src.includes('.reflectedType5')) {
|
const typeDefMatches = defs.matchAll(/: ({(?:(?!\n}).)+\n}) & (?:(?!ReflectedTypeInfo).)+ReflectedTypeInfo/gs)
|
||||||
log(' Source file already contains reflected types and will be ignored')
|
if (!typeDefMatches) {
|
||||||
|
log('No ReflectedTypeInfo found.')
|
||||||
return
|
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) {
|
let index = 0
|
||||||
log(` No implementations found`)
|
const srcReflected = src.replaceAll(/(\s*)\.ship\(\)/g, () => {
|
||||||
return
|
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) {
|
writeFileSync(srcFile, srcReflected)
|
||||||
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}"`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function log(...args) {
|
function log(...args) {
|
||||||
if (options.debug) {
|
if (options.debug) {
|
||||||
|
Loading…
Reference in New Issue
Block a user