Improved new-package script.

* Add more info (homepage and version)
* Handle errors more gracefully (Handle existing module and clean up otherwise)
This commit is contained in:
Philipp A 2016-11-16 19:39:36 +01:00
parent 110ce01c72
commit 86334d469d
2 changed files with 221 additions and 60 deletions

View File

@ -1,42 +1,120 @@
/// <reference types="node" />
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
const http_1 = require("http");
const fs_1 = require("fs");
const path = require("path");
const newPackageName = process.argv[2];
if (!newPackageName) {
throw new Error("Usage: node scripts/new-package.js new-package-name");
}
fs_1.mkdirSync(newPackageName);
write("index.d.ts", `// Type definitions for ${newPackageName} 1.2
// Project: https://github.com/baz/foo (Does not have to be to GitHub, but prefer linking to a source code repository rather than to a project website.)
run().catch(e => {
console.error(e);
process.exit(1);
});
function run() {
return __awaiter(this, void 0, void 0, function* () {
const files = [
["index.d.ts", yield getIndex()],
[`${newPackageName}-tests.ts`, ""],
["tsconfig.json", `${JSON.stringify(getTSConfig(), undefined, 4)}\n`],
["tslint.json", '{ "extends": "../tslint.json" }\n'],
];
try {
yield pify1(fs_1.mkdir, newPackageName);
yield Promise.all(files.map(([name, text]) => write(name, text)));
}
catch (e) {
if (e.code === "EEXIST") {
console.warn(`Module “${newPackageName}” already exists!`);
}
else {
console.error(`Error creating module files: ${e}\nCleaning Up.`);
yield Promise.all(files.map(([name]) => rm(name)));
yield pify1(fs_1.rmdir, newPackageName);
}
process.exit(1);
}
});
}
function getIndex() {
return __awaiter(this, void 0, void 0, function* () {
let version = "x.x";
let project = "https://github.com/baz/foo (Does not have to be to GitHub, but prefer linking to a source code repository rather than to a project website.)";
try {
const reg = yield loadString(`http://registry.npmjs.org/${newPackageName}`).then(JSON.parse);
const { latest } = reg["dist-tags"];
const { homepage } = reg.versions[latest];
version = latest.split(".").slice(0, 2).join(".");
if (homepage !== undefined)
project = homepage;
}
catch (e) {
console.warn(`Could not retrieve version/homepage information: ${e.stack}`);
}
return `// Type definitions for ${newPackageName} ${version}
// Project: ${project}
// Definitions by: My Self <https://github.com/me>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Fill the header in!
`);
const testsFile = `${newPackageName}-tests.ts`;
write(testsFile, "");
const tsconfig = {
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
`${newPackageName}-tests.ts`
]
};
write("tsconfig.json", JSON.stringify(tsconfig, undefined, 4));
write("tslint.json", '{ "extends": "../tslint.json" }');
function write(name, content) {
fs_1.writeFileSync(path.join(newPackageName, name), content);
`;
});
}
function getTSConfig() {
return {
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
`${newPackageName}-tests.ts`
]
};
}
function write(name, content) {
return new Promise((resolve, reject) => {
fs_1.writeFile(path.join(newPackageName, name), content, err => err ? reject(err) : resolve());
});
}
function rm(name) {
return pify1(fs_1.unlink, path.join(newPackageName, name)).catch((e) => {
if (e.code === "ENOENT")
return;
throw e;
});
}
function pify1(fn, arg) {
return new Promise((resolve, reject) => {
fn(arg, err => err ? reject(err) : resolve());
});
}
function loadString(url) {
return new Promise((resolve, reject) => {
http_1.get(url, (res) => {
if (res.statusCode !== 200) {
return reject(new Error(`HTTP Error ${res.statusCode}: ${http_1.STATUS_CODES[res.statusCode || 500]} for ${url}`));
}
let rawData = "";
res.on("data", chunk => rawData += chunk);
res.on("end", () => resolve(rawData));
}).on("error", e => reject(e));
});
}

View File

@ -1,47 +1,130 @@
/// <reference types="node" />
import { mkdirSync, writeFileSync } from "fs";
import * as path from "path";
import { get, STATUS_CODES } from "http"
import { mkdir, writeFile, unlink, rmdir } from "fs"
import * as path from "path"
const newPackageName = process.argv[2];
interface Package {
name: string
description: string
version: string
homepage?: string
}
interface Registry {
name: string
description: string
"dist-tags": { latest: string }
versions: { [version: string]: Package }
}
const newPackageName = process.argv[2]
if (!newPackageName) {
throw new Error("Usage: node scripts/new-package.js new-package-name")
}
mkdirSync(newPackageName);
run().catch(e => {
console.error(e)
process.exit(1)
})
write("index.d.ts", `// Type definitions for ${newPackageName} 1.2
// Project: https://github.com/baz/foo (Does not have to be to GitHub, but prefer linking to a source code repository rather than to a project website.)
async function run() {
const files: [string, string][] = [
["index.d.ts", await getIndex()],
[`${newPackageName}-tests.ts`, ""],
["tsconfig.json", `${JSON.stringify(getTSConfig(), undefined, 4)}\n`],
["tslint.json", '{ "extends": "../tslint.json" }\n'],
]
try {
await pify1(mkdir, newPackageName)
await Promise.all(files.map(([name, text]) => write(name, text)))
} catch (e) {
if (e.code === "EEXIST") {
console.warn(`Module “${newPackageName}” already exists!`)
} else {
console.error(`Error creating module files: ${e}\nCleaning Up.`)
await Promise.all(files.map(([name]) => rm(name)))
await pify1(rmdir, newPackageName)
}
process.exit(1)
}
}
async function getIndex() {
let version = "x.x"
let project = "https://github.com/baz/foo (Does not have to be to GitHub, but prefer linking to a source code repository rather than to a project website.)"
try {
const reg: Registry = await loadString(`http://registry.npmjs.org/${newPackageName}`).then(JSON.parse)
const { latest } = reg["dist-tags"]
const { homepage } = reg.versions[latest]
version = latest.split(".").slice(0, 2).join(".")
if (homepage !== undefined) project = homepage
} catch (e) {
console.warn(`Could not retrieve version/homepage information: ${e.stack}`)
}
return `// Type definitions for ${newPackageName} ${version}
// Project: ${project}
// Definitions by: My Self <https://github.com/me>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Fill the header in!
`);
const testsFile = `${newPackageName}-tests.ts`;
write(testsFile, "");
const tsconfig = {
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
`${newPackageName}-tests.ts`
]
};
write("tsconfig.json", JSON.stringify(tsconfig, undefined, 4));
`
}
write("tslint.json", '{ "extends": "../tslint.json" }');
function getTSConfig() {
return {
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.d.ts",
`${newPackageName}-tests.ts`
]
}
}
function write(name: string, content: string) {
writeFileSync(path.join(newPackageName, name), content);
return new Promise((resolve, reject) => {
writeFile(path.join(newPackageName, name), content, err => err ? reject(err): resolve())
})
}
function rm(name: string) {
return pify1(unlink, path.join(newPackageName, name)).catch((e: NodeJS.ErrnoException) => {
if (e.code === "ENOENT") return
throw e
})
}
function pify1<F extends (a: A, cb: (err?: Error) => void) => void, A>(fn: F, arg: A) {
return new Promise((resolve, reject) => {
fn(arg, err => err ? reject(err): resolve())
})
}
function loadString(url: string): Promise<string> {
return new Promise((resolve, reject) => {
get(url, (res) => {
if (res.statusCode !== 200) {
return reject(new Error(`HTTP Error ${res.statusCode}: ${STATUS_CODES[res.statusCode || 500]} for ${url}`))
}
let rawData = ""
res.on("data", chunk => rawData += chunk)
res.on("end", () => resolve(rawData))
}).on("error", e => reject(e))
})
}