-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: allow import internal types
- Loading branch information
1 parent
a1b75a6
commit 7837186
Showing
14 changed files
with
381 additions
and
329 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,182 +1,8 @@ | ||
/* eslint-disable no-console */ | ||
|
||
import { isText } from '@whisklabs/typeguards'; | ||
import { promises as fs } from 'fs'; | ||
import { extname, isAbsolute, join, parse as pathParse, relative } from 'path'; | ||
import { CompilerOptions, ModuleKind, ModuleResolutionKind, ScriptTarget, transpileModule } from 'typescript'; | ||
|
||
import { parser } from '../parser'; | ||
import { Schema } from '../parser/types'; | ||
import { enums } from './enum'; | ||
import { Config, EnumsList, MakeOuts, Out } from './generator'; | ||
import { messages } from './message'; | ||
import { services } from './service'; | ||
|
||
export async function generator({ | ||
dir, | ||
out, | ||
exclude = /^$/, | ||
version = 'unknown', | ||
debug = false, | ||
packageName, | ||
packageVersion, | ||
packageUrl = 'git@github.com:whisklabs/npm.git', | ||
packageRegistry = 'https://npm.pkg.github.com/', | ||
}: Config) { | ||
const IN_DIR = isAbsolute(dir) ? dir : join(process.cwd(), dir); | ||
const OUT_DIR = isAbsolute(out) ? out : join(process.cwd(), out); | ||
const DEBUG_DIR = join(OUT_DIR, 'debug'); | ||
|
||
const lic = `// Code created by grpc-generator. Version: ${version}`; | ||
const lib = `import { | ||
FieldMap, | ||
FieldRepeated, | ||
FieldType, | ||
FieldItem, | ||
Field, | ||
FieldEmpty, | ||
FieldGet, | ||
Service, | ||
ServiceRequest, | ||
ServiceResponse, | ||
Values | ||
} from '${version === 'test' ? '../../src' : '@whisklabs/grpc'}';`; | ||
let lastFile = ''; | ||
|
||
async function walk(directory: string, result: Out = { filepaths: [], schemas: [] }) { | ||
const dirFiles = await fs.readdir(directory); | ||
for (const filename of dirFiles) { | ||
const filepath = join(directory, filename); | ||
lastFile = filepath; | ||
if ((await fs.stat(filepath)).isDirectory()) { | ||
await walk(filepath, result); | ||
} else if (extname(filename) === '.proto' && !exclude.test(filepath)) { | ||
result.filepaths.push(filepath); | ||
|
||
const parsed = parser(await fs.readFile(filepath, 'utf8')); | ||
if (debug) { | ||
const outFile = pathParse(join(DEBUG_DIR, relative(dir ?? '', filepath))); | ||
|
||
await fs.mkdir(outFile.dir, { recursive: true }); | ||
await fs.writeFile(join(outFile.dir, `${outFile.name}.json`), JSON.stringify(parsed, null, 2)); | ||
} | ||
result.schemas.push(parsed); | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
return walk(IN_DIR) | ||
.then(async ({ schemas }) => { | ||
const { js, dts, errors, fields, names } = make(schemas); | ||
|
||
for (const [type, field] of fields) { | ||
if (!names.has(type)) { | ||
errors.push(`\x1b[31mNo found message or enum:\x1b[0m ${type} [${field}]`); | ||
} | ||
} | ||
|
||
dts.unshift(lic, lib, ''); | ||
js.unshift(lic, '"use strict";', ''); | ||
|
||
const dtsString = dts.join('\n'); | ||
const jsString = js.join('\n'); | ||
|
||
checkTypes(dtsString, errors); | ||
checkTypes(jsString, errors); | ||
|
||
const hasError = errors.length > 0; | ||
|
||
if (hasError) { | ||
errors.forEach(i => console.error(i)); | ||
} else { | ||
await fs.mkdir(OUT_DIR, { recursive: true }); | ||
await fs.writeFile(join(OUT_DIR, 'index.d.ts'), dtsString); | ||
await fs.writeFile(join(OUT_DIR, 'index.js'), transpile(jsString)); | ||
await fs.writeFile(join(OUT_DIR, 'esm.js'), transpile(jsString, { module: ModuleKind.ES2015 })); | ||
if (isText(packageName) && isText(packageVersion)) { | ||
await fs.writeFile( | ||
join(OUT_DIR, 'package.json'), | ||
packageTemplate({ packageName, packageVersion, packageUrl, packageRegistry }) | ||
); | ||
} | ||
} | ||
|
||
return hasError; | ||
}) | ||
.catch(e => { | ||
console.info(`Last processing file was "\x1b[31m${lastFile}\x1b[0m"`); | ||
console.error(e); | ||
return true; | ||
}); | ||
} | ||
|
||
const transpile = (source: string, options?: CompilerOptions) => | ||
transpileModule(source, { | ||
compilerOptions: { | ||
allowJs: true, | ||
module: ModuleKind.CommonJS, | ||
target: ScriptTarget.ES5, | ||
moduleResolution: ModuleResolutionKind.NodeJs, | ||
...options, | ||
}, | ||
}).outputText; | ||
|
||
function checkTypes(file: string, errors: string[]) { | ||
const { diagnostics } = transpileModule(file, { reportDiagnostics: true }); | ||
|
||
for (const diagnostic of diagnostics ?? []) { | ||
errors.push(`\x1b[31mTS error:\x1b[0m ${JSON.stringify(diagnostic.messageText)}`); | ||
} | ||
} | ||
|
||
function make(schemas: Schema[]): MakeOuts { | ||
const enumsList: EnumsList = new Set(); | ||
|
||
const out: MakeOuts = { | ||
js: [], | ||
dts: [], | ||
names: new Set(), | ||
errors: [], | ||
fields: [], | ||
}; | ||
|
||
for (const schema of schemas) { | ||
const path = schema.package ?? ''; | ||
enums(path, out, schema.enums, enumsList); | ||
} | ||
|
||
for (const schema of schemas) { | ||
const path = schema.package ?? ''; | ||
messages(path, out, schema.messages, [], enumsList); | ||
|
||
services(path, out, schema.services); | ||
} | ||
|
||
return out; | ||
} | ||
|
||
interface Package { | ||
packageName: string; | ||
packageVersion: string; | ||
packageUrl: string; | ||
packageRegistry: string; | ||
} | ||
|
||
const packageTemplate = ({ packageName, packageVersion, packageUrl, packageRegistry }: Package) => `{ | ||
"name": "${packageName}", | ||
"version": "${packageVersion}", | ||
"repository": { | ||
"type": "git", | ||
"url": "${packageUrl}" | ||
}, | ||
"publishConfig": { | ||
"registry": "${packageRegistry}" | ||
}, | ||
"main": "./index.js", | ||
"module": "./esm.js", | ||
"types": "./index.d.ts", | ||
"peerDependencies": { | ||
"@whisklabs/grpc": "*" | ||
} | ||
}`; | ||
export * from './main'; | ||
export * from './utils'; | ||
export * from './generator'; | ||
export * from './constants'; | ||
export * from './enum'; | ||
export * from './field'; | ||
export * from './message'; | ||
export * from './service'; |
Oops, something went wrong.