Remvoed dead files.

This commit is contained in:
Richard Moore 2020-12-08 01:22:09 -05:00
parent 5cb418cf7d
commit 70c2b1b300
No known key found for this signature in database
GPG Key ID: 665176BE8E9DC651
24 changed files with 0 additions and 2512 deletions

@ -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

@ -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(">", "&gt;") }>`);
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);
}
})();

@ -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
}

@ -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,
}

@ -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,
}

@ -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();
}
})();

@ -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,
}

@ -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
}

@ -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"
}