@agoric/deploy-script-support 0.10.4-dev-99fc025.0 → 0.10.4-dev-2c609b8.0

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.
Files changed (2) hide show
  1. package/package.json +11 -11
  2. package/src/extract-proposal.js +188 -143
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/deploy-script-support",
3
- "version": "0.10.4-dev-99fc025.0+99fc025",
3
+ "version": "0.10.4-dev-2c609b8.0+2c609b8",
4
4
  "description": "Helpers and other support for writing deploy scripts",
5
5
  "type": "module",
6
6
  "main": "src/helpers.js",
@@ -34,14 +34,14 @@
34
34
  },
35
35
  "homepage": "https://github.com/Agoric/agoric-sdk#readme",
36
36
  "dependencies": {
37
- "@agoric/assert": "0.6.1-dev-99fc025.0+99fc025",
38
- "@agoric/ertp": "0.16.3-dev-99fc025.0+99fc025",
39
- "@agoric/import-manager": "0.3.12-dev-99fc025.0+99fc025",
40
- "@agoric/internal": "0.3.3-dev-99fc025.0+99fc025",
41
- "@agoric/notifier": "0.6.3-dev-99fc025.0+99fc025",
42
- "@agoric/store": "0.9.3-dev-99fc025.0+99fc025",
43
- "@agoric/time": "0.3.3-dev-99fc025.0+99fc025",
44
- "@agoric/zoe": "0.26.3-dev-99fc025.0+99fc025",
37
+ "@agoric/assert": "0.6.1-dev-2c609b8.0+2c609b8",
38
+ "@agoric/ertp": "0.16.3-dev-2c609b8.0+2c609b8",
39
+ "@agoric/import-manager": "0.3.12-dev-2c609b8.0+2c609b8",
40
+ "@agoric/internal": "0.3.3-dev-2c609b8.0+2c609b8",
41
+ "@agoric/notifier": "0.6.3-dev-2c609b8.0+2c609b8",
42
+ "@agoric/store": "0.9.3-dev-2c609b8.0+2c609b8",
43
+ "@agoric/time": "0.3.3-dev-2c609b8.0+2c609b8",
44
+ "@agoric/zoe": "0.26.3-dev-2c609b8.0+2c609b8",
45
45
  "@endo/base64": "^1.0.1",
46
46
  "@endo/bundle-source": "^3.0.2",
47
47
  "@endo/far": "^1.0.2",
@@ -51,7 +51,7 @@
51
51
  "@endo/zip": "^1.0.1"
52
52
  },
53
53
  "devDependencies": {
54
- "@agoric/vats": "0.15.2-dev-99fc025.0+99fc025",
54
+ "@agoric/vats": "0.15.2-dev-2c609b8.0+2c609b8",
55
55
  "@endo/init": "^1.0.2",
56
56
  "ava": "^5.3.0",
57
57
  "import-meta-resolve": "^2.2.1"
@@ -75,5 +75,5 @@
75
75
  "typeCoverage": {
76
76
  "atLeast": 80.06
77
77
  },
78
- "gitHead": "99fc025340e007fa01de005fa6133491d2c75d6e"
78
+ "gitHead": "2c609b84ddd07536404dedf45b118b1625ce81a0"
79
79
  }
@@ -11,13 +11,38 @@ import {
11
11
  } from './coreProposalBehavior.js';
12
12
 
13
13
  /**
14
- * @typedef {string | { module: string, entrypoint: string, args?: Array<unknown> }} ConfigProposal
14
+ * @typedef {string | {module: string, entrypoint?: string, args?: Array<unknown>}} ConfigProposal
15
+ */
16
+
17
+ /**
18
+ * @typedef {ConfigProposal[] | {steps: ConfigProposal[][]}} CoreProposals
15
19
  */
16
20
 
17
21
  const { Fail } = assert;
18
22
 
19
23
  const req = createRequire(import.meta.url);
20
24
 
