Remvoed dead files.
This commit is contained in:
parent
5cb418cf7d
commit
70c2b1b300
@ -1,59 +0,0 @@
|
||||
Admin Tool
|
||||
==========
|
||||
|
||||
This tool is meant for admin tasks related to ethers.js.
|
||||
|
||||
|
||||
Workflow
|
||||
--------
|
||||
|
||||
After a new series of changes have been made and tested:
|
||||
|
||||
1. Run `npm run update-versions` to update and build all packages
|
||||
2. Make any human-necessary changes to the automatically updated `CHANGELOG.md`
|
||||
3. Run `git add .`
|
||||
4. Run `git commit -S -m "Updated dist files."`
|
||||
5. Run `git push`
|
||||
6. Wait for TravisCI to complete running test cases
|
||||
7. Run `npm run publish-all` to publish changed packages to NPM and tag GitHub
|
||||
|
||||
|
||||
Update Dependency Graph: admin/cmds/update-depgraph
|
||||
---------------------------------------------------
|
||||
|
||||
This is run as part of `npm run bootstrap` before running lerna bootstrap.
|
||||
It recomputes the dependency graph and writes out the ordered
|
||||
**tsconfig.project.json**
|
||||
|
||||
|
||||
Update Versions: admin/cmds/update-versions
|
||||
-------------------------------------------
|
||||
|
||||
Run using the `npm run update-versions`, which also cleans, bootstraps and
|
||||
rebuilds the project before running the script.
|
||||
|
||||
For each package that has changed from the version in NPM (the published
|
||||
tarballs are compared):
|
||||
|
||||
- Update the `version` in the **package.json**
|
||||
- Update the `src.ts/_version.ts` (matches the **package.json**)
|
||||
- Updates the `tarballHash` in the **package.json**
|
||||
- Compiles the TypeScript (which updates the `_version.js` and `_version.d.js`)
|
||||
- Lists all changed files (highlighting src.ts files)
|
||||
|
||||
Then:
|
||||
|
||||
- Generate the distribution files
|
||||
- Update the `CHANGELOG.md`
|
||||
|
||||
|
||||
Publish: admin/cmds/publish
|
||||
---------------------------
|
||||
|
||||
Run using `npm run publish-all`. This requires a password for the secure
|
||||
local config and the OTP for NPM.
|
||||
|
||||
- Publish (in dependency order) changed files to NPM
|
||||
- The `gitHead` is updated in **only** the NPM **package.json**
|
||||
- @TODO: Cut a release on GitHub including the relevant CHANGELOG entry
|
||||
|
111
admin/build.js
111
admin/build.js
@ -1,111 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const resolve = require("path").resolve;
|
||||
const spawn = require("child_process").spawn;
|
||||
|
||||
const { dirnames } = require("./local");
|
||||
const { loadPackage, savePackage } = require("./local");
|
||||
const { loadJson, saveJson } = require("./utils");
|
||||
|
||||
function run(progname, args, ignoreErrorStream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const proc = spawn(progname, args);
|
||||
|
||||
let stdout = Buffer.from([]);
|
||||
let stderr = Buffer.from([]);
|
||||
|
||||
proc.stdout.on("data", (data) => {
|
||||
stdout = Buffer.concat([ stdout, data ]);
|
||||
});
|
||||
|
||||
proc.stderr.on("data", (data) => {
|
||||
stderr = Buffer.concat([ stdout, data ]);
|
||||
});
|
||||
|
||||
proc.on("error", (error) => {
|
||||
console.log("ERROR");
|
||||
console.log(stderr.toString());
|
||||
error.stderr = stderr.toString();
|
||||
error.stdout = stdout.toString();
|
||||
reject(error);
|
||||
});
|
||||
|
||||
proc.on("close", (code) => {
|
||||
if ((stderr.length && !ignoreErrorStream) || code !== 0) {
|
||||
console.log("ERROR");
|
||||
console.log(stderr.toString());
|
||||
|
||||
let error = new Error(`stderr not empty: ${ progname } ${ JSON.stringify(args) }`);
|
||||
error.stderr = stderr.toString();
|
||||
error.stdout = stdout.toString();
|
||||
error.statusCode = code;
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(stdout.toString());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupConfig(outDir, moduleType, targetType) {
|
||||
|
||||
// Configure the tsconfit.package.json...
|
||||
const path = resolve(__dirname, "../tsconfig.package.json");
|
||||
const content = loadJson(path);
|
||||
content.compilerOptions.module = moduleType;
|
||||
content.compilerOptions.target = targetType;
|
||||
saveJson(path, content);
|
||||
|
||||
// Configure the browser field for every pacakge, copying the
|
||||
// browser.umd filed for UMD and browser.esm for ESM
|
||||
dirnames.forEach((dirname) => {
|
||||
let info = loadPackage(dirname);
|
||||
|
||||
if (info._ethers_nobuild) { return; }
|
||||
|
||||
if (targetType === "es2015") {
|
||||
if (info["browser.esm"]) {
|
||||
info.browser = info["browser.esm"];
|
||||
}
|
||||
} else if (targetType === "es5") {
|
||||
if (info["browser.umd"]) {
|
||||
info.browser = info["browser.umd"];
|
||||
}
|
||||
} else {
|
||||
throw new Error("unsupported target");
|
||||
}
|
||||
savePackage(dirname, info);
|
||||
|
||||
let path = resolve(__dirname, "../packages", dirname, "tsconfig.json");
|
||||
let content = loadJson(path);
|
||||
content.compilerOptions.outDir = outDir;
|
||||
saveJson(path, content);
|
||||
});
|
||||
}
|
||||
|
||||
function setupBuild(buildModule) {
|
||||
if (buildModule) {
|
||||
setupConfig("./lib.esm/", "es2015", "es2015");
|
||||
} else {
|
||||
setupConfig("./lib/", "commonjs", "es5");
|
||||
}
|
||||
}
|
||||
|
||||
function runBuild(buildModule) {
|
||||
setupBuild(buildModule);
|
||||
|
||||
// Compile
|
||||
return run("npx", [ "tsc", "--build", resolve(__dirname, "../tsconfig.project.json"), "--force" ]);
|
||||
}
|
||||
|
||||
function runDist() {
|
||||
return run("npm", [ "run", "_dist" ], true);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run: run,
|
||||
runDist: runDist,
|
||||
runBuild: runBuild,
|
||||
setupBuild: setupBuild
|
||||
};
|
@ -1,145 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const resolve = require("path").resolve;
|
||||
|
||||
const git = require("./git");
|
||||
const local = require("./local");
|
||||
const npm = require("./npm");
|
||||
const utils = require("./utils");
|
||||
|
||||
const ChangelogPath = resolve(__dirname, "../CHANGELOG.md");
|
||||
|
||||
async function generate() {
|
||||
|
||||
// Get each section of the Changelog
|
||||
let existing = fs.readFileSync(ChangelogPath).toString().split("\n");
|
||||
let sections = [ ];
|
||||
let lastLine = existing[0];
|
||||
existing.slice(1).forEach((line) => {
|
||||
if (line.substring(0, 5) === "=====" || line.substring(0, 5) === "-----") {
|
||||
sections.push({
|
||||
title: lastLine,
|
||||
underline: line.substring(0, 1),
|
||||
body: [ ]
|
||||
});
|
||||
lastLine = null;
|
||||
return;
|
||||
} else if (lastLine) {
|
||||
sections[sections.length - 1].body.push(lastLine);
|
||||
}
|
||||
lastLine = line;
|
||||
});
|
||||
sections[sections.length - 1].body.push(lastLine);
|
||||
|
||||
let lastVersion = await npm.getPackageVersion("ethers");
|
||||
|
||||
let logs = await git.run([ "log", (lastVersion.gitHead + "..") ]);
|
||||
|
||||
let changes = [ ];
|
||||
logs.split("\n").forEach((line) => {
|
||||
if (line.toLowerCase().substring(0, 6) === "commit") {
|
||||
changes.push({
|
||||
commit: line.substring(6).trim(),
|
||||
body: [ ]
|
||||
});
|
||||
} else if (line.toLowerCase().substring(0, 5) === "date:") {
|
||||
changes[changes.length - 1].date = utils.getDateTime(new Date(line.substring(5).trim()));
|
||||
} else if (line.substring(0, 1) === " ") {
|
||||
line = line.trim();
|
||||
if (line === "") { return; }
|
||||
changes[changes.length - 1].body += line + " ";
|
||||
}
|
||||
});
|
||||
|
||||
// @TODO:
|
||||
// ethers/version ([date](tag))
|
||||
let newSection = {
|
||||
title: `ethers/v${ local.loadPackage("ethers").version } (${utils.getDateTime(new Date())})`,
|
||||
underline: "-",
|
||||
body: [ ]
|
||||
}
|
||||
|
||||
// Delete duplicate sections for the same version (ran update multiple times)
|
||||
while (sections[1].title === newSection.title) {
|
||||
sections.splice(1, 1);
|
||||
}
|
||||
|
||||
changes.forEach((change) => {
|
||||
let body = change.body.trim();
|
||||
let link = body.match(/(\((.*#.*)\))/)
|
||||
let commit = `[${ change.commit.substring(0, 7) }](https://github.com/ethers-io/ethers.js/commit/${ change.commit })`;
|
||||
if (link) {
|
||||
body = body.replace(/ *(\(.*#.*)\) */, "");
|
||||
link = link[2].replace(/#([0-9]+)/g, (all, issue) => {
|
||||
return `[#${ issue }](https://github.com/ethers-io/ethers.js/issues/${ issue })`;
|
||||
}) + "; " + commit;
|
||||
} else {
|
||||
link = commit;
|
||||
}
|
||||
newSection.body.push(` - ${ body } (${ link })`);
|
||||
});
|
||||
|
||||
sections.splice(1, 0, newSection);
|
||||
|
||||
|
||||
let formatted = [ ];
|
||||
sections.forEach((section) => {
|
||||
formatted.push(section.title);
|
||||
formatted.push(utils.repeat(section.underline, section.title.length));
|
||||
formatted.push("");
|
||||
section.body.forEach((line) => {
|
||||
line = line.trim();
|
||||
if (line === "") { return; }
|
||||
if (line.substring(0, 1) === "-") {
|
||||
line = "- " + line.substring(1).trim();
|
||||
}
|
||||
if (section.underline === "-") {
|
||||
line = " " + line;
|
||||
}
|
||||
formatted.push(line);
|
||||
});
|
||||
formatted.push("");
|
||||
});
|
||||
|
||||
return formatted.join("\n") + "\n";
|
||||
}
|
||||
|
||||
function getChanges() {
|
||||
const changes = [ ];
|
||||
|
||||
let lastLine = null;
|
||||
fs.readFileSync(ChangelogPath).toString().split("\n").forEach((line) => {
|
||||
line = line.trim();
|
||||
if (line === "") { return; }
|
||||
|
||||
if (line.substring(0, 5) === "-----") {
|
||||
changes.push({ title: lastLine, lines: [ ] });
|
||||
} else if (line.substring(0, 1) === "-" && changes.length) {
|
||||
changes[changes.length - 1].lines.push(line);
|
||||
}
|
||||
lastLine = line;
|
||||
});
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
function latestChange() {
|
||||
const recent = getChanges()[0];
|
||||
|
||||
const match = recent.title.match(/ethers\/([^\(]*)\(([^\)]*)\)/);
|
||||
|
||||
return {
|
||||
title: recent.title,
|
||||
version: match[1].trim(),
|
||||
data: match[2].trim(),
|
||||
content: recent.lines.join("\n")
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generate: generate,
|
||||
latestChange: latestChange,
|
||||
ChangelogPath: ChangelogPath,
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const config = require("../config");
|
||||
const { syncIssues } = require("../github");
|
||||
|
||||
(async function() {
|
||||
const user = await config.get("github-user");
|
||||
const password = await config.get("github-readonly");
|
||||
await syncIssues(user, password);
|
||||
})();
|
@ -1,142 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const { colorify } = require("../log");
|
||||
const { getIssues } = require("../github");
|
||||
const { repeat } = require("../utils");
|
||||
|
||||
const Options = {
|
||||
"body": 1,
|
||||
"end": 1,
|
||||
"issue": 1,
|
||||
"start": 1,
|
||||
"title": 1,
|
||||
"user": 1,
|
||||
};
|
||||
|
||||
const Flags = {
|
||||
"open": 1,
|
||||
"match-case": 1,
|
||||
};
|
||||
|
||||
(async function() {
|
||||
const options = { };
|
||||
for (let i = 2; i < process.argv.length; i++) {
|
||||
const option = process.argv[i];
|
||||
if (option.substring(0, 2) === "--") {
|
||||
const comps = option.substring(2).split(/=/);
|
||||
if (Flags[comps[0]]) {
|
||||
if (comps[1] != null) { throw new Error("Invalid flag: " + option); }
|
||||
options[comps[0]] = true;
|
||||
} else if (Options[comps[0]]) {
|
||||
if (comps[1] == null) {
|
||||
options[comps[0]] = process.argv[++i];
|
||||
if (options[comps[0]] == null) {
|
||||
throw new Error("Missing option value: " + option);
|
||||
}
|
||||
} else {
|
||||
options[comps[0]] = comps[1];
|
||||
}
|
||||
} else {
|
||||
throw new Error("Unexpected option: " + option);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Unexpected argument: " + option);
|
||||
}
|
||||
}
|
||||
|
||||
if (options["title"]) { options.title = new RegExp(options.title, (options["match-case"] ? "": "i")); }
|
||||
if (options["body"]) { options.body = new RegExp(options.title, (options["match-case"] ? "": "i")); }
|
||||
if (options["start"]) {
|
||||
if (options["start"].match(/^[0-9]{4}-[0-9]{2}-[0-9{2}]$/)) {
|
||||
throw new Error("Expected YYYY-MM-DD");
|
||||
}
|
||||
}
|
||||
if (options["end"]) {
|
||||
if (options["end"].match(/^[0-9]{4}-[0-9]{2}-[0-9{2}]$/)) {
|
||||
throw new Error("Expected YYYY-MM-DD");
|
||||
}
|
||||
}
|
||||
|
||||
const count = { issues: 0, comments: 0, code: 0, responses: 0 };
|
||||
|
||||
const issues = await getIssues();
|
||||
issues.forEach((issue) => {
|
||||
const info = issue.issue;
|
||||
const comments = issue.comments;
|
||||
|
||||
if (options.issue && parseInt(options.issue) != info.number) { return; }
|
||||
if (options.open && info.state !== "open") { return; }
|
||||
if (options.title && !info.title.match(options.title)) { return; }
|
||||
if (options.body) {
|
||||
const body = info.body + "\n" + comments.map((c) => (c.body)).join("\n");
|
||||
if (!body.match(options.body)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (options.user) {
|
||||
const users = comments.map((c) => (c.user.login));
|
||||
users.push(info.user.login);
|
||||
if (users.indexOf(options.user) === -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const dates = comments.map((c) => (c.created_at.split("T")[0]));
|
||||
dates.push(info.created_at.split("T")[0]);
|
||||
|
||||
if (options.start) {
|
||||
if (dates.filter((d) => (d >= options.start)).length === 0) { return; }
|
||||
}
|
||||
if (options.end) {
|
||||
if (dates.filter((d) => (d <= options.start)).length === 0) { return; }
|
||||
}
|
||||
|
||||
count.issues++;
|
||||
|
||||
console.log(colorify(repeat("=", 70), "bold"))
|
||||
console.log(colorify("Issue:", "bold"), info.title, ` (#${ info.number })`);
|
||||
console.log(colorify("User:","bold"), colorify(info.user.login, "blue"));
|
||||
console.log(colorify("State:", "bold"), info.state);
|
||||
if (info.created_at === info.updated_at) {
|
||||
console.log(colorify("Created:", "bold"), info.created_at);
|
||||
} else {
|
||||
console.log(colorify("Created:", "bold"), info.created_at, ` (updated: ${ info.updated_at })`);
|
||||
}
|
||||
info.body.trim().split("\n").forEach((line) => {
|
||||
console.log(" " + line);
|
||||
});
|
||||
|
||||
if (comments.length) {
|
||||
comments.forEach((info) => {
|
||||
if (options.start && info.created_at < options.start) { return ; }
|
||||
if (options.end && info.created_at > options.end) { return; }
|
||||
count.comments++;
|
||||
if (options.user && info.user.login !== options.user) { return; }
|
||||
count.responses++;
|
||||
if (info.body.indexOf("`") >= 0) { count.code++; }
|
||||
console.log(colorify(repeat("-", 70), "bold"));
|
||||
console.log(colorify("User:", "bold"), colorify(info.user.login, "green"));
|
||||
if (info.created_at === info.updated_at) {
|
||||
console.log(colorify("Created:", "bold"), info.created_at);
|
||||
} else {
|
||||
console.log(colorify("Created:", "bold"), info.created_at, ` (updated: ${ info.updated_at })`);
|
||||
}
|
||||
info.body.trim().split("\n").forEach((line) => {
|
||||
console.log(" " + line);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log(colorify(repeat("=", 70), "bold"))
|
||||
|
||||
// @TODO: Add stats on new/closed issues
|
||||
//if (options.user) {
|
||||
// console.log(`${ count.responses } responses (${ count.code } w/ code) on ${ count.comments } comments across ${ count.issues } issues.`);
|
||||
//} else {
|
||||
console.log(`${ count.comments } comment${ (count.comments !== 1) ? "s": "" } across ${ count.issues } issue${ (count.issues !== 1) ? "s": ""}.`);
|
||||
//}
|
||||
|
||||
})().catch((error) => {
|
||||
console.log("Error: " + error.message);
|
||||
});
|
@ -1,49 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const { getOrdered, loadPackage } = require("../depgraph");
|
||||
const { savePackage } = require("../local");
|
||||
const { log } = require("../log");
|
||||
|
||||
(async function() {
|
||||
let versions = { };
|
||||
|
||||
const dirnames = getOrdered();
|
||||
|
||||
dirnames.forEach((dirname) => {
|
||||
let info = loadPackage(dirname);
|
||||
if (info.name.split("/")[0] === "@ethersproject" || info.name === "ethers") {
|
||||
versions[info.name] = info.version;
|
||||
}
|
||||
});
|
||||
|
||||
dirnames.forEach((dirname) => {
|
||||
const info = loadPackage(dirname);
|
||||
let shown = false;
|
||||
["dependencies", "devDependencies"].forEach((key) => {
|
||||
const deps = info[key];
|
||||
if (!deps) { return; }
|
||||
Object.keys(deps).forEach((name) => {
|
||||
// Not a package in this monorepoa
|
||||
const version = versions[name];
|
||||
if (version == null) { return; }
|
||||
|
||||
const value = ((version.indexOf("beta") !== -1) ? ">=": "^") + version;
|
||||
|
||||
// No change
|
||||
if (value === deps[name]) { return; }
|
||||
|
||||
// Show a header for the first change
|
||||
if (!shown) {
|
||||
log(`<bold:Locking ${ info.name }:>`);
|
||||
shown = true;
|
||||
}
|
||||
|
||||
// Show the locked version
|
||||
log(` <green:${ name }>: ${ deps[name] } => <bold:${ value.replace(">", ">") }>`);
|
||||
deps[name] = value;
|
||||
});
|
||||
});
|
||||
savePackage(dirname, info);
|
||||
});
|
||||
|
||||
})();
|
@ -1,210 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const { basename, resolve } = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const AWS = require('aws-sdk');
|
||||
|
||||
const config = require("../config");
|
||||
|
||||
const { ChangelogPath, latestChange } = require("../changelog");
|
||||
const { getOrdered, loadPackage } = require("../depgraph");
|
||||
const { getGitTag } = require("../git");
|
||||
const { createRelease } = require("../github");
|
||||
const { getPackageVersion, publish } = require("../npm");
|
||||
const { log } = require("../log");
|
||||
|
||||
const USER_AGENT = "ethers-dist@0.0.0";
|
||||
const TAG = "latest";
|
||||
|
||||
|
||||
let dirnames = getOrdered();
|
||||
|
||||
// Only publish specific packages
|
||||
if (process.argv.length > 2) {
|
||||
let filter = process.argv.slice(2);
|
||||
|
||||
// Verify all named packages exist
|
||||
filter.forEach((dirname) => {
|
||||
try {
|
||||
loadPackage(dirname);
|
||||
} catch (error) {
|
||||
console.log("Package not found: " + dirname);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Filter out pacakges we don't care about
|
||||
dirnames = dirnames.filter((dirname) => (filter.indexOf(dirname) >= 0));
|
||||
}
|
||||
|
||||
|
||||
function putObject(s3, info) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
s3.putObject(info, function(error, data) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve({
|
||||
name: info.Key,
|
||||
hash: data.ETag.replace(/"/g, '')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function invalidate(cloudfront, distributionId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
cloudfront.createInvalidation({
|
||||
DistributionId: distributionId,
|
||||
InvalidationBatch: {
|
||||
CallerReference: `${ USER_AGENT }-${ parseInt(((new Date()).getTime()) / 1000) }`,
|
||||
Paths: {
|
||||
Quantity: "1",
|
||||
Items: [
|
||||
"/\*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}, function(error, data) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
resolve(data.Invalidation.Id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(async function() {
|
||||
let token = null;
|
||||
|
||||
const gitCommit = await getGitTag(ChangelogPath);
|
||||
|
||||
let includeEthers = false;
|
||||
|
||||
// @TODO: Fail if there are any untracked files or unchecked in files
|
||||
|
||||
// Load the token from the encrypted store
|
||||
try {
|
||||
token = await config.get("npm-token");
|
||||
} catch (error) {
|
||||
switch (error.message) {
|
||||
case "wrong password":
|
||||
log("<bold:Wrong password>");
|
||||
break;
|
||||
case "cancelled":
|
||||
break;
|
||||
default:
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
log("<red:Aborting.>");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
token = token.trim().split("=");
|
||||
|
||||
let options = {
|
||||
npmVersion: USER_AGENT,
|
||||
tag: TAG
|
||||
};
|
||||
|
||||
// Set the authentication token
|
||||
options[token[0]] = token[1];
|
||||
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
let dirname = dirnames[i];
|
||||
|
||||
if (dirname === "ethers") {
|
||||
includeEthers = true;
|
||||
}
|
||||
|
||||
let info = loadPackage(dirname);
|
||||
let npmInfo = await getPackageVersion(info.name);
|
||||
if (!npmInfo) { npmInfo = { version: "NEW" }; }
|
||||
|
||||
if (info.tarballHash === npmInfo.tarballHash) { continue; }
|
||||
|
||||
log(`<bold:Publishing:> ${info.name}...`);
|
||||
log(` <blue:Version:> ${npmInfo.version} <bold:=\\>> ${info.version}`);
|
||||
|
||||
let success = await publish(dirname, options);
|
||||
if (!success) {
|
||||
log(" <red:FAILED! Aborting.>");
|
||||
return;
|
||||
}
|
||||
log(" <green:Done.>");
|
||||
}
|
||||
|
||||
// Publish the GitHub release
|
||||
const beta = false;
|
||||
if (includeEthers) {
|
||||
|
||||
// Get the latest change from the changelog
|
||||
const change = latestChange();
|
||||
|
||||
// Publish the release to GitHub
|
||||
{
|
||||
// The password above already succeeded
|
||||
const username = await config.get("github-user");
|
||||
const password = await config.get("github-release");
|
||||
|
||||
|
||||
// Publish the release
|
||||
const link = await createRelease(username, password, change.version, change.title, change.content, beta, gitCommit);
|
||||
log(`<bold:Published Release:> ${ link }`);
|
||||
}
|
||||
|
||||
// Upload the scripts to the CDN and refresh the edge caches
|
||||
{
|
||||
const awsAccessId = await config.get("aws-upload-scripts-accesskey");
|
||||
const awsSecretKey = await config.get("aws-upload-scripts-secretkey");
|
||||
const bucketName = await config.get("aws-upload-scripts-bucket");
|
||||
const originRoot = await config.get("aws-upload-scripts-root");
|
||||
const distributionId = await config.get("aws-upload-scripts-distribution-id");
|
||||
|
||||
const s3 = new AWS.S3({
|
||||
apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
|
||||
// Upload the libs to ethers-v5.0 and ethers-5.0.x
|
||||
const fileInfos = [
|
||||
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: `ethers-${ change.version.substring(1) }.esm.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: `ethers-${ change.version.substring(1) }.umd.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: `ethers-5.0.esm.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: `ethers-5.0.umd.min.js` },
|
||||
];
|
||||
|
||||
for (let i = 0; i < fileInfos.length; i++) {
|
||||
const fileInfo = fileInfos[i];
|
||||
const status = await putObject(s3, {
|
||||
ACL: 'public-read',
|
||||
Body: fs.readFileSync(resolve(__dirname, "../../", fileInfo.filename)),
|
||||
Bucket: bucketName,
|
||||
ContentType: "application/javascript; charset=utf-8",
|
||||
Key: (originRoot + fileInfo.key)
|
||||
});
|
||||
|
||||
log(`<bold:Uploaded :> https://cdn.ethers.io/lib/${ fileInfo.key }`);
|
||||
}
|
||||
|
||||
// Flush the edge caches
|
||||
{
|
||||
const cloudfront = new AWS.CloudFront({
|
||||
//apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
|
||||
const invalidationId = await invalidate(cloudfront, distributionId);
|
||||
log(`<bold:Invalidated Cache :> ${ invalidationId }`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,100 +0,0 @@
|
||||
const fs = require("fs");
|
||||
const http = require("http");
|
||||
const path = require("path");
|
||||
|
||||
function getMime(filename) {
|
||||
const comps = filename.split('.');
|
||||
const ext = comps[comps.length - 1];
|
||||
switch (ext.toLowerCase()) {
|
||||
case 'css': return 'text/css';
|
||||
case 'doctree': return 'application/x-doctree';
|
||||
case 'eot': return 'application/vnd.ms-fontobject';
|
||||
case 'gif': return 'image/gif';
|
||||
case 'html': return 'text/html';
|
||||
case 'js': return 'application/javascript';
|
||||
case 'jpg': return 'image/jpeg';
|
||||
case 'jpeg': return 'image/jpeg';
|
||||
case 'md': return 'text/markdown';
|
||||
case 'pickle': return 'application/x-pickle';
|
||||
case 'png': return 'image/png';
|
||||
case 'svg': return 'image/svg+xml';
|
||||
case 'ttf': return 'application/x-font-ttf';
|
||||
case 'txt': return 'text/plain';
|
||||
case 'woff': return 'application/font-woff';
|
||||
}
|
||||
console.log('NO MIME', filename);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function start(root, options) {
|
||||
if (root == null) { throw new Error("root required"); }
|
||||
if (options == null) { options = { }; }
|
||||
if (options.port == null) { options.port = 8000; }
|
||||
root = path.resolve(root);
|
||||
|
||||
const server = http.createServer((req, resp) => {
|
||||
|
||||
// Follow redirects in options
|
||||
if (options.redirects && options.redirects[req.url]) {
|
||||
resp.writeHead(301, { Location: options.redirects[req.url] });
|
||||
resp.end();
|
||||
return;
|
||||
}
|
||||
|
||||
let filename = path.resolve(root, "." + req.url);
|
||||
|
||||
// Make sure we aren't crawling out of our sandbox
|
||||
if (req.url[0] !== "/" || filename.substring(0, filename.length) !== filename) {
|
||||
resp.writeHead(403);
|
||||
resp.end();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const stat = fs.statSync(filename);
|
||||
if (stat.isDirectory()) {
|
||||
|
||||
// Redirect bare directory to its path (i.e. "/foo" => "/foo/")
|
||||
if (req.url[req.url.length - 1] !== "/") {
|
||||
resp.writeHead(301, { Location: req.url + "/" });
|
||||
resp.end();
|
||||
return;
|
||||
}
|
||||
|
||||
filename += "/index.html";
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(filename);
|
||||
|
||||
resp.writeHead(200, {
|
||||
"Content-Length": content.length,
|
||||
"Content-Type": getMime(filename)
|
||||
});
|
||||
resp.end(content);
|
||||
return;
|
||||
|
||||
} catch (error) {
|
||||
if (error.code === "ENOENT") {
|
||||
resp.writeHead(404, { });
|
||||
resp.end();
|
||||
return;
|
||||
}
|
||||
|
||||
resp.writeHead(500, { });
|
||||
resp.end();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(options.port, () => {
|
||||
console.log(`Server running on: http://localhost:${ options.port }`);
|
||||
});
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
start(path.resolve(__dirname, "../../docs"), {
|
||||
redirects: {
|
||||
"/": "/v5/"
|
||||
}
|
||||
});
|
@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const { prompt } = require("../../packages/cli");
|
||||
const config = require("../config");
|
||||
|
||||
if (process.argv.length !== 3) {
|
||||
console.log("Usage: set-config KEY");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const key = process.argv[2];
|
||||
|
||||
(async function() {
|
||||
const value = await prompt.getPassword("Value: ");
|
||||
await config.set(key, value);
|
||||
})();
|
@ -1,146 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
// Expected this to be run after
|
||||
// - npm run clean
|
||||
// - npm run bootstrap
|
||||
// - npm run build
|
||||
|
||||
const fs = require("fs");
|
||||
|
||||
const semver = require("semver");
|
||||
|
||||
const { runBuild, runDist } = require("../build");
|
||||
const { ChangelogPath, generate } = require("../changelog");
|
||||
const { getOrdered, loadPackage } = require("../depgraph");
|
||||
const { getDiff, getStatus, getGitTag } = require("../git");
|
||||
const { updatePackage } = require("../local");
|
||||
const { getPackageVersion } = require("../npm");
|
||||
const { resolve } = require("../utils");
|
||||
const { colorify, log } = require("../log");
|
||||
|
||||
const { prompt } = require("../../packages/cli");
|
||||
|
||||
let dirnames = getOrdered();
|
||||
|
||||
// Only publish specific packages
|
||||
if (process.argv.length > 2) {
|
||||
let filter = process.argv.slice(2);
|
||||
|
||||
// Verify all named packages exist
|
||||
filter.forEach((dirname) => {
|
||||
try {
|
||||
loadPackage(dirname);
|
||||
} catch (error) {
|
||||
console.log("Package not found: " + dirname);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Filter out pacakges we don't care about
|
||||
dirnames = dirnames.filter((dirname) => (filter.indexOf(dirname) >= 0));
|
||||
}
|
||||
|
||||
(async function() {
|
||||
let progress = prompt.getProgressBar(colorify("Updating versions", "bold"));
|
||||
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
|
||||
let dirname = dirnames[i];
|
||||
let path = resolve("packages", dirname);
|
||||
|
||||
// Get local package.json (update the tarballHash)
|
||||
let info = await updatePackage(dirname);
|
||||
|
||||
// Get the remote package.json (or sub in a placeholder for new pacakges)
|
||||
let npmInfo = await getPackageVersion(info.name);
|
||||
if (!npmInfo) { npmInfo = { version: "NEW" }; }
|
||||
|
||||
if (info.tarballHash === npmInfo.tarballHash) { continue; }
|
||||
|
||||
// Bump the version if necessary
|
||||
if (info.version === npmInfo.version) {
|
||||
let newVersion = semver.inc(info.version, "patch");
|
||||
|
||||
// Write out the _version.ts
|
||||
if (!info._ethers_nobuild) {
|
||||
let code = "export const version = " + JSON.stringify(dirname + "/" + newVersion) + ";\n";
|
||||
fs.writeFileSync(resolve(path, "src.ts/_version.ts"), code);
|
||||
}
|
||||
|
||||
// Update the package.json (we do this after _version, so if we fail,
|
||||
// this remains old; which is what triggers the version bump)
|
||||
info = await updatePackage(dirname, { version: newVersion });
|
||||
}
|
||||
}
|
||||
progress(1);
|
||||
|
||||
try {
|
||||
log("<bold:Building TypeScript source (es6)...>");
|
||||
await runBuild(true);
|
||||
log("<bold:Building TypeScript source (commonjs)...>");
|
||||
await runBuild(false);
|
||||
log("<bold:Building distribution files...>");
|
||||
let content = await runDist();
|
||||
console.log(content);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
log("<red:Aborting.>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the tarball hash now that _version and package.json may have changed.
|
||||
progress = prompt.getProgressBar(colorify("Updating tarballHash", "bold"));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
await updatePackage(dirnames[i]);
|
||||
}
|
||||
progress(1);
|
||||
|
||||
// Show the changed files (compared to npm)
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
let dirname = dirnames[i];
|
||||
|
||||
// Get local package.json
|
||||
let info = await loadPackage(dirname);
|
||||
let path = resolve("packages/", dirname);
|
||||
|
||||
// Get the remote package.json (or sub in a placeholder for new pacakges)
|
||||
let npmInfo = await getPackageVersion(info.name);
|
||||
if (!npmInfo) { npmInfo = { version: "NEW" }; }
|
||||
|
||||
// No change
|
||||
if (info.tarballHash === npmInfo.tarballHash) { continue; }
|
||||
|
||||
let gitHead = await getGitTag(path);
|
||||
|
||||
log(`<bold:Package>: ${info.name}`);
|
||||
log(` <green:Tarball Changed:> (bumping version)`);
|
||||
log(` ${npmInfo.version} => ${info.version}`)
|
||||
log(` <blue:Changed:>`);
|
||||
let filenames = await getDiff(path, npmInfo.gitHead, true);
|
||||
filenames.forEach((filename) => {
|
||||
let short = filename.split("/").slice(1).join("/");
|
||||
if (short.indexOf("/src.ts/") >= 0 || short.indexOf("/dist/") >= 0) {
|
||||
log(` <bold:${short}>`);
|
||||
} else {
|
||||
log(` ${short}`);
|
||||
}
|
||||
});
|
||||
log("");
|
||||
}
|
||||
|
||||
let existing = fs.readFileSync(ChangelogPath).toString();
|
||||
let changelog = await generate();
|
||||
if (existing !== changelog) {
|
||||
let changelogStatus = await getStatus(ChangelogPath);
|
||||
if (changelogStatus !== "unmodified") {
|
||||
log("<bold:WARNING:> There are local changes to the CHANGELOG (they will be discarded)");
|
||||
console.log(existing);
|
||||
}
|
||||
log("<bold:Updating CHANGELOG>...");
|
||||
fs.writeFileSync(ChangelogPath, changelog);
|
||||
}
|
||||
|
||||
|
||||
})();
|
@ -1,181 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const AWS = require('aws-sdk');
|
||||
|
||||
const config = require("../config");
|
||||
|
||||
|
||||
const Bucket = "docs.ethers.io";
|
||||
|
||||
|
||||
function _getKeys(s3, result, nextToken, callback) {
|
||||
const params = {
|
||||
Bucket: Bucket,
|
||||
MaxKeys: 1000,
|
||||
ContinuationToken: nextToken,
|
||||
};
|
||||
s3.listObjectsV2(params, function(error, data) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
data.Contents.forEach(function(item) {
|
||||
result[item.Key] = item.ETag.replace(/"/g,'');
|
||||
});
|
||||
callback(null, data.IsTruncated ? data.NextContinuationToken: null);
|
||||
});
|
||||
}
|
||||
|
||||
function getKeys(s3) {
|
||||
const result = {};
|
||||
return new Promise(function(resolve, reject) {
|
||||
function handleBlock(error, nextToken) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else if (nextToken) {
|
||||
nextBlock(nextToken);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
function nextBlock(nextToken) {
|
||||
_getKeys(s3, result, nextToken, handleBlock);
|
||||
}
|
||||
nextBlock(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
function getMime(filename) {
|
||||
const comps = filename.split('.');
|
||||
const ext = comps[comps.length - 1];
|
||||
switch (ext.toLowerCase()) {
|
||||
case 'css': return 'text/css';
|
||||
case 'doctree': return 'application/x-doctree';
|
||||
case 'eot': return 'application/vnd.ms-fontobject';
|
||||
case 'gif': return 'image/gif';
|
||||
case 'html': return 'text/html';
|
||||
case 'js': return 'application/javascript';
|
||||
case 'jpg': return 'image/jpeg';
|
||||
case 'jpeg': return 'image/jpeg';
|
||||
case 'json': return 'application/json';
|
||||
case 'md': return 'text/markdown';
|
||||
case 'pickle': return 'application/x-pickle';
|
||||
case 'png': return 'image/png';
|
||||
case 'svg': return 'image/svg+xml';
|
||||
case 'ttf': return 'application/x-font-ttf';
|
||||
case 'txt': return 'text/plain';
|
||||
case 'woff': return 'application/font-woff';
|
||||
}
|
||||
console.log('NO MIME', filename);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function putObject(s3, name, content) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
s3.putObject({
|
||||
ACL: 'public-read',
|
||||
Body: content,
|
||||
Bucket: Bucket,
|
||||
ContentType: getMime(name),
|
||||
Key: name
|
||||
}, function(error, data) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
console.log(" Done.")
|
||||
resolve({
|
||||
name: name,
|
||||
hash: data.ETag.replace(/"/g, '')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function hash(filename) {
|
||||
const hasher = crypto.createHash('md5');
|
||||
hasher.update(fs.readFileSync(filename));
|
||||
return hasher.digest().toString('hex');
|
||||
}
|
||||
|
||||
function _getFiles(result, root) {
|
||||
fs.readdirSync(root).forEach(function(filename) {
|
||||
|
||||
// We don't need to upload junk
|
||||
if (filename === '.DS_Store') { return; }
|
||||
|
||||
const fullFilename = path.join(root, filename)
|
||||
const stat = fs.statSync(fullFilename);
|
||||
if (stat.isDirectory()) {
|
||||
_getFiles(result, fullFilename);
|
||||
} else {
|
||||
result[fullFilename] = hash(fullFilename);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getFiles(basedir) {
|
||||
// Make sure we have a trailing slash
|
||||
if (!basedir.match(/\/$/)) { basedir += "/"; }
|
||||
|
||||
// Fetch all the file hashes
|
||||
const hashes = { };
|
||||
_getFiles(hashes, basedir);
|
||||
|
||||
return Object.keys(hashes).reduce((accum, key) => {
|
||||
accum[key.substring(basedir.length)] = hashes[key];
|
||||
return accum;
|
||||
}, { });
|
||||
}
|
||||
|
||||
(async function() {
|
||||
const awsAccessId = await config.get("aws-upload-docs-accesskey");
|
||||
const awsSecretKey = await config.get("aws-upload-docs-secretkey");
|
||||
|
||||
const s3 = new AWS.S3({
|
||||
apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
|
||||
const added = [], removed = [], changed = [], upload = [];
|
||||
|
||||
const basedir = path.resolve(__dirname, "../../docs");
|
||||
|
||||
const local = await getFiles(basedir);
|
||||
const remote = await getKeys(s3);
|
||||
|
||||
Object.keys(local).forEach((filename) => {
|
||||
if (!remote[filename]) {
|
||||
added.push(filename);
|
||||
upload.push(filename);
|
||||
} else if (remote[filename] != local[filename]) {
|
||||
changed.push(filename);
|
||||
upload.push(filename);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(remote).forEach((filename) => {
|
||||
if (!local[filename]) {
|
||||
removed.push(filename);
|
||||
} else if (!local[filename] && remote[filename] != local[filename]) {
|
||||
changed.push(filename);
|
||||
upload.push(filename);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Added: ', added.length);
|
||||
console.log('Removed: ', removed.length);
|
||||
console.log('Changed: ', changed.length);
|
||||
|
||||
for (let i = 0; i < upload.length; i++) {
|
||||
const filename = upload[i];
|
||||
const content = fs.readFileSync(path.resolve(basedir, filename));
|
||||
console.log(`Uploading: ${ filename } (${ content.length } bytes)`);
|
||||
await putObject(s3, filename, content);
|
||||
}
|
||||
})();
|
120
admin/config.js
120
admin/config.js
@ -1,120 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const resolve = require("path").resolve;
|
||||
|
||||
const AES = require("aes-js");
|
||||
const scrypt = require("scrypt-js");
|
||||
|
||||
const { prompt } = require("../packages/cli");
|
||||
const randomBytes = require("../packages/random").randomBytes;
|
||||
const computeHmac = require("../packages/sha2").computeHmac;
|
||||
|
||||
const colorify = require("./log").colorify;
|
||||
|
||||
function getScrypt(message, password, salt) {
|
||||
let progressBar = prompt.getProgressBar(message);
|
||||
return scrypt.scrypt(Buffer.from(password), Buffer.from(salt), (1 << 17), 8, 1, 64, progressBar);
|
||||
}
|
||||
|
||||
function Config(filename) {
|
||||
this.salt = null;
|
||||
this.dkey = null;
|
||||
this.values = { };
|
||||
this.canary = "";
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
Config.prototype.load = async function() {
|
||||
if (this.dkey) { return; }
|
||||
|
||||
let data = null;
|
||||
if (fs.existsSync(this.filename)) {
|
||||
data = JSON.parse(fs.readFileSync(this.filename));
|
||||
} else {
|
||||
data = {
|
||||
salt: Buffer.from(randomBytes(32)).toString("hex")
|
||||
};
|
||||
}
|
||||
|
||||
this.canary = data.canary || "";
|
||||
|
||||
this.salt = data.salt;
|
||||
|
||||
const password = await prompt.getPassword(colorify("Password (config-store): ", "bold"));
|
||||
|
||||
this.dkey = await getScrypt(colorify("Unlocking config", "bold"), password, this.salt);
|
||||
|
||||
if (data.ciphertext) {
|
||||
const ciphertext = Buffer.from(data.ciphertext, "base64");
|
||||
const iv = Buffer.from(data.iv, "base64");
|
||||
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
|
||||
const plaintext = aes.decrypt(ciphertext);
|
||||
const hmac = computeHmac("sha512", this.dkey.slice(32, 64), plaintext);
|
||||
if (hmac !== data.hmac) {
|
||||
throw new Error("wrong password");
|
||||
}
|
||||
|
||||
this.values = JSON.parse(Buffer.from(plaintext).toString());
|
||||
}
|
||||
};
|
||||
|
||||
Config.prototype.keys = async function() {
|
||||
await this.load();
|
||||
return Object.keys(this.values);
|
||||
}
|
||||
|
||||
Config.prototype.save = function() {
|
||||
this.values._junk = Buffer.from(randomBytes(16 + parseInt(Math.random() * 48))).toString("base64")
|
||||
|
||||
const plaintext = Buffer.from(JSON.stringify(this.values));
|
||||
|
||||
const iv = Buffer.from(randomBytes(16));
|
||||
const hmac = computeHmac("sha512", this.dkey.slice(32, 64), plaintext);
|
||||
|
||||
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
|
||||
const ciphertext = Buffer.from(aes.encrypt(plaintext));
|
||||
|
||||
const data = {
|
||||
ciphertext: ciphertext.toString("base64"),
|
||||
iv: iv.toString("base64"),
|
||||
salt: this.salt,
|
||||
hmac: hmac,
|
||||
canary: this.canary
|
||||
};
|
||||
|
||||
fs.writeFileSync(this.filename, JSON.stringify(data, null, 2));
|
||||
}
|
||||
|
||||
Config.prototype.get = async function(key) {
|
||||
await this.load();
|
||||
return this.values[key];
|
||||
};
|
||||
|
||||
Config.prototype.set = async function(key, value) {
|
||||
await this.load();
|
||||
this.values[key] = value;
|
||||
this.save();
|
||||
};
|
||||
|
||||
Config.prototype.lock = function() {
|
||||
this.salt = this.dkey = null;
|
||||
}
|
||||
|
||||
const config = new Config(resolve(os.homedir(), ".ethers-dist"));
|
||||
|
||||
module.exports = {
|
||||
get: function(key) {
|
||||
return config.get(key);
|
||||
},
|
||||
set: function(key, value) {
|
||||
config.set(key, value);
|
||||
},
|
||||
keys: function() {
|
||||
return config.keys();
|
||||
},
|
||||
lock: function() {
|
||||
config.lock();
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
|
||||
const { loadJson, resolve } = require("./utils");
|
||||
|
||||
const ROOT = resolve("packages");
|
||||
|
||||
const dirnames = fs.readdirSync(ROOT);
|
||||
|
||||
function loadPackage(dirname) {
|
||||
return loadJson(resolve("packages", dirname, "package.json"));
|
||||
}
|
||||
|
||||
function getOrdered(skipNobuild) {
|
||||
let packages = { };
|
||||
let filenames = { };
|
||||
|
||||
let addDeps = (name, depends) => {
|
||||
Object.keys(depends).forEach((dep) => {
|
||||
// Not a package we manage
|
||||
if (packages[dep] == null) { return; }
|
||||
deps[name][dep] = true;
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
let dirname = dirnames[i];
|
||||
let info = loadPackage(dirname);
|
||||
if (skipNobuild && info._ethers_nobuild) { continue; }
|
||||
packages[info.name] = info;
|
||||
filenames[info.name] = dirname;
|
||||
}
|
||||
|
||||
// Maps names to list of dependencies; { [ name:string]: Array<name: string> }
|
||||
let deps = { };
|
||||
let depGraph = { };
|
||||
|
||||
Object.keys(packages).forEach((name) => {
|
||||
let info = packages[name];
|
||||
deps[info.name] = { };
|
||||
addDeps(info.name, info.dependencies || { });
|
||||
addDeps(info.name, info.devDependencies || { });
|
||||
deps[info.name] = Object.keys(deps[info.name]);
|
||||
deps[info.name].sort();
|
||||
});
|
||||
|
||||
let ordered = [ ];
|
||||
let remaining = Object.keys(deps);
|
||||
|
||||
let isSatisfied = (name) => {
|
||||
for (let i = 0; i < deps[name].length; i++) {
|
||||
if (ordered.indexOf(deps[name][i]) === -1) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
while (remaining.length) {
|
||||
let bail = true;
|
||||
for (let i = 0; i < remaining.length; i++) {
|
||||
if (!isSatisfied(remaining[i])) { continue; }
|
||||
bail = false;
|
||||
ordered.push(remaining[i]);
|
||||
remaining.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bail) {
|
||||
throw new Error("Nothing processed; circular dependencies...");
|
||||
}
|
||||
}
|
||||
|
||||
return ordered.map((name) => filenames[name]);
|
||||
}
|
||||
|
||||
function sort(dirnames) {
|
||||
let ordered = getOrdered();
|
||||
dirnames.sort((a, b) => {
|
||||
let ai = ordered.indexOf(local.loadPackage(a).name);
|
||||
let bi = ordered.indexOf(local.loadPackage(b).name);
|
||||
if (ai === -1 || bi === -1) {
|
||||
throw new Error("unknown dirname - " + [a, b].join(", "));
|
||||
}
|
||||
return ai - bi;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
dirnames: dirnames,
|
||||
getOrdered: getOrdered,
|
||||
loadPackage: loadPackage,
|
||||
ROOT: ROOT,
|
||||
sort: sort
|
||||
}
|
186
admin/git.js
186
admin/git.js
@ -1,186 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const resolve = require("path").resolve;
|
||||
const spawn = require("child_process").spawn;
|
||||
|
||||
const semver = require("semver");
|
||||
|
||||
const { run } = require("./build");
|
||||
const { loadPackage } = require("./local");
|
||||
|
||||
function git(args) {
|
||||
return run("git", args);
|
||||
}
|
||||
|
||||
function getStatus(filename) {
|
||||
return git([ "status", "-s", resolve(__dirname, "..", filename) ]).then((result) => {
|
||||
result = result.trim();
|
||||
if (result === "") { return "unmodified"; }
|
||||
switch (result.substring(0, 2)) {
|
||||
case 'M ': return "modified";
|
||||
case 'A ': return "added";
|
||||
case 'D ': return "deleted";
|
||||
case 'R ': return "renamed";
|
||||
case 'C ': return "copied";
|
||||
case 'U ': return "updated";
|
||||
case '??': return "untracked";
|
||||
}
|
||||
console.log(result);
|
||||
return "unknown";
|
||||
});
|
||||
}
|
||||
|
||||
async function getChanges(latest) {
|
||||
let diff = await git(["diff", "--name-only", latest ]);
|
||||
|
||||
// Map dirname => { dist: [ ], src: [ ] }
|
||||
let changes = { "_": { filename: "_", dist: [], src: [] } };
|
||||
|
||||
diff.split("\n").forEach((line) => {
|
||||
// e.g. packages/constants/index.d.ts
|
||||
let comps = line.trim().split("/");
|
||||
|
||||
// Track non-packages as dist
|
||||
if (comps.length < 2 || comps[0] !== "packages") {
|
||||
let filename = comps.join("/").trim();
|
||||
if (filename === "") { return; }
|
||||
changes._.dist.push(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
let name = loadPackage(comps[1]).name;
|
||||
|
||||
let change = changes[name];
|
||||
if (!change) {
|
||||
change = { filename: comps[1], dist: [ ], src: [ ] }
|
||||
changes[name] = change;
|
||||
}
|
||||
|
||||
// Split changes into source changes (src.ts/) or dist changes (output of TypeScript)
|
||||
if (comps[2] === "src.ts") {
|
||||
change.src.push(comps.join("/"));
|
||||
} else {
|
||||
change.dist.push(comps.join("/"));
|
||||
}
|
||||
});
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
function getLatestTag() {
|
||||
let seq = Promise.resolve();
|
||||
|
||||
// @TODO: Pull
|
||||
if (false) {
|
||||
seq = seq.then(() => {
|
||||
console.log("Pulling remote changes...");
|
||||
return git([ "pull" ]);
|
||||
});
|
||||
}
|
||||
|
||||
seq = seq.then(() => {
|
||||
return git([ "tag" ]).then((tags) => {
|
||||
tags = tags.split("\n").filter(tag => (tag.match(/^v[0-9]+\.[0-9]+\.[0-9]+\-/)));
|
||||
tags.sort(semver.compare)
|
||||
return tags.pop();
|
||||
});
|
||||
});
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
function findChanges(latest) {
|
||||
let seq = Promise.resolve();
|
||||
|
||||
seq = seq.then(() => {
|
||||
return git(["diff", "--name-only", latest, "HEAD" ]).then((result) => {
|
||||
let filenames = { };
|
||||
result.split("\n").forEach((line) => {
|
||||
// e.g. packages/constants/index.d.ts
|
||||
let comps = line.trim().split("/");
|
||||
if (comps.length < 2) { return; }
|
||||
filenames[comps[1]] = true;
|
||||
});
|
||||
return Object.keys(filenames);
|
||||
});
|
||||
});
|
||||
|
||||
seq = seq.then((filenames) => {
|
||||
return filenames.map((filename) => {
|
||||
let name = packages[filename].name;
|
||||
return {
|
||||
filename: filename,
|
||||
name: name,
|
||||
localVersion: getLocalVersion(name),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
seq = seq.then((packages) => {
|
||||
let seq = Promise.resolve();
|
||||
packages.forEach((p) => {
|
||||
seq = seq.then(() => {
|
||||
return getNpmVersion(p.name).then((version) => {
|
||||
p.npmVersion = version;
|
||||
});
|
||||
});
|
||||
});
|
||||
return seq.then(() => packages);
|
||||
});
|
||||
return seq;
|
||||
}
|
||||
|
||||
async function getGitTag(filename) {
|
||||
let result = await git([ "log", "-n", "1", "--", filename ]);
|
||||
result = result.trim();
|
||||
if (!result) { return null; }
|
||||
result = result.match(/^commit\s+([0-9a-f]{40})\n/i);
|
||||
if (!result) { return null; }
|
||||
return result[1];
|
||||
}
|
||||
|
||||
async function getDiff(filename, tag, nameOnly) {
|
||||
if (tag == null) { tag = "HEAD"; }
|
||||
let cmd = [ "diff", "--name-only", tag, "--", filename ]
|
||||
if (!nameOnly) { cmd.splice(1, 1); }
|
||||
try {
|
||||
let result = await git(cmd);
|
||||
result = result.trim();
|
||||
if (result === "") { return [ ]; }
|
||||
return result.split("\n");
|
||||
} catch (error) {
|
||||
// This tag does not exist, so compare against beginning of time
|
||||
// This happens when there is a new history (like an orphan branch)
|
||||
if (error.stderr.trim().match(/^fatal: bad object/)) {
|
||||
console.log("Could not find history; showing all");
|
||||
let cmd = [ "rev-list", "--max-parents=0", "HEAD" ];
|
||||
let tag = await git(cmd);
|
||||
return getDiff(filename, tag.trim(), nameOnly);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function getUntracked(filename) {
|
||||
let cmd = [ "ls-files", "-o", "--exclude-standard"];
|
||||
if (filename) {
|
||||
cmd.push("--");
|
||||
cmd.push(filename);
|
||||
}
|
||||
let result = await git(cmd);
|
||||
result = result.trim();
|
||||
if (result === "") { return [ ]; }
|
||||
return result.split("\n");
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
findChanges: findChanges,
|
||||
getChanges: getChanges,
|
||||
getDiff: getDiff,
|
||||
getGitTag: getGitTag,
|
||||
getLatestTag: getLatestTag,
|
||||
getStatus: getStatus,
|
||||
getUntracked: getUntracked,
|
||||
run: git,
|
||||
}
|
162
admin/github.js
162
admin/github.js
@ -1,162 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const { resolve } = require("path");
|
||||
const zlib = require("zlib");
|
||||
|
||||
const { id } = require("../packages/hash");
|
||||
const { fetchJson } = require("../packages/web");
|
||||
|
||||
const CacheDir = resolve(__dirname, "../github-cache/");
|
||||
|
||||
function addResponse(result, response) {
|
||||
return { result, response };
|
||||
}
|
||||
|
||||
function loadFile(filename) {
|
||||
return JSON.parse(zlib.gunzipSync(fs.readFileSync(filename)).toString());
|
||||
//return JSON.parse(fs.readFileSync(filename).toString());
|
||||
}
|
||||
|
||||
// @TODO: atomic
|
||||
function saveFile(filename, content) {
|
||||
fs.writeFileSync(filename, zlib.gzipSync(JSON.stringify(content)));
|
||||
//fs.writeFileSync(filename, JSON.stringify(content));
|
||||
}
|
||||
|
||||
function mockFetchJson(url, body, headers) {
|
||||
return {
|
||||
result: null,
|
||||
response: {
|
||||
statusCode: 304
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function _fetchGitHub(user, password, fetchJson, url) {
|
||||
const result = [ ];
|
||||
while (true) {
|
||||
|
||||
const filename = resolve(CacheDir, id(url).substring(2, 14));
|
||||
|
||||
const headers = {
|
||||
"User-Agent": "ethers-io",
|
||||
};
|
||||
|
||||
let items = null;
|
||||
let link = null;
|
||||
try {
|
||||
const data = loadFile(filename);
|
||||
headers["if-none-match"] = data.etag;
|
||||
items = data.items;
|
||||
link = data.link;
|
||||
} catch (error) {
|
||||
if (error.code !== "ENOENT") { throw error; }
|
||||
}
|
||||
|
||||
const fetch = await fetchJson({
|
||||
url: url,
|
||||
user: user,
|
||||
password: password,
|
||||
headers: headers
|
||||
}, null, addResponse);
|
||||
|
||||
// Cached response is good; use it!
|
||||
if (fetch.response.statusCode !== 304) {
|
||||
items = fetch.result;
|
||||
if (fetch.response.headers) {
|
||||
link = (fetch.response.headers.link || null);
|
||||
}
|
||||
if (fetch.response.headers.etag){
|
||||
saveFile(filename, {
|
||||
timestamp: (new Date()).getTime(),
|
||||
url: url,
|
||||
link: link,
|
||||
etag: fetch.response.headers.etag,
|
||||
items: items,
|
||||
version: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
items.forEach((item) => { result.push(item)});
|
||||
|
||||
url = null;
|
||||
(link || "").split(",").forEach((item) => {
|
||||
if (item.indexOf('rel="next"') >= 0) {
|
||||
const match = item.match(/<([^>]*)>/);
|
||||
if (match) { url = match[1]; }
|
||||
}
|
||||
});
|
||||
|
||||
if (!url) { break; }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function fetchGitHub(user, password, url, cacheOnly) {
|
||||
if (cacheOnly) {
|
||||
return await _fetchGitHub("none", "none", mockFetchJson, url);
|
||||
}
|
||||
|
||||
const results = await _fetchGitHub(user, password, fetchJson, url);
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
async function _getIssues(user, password) {
|
||||
const cacheOnly = (user == null);
|
||||
|
||||
let issues = await fetchGitHub(user, password, "https:/\/api.github.com/repos/ethers-io/ethers.js/issues?state=all&per_page=100", cacheOnly)
|
||||
if (!cacheOnly) { console.log(`Found ${ issues.length } issues`); }
|
||||
const result = [ ];
|
||||
for (let i = 0; i < issues.length; i++) {
|
||||
const issue = issues[i];
|
||||
let comments = await fetchGitHub(user, password, issue.comments_url, cacheOnly);
|
||||
result.push({ issue, comments});
|
||||
if (!cacheOnly) { console.log(` Issue ${ issue.number }: ${ comments.length } comments`); }
|
||||
}
|
||||
result.sort((a, b) => (a.issue.number - b.issue.number));
|
||||
return result;
|
||||
}
|
||||
|
||||
function getIssues() {
|
||||
return _getIssues();
|
||||
}
|
||||
|
||||
function syncIssues(user, password) {
|
||||
return _getIssues(user, password);
|
||||
}
|
||||
|
||||
async function createRelease(user, password, tagName, title, body, prerelease, commit) {
|
||||
const payload = {
|
||||
tag_name: tagName,
|
||||
target_commitish: (commit || "master"),
|
||||
name: title,
|
||||
body: body,
|
||||
//draft: true,
|
||||
draft: false,
|
||||
prerelease: !!prerelease
|
||||
};
|
||||
|
||||
const headers = {
|
||||
"User-Agent": "ethers-io",
|
||||
};
|
||||
|
||||
const result = await fetchJson({
|
||||
url: "https://api.github.com/repos/ethers-io/ethers.js/releases",
|
||||
user: user,
|
||||
password: password,
|
||||
headers: headers
|
||||
}, JSON.stringify(payload));
|
||||
|
||||
|
||||
return result.html_url;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getIssues,
|
||||
syncIssues,
|
||||
createRelease,
|
||||
}
|
||||
|
401
admin/index.js
401
admin/index.js
@ -1,401 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const resolve = require("path").resolve;
|
||||
|
||||
const diff = require("diff");
|
||||
const semver = require("semver");
|
||||
|
||||
const { prompt } = require("../packages/cli");
|
||||
|
||||
const build = require("./build");
|
||||
const changelog = require("./changelog");
|
||||
const depgraph = require("./depgraph");
|
||||
const { colorify, colorifyStatus, log } = require("./log");
|
||||
const config = require("./config")
|
||||
const git = require("./git");
|
||||
const local = require("./local");
|
||||
const npm = require("./npm");
|
||||
const utils = require("./utils");
|
||||
|
||||
/*
|
||||
async function runChanged(dirnames, callback) {
|
||||
try {
|
||||
await callback(dirname, info, npmInfo);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.log(colorify("Aborting! " + error.message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (diff) {
|
||||
} else {
|
||||
*/
|
||||
|
||||
async function runDiff(dirnames) {
|
||||
// Default to all packages
|
||||
if (dirnames == null || dirnames.length === 0) { dirnames = local.dirnames; }
|
||||
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
let dirname = dirnames[i];
|
||||
|
||||
// Get local (update the tarballHash) and remote package.json
|
||||
let info = await local.loadPackage(dirname);
|
||||
let npmInfo = await npm.getPackageVersion(info.name);
|
||||
if (!npmInfo) { npmInfo = { gitHead: "HEAD", version: "NEW" }; }
|
||||
|
||||
let delta = await git.getDiff(resolve(__dirname, "../packages", dirname), npmInfo.gitHead);
|
||||
|
||||
if (delta.length === 0) { continue; }
|
||||
|
||||
// Bump the version if necessary
|
||||
if (info.version === npmInfo.version) {
|
||||
info.version = semver.inc(info.version, "patch");
|
||||
}
|
||||
|
||||
console.log(colorify("<bold:Package>: ") + info.name);
|
||||
console.log(colorify(" <green:Git Head Changed:> (run update to bump version)"));
|
||||
console.log(" " + npmInfo.gitHead)
|
||||
console.log(" " + npmInfo.version + colorify(" => ", "bold") + info.version)
|
||||
|
||||
console.log(colorify(" Diff", "bold"));
|
||||
delta.forEach((line) => {
|
||||
let color = "blue";
|
||||
switch (line.substring(0, 1)) {
|
||||
case '+':
|
||||
color = "green";
|
||||
break;
|
||||
case '-':
|
||||
color = "red";
|
||||
break;
|
||||
case ' ':
|
||||
color = "normal";
|
||||
break;
|
||||
}
|
||||
console.log(" " + colorify(line, color));
|
||||
});
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
async function updateChangelog() {
|
||||
let filename = resolve(local.ROOT, "../CHANGELOG.md");
|
||||
|
||||
let lastVersion = await git.getLatestTag();
|
||||
let newVersion = "v" + local.getVersion("ethers");
|
||||
|
||||
let current = fs.readFileSync(filename).toString();
|
||||
let log = await changelog.generate();
|
||||
if (log === current) { return; }
|
||||
|
||||
let changes = diff.createTwoFilesPatch("CHANGELOG-old.md", "CHANGELOG.md", current, log, lastVersion, newVersion);
|
||||
console.log(changes);
|
||||
|
||||
try {
|
||||
let response = await prompt.getChoice(colorify("Accept changes?", "bold"), "yn", "n");
|
||||
if (response === "n") { throw new Error("Not changing."); }
|
||||
} catch (error) {
|
||||
console.log("Abort: " + error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.writeFileSync(filename, log);
|
||||
}
|
||||
|
||||
// Updates the dependency-graph (tsconfig.project.json) so the build order is correct
|
||||
async function runUpdateDepgraph() {
|
||||
log(`<bold:Updating dependency-graph build order (tsconfig.project.json)...>`);
|
||||
let ordered = depgraph.getOrdered();
|
||||
|
||||
let path = resolve(local.ROOT, "../tsconfig.project.json")
|
||||
|
||||
let projectConfig = local.loadJson(path);
|
||||
projectConfig.references = ordered.map((name) => ({ path: ("./packages/" + name) }));
|
||||
local.saveJson(path, projectConfig);
|
||||
}
|
||||
|
||||
async function runUpdate(dirnames) {
|
||||
|
||||
// Check for untracked files...
|
||||
let untracked = [ ];
|
||||
if (dirnames == null || dirnames.length === 0) {
|
||||
dirnames = local.dirnames;
|
||||
let filenames = await git.getUntracked(resolve(__dirname, ".."));
|
||||
for (let i = 0; i < filenames.length; i++) {
|
||||
untracked.push(filenames[i]);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
let filenames = await git.getUntracked(resolve(local.ROOT, dirnames[i]));
|
||||
for (let j = 0; j < filenames.length; j++) {
|
||||
untracked.push(filenames[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Untracked files! Abort.
|
||||
if (untracked.length) {
|
||||
log("<bold:Untracked Files:>");
|
||||
untracked.forEach((filename) => {
|
||||
console.log(" " + filename);
|
||||
});
|
||||
log("<red:Aborting.>");
|
||||
return;
|
||||
}
|
||||
|
||||
log(`<bold:Run TypeScript build...>`);
|
||||
await build.runBuild()
|
||||
|
||||
log("");
|
||||
|
||||
// @TODO: Root
|
||||
|
||||
// Update all the package.json and _version.ts
|
||||
let progress = prompt.getProgressBar(colorify("Updating versions", "bold"));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
|
||||
let dirname = dirnames[i];
|
||||
let path = resolve(__dirname, "../packages/", dirname);
|
||||
|
||||
// Get local package.json (update the tarballHash)
|
||||
let info = await local.updatePackage(dirname);
|
||||
|
||||
// Get the remote package.json (or sub in a placeholder for new pacakges)
|
||||
let npmInfo = await npm.getPackageVersion(info.name);
|
||||
if (!npmInfo) { npmInfo = { version: "NEW" }; }
|
||||
|
||||
if (info.tarballHash === npmInfo.tarballHash) { continue; }
|
||||
|
||||
// Bump the version if necessary
|
||||
if (info.version === npmInfo.version) {
|
||||
let newVersion = semver.inc(info.version, "patch");
|
||||
|
||||
// Write out the _version.ts
|
||||
if (!info._ethers_skipPrepare) {
|
||||
let code = "export const version = " + JSON.stringify(newVersion) + ";\n";
|
||||
fs.writeFileSync(resolve(path, "src.ts/_version.ts"), code);
|
||||
}
|
||||
|
||||
// Update the package.json (we do this after _version, so if we fail,
|
||||
// this remains old; which is what triggers the version bump)
|
||||
info = await local.updatePackage(dirname, { version: newVersion });
|
||||
}
|
||||
}
|
||||
progress(1);
|
||||
|
||||
// Build the TypeScript sources
|
||||
log("<bold:Runing TypeScript build...>");
|
||||
try {
|
||||
await build.runTsc();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
log("<red:Aborting.>");
|
||||
return;
|
||||
}
|
||||
|
||||
// Run the dist
|
||||
// @TODO:
|
||||
|
||||
// Update the tarball hash now that _version and package.json may have changed.
|
||||
progress = prompt.getProgressBar(colorify("Updating tarballHash", "bold"));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
await local.updatePackage(dirnames[i]);
|
||||
}
|
||||
progress(1);
|
||||
|
||||
// Show the changed files (compared to npm)
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
let dirname = dirnames[i];
|
||||
|
||||
// Get local package.json
|
||||
let info = await local.loadPackage(dirname);
|
||||
let path = resolve(__dirname, "../packages/", dirname);
|
||||
|
||||
// Get the remote package.json (or sub in a placeholder for new pacakges)
|
||||
let npmInfo = await npm.getPackageVersion(info.name);
|
||||
if (!npmInfo) { npmInfo = { version: "NEW" }; }
|
||||
|
||||
// No change
|
||||
if (info.tarballHash === npmInfo.tarballHash) { continue; }
|
||||
|
||||
let gitHead = await git.getGitTag(path);
|
||||
|
||||
log(`<bold:Package>: ${info.name}`);
|
||||
log(` <green:Tarball Changed:> (bumping version)`);
|
||||
log(` ${npmInfo.version} => ${info.version}`)
|
||||
log(` <blue:Changed:>`);
|
||||
let filenames = await git.getDiff(resolve(__dirname, "../packages", dirname), npmInfo.gitHead, true);
|
||||
filenames.forEach((filename) => {
|
||||
let short = filename.split("/").slice(1).join("/");
|
||||
if (short.indexOf("/src.ts/") >= 0) {
|
||||
log(` <bold:${short}>`);
|
||||
} else {
|
||||
log(` ${short}`);
|
||||
}
|
||||
});
|
||||
log("");
|
||||
}
|
||||
|
||||
// @TODO: Changelog
|
||||
await updateChangelog();
|
||||
}
|
||||
|
||||
async function runAdd(type, names) {
|
||||
let latest = await git.getLatestTag();
|
||||
console.log("");
|
||||
console.log(colorify("<bold:Latest Published>: ") + latest);
|
||||
console.log("");
|
||||
|
||||
let changes = await git.getChanges("HEAD");
|
||||
|
||||
if (!names || names.length === 0) {
|
||||
names = Object.keys(changes);
|
||||
}
|
||||
|
||||
let filenames = [ ];
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
let name = names[i];
|
||||
let change = changes[name] || changes[(packages[name] || {}).name];
|
||||
if (!change) { return; }
|
||||
change[type].forEach((filename) => {
|
||||
filenames.push(filename);
|
||||
});
|
||||
}
|
||||
|
||||
if (filenames.length === 0) {
|
||||
console.log(colorify("<bold:Nothing to add.>"));
|
||||
console.log("");
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < filenames.length; i++) {
|
||||
let filename = filenames[i];
|
||||
let status = await git.getStatus(filename);
|
||||
console.log(" " + colorifyStatus(status) + ": " + utils.repeat(" ", 10 - status.length) + filename);
|
||||
}
|
||||
|
||||
console.log("");
|
||||
|
||||
try {
|
||||
let response = await prompt.getChoice(colorify("Add these files?", "bold"), "yn", "n");
|
||||
if (response === "n") { throw new Error("Not adding."); }
|
||||
} catch (error) {
|
||||
console.log("Abort: " + error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
let params = filenames.map((f) => f); //resolve(ROOT, f));
|
||||
params.unshift("--");
|
||||
params.unshift("add");
|
||||
|
||||
console.log("git " + params.join(" "));
|
||||
|
||||
try {
|
||||
await git.run(params);
|
||||
} catch (error) {
|
||||
console.log("Error: (status: " + error.code + ")");
|
||||
console.log(" " + error.stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Added.");
|
||||
}
|
||||
|
||||
function runDist() {
|
||||
// Run npm dist
|
||||
// Generate changelog
|
||||
// run status to update all the package
|
||||
// add dist files?
|
||||
}
|
||||
|
||||
async function runPublish(dirnames) {
|
||||
|
||||
// @TODO: Make sure there are no staged files
|
||||
|
||||
// @TODO: Make sure the repo has been pushed
|
||||
|
||||
// @TODO: Run the publish in the correct order
|
||||
|
||||
// Get the authentication token from our encrypted store
|
||||
let token = await config.get("token");
|
||||
token = token.trim().split("=");
|
||||
|
||||
let options = {
|
||||
npmVersion: "ethers-dist@0.0.0",
|
||||
tag: "next"
|
||||
};
|
||||
|
||||
// Set the authentication token
|
||||
options[token[0]] = token[1];
|
||||
|
||||
if (dirnames == null || dirnames.length === 0) { dirnames = local.dirnames; }
|
||||
depgraph.sort(dirnames);
|
||||
|
||||
await runChanged(dirnames, async (dirname, info, npmInfo) => {
|
||||
console.log(colorify("<bold:Publishing:> ") + info.name + "...")
|
||||
console.log(colorify(" Version: ", "blue") + npmInfo.version + colorify(" => ", "bold") + info.version);
|
||||
|
||||
let success = await npm.publish(dirname, options);
|
||||
if (!success) {
|
||||
console.log(colorify(" <red:FAILED! Aborting.>"));
|
||||
throw new Error("");
|
||||
}
|
||||
console.log(colorify(" <green:Done.>"));
|
||||
});
|
||||
}
|
||||
|
||||
async function runTest() {
|
||||
let r = await git([ "tag", "--porcelain", "-a", "-m", "Title of Release\n\nHello\n-----\n\nTesting 4 **bold** #1\nHello World", "test6", "HEAD" ]);
|
||||
console.log(r);
|
||||
try {
|
||||
r = await git([ "push", "--tags" ])
|
||||
} catch(e) { console.log(e); }
|
||||
console.log(r);
|
||||
}
|
||||
|
||||
(function() {
|
||||
let args = process.argv.slice(2);
|
||||
switch (args[0]) {
|
||||
|
||||
// Compare published to current stage
|
||||
case "diff":
|
||||
return runDiff(args.slice(1));
|
||||
|
||||
// Add unchecked-in source files
|
||||
case "add-source":
|
||||
return runAdd("src", args.slice(1));
|
||||
|
||||
// Update all package.json. the changelog and dist files
|
||||
case "update":
|
||||
return runUpdate(args.slice(1));
|
||||
|
||||
// Update dependency graph (./tsconfig-project.json)
|
||||
case "update-depgraph":
|
||||
return runUpdateDepgraph();
|
||||
|
||||
// Add unchecked-in dist files
|
||||
case "add-dist":
|
||||
return runAdd("dist", args.slice(1));
|
||||
|
||||
|
||||
// Add unchecked-in source files
|
||||
case "changelog":
|
||||
return updateChangelog();
|
||||
|
||||
// Add unchecked-in source files
|
||||
case "publish":
|
||||
return runPublish(args.slice(1));
|
||||
|
||||
case "test":
|
||||
return runTest();
|
||||
}
|
||||
})();
|
101
admin/local.js
101
admin/local.js
@ -1,101 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const packlist = require("npm-packlist");
|
||||
const tar = require("tar");
|
||||
|
||||
const keccak256 = (function() {
|
||||
try {
|
||||
return require("../packages/keccak256").keccak256;
|
||||
} catch (error) {
|
||||
console.log("Cannot load Keccak256 (maybe not built yet? Not really a problem for most things)");
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
|
||||
const { dirnames, loadPackage, ROOT } = require("./depgraph");
|
||||
const { resolve, saveJson } = require("./utils");
|
||||
|
||||
function sorted(obj) {
|
||||
if (Array.isArray(obj)) { return obj.map(sorted); }
|
||||
if (obj == null || typeof(obj) !== "object") { return obj; }
|
||||
|
||||
const keys = Object.keys(obj);
|
||||
keys.sort();
|
||||
|
||||
const result = { };
|
||||
keys.forEach((key) => { result[key] = sorted(obj[key]); });
|
||||
return result;
|
||||
}
|
||||
|
||||
function savePackage(dirname, info) {
|
||||
return saveJson(resolve(ROOT, dirname, "package.json"), sorted(info));
|
||||
}
|
||||
|
||||
async function createTarball(dirname) {
|
||||
let base = resolve(ROOT, dirname);
|
||||
|
||||
// From NPM publish, create the packed version
|
||||
let files = await packlist({ path: base });
|
||||
files = files.map((f) => ("./" + f));
|
||||
|
||||
let options = {
|
||||
cwd: base,
|
||||
prefix: 'package/',
|
||||
portable: true,
|
||||
sync: true,
|
||||
// Provide a specific date in the 1980s for the benefit of zip,
|
||||
// which is confounded by files dated at the Unix epoch 0.
|
||||
mtime: new Date('1985-10-26T08:15:00.000Z'),
|
||||
gzip: true
|
||||
};
|
||||
|
||||
// Take the hash of the package sans
|
||||
return tar.create(options, files).read();
|
||||
}
|
||||
|
||||
async function updatePackage(dirname, values) {
|
||||
let info = loadPackage(dirname);
|
||||
|
||||
if (values) {
|
||||
for (let key in values) {
|
||||
info[key] = values[key];
|
||||
}
|
||||
}
|
||||
/*
|
||||
["dependencies", "devDependencies"].forEach((key) => {
|
||||
let deps = info[key] || [];
|
||||
for (let name in deps) {
|
||||
if (name.substring(0, "@ethersproject".length) === "@ethersproject" || name === "ethers") {
|
||||
deps[name] = ">5.0.0-beta.0";
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
//if (dirname !== "ethers") {
|
||||
// delete info.publishConfig.tag;
|
||||
//}
|
||||
|
||||
// Create a normalized version sans tarballHash to compute the tarballHash
|
||||
delete info.tarballHash;
|
||||
savePackage(dirname, info);
|
||||
|
||||
// Compute the tarballHash
|
||||
let tarball = await createTarball(dirname);
|
||||
info.tarballHash = keccak256(tarball);
|
||||
|
||||
// Save the updated package.json to disk
|
||||
savePackage(dirname, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ROOT: ROOT,
|
||||
createTarball: createTarball,
|
||||
dirnames: dirnames,
|
||||
getVersion: function(dirname) { return ((loadPackage(dirname) || {}).version || null); },
|
||||
loadPackage: loadPackage,
|
||||
savePackage: savePackage,
|
||||
updatePackage: updatePackage,
|
||||
}
|
53
admin/log.js
53
admin/log.js
@ -1,53 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
function getColor(color) {
|
||||
if (!color || color === "normal") { return "\x1b[0m"; }
|
||||
return "\x1b[1m" + ({
|
||||
blue: "\x1b[34m",
|
||||
cyan: "\x1b[36m",
|
||||
green: "\x1b[32m",
|
||||
magenta: "\x1b[35m",
|
||||
red: "\x1b[31m",
|
||||
yellow: "\x1b[33m",
|
||||
bold: ""
|
||||
})[color];
|
||||
}
|
||||
|
||||
// See: https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
|
||||
let disableColor = !(process.stdout.isTTY);
|
||||
function colorify(message, color) {
|
||||
if (color) {
|
||||
if (disableColor) { return message; }
|
||||
return getColor(color) + message + getColor();
|
||||
}
|
||||
|
||||
return message.replace(/<([^:]*):((?:[^<>\\]|\\.)*)>/g, (all, color, message) => {
|
||||
message = message.replace("\\>", ">");
|
||||
if (disableColor) { return message; }
|
||||
return getColor(color) + message + getColor();
|
||||
});
|
||||
}
|
||||
|
||||
function colorifyStatus(status) {
|
||||
switch (status) {
|
||||
case "modified": return colorify("<blue:" + status + ">");
|
||||
case "added": return colorify("<green:" + status + ">");
|
||||
case "deleted": return colorify("<red:" + status + ">");
|
||||
case "unmodified": return colorify("<magenta:" + status + ">");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
function log(message, color) {
|
||||
if (color) {
|
||||
console.log(colorify(message, color));
|
||||
} else {
|
||||
console.log(colorify(message));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
colorify: colorify,
|
||||
colorifyStatus: colorifyStatus,
|
||||
log: log
|
||||
}
|
104
admin/npm.js
104
admin/npm.js
@ -1,104 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const resolve = require("path").resolve;
|
||||
|
||||
const npmpub = require("libnpmpublish");
|
||||
const semver = require("semver");
|
||||
|
||||
const local = require("./local");
|
||||
|
||||
const keccak256 = require("../packages/keccak256").keccak256;
|
||||
const fetchJson = require("../packages/web").fetchJson;
|
||||
const { prompt } = require("../packages/cli");
|
||||
|
||||
const colorify = require("./log").colorify;
|
||||
const git = require("./git");
|
||||
|
||||
|
||||
let cache = { };
|
||||
|
||||
async function getPackage(name) {
|
||||
if (cache[name]) { return cache[name]; }
|
||||
|
||||
return fetchJson("http:/" + "/registry.npmjs.org/" + name).then((result) => {
|
||||
cache[name] = result;
|
||||
return result;
|
||||
}, (error) => {
|
||||
if (error.status === 404) {
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
async function getVersion(name) {
|
||||
return getPackage(name).then((result) => {
|
||||
if (!result) { return null; }
|
||||
let versions = Object.keys(result.versions);
|
||||
versions.sort(semver.compare)
|
||||
return versions.pop();
|
||||
});
|
||||
}
|
||||
|
||||
async function getPackageVersion(name, version) {
|
||||
let info = await getPackage(name)
|
||||
if (!info) { return null; }
|
||||
|
||||
if (version == null) {
|
||||
let versions = Object.keys(info.versions);
|
||||
versions.sort(semver.compare);
|
||||
version = versions.pop();
|
||||
}
|
||||
|
||||
return info.versions[version] || null;
|
||||
}
|
||||
|
||||
async function getTarballHash(name, version) {
|
||||
let info = await getPackageVersion(name, version);
|
||||
return (info || {}).tarballHash;
|
||||
}
|
||||
|
||||
async function _publish(info, tarball, options) {
|
||||
try {
|
||||
let result = await npmpub.publish(info, tarball, options);
|
||||
return result;
|
||||
} catch (error) {
|
||||
|
||||
// We need an OTP
|
||||
if (error.code === "EOTP") {
|
||||
try {
|
||||
let otp = await prompt.getMessage(colorify("Enter OTP: ", "bold"));
|
||||
options.otp = otp.replace(" ", "");
|
||||
} catch (error) {
|
||||
|
||||
// CTRL-C
|
||||
if (error.message === "cancelled") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Something unexpected...
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Retry with the new OTP
|
||||
return _publish(info, tarball, options);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function publish(dirname, options) {
|
||||
let info = local.loadPackage(dirname);
|
||||
info.gitHead = await git.getGitTag(resolve(__dirname, "../packages/", dirname));
|
||||
if (info.gitHead == null) { throw new Error("no git tag found - " + dirname); }
|
||||
let tarball = await local.createTarball(dirname);
|
||||
return _publish(info, tarball, options);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getPackage: getPackage,
|
||||
getPackageVersion: getPackageVersion,
|
||||
getTarballHash: getTarballHash,
|
||||
getVersion: getVersion,
|
||||
publish: publish,
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
{
|
||||
"name": "DevelopmentChain",
|
||||
"engine": {
|
||||
"instantSeal": null
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"accountStartNonce": "0x0",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x11",
|
||||
"registrar" : "0x0000000000000000000000000000000000001337",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip140Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"wasmActivationTransition": "0x0"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"generic": "0x0"
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x7A1200"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
|
||||
"0x7454a8f5a7c7555d79b172c89d20e1f4e4cc226c": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
{"id":"24d70b97-fff9-d322-e760-4b8cc2e21751","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"45d392cd16dbbd5c0f5b2d145c112da9"},"ciphertext":"b001ccd09fc5431dc055975b58ee61f86e85529245506c04182c902716e750e5","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"028594da27a0e864105f33b912e5dc6ce7c75ecd13c81bfc158fe963d30c93bb"},"mac":"374bf2e9144b74b889708abc19e9ebc164f90bc27e83fd9f01da4571a9f81a70"},"address":"7454a8f5a7c7555d79b172c89d20e1f4e4cc226c","name":"","meta":"{}"}
|
@ -1,64 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const _resolve = require("path").resolve;
|
||||
|
||||
function repeat(chr, length) {
|
||||
let result = chr;
|
||||
while (result.length < length) { result += chr; }
|
||||
return result;
|
||||
}
|
||||
|
||||
function zpad(value) {
|
||||
value = String(value);
|
||||
while (value.length < 2) { value = "0" + value; }
|
||||
return value;
|
||||
}
|
||||
|
||||
function getDate(date) {
|
||||
return [
|
||||
date.getFullYear(),
|
||||
zpad(date.getMonth() + 1),
|
||||
zpad(date.getDate())
|
||||
].join("-");
|
||||
}
|
||||
|
||||
function getDateTime(date) {
|
||||
return getDate(date) + " " + [
|
||||
zpad(date.getHours()) ,
|
||||
zpad(date.getMinutes() + 1)
|
||||
].join(":");
|
||||
}
|
||||
|
||||
function today() {
|
||||
return getDate(new Date());
|
||||
}
|
||||
|
||||
function loadJson(filename) {
|
||||
return JSON.parse(fs.readFileSync(filename).toString());
|
||||
}
|
||||
|
||||
// @TODO: atomic write
|
||||
function saveJson(filename, json) {
|
||||
fs.writeFileSync(filename, JSON.stringify(json, null, 2) + "\n");
|
||||
}
|
||||
|
||||
function resolve(...args) {
|
||||
args = args.slice();
|
||||
args.unshift("..");
|
||||
args.unshift(__dirname);
|
||||
return _resolve.apply(null, args);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolve: resolve,
|
||||
|
||||
loadJson: loadJson,
|
||||
saveJson: saveJson,
|
||||
|
||||
repeat: repeat,
|
||||
|
||||
today: today,
|
||||
getDate: getDate,
|
||||
getDateTime: getDateTime
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "independent"
|
||||
}
|
Loading…
Reference in New Issue
Block a user