diff --git a/packages/types-publisher/definition-parser.ts b/packages/types-publisher/definition-parser.ts index b60405bf..c0ceea83 100644 --- a/packages/types-publisher/definition-parser.ts +++ b/packages/types-publisher/definition-parser.ts @@ -46,7 +46,7 @@ export function isFail(t: TypingParseSucceedResult | TypingParseFailResult): t i } export interface TypingsData { - type: DefinitionFileKind; + type: string; moduleDependencies: string[]; libraryDependencies: string[]; @@ -80,6 +80,9 @@ export interface TypingsData { libraryMajorVersion: string; // The minor version of the library libraryMinorVersion: string; + + // Files that should be published with this definition + files: string[]; } function isSupportedFileKind(kind: DefinitionFileKind) { @@ -334,7 +337,7 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing const projectName = regexMatch(/^\/\/ Project: (.+)$/m, ''); const packageName = isProperModule ? path.basename(directory) : undefined; const sourceRepoURL = 'https://www.github.com/DefinitelyTyped/DefinitelyTyped'; - + return { log, data: { @@ -350,8 +353,9 @@ export function getTypingInfo(directory: string): TypingParseFailResult | Typing packageName, projectName, sourceRepoURL, - type: fileKind, - globals: Object.keys(globalSymbols).filter(k => !!(globalSymbols[k] & DeclarationFlags.Value)) + type: DefinitionFileKind[fileKind], + globals: Object.keys(globalSymbols).filter(k => !!(globalSymbols[k] & DeclarationFlags.Value)), + files: [declFiles[0]] } } } diff --git a/packages/types-publisher/definition-publisher.ts b/packages/types-publisher/definition-publisher.ts index d0f364db..77a61fd3 100644 --- a/packages/types-publisher/definition-publisher.ts +++ b/packages/types-publisher/definition-publisher.ts @@ -1,18 +1,80 @@ import { TypingsData, DefinitionFileKind } from './definition-parser'; +import * as fs from 'fs'; +import * as crypto from 'crypto'; +import * as path from 'path'; export interface PublishSettings { + // e.g. 'typings', not '@typings' scopeName: string; + // e.g. ./output/ outputPath: string; } -export function publish() { +namespace Versions { + const versionFilename = 'versions.json'; + + interface VersionMap { + [typingsPackageName: string]: { + lastVersion: number; + lastContentHash: string; + }; + } + + export function performUpdate(key: string, content: string, update: (version: number) => void) { + let data: VersionMap = fs.existsSync(versionFilename) ? JSON.parse(fs.readFileSync(versionFilename, 'utf-8')) : {}; + + const hashValue = computeHash(key); + let entry = data[key]; + + if (entry === undefined) { + data[key] = entry = { lastVersion: 0, lastContentHash: '' }; + } + + if (entry.lastContentHash !== hashValue) { + const vNext = entry.lastVersion + 1; + update(vNext); + + data[key] = { lastVersion: vNext, lastContentHash: hashValue }; + fs.writeFileSync(versionFilename, JSON.stringify(data, undefined, 4)); + + return true; + } + + return false; + } + + export function computeHash(content: string) { + const h = crypto.createHash('sha256'); + h.update(content, 'utf-8'); + return h.digest('base64'); + } +} + +export function publish(typing: TypingsData, settings: PublishSettings): boolean { const args: string[] = [ 'publish', // packagePath, '--access public' ]; + + const content = fs.readFileSync(typing.definitionFilename, 'utf-8'); + + return Versions.performUpdate(typing.folder, content, version => { + const packageJson = createPackageJSON(typing, settings, version); + const readme = createReadme(typing); + + const outputPath = path.join(settings.outputPath, typing.folder); + if (!fs.exists(outputPath)) { + fs.mkdirSync(outputPath); + } + + fs.writeFileSync(path.join(outputPath, 'package.json'), packageJson, 'utf-8'); + fs.writeFileSync(path.join(outputPath, 'README.md'), readme, 'utf-8'); + fs.writeFileSync(path.join(outputPath, path.basename(typing.definitionFilename)), fs.readFileSync(typing.definitionFilename)); + }); } + function createPackageJSON(typing: TypingsData, settings: PublishSettings, fileVersion: number) { const dependencies: any = {}; typing.moduleDependencies.forEach(d => dependencies[d] = '*');