@agoric/solo 0.10.4-dev-488dec7.0.488dec7 → 0.10.4-dev-b85a94d.0.b85a94d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/solo",
3
- "version": "0.10.4-dev-488dec7.0.488dec7",
3
+ "version": "0.10.4-dev-b85a94d.0.b85a94d",
4
4
  "description": "Agoric's Solo vat runner",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,20 +22,20 @@
22
22
  "author": "Agoric",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@agoric/access-token": "0.4.22-dev-488dec7.0.488dec7",
26
- "@agoric/cache": "0.3.3-dev-488dec7.0.488dec7",
27
- "@agoric/cosmic-proto": "0.4.1-dev-488dec7.0.488dec7",
28
- "@agoric/cosmic-swingset": "0.41.4-dev-488dec7.0.488dec7",
29
- "@agoric/internal": "0.3.3-dev-488dec7.0.488dec7",
30
- "@agoric/notifier": "0.6.3-dev-488dec7.0.488dec7",
31
- "@agoric/spawner": "0.6.9-dev-488dec7.0.488dec7",
32
- "@agoric/store": "0.9.3-dev-488dec7.0.488dec7",
33
- "@agoric/swing-store": "0.9.2-dev-488dec7.0.488dec7",
34
- "@agoric/swingset-vat": "0.32.3-dev-488dec7.0.488dec7",
35
- "@agoric/telemetry": "0.6.3-dev-488dec7.0.488dec7",
36
- "@agoric/time": "0.3.3-dev-488dec7.0.488dec7",
37
- "@agoric/vats": "0.15.2-dev-488dec7.0.488dec7",
38
- "@agoric/wallet": "0.18.4-dev-488dec7.0.488dec7",
25
+ "@agoric/access-token": "0.4.22-dev-b85a94d.0.b85a94d",
26
+ "@agoric/cache": "0.3.3-dev-b85a94d.0.b85a94d",
27
+ "@agoric/cosmic-proto": "0.4.1-dev-b85a94d.0.b85a94d",
28
+ "@agoric/cosmic-swingset": "0.41.4-dev-b85a94d.0.b85a94d",
29
+ "@agoric/internal": "0.3.3-dev-b85a94d.0.b85a94d",
30
+ "@agoric/notifier": "0.6.3-dev-b85a94d.0.b85a94d",
31
+ "@agoric/spawner": "0.6.9-dev-b85a94d.0.b85a94d",
32
+ "@agoric/store": "0.9.3-dev-b85a94d.0.b85a94d",
33
+ "@agoric/swing-store": "0.9.2-dev-b85a94d.0.b85a94d",
34
+ "@agoric/swingset-vat": "0.32.3-dev-b85a94d.0.b85a94d",
35
+ "@agoric/telemetry": "0.6.3-dev-b85a94d.0.b85a94d",
36
+ "@agoric/time": "0.3.3-dev-b85a94d.0.b85a94d",
37
+ "@agoric/vats": "0.15.2-dev-b85a94d.0.b85a94d",
38
+ "@agoric/wallet": "0.18.4-dev-b85a94d.0.b85a94d",
39
39
  "@endo/base64": "^1.0.12",
40
40
  "@endo/captp": "^4.4.8",
41
41
  "@endo/errors": "^1.2.13",
@@ -48,14 +48,12 @@
48
48
  "express": "^5.0.1",
49
49
  "http-proxy-middleware": "^2.0.6",
50
50
  "import-meta-resolve": "^4.1.0",
51
- "minimist": "^1.2.0",
52
51
  "morgan": "^1.10.0",
53
- "temp": "^0.9.1",
54
52
  "tmp": "^0.2.1",
55
53
  "ws": "^7.2.0"
56
54
  },
