feat: Try two different kinds of type reflection #5
@ -4,7 +4,8 @@
|
|||||||
description: 'Another prototype for a math core',
|
description: 'Another prototype for a math core',
|
||||||
scripts: {
|
scripts: {
|
||||||
build: 'tsc && cp etc/package.json build/',
|
build: 'tsc && cp etc/package.json build/',
|
||||||
go: 'pnpm build && pnpm start',
|
reflect: 'node tools/reflectTypes.mjs',
|
||||||
|
go: 'pnpm build && pnpm reflect && pnpm start',
|
||||||
start: 'node --experimental-loader tsc-module-loader build',
|
start: 'node --experimental-loader tsc-module-loader build',
|
||||||
test: 'echo Error no test specified && exit 1',
|
test: 'echo Error no test specified && exit 1',
|
||||||
},
|
},
|
||||||
|
@ -135,7 +135,7 @@ interface ImplementationBuilder<
|
|||||||
Specs & {[K in NewKeys]: DepCheck<RD, Signatures>}
|
Specs & {[K in NewKeys]: DepCheck<RD, Signatures>}
|
||||||
>
|
>
|
||||||
|
|
||||||
ship(): Implementations<Signatures, NeedKeys, NeedList, Specs>
|
ship(): Implementations<Signatures, NeedKeys, NeedList, Specs> & { reflectedType5: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
// And a function that actually provides the builder interface:
|
// And a function that actually provides the builder interface:
|
||||||
@ -189,7 +189,7 @@ function impBuilder<
|
|||||||
},
|
},
|
||||||
ship() {
|
ship() {
|
||||||
return (sofar as
|
return (sofar as
|
||||||
Implementations<Signatures, NeedKeys, NeedList, Specs>)
|
Implementations<Signatures, NeedKeys, NeedList, Specs> & { reflectedType5: string })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
58
tools/reflectTypes.mjs
Normal file
58
tools/reflectTypes.mjs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { readFileSync, writeFileSync, readdirSync } from 'node:fs'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { dirname, join, relative } from 'node:path'
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
|
const __dirname = dirname(__filename)
|
||||||
|
|
||||||
|
const buildDir = join(__dirname, '..', 'build')
|
||||||
|
const files = (await readdirSync(buildDir, { recursive: true }))
|
||||||
|
.filter(file => file.endsWith('.js'))
|
||||||
|
.map(file => join(buildDir, file))
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
reflectType(file, { debug: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
function reflectType(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')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const matches = Array.from(src.matchAll(/[^\n](export +)?const +([\w$]+) += +implementations\b/g))
|
||||||
|
|
||||||
|
if (matches.length === 0) {
|
||||||
|
log(` No implementations found`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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}"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(...args) {
|
||||||
|
if (options.debug) {
|
||||||
|
console.log(...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user