25
+ /**
26
+ * @param {...(CoreProposals | undefined | null)} args
27
+ * @returns {CoreProposals}
28
+ */
29
+ export const mergeCoreProposals = (...args) => {
30
+ /** @type {ConfigProposal[][]} */
31
+ const steps = [];
32
+ for (const coreProposal of args) {
33
+ if (!coreProposal) {
34
+ continue;
35
+ }
36
+ if ('steps' in coreProposal) {
37
+ steps.push(...coreProposal.steps);
38
+ } else {
39
+ steps.push(coreProposal);
40
+ }
41
+ }
42
+ return harden({ steps });
43
+ };
44
+ harden(mergeCoreProposals);
45
+
21
46
  /**
22
47
  * @param {(ModuleSpecifier | FilePath)[]} paths
23
48
  * @typedef {string} ModuleSpecifier
@@ -43,12 +68,12 @@ const findModule = (initDir, srcSpec) =>
43
68
  /**
44
69
  * @param {{ bundleID?: string, bundleName?: string }} handle - mutated then hardened
45
70
  * @param {string} sourceSpec - the specifier of a module to load
46
- * @param {number} sequence - the sequence number of the proposal
71
+ * @param {string} key - the key of the proposal
47
72
  * @param {string} piece - the piece of the proposal
48
73
  * @returns {Promise<[string, any]>}
49
74
  */
50
- const namedHandleToBundleSpec = async (handle, sourceSpec, sequence, piece) => {
51
- handle.bundleName = `coreProposal${sequence}_${piece}`;
75
+ const namedHandleToBundleSpec = async (handle, sourceSpec, key, piece) => {
76
+ handle.bundleName = `coreProposal${String(key)}_${piece}`;
52
77
  harden(handle);
53
78
  return harden([handle.bundleName, { sourceSpec }]);
54
79
  };
@@ -64,12 +89,12 @@ const namedHandleToBundleSpec = async (handle, sourceSpec, sequence, piece) => {
64
89
  * but for sim-chain and such, they can be declared statically in
65
90
  * the chain configuration, in which case they are run at bootstrap.
66
91
  *
67
- * @param {ConfigProposal[]} coreProposals - governance
92
+ * @param {CoreProposals} coreProposals - governance
68
93
  * proposals to run at chain bootstrap for scenarios such as sim-chain.
69
94
  * @param {FilePath} [dirname]
70
95
  * @param {object} [opts]
71
96
  * @param {typeof makeEnactCoreProposalsFromBundleRef} [opts.makeEnactCoreProposals]
72
- * @param {(i: number) => number} [opts.getSequenceForProposal]
97
+ * @param {(key: PropertyKey) => PropertyKey} [opts.getSequenceForProposal]
73
98
  * @param {typeof namedHandleToBundleSpec} [opts.handleToBundleSpec]
74
99
  */
75
100
  export const extractCoreProposalBundles = async (
@@ -79,7 +104,7 @@ export const extractCoreProposalBundles = async (
79
104
  ) => {
80
105
  const {
81
106
  makeEnactCoreProposals = makeEnactCoreProposalsFromBundleRef,
82
- getSequenceForProposal = i => i,
107
+ getSequenceForProposal = key => key,
83
108
  handleToBundleSpec = namedHandleToBundleSpec,
84
109
  } = opts || {};
85
110
 
@@ -91,159 +116,177 @@ export const extractCoreProposalBundles = async (
91
116
  /** @type {Map<{ bundleID?: string, bundleName?: string }, { source: string, bundle?: string }>} */
92
117
  const bundleHandleToAbsolutePaths = new Map();
93
118
 
119
+ const proposalSteps =
120
+ 'steps' in coreProposals ? coreProposals.steps : [coreProposals];
94
121
  const bundleToSource = new Map();
95
- const extracted = await Promise.all(
96
- coreProposals.map(async (coreProposal, i) => {
97
- // console.debug(`Parsing core proposal:`, coreProposal);
122
+ const extractedSteps = await Promise.all(
123
+ proposalSteps.map((proposalStep, i) =>
124
+ Promise.all(
125
+ proposalStep.map(async (coreProposal, j) => {
126
+ const key = `${i}.${j}`;
127
+ // console.debug(`Parsing core proposal:`, coreProposal);
98
128
 
99
- /** @type {string} */
100
- let entrypoint;
101
- /** @type {unknown[]} */
102
- let args;
103
- /** @type {string} */
104
- let module;
105
- if (typeof coreProposal === 'string') {
106
- module = coreProposal;
107
- entrypoint = 'defaultProposalBuilder';
108
- args = [];
109
- } else {
110
- ({ module, entrypoint, args = [] } = coreProposal);
111
- }
112
-
113
- typeof module === 'string' ||
114
- Fail`coreProposal module ${module} must be string`;
115
- typeof entrypoint === 'string' ||
116
- Fail`coreProposal entrypoint ${entrypoint} must be string`;
117
- Array.isArray(args) || Fail`coreProposal args ${args} must be array`;
118
-
119
- const thisProposalBundleHandles = new Set();
120
- assert(getSequenceForProposal);
121
- const thisProposalSequence = getSequenceForProposal(i);
122
- const initPath = findModule(dirname, module);
123
- const initDir = path.dirname(initPath);
124
- /** @type {Record<string, import('./externalTypes.js').ProposalBuilder>} */
125
- const ns = await import(initPath);
126
- const install = (srcSpec, bundlePath) => {
127
- const absoluteSrc = findModule(initDir, srcSpec);
128
- const bundleHandle = {};
129
- const absolutePaths = { source: absoluteSrc };
130
- if (bundlePath) {
131
- const absoluteBundle = pathResolve(initDir, bundlePath);
132
- absolutePaths.bundle = absoluteBundle;
133
- const oldSource = bundleToSource.get(absoluteBundle);
134
- if (oldSource) {
135
- oldSource === absoluteSrc ||
136
- Fail`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`;
129
+ /** @type {string} */
130
+ let entrypoint;
131
+ /** @type {unknown[]} */
132
+ let args;
133
+ /** @type {string} */
134
+ let module;
135
+ if (typeof coreProposal === 'string') {
136
+ module = coreProposal;
137
+ entrypoint = 'defaultProposalBuilder';
138
+ args = [];
137
139
  } else {
138
- bundleToSource.set(absoluteBundle, absoluteSrc);
140
+ ({
141
+ module,
142
+ entrypoint = 'defaultProposalBuilder',
143
+ args = [],
144
+ } = coreProposal);
139
145
  }
140
- }
141
- // Don't harden the bundleHandle since we need to set the bundleName on
142
- // its unique identity later.
143
- thisProposalBundleHandles.add(bundleHandle);
144
- bundleHandleToAbsolutePaths.set(bundleHandle, harden(absolutePaths));
145
- return bundleHandle;
146
- };
147
- /** @type {import('./externalTypes.js').PublishBundleRef} */
148
- const publishRef = async handleP => {
149
- const handle = await handleP;
150
- // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */
151
- // @ts-ignore xxx types
152
- bundleHandleToAbsolutePaths.has(handle) ||
153
- Fail`${handle} not in installed bundles`;
154
- return handle;
155
- };
156
- const proposal = await ns[entrypoint](
157
- {
158
- publishRef,
159
- // @ts-expect-error not statically verified to return a full obj
160
- install,
161
- },
162
- ...args,
163
- );
164
146
 
165
- // Add the proposal bundle handles in sorted order.
166
- const bundleSpecEntries = await Promise.all(
167
- [...thisProposalBundleHandles.keys()]
168
- .map(handle => [handle, bundleHandleToAbsolutePaths.get(handle)])
169
- .sort(([_hnda, { source: a }], [_hndb, { source: b }]) => {
170
- if (a < b) {
171
- return -1;
172
- }
173
- if (a > b) {
174
- return 1;
147
+ typeof module === 'string' ||
148
+ Fail`coreProposal module ${module} must be string`;
149
+ typeof entrypoint === 'string' ||
150
+ Fail`coreProposal entrypoint ${entrypoint} must be string`;
151
+ Array.isArray(args) || Fail`coreProposal args ${args} must be array`;
152
+
153
+ const thisProposalBundleHandles = new Set();
154
+ assert(getSequenceForProposal);
155
+ const thisProposalSequence = getSequenceForProposal(key);
156
+ const initPath = findModule(dirname, module);
157
+ const initDir = path.dirname(initPath);
158
+ /** @type {Record<string, import('./externalTypes.js').ProposalBuilder>} */
159
+ const ns = await import(initPath);
160
+ const install = (srcSpec, bundlePath) => {
161
+ const absoluteSrc = findModule(initDir, srcSpec);
162
+ const bundleHandle = {};
163
+ const absolutePaths = { source: absoluteSrc };
164
+ if (bundlePath) {
165
+ const absoluteBundle = pathResolve(initDir, bundlePath);
166
+ absolutePaths.bundle = absoluteBundle;
167
+ const oldSource = bundleToSource.get(absoluteBundle);
168
+ if (oldSource) {
169
+ oldSource === absoluteSrc ||
170
+ Fail`${bundlePath} already installed from ${oldSource}, now ${absoluteSrc}`;
171
+ } else {
172
+ bundleToSource.set(absoluteBundle, absoluteSrc);
173
+ }
175
174
  }
176
- return 0;
177
- })
178
- .map(async ([handle, absolutePaths], j) => {
179
- // Transform the bundle handle identity into a bundleName reference.
180
- const specEntry = await handleToBundleSpec(
181
- handle,
182
- absolutePaths.source,
183
- thisProposalSequence,
184
- String(j),
175
+ // Don't harden the bundleHandle since we need to set the bundleName on
176
+ // its unique identity later.
177
+ thisProposalBundleHandles.add(bundleHandle);
178
+ bundleHandleToAbsolutePaths.set(
179
+ bundleHandle,
180
+ harden(absolutePaths),
185
181
  );
186
- harden(handle);
187
- return specEntry;
188
- }),
189
- );
182
+ return bundleHandle;
183
+ };
184
+ /** @type {import('./externalTypes.js').PublishBundleRef} */
185
+ const publishRef = async handleP => {
186
+ const handle = await handleP;
187
+ // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */
188
+ // @ts-ignore xxx types
189
+ bundleHandleToAbsolutePaths.has(handle) ||
190
+ Fail`${handle} not in installed bundles`;
191
+ return handle;
192
+ };
193
+ const proposal = await ns[entrypoint](
194
+ {
195
+ publishRef,
196
+ // @ts-expect-error not statically verified to return a full obj
197
+ install,
198
+ },
199
+ ...args,
200
+ );
190
201
 
191
- // Now that we've assigned all the bundleNames and hardened the
192
- // handles, we can extract the behavior bundle.
193
- const { sourceSpec, getManifestCall } = await deeplyFulfilledObject(
194
- harden(proposal),
195
- );
202
+ // Add the proposal bundle handles in sorted order.
203
+ const bundleSpecEntries = await Promise.all(
204
+ [...thisProposalBundleHandles.keys()]
205
+ .map(handle => [handle, bundleHandleToAbsolutePaths.get(handle)])
206
+ .sort(([_hnda, { source: a }], [_hndb, { source: b }]) => {
207
+ if (a < b) {
208
+ return -1;
209
+ }
210
+ if (a > b) {
211
+ return 1;
212
+ }
213
+ return 0;
214
+ })
215
+ .map(async ([handle, absolutePaths], k) => {
216
+ // Transform the bundle handle identity into a bundleName reference.
217
+ const specEntry = await handleToBundleSpec(
218
+ handle,
219
+ absolutePaths.source,
220
+ thisProposalSequence,
221
+ String(k),
222
+ );
223
+ harden(handle);
224
+ return specEntry;
225
+ }),
226
+ );
196
227
 
197
- const proposalSource = pathResolve(initDir, sourceSpec);
198
- const proposalNS = await import(proposalSource);
199
- const [manifestGetterName, ...manifestGetterArgs] = getManifestCall;
200
- manifestGetterName in proposalNS ||
201
- Fail`proposal ${proposalSource} missing export ${manifestGetterName}`;
202
- const { manifest: customManifest } = await proposalNS[manifestGetterName](
203
- harden({ restoreRef: () => null }),
204
- ...manifestGetterArgs,
205
- );
228
+ // Now that we've assigned all the bundleNames and hardened the
229
+ // handles, we can extract the behavior bundle.
230
+ const { sourceSpec, getManifestCall } = await deeplyFulfilledObject(
231
+ harden(proposal),
232
+ );
206
233
 
207
- const behaviorBundleHandle = {};
208
- const specEntry = await handleToBundleSpec(
209
- behaviorBundleHandle,
210
- proposalSource,
211
- thisProposalSequence,
212
- 'behaviors',
213
- );
214
- bundleSpecEntries.unshift(specEntry);
234
+ const proposalSource = pathResolve(initDir, sourceSpec);
235
+ const proposalNS = await import(proposalSource);
236
+ const [manifestGetterName, ...manifestGetterArgs] = getManifestCall;
237
+ manifestGetterName in proposalNS ||
238
+ Fail`proposal ${proposalSource} missing export ${manifestGetterName}`;
239
+ const { manifest: customManifest } = await proposalNS[
240
+ manifestGetterName
241
+ ](harden({ restoreRef: () => null }), ...manifestGetterArgs);
215
242
 
216
- bundleHandleToAbsolutePaths.set(
217
- behaviorBundleHandle,
218
- harden({
219
- source: proposalSource,
220
- }),
221
- );
243
+ const behaviorBundleHandle = {};
244
+ const specEntry = await handleToBundleSpec(
245
+ behaviorBundleHandle,
246
+ proposalSource,
247
+ thisProposalSequence,
248
+ 'proposalNS',
249
+ );
250
+ bundleSpecEntries.unshift(specEntry);
251
+
252
+ bundleHandleToAbsolutePaths.set(
253
+ behaviorBundleHandle,
254
+ harden({
255
+ source: proposalSource,
256
+ }),
257
+ );
222
258
 
223
- return harden({
224
- ref: behaviorBundleHandle,
225
- call: getManifestCall,
226
- customManifest,
227
- bundleSpecs: bundleSpecEntries,
228
- });
229
- }),
259
+ return /** @type {const} */ ([
260
+ key,
261
+ {
262
+ ref: behaviorBundleHandle,
263
+ call: getManifestCall,
264
+ customManifest,
265
+ bundleSpecs: bundleSpecEntries,
266
+ },
267
+ ]);
268
+ }),
269
+ ),
270
+ ),
230
271
  );
231
272
 
232
273
  // Extract all the bundle specs in already-sorted order.
233
274
  const bundles = Object.fromEntries(
234
- extracted.flatMap(({ bundleSpecs }) => bundleSpecs),
275
+ extractedSteps.flatMap(step =>
276
+ step.flatMap(([_key, { bundleSpecs }]) => bundleSpecs),
277
+ ),
235
278
  );
236
279
  harden(bundles);
237
280
 
238
- // Extract the manifest references and calls.
239
- const metadataRecords = extracted.map(({ ref, call, customManifest }) => ({
240
- ref,
241
- call,
242
- customManifest,
243
- }));
244
- harden(metadataRecords);
281
+ const codeSteps = extractedSteps.map(extractedStep => {
282
+ // Extract the manifest references and calls.
283
+ const metadataRecords = extractedStep.map(([_key, extractedSpec]) => {
284
+ const { ref, call, customManifest } = extractedSpec;
285
+ return { ref, call, customManifest };
286
+ });
287
+ harden(metadataRecords);
245
288
 
246
- const code = `\
289
+ const code = `\
247
290
  // This is generated by @agoric/deploy-script-support/src/extract-proposal.js - DO NOT EDIT
248
291
  /* eslint-disable */
249
292
 
@@ -260,11 +303,13 @@ const enactCoreProposals = ((
260
303
  ) => makeEnactCoreProposals({ metadataRecords, E }))();
261
304
  enactCoreProposals;
262
305
  `;
306
+ return defangAndTrim(code);
307
+ });
263
308
 
264
309
  // console.debug('created bundles from proposals:', coreProposals, bundles);
265
- return {
310
+ return harden({
266
311
  bundles,
267
- code: defangAndTrim(code),
312
+ codeSteps,
268
313
  bundleHandleToAbsolutePaths,
269
- };
314
+ });
270
315
  };