57
55
  "devDependencies": {
58
- "@agoric/ertp": "0.16.3-dev-488dec7.0.488dec7",
56
+ "@agoric/ertp": "0.16.3-dev-b85a94d.0.b85a94d",
59
57
  "@endo/bundle-source": "^4.1.2",
60
58
  "ava": "^7.0.0",
61
59
  "c8": "^10.1.3"
@@ -78,5 +76,5 @@
78
76
  "typeCoverage": {
79
77
  "atLeast": 74.43
80
78
  },
81
- "gitHead": "488dec73a49f5a4fd66eea6521638ce5ba11dd2f"
79
+ "gitHead": "b85a94d36a78e1fac36766d1cb9649c5db9e869c"
82
80
  }
@@ -2,9 +2,10 @@
2
2
  /* global clearTimeout setTimeout */
3
3
  import path from 'node:path';
4
4
  import fs from 'node:fs';
5
+ import { mkdtemp, writeFile, unlink } from 'node:fs/promises';
6
+ import { tmpdir } from 'node:os';
5
7
  import url from 'node:url';
6
8
  import { execFile } from 'node:child_process';
7
- import { open as tempOpen } from 'temp';
8
9
 
9
10
  import WebSocket from 'ws';
10
11
 
@@ -71,35 +72,28 @@ const randomizeDelay = delay =>
71
72
  Math.ceil(delay + delay * RANDOM_SCALE * Math.random());
72
73
 
73
74
  const makeTempFile = async (prefix, contents) => {
74
- const tmpInfo = await new Promise((resolve, reject) => {
75
- tempOpen({ prefix }, (err, info) => {
76
- if (err) {
77
- return reject(err);
78
- }
79
- return resolve(info);
80
- });
81
- });
75
+ await null;
82
76
 
83
- try {
84
- await new Promise((resolve, reject) => {
85
- fs.write(tmpInfo.fd, contents, err => {
86
- if (err) {
87
- return reject(err);
88
- }
89
- return resolve();
90
- });
91
- });
92
- } finally {
93
- await new Promise((resolve, reject) => {
94
- fs.close(tmpInfo.fd, e => {
95
- if (e) {
96
- return reject(e);
97
- }
98
- return resolve();
99
- });
100
- });
101
- }
102
- return tmpInfo;
77
+ // Create temporary directory with Node native fs.mkdtemp
78
+ const tempDir = await mkdtemp(path.join(tmpdir(), prefix));
79
+ const tempPath = path.join(tempDir, 'tempfile');
80
+
81
+ // Write contents to file
82
+ await writeFile(tempPath, contents);
83
+
84
+ return {
85
+ path: tempPath,
86
+ async cleanup() {
87
+ await null;
88
+
89
+ try {
90
+ await unlink(tempPath);
91
+ await fs.promises.rmdir(tempDir);
92
+ } catch (err) {
93
+ // Ignore cleanup errors
94
+ }
95
+ },
96
+ };
103
97
  };
104
98
 
105
99
  export async function connectToChain(
@@ -717,7 +711,7 @@ ${chainID} chain does not yet know of address ${clientAddr}${adviseEgress(
717
711
  }
718
712
  };
719
713
 
720
- await tryBody().finally(() => tmpInfo && fs.promises.unlink(tmpInfo.path));
714
+ await tryBody().finally(() => tmpInfo && tmpInfo.cleanup());
721
715
  };
722
716
 
723
717
  /**
package/src/main.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import parseArgs from 'minimist';
3
+ import { parseArgs } from 'node:util';
4
4
  import process from 'node:process';
5
5
  import { spawnSync } from 'node:child_process';
6
6
  import { assert } from '@endo/errors';
@@ -23,6 +23,41 @@ const DEFAULT_EGRESSES = 'cosmos';
23
23
  const AG_SOLO_BASEDIR =
24
24
  process.env.AG_SOLO_BASEDIR && path.resolve(process.env.AG_SOLO_BASEDIR);
25
25
 
26
+ /**
27
+ * @param {string | boolean | (string | boolean)[] | undefined} value
28
+ * @param {string} defaultValue
29
+ */
30
+ const stringOption = (value, defaultValue) =>
31
+ typeof value === 'string' ? value : defaultValue;
32
+
33
+ /** @param {string | boolean | (string | boolean)[] | undefined} value */
34
+ const optionalStringOption = value =>
35
+ typeof value === 'string' ? value : undefined;
36
+
37
+ /**
38
+ * @param {string | boolean | (string | boolean)[] | undefined} value
39
+ * @param {boolean} defaultValue
40
+ */
41
+ const booleanOption = (value, defaultValue) =>
42
+ typeof value === 'boolean' ? value : defaultValue;
43
+
44
+ const parseTopLevelArgs = rawArgv => {
45
+ const commandIndex = rawArgv.findIndex(arg => !arg.startsWith('-'));
46
+ const optionArgs =
47
+ commandIndex < 0 ? rawArgv : rawArgv.slice(0, commandIndex);
48
+ const commandArgs = commandIndex < 0 ? [] : rawArgv.slice(commandIndex);
49
+ const { values: opts } = parseArgs({
50
+ args: optionArgs,
51
+ options: {
52
+ help: { type: 'boolean' },
53
+ version: { type: 'boolean' },
54
+ },
55
+ allowPositionals: false,
56
+ strict: false,
57
+ });
58
+ return { opts, argv: commandArgs };
59
+ };
60
+
26
61
  function insistIsBasedir() {
27
62
  if (AG_SOLO_BASEDIR) {
28
63
  process.chdir(AG_SOLO_BASEDIR);
@@ -39,10 +74,7 @@ function insistIsBasedir() {
39
74
 
40
75
  export default async function solo(progname, rawArgv) {
41
76
  log.debug('solo', rawArgv);
42
- const { _: argv, ...opts } = parseArgs(rawArgv, {
43
- stopEarly: true,
44
- boolean: ['help', 'version'],
45
- });
77
+ const { opts, argv } = parseTopLevelArgs(rawArgv);
46
78
 
47
79
  if (opts.help) {
48
80
  process.stdout.write(`\
@@ -57,7 +89,15 @@ start
57
89
  await null;
58
90
  switch (argv[0]) {
59
91
  case 'setup': {
60
- const { netconfig } = parseArgs(argv.slice(1));
92
+ const { values: setupOpts } = parseArgs({
93
+ args: argv.slice(1),
94
+ options: {
95
+ netconfig: { type: 'string' },
96
+ },
97
+ allowPositionals: true,
98
+ strict: false,
99
+ });
100
+ const netconfig = optionalStringOption(setupOpts.netconfig);
61
101
  if (!AG_SOLO_BASEDIR) {
62
102
  console.error(`setup: you must set $AG_SOLO_BASEDIR`);
63
103
  return 1;
@@ -71,16 +111,23 @@ start
71
111
  break;
72
112
  }
73
113
  case 'init': {
74
- const { _: subArgs, ...subOpts } = parseArgs(argv.slice(1), {
75
- default: {
76
- webport: '8000',
77
- webhost: '127.0.0.1',
78
- egresses: DEFAULT_EGRESSES,
79
- defaultManagerType: process.env.SWINGSET_WORKER_TYPE || 'xs-worker',
114
+ const { values: subOpts, positionals: subArgs } = parseArgs({
115
+ args: argv.slice(1),
116
+ options: {
117
+ webport: { type: 'string', default: '8000' },
118
+ webhost: { type: 'string', default: '127.0.0.1' },
119
+ egresses: { type: 'string', default: DEFAULT_EGRESSES },
120
+ defaultManagerType: {
121
+ type: 'string',
122
+ default: process.env.SWINGSET_WORKER_TYPE || 'xs-worker',
123
+ },
80
124
  },
125
+ allowPositionals: true,
126
+ strict: false,
81
127
  });
82
- const webport = Number(subOpts.webport);
83
- const { webhost, egresses } = subOpts;
128
+ const webport = Number(stringOption(subOpts.webport, '8000'));
129
+ const webhost = stringOption(subOpts.webhost, '127.0.0.1');
130
+ const egresses = stringOption(subOpts.egresses, DEFAULT_EGRESSES);
84
131
  const basedir = subArgs[0] || AG_SOLO_BASEDIR;
85
132
  const subdir = subArgs[1];
86
133
  assert(basedir !== undefined, 'you must provide a BASEDIR');
@@ -103,18 +150,30 @@ start
103
150
  }
104
151
  case 'add-chain': {
105
152
  const basedir = insistIsBasedir();
106
- const { _: subArgs, ...subOpts } = parseArgs(argv.slice(1), {
107
- boolean: ['reset'],
153
+ const { values: subOpts, positionals: subArgs } = parseArgs({
154
+ args: argv.slice(1),
155
+ options: {
156
+ reset: { type: 'boolean' },
157
+ },
158
+ allowPositionals: true,
159
+ strict: false,
108
160
  });
109
161
  const [chainConfig] = subArgs;
110
- await addChain(basedir, chainConfig, subOpts.reset);
162
+ await addChain(basedir, chainConfig, booleanOption(subOpts.reset, false));
111
163
  break;
112
164
  }
113
165
  case 'set-gci-ingress': {
114
166
  const basedir = insistIsBasedir();
115
- const { _: subArgs, ...subOpts } = parseArgs(argv.slice(1), {});
167
+ const { values: subOpts, positionals: subArgs } = parseArgs({
168
+ args: argv.slice(1),
169
+ options: {
170
+ chainID: { type: 'string' },
171
+ },
172
+ allowPositionals: true,
173
+ strict: false,
174
+ });
116
175
  const GCI = subArgs[0];
117
- const chainID = subOpts.chainID || 'agoric';
176
+ const chainID = stringOption(subOpts.chainID, 'agoric');
118
177
  const rpcAddresses = subArgs.slice(1);
119
178
  setGCIIngress(basedir, GCI, rpcAddresses, chainID);
120
179
  break;
package/src/start.js CHANGED
@@ -3,7 +3,7 @@
3
3
  import fs from 'node:fs';
4
4
  import url from 'node:url';
5
5
  import path from 'node:path';
6
- import temp from 'temp';
6
+ import { mkdtemp, writeFile, unlink } from 'node:fs/promises';
7
7
  import { fork } from 'node:child_process';
8
8
  import { promisify } from 'node:util';
9
9
  import { resolve as importMetaResolve } from 'import-meta-resolve';
@@ -53,41 +53,33 @@ const log = anylogger('start');
53
53
 
54
54
  let swingSetRunning = false;
55
55
 
56
- const fsWrite = promisify(fs.write);
57
- const fsClose = promisify(fs.close);
58
56
  const rename = promisify(fs.rename);
59
- const unlink = promisify(fs.unlink);
60
57
 
61
58
  const atomicReplaceFile = async (filename, contents) => {
62
- const info = await new Promise((resolve, reject) => {
63
- temp.open(
64
- {
65
- dir: path.dirname(filename),
66
- prefix: `${path.basename(filename)}.`,
67
- },
68
- (err, inf) => {
69
- if (err) {
70
- reject(err);
71
- return;
72
- }
73
- resolve(inf);
74
- },
75
- );
76
- });
59
+ const basename = path.basename(filename);
60
+ const tempDir = await mkdtemp(
61
+ path.join(path.dirname(filename), `${basename}.`),
62
+ );
63
+ const tempPath = path.join(tempDir, basename);
64
+
77
65
  try {
78
- // Write the contents, close, and rename.
79
- await fsWrite(info.fd, contents);
80
- await fsClose(info.fd);
81
- await rename(info.path, filename);
66
+ await writeFile(tempPath, contents);
67
+ await rename(tempPath, filename);
82
68
  } catch (e) {
83
- // Unlink on error.
84
69
  try {
85
- await unlink(info.path);
70
+ await unlink(tempPath);
71
+ await fs.promises.rmdir(tempDir);
86
72
  } catch (e2) {
87
73
  // do nothing, we're already failing
88
74
  }
89
75
  throw e;
90
76
  }
77
+
78
+ try {
79
+ await fs.promises.rmdir(tempDir);
80
+ } catch (e) {
81
+ // Ignore cleanup errors
82
+ }
91
83
  };
92
84
 
93
85
  const neverStop = () => {