@haneullabs/mvr-static 0.1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,329 @@
1
+ # @haneullabs/mvr-static
2
+
3
+ ## 0.2.12
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [29e8b92]
8
+ - @haneullabs/haneul@1.45.2
9
+
10
+ ## 0.2.11
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [e3811f1]
15
+ - @haneullabs/haneul@1.45.1
16
+
17
+ ## 0.2.10
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [88bdbac]
22
+ - @haneullabs/haneul@1.45.0
23
+
24
+ ## 0.2.9
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [44d9b4f]
29
+ - @haneullabs/haneul@1.44.0
30
+
31
+ ## 0.2.8
32
+
33
+ ### Patch Changes
34
+
35
+ - @haneullabs/haneul@1.43.2
36
+
37
+ ## 0.2.7
38
+
39
+ ### Patch Changes
40
+
41
+ - @haneullabs/haneul@1.43.1
42
+
43
+ ## 0.2.6
44
+
45
+ ### Patch Changes
46
+
47
+ - Updated dependencies [f3b19a7]
48
+ - Updated dependencies [bf9f85c]
49
+ - @haneullabs/haneul@1.43.0
50
+
51
+ ## 0.2.5
52
+
53
+ ### Patch Changes
54
+
55
+ - Updated dependencies [98c8a27]
56
+ - @haneullabs/haneul@1.42.0
57
+
58
+ ## 0.2.4
59
+
60
+ ### Patch Changes
61
+
62
+ - Updated dependencies [d554cd2]
63
+ - Updated dependencies [04fcfbc]
64
+ - @haneullabs/haneul@1.41.0
65
+
66
+ ## 0.2.3
67
+
68
+ ### Patch Changes
69
+
70
+ - Updated dependencies [f5fc0c0]
71
+ - @haneullabs/haneul@1.40.0
72
+
73
+ ## 0.2.2
74
+
75
+ ### Patch Changes
76
+
77
+ - Updated dependencies [a9f9035]
78
+ - @haneullabs/haneul@1.39.1
79
+
80
+ ## 0.2.1
81
+
82
+ ### Patch Changes
83
+
84
+ - Updated dependencies [ca92487]
85
+ - Updated dependencies [5ab3c0a]
86
+ - @haneullabs/haneul@1.39.0
87
+
88
+ ## 0.2.0
89
+
90
+ ### Minor Changes
91
+
92
+ - ea1ac70: Update dependencies and improve support for typescript 5.9
93
+
94
+ ### Patch Changes
95
+
96
+ - Updated dependencies [3c1741f]
97
+ - Updated dependencies [ea1ac70]
98
+ - @haneullabs/haneul@1.38.0
99
+
100
+ ## 0.1.31
101
+
102
+ ### Patch Changes
103
+
104
+ - Updated dependencies [c689b98]
105
+ - Updated dependencies [5b9ff1a]
106
+ - @haneullabs/haneul@1.37.6
107
+
108
+ ## 0.1.30
109
+
110
+ ### Patch Changes
111
+
112
+ - Updated dependencies [3980d04]
113
+ - @haneullabs/haneul@1.37.5
114
+
115
+ ## 0.1.29
116
+
117
+ ### Patch Changes
118
+
119
+ - Updated dependencies [6b03e57]
120
+ - @haneullabs/haneul@1.37.4
121
+
122
+ ## 0.1.28
123
+
124
+ ### Patch Changes
125
+
126
+ - Updated dependencies [8ff1471]
127
+ - @haneullabs/haneul@1.37.3
128
+
129
+ ## 0.1.27
130
+
131
+ ### Patch Changes
132
+
133
+ - Updated dependencies [660377c]
134
+ - @haneullabs/haneul@1.37.2
135
+
136
+ ## 0.1.26
137
+
138
+ ### Patch Changes
139
+
140
+ - @haneullabs/haneul@1.37.1
141
+
142
+ ## 0.1.25
143
+
144
+ ### Patch Changes
145
+
146
+ - Updated dependencies [72168f0]
147
+ - @haneullabs/haneul@1.37.0
148
+
149
+ ## 0.1.24
150
+
151
+ ### Patch Changes
152
+
153
+ - Updated dependencies [44354ab]
154
+ - @haneullabs/haneul@1.36.2
155
+
156
+ ## 0.1.23
157
+
158
+ ### Patch Changes
159
+
160
+ - Updated dependencies [c76ddc5]
161
+ - @haneullabs/haneul@1.36.1
162
+
163
+ ## 0.1.22
164
+
165
+ ### Patch Changes
166
+
167
+ - Updated dependencies [783bb9e]
168
+ - Updated dependencies [783bb9e]
169
+ - Updated dependencies [5cbbb21]
170
+ - @haneullabs/haneul@1.36.0
171
+
172
+ ## 0.1.21
173
+
174
+ ### Patch Changes
175
+
176
+ - Updated dependencies [888afe6]
177
+ - @haneullabs/haneul@1.35.0
178
+
179
+ ## 0.1.20
180
+
181
+ ### Patch Changes
182
+
183
+ - Updated dependencies [3fb7a83]
184
+ - @haneullabs/haneul@1.34.0
185
+
186
+ ## 0.1.19
187
+
188
+ ### Patch Changes
189
+
190
+ - Updated dependencies [a00522b]
191
+ - @haneullabs/haneul@1.33.0
192
+
193
+ ## 0.1.18
194
+
195
+ ### Patch Changes
196
+
197
+ - Updated dependencies [6b7deb8]
198
+ - @haneullabs/haneul@1.32.0
199
+
200
+ ## 0.1.17
201
+
202
+ ### Patch Changes
203
+
204
+ - Updated dependencies [1ff4e57]
205
+ - Updated dependencies [550e2e3]
206
+ - Updated dependencies [550e2e3]
207
+ - @haneullabs/haneul@1.31.0
208
+
209
+ ## 0.1.16
210
+
211
+ ### Patch Changes
212
+
213
+ - Updated dependencies [5bd6ca3]
214
+ - @haneullabs/haneul@1.30.5
215
+
216
+ ## 0.1.15
217
+
218
+ ### Patch Changes
219
+
220
+ - Updated dependencies [5dce590]
221
+ - Updated dependencies [4a5aef6]
222
+ - @haneullabs/haneul@1.30.4
223
+
224
+ ## 0.1.14
225
+
226
+ ### Patch Changes
227
+
228
+ - bb7c03a: Update dependencies
229
+ - Updated dependencies [4457f10]
230
+ - Updated dependencies [bb7c03a]
231
+ - @haneullabs/haneul@1.30.3
232
+
233
+ ## 0.1.13
234
+
235
+ ### Patch Changes
236
+
237
+ - Updated dependencies [b265f7e]
238
+ - @haneullabs/haneul@1.30.2
239
+
240
+ ## 0.1.12
241
+
242
+ ### Patch Changes
243
+
244
+ - Updated dependencies [ec519fc]
245
+ - @haneullabs/haneul@1.30.1
246
+
247
+ ## 0.1.11
248
+
249
+ ### Patch Changes
250
+
251
+ - Updated dependencies [2456052]
252
+ - Updated dependencies [5264038]
253
+ - Updated dependencies [2456052]
254
+ - Updated dependencies [2456052]
255
+ - Updated dependencies [2456052]
256
+ - Updated dependencies [2456052]
257
+ - @haneullabs/haneul@1.30.0
258
+
259
+ ## 0.1.10
260
+
261
+ ### Patch Changes
262
+
263
+ - @haneullabs/haneul@1.29.1
264
+
265
+ ## 0.1.9
266
+
267
+ ### Patch Changes
268
+
269
+ - Updated dependencies [7d66a32]
270
+ - Updated dependencies [eb91fba]
271
+ - Updated dependencies [19a8045]
272
+ - @haneullabs/haneul@1.29.0
273
+
274
+ ## 0.1.8
275
+
276
+ ### Patch Changes
277
+
278
+ - Updated dependencies [9a94aea]
279
+ - @haneullabs/haneul@1.28.2
280
+
281
+ ## 0.1.7
282
+
283
+ ### Patch Changes
284
+
285
+ - Updated dependencies [3cd4e53]
286
+ - @haneullabs/haneul@1.28.1
287
+
288
+ ## 0.1.6
289
+
290
+ ### Patch Changes
291
+
292
+ - Updated dependencies [2705dc8]
293
+ - @haneullabs/haneul@1.28.0
294
+
295
+ ## 0.1.5
296
+
297
+ ### Patch Changes
298
+
299
+ - Updated dependencies [5cea435]
300
+ - @haneullabs/haneul@1.27.1
301
+
302
+ ## 0.1.4
303
+
304
+ ### Patch Changes
305
+
306
+ - Updated dependencies [4d13ef8]
307
+ - Updated dependencies [4d13ef8]
308
+ - @haneullabs/haneul@1.27.0
309
+
310
+ ## 0.1.3
311
+
312
+ ### Patch Changes
313
+
314
+ - 7ba32a4: update dependencies
315
+ - Updated dependencies [7ba32a4]
316
+ - @haneullabs/haneul@1.26.1
317
+
318
+ ## 0.1.2
319
+
320
+ ### Patch Changes
321
+
322
+ - Updated dependencies [906dd14]
323
+ - @haneullabs/haneul@1.26.0
324
+
325
+ ## 0.1.1
326
+
327
+ ### Patch Changes
328
+
329
+ - ddcbc1a: Introduces mvr-static package
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # mvr-static
2
+
3
+ The mvr-static tool is a typescript CLI tool to generate a static file for Move Registry (mvr)
4
+ resolution. This can be used to cache all MVR names for performance & security reasons, and used in
5
+ the `NamedPackagesPlugin` (exported from `@haneullabs/haneul`) in your project.
6
+
7
+ ## Usage
8
+
9
+ ### Generate a static file for MVR resolution
10
+
11
+ You can generate your static file by running the following command:
12
+
13
+ ```bash
14
+ pnpm dlx @haneullabs/mvr-static
15
+ ```
16
+
17
+ Available options:
18
+
19
+ - `--directory <directory>`: The directory to run the command in (defaults to `.`)
20
+ - `--output <file-name>`: The output's file name (defaults to `mvr.ts`)
21
+ - `--depth <depth>`: The depth of recursive search for MVR names (defaults to `10`)
22
+ - `--url-mainnet <url>`: The URL to the mainnet MVR (defaults to
23
+ `https://mainnet.mvr.haneullabs.com`)
24
+ - `--url-testnet <url>`: The URL to the testnet MVR (defaults to
25
+ `https://testnet.mvr.haneullabs.com`)
26
+ - `--include <dir_patterns>`: The directory patterns to include in the search (defaults to
27
+ `**/*.{js,ts,jsx,tsx,mjs,cjs}`)
28
+ - `--exclude <dir_patterns>`: The directory patterns to exclude in the search (defaults to
29
+ `'node_modules/**', '**/.*'`)
30
+ - `--force`: Force overwrite the existing MVR file (useful in CI) (defaults to `false`)
31
+
32
+ ### Use the static file in your project
33
+
34
+ Once you have your static file, you can use it in your project by importing it and passing it to the
35
+ `NamedPackagesPlugin` in your project.
36
+
37
+ ```ts
38
+ import { NamedPackagesPlugin } from '@haneullabs/haneul/src/transactions';
39
+
40
+ import { getMvrCache } from './mvr.ts';
41
+
42
+ // create a cache for your network.
43
+ const cache = getMvrCache('mainnet');
44
+
45
+ const plugin = new NamedPackagesPlugin({
46
+ // ...,
47
+ overrides: cache,
48
+ });
49
+ ```
package/bin/parser.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // Copyright (c) Mysten Labs, Inc.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ require('../dist/execute.js');
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Copyright (c) Mysten Labs, Inc.
4
+ // SPDX-License-Identifier: Apache-2.0
5
+ const parsing_js_1 = require("./parsing.js");
6
+ (0, parsing_js_1.parser)();
7
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":";;AAAA,kCAAkC;AAClC,sCAAsC;AACtC,6CAAsC;AAEtC,IAAA,mBAAM,GAAE,CAAC"}
@@ -0,0 +1,23 @@
1
+ export declare function parser(): Promise<undefined>;
2
+ export declare function crossNetworkResolution(detectedNames: Set<string>): Promise<{
3
+ mainnet: {
4
+ packages: Record<string, string>;
5
+ types: Record<string, string>;
6
+ };
7
+ testnet: {
8
+ packages: Record<string, string>;
9
+ types: Record<string, string>;
10
+ };
11
+ }>;
12
+ /**
13
+ * Finds all the MVR names in the given directory.
14
+ * @param directory - The directory to search for MVR names.
15
+ * @returns A set of all the MVR names found in the directory.
16
+ */
17
+ export declare function findNames({ directory, include, exclude, depth, output, }: {
18
+ directory?: string;
19
+ include?: string[];
20
+ exclude?: string[];
21
+ depth?: number;
22
+ output?: string;
23
+ }): Promise<Set<string>>;
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parser = parser;
4
+ exports.crossNetworkResolution = crossNetworkResolution;
5
+ exports.findNames = findNames;
6
+ // Copyright (c) Mysten Labs, Inc.
7
+ // SPDX-License-Identifier: Apache-2.0
8
+ const fs_1 = require("fs");
9
+ const promises_1 = require("fs/promises");
10
+ const path_1 = require("path");
11
+ const util_1 = require("util");
12
+ const utils_1 = require("@haneullabs/haneul/utils");
13
+ const enquirer_1 = require("enquirer");
14
+ const glob_1 = require("glob");
15
+ const prettier_1 = require("prettier");
16
+ const TYPES_AND_TARGET_MATCHES = /[@a-zA-Z0-9/.-]+::[a-zA-Z0-9_]+::[a-zA-Z0-9_]+/g;
17
+ const MVR_NAME_MATCHES = /[@a-zA-Z0-9/.-]+::/g;
18
+ const DEFAULT_INCLUDE_PATTERNS = ['**/*.{js,ts,jsx,tsx,mjs,cjs}'];
19
+ const DEFAULT_EXCLUDE_PATTERNS = ['node_modules/**', '**/.*'];
20
+ const DEFAULT_FILE_NAME = `mvr.ts`;
21
+ const MAX_BATCH_SIZE = 25; // files to process per batch.
22
+ const MAINNET_API_URL = 'https://mainnet.mvr.haneullabs.com';
23
+ const TESTNET_API_URL = 'https://testnet.mvr.haneullabs.com';
24
+ const WARNING_MESSAGE = `/**
25
+ * This file is automatically generated by the mvr SDK.
26
+ * You can edit this file, but it will be overwritten on the next run.
27
+ * You should check this file in your version control system.
28
+ *
29
+ * Run this script before building your project to ensure that the mvr.ts file stays up to date.
30
+ *
31
+ * You can use this pre-built cache when initializing your "NamedPackagesPlugin" by calling
32
+ * \`getMvrCache("mainnet")\` or \`getMvrCache("testnet")\`
33
+ */
34
+ `;
35
+ const { values: args } = (0, util_1.parseArgs)({
36
+ options: {
37
+ directory: {
38
+ type: 'string',
39
+ default: '.',
40
+ short: 'd',
41
+ },
42
+ output: {
43
+ type: 'string',
44
+ default: DEFAULT_FILE_NAME,
45
+ short: 'o',
46
+ },
47
+ depth: {
48
+ type: 'string',
49
+ default: '10',
50
+ short: 'd',
51
+ },
52
+ 'url-mainnet': {
53
+ type: 'string',
54
+ default: MAINNET_API_URL,
55
+ },
56
+ 'url-testnet': {
57
+ type: 'string',
58
+ default: TESTNET_API_URL,
59
+ },
60
+ include: {
61
+ type: 'string',
62
+ multiple: true,
63
+ default: DEFAULT_INCLUDE_PATTERNS,
64
+ short: 'i',
65
+ },
66
+ exclude: {
67
+ type: 'string',
68
+ multiple: true,
69
+ default: DEFAULT_EXCLUDE_PATTERNS,
70
+ short: 'e',
71
+ },
72
+ force: {
73
+ type: 'boolean',
74
+ default: false,
75
+ short: 'f',
76
+ },
77
+ },
78
+ });
79
+ async function parser() {
80
+ const path = (0, path_1.isAbsolute)(args.output) ? args.output : (0, path_1.join)(process.cwd(), args.output);
81
+ const dir = (0, path_1.dirname)(path);
82
+ if (!(0, fs_1.existsSync)(dir))
83
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
84
+ if (!isSupportedFile(path))
85
+ throw new Error(`Unsupported file type: ${path}. Please use a .ts (or equivalent) file name for the output.`);
86
+ if ((0, fs_1.existsSync)(path) && !args.force) {
87
+ const { overwrite } = (await (0, enquirer_1.prompt)({
88
+ type: 'confirm',
89
+ name: 'overwrite',
90
+ message: `The file ${path} already exists. Do you want to overwrite it?`,
91
+ }));
92
+ console.log(`Skipping generation of MVR file.`);
93
+ if (!overwrite)
94
+ return process.exit(1);
95
+ }
96
+ console.log(`Generating ${args.output}...`);
97
+ const detectedNames = await findNames({});
98
+ const { mainnet, testnet } = await crossNetworkResolution(detectedNames);
99
+ await writeOutputFile(path, mainnet, testnet);
100
+ }
101
+ async function writeOutputFile(outDir, mainnet, testnet) {
102
+ const outputFile = `${WARNING_MESSAGE}
103
+ const mainnetResolution = ${JSON.stringify(mainnet, null, 2)}
104
+ const testnetResolution = ${JSON.stringify(testnet, null, 2)}
105
+
106
+ export function getMvrCache(network: 'mainnet' | 'testnet') {
107
+ return network === 'mainnet' ? mainnetResolution : testnetResolution;
108
+ }\n
109
+ `;
110
+ (0, fs_1.writeFileSync)(outDir, await (0, prettier_1.format)(outputFile, { parser: 'typescript' }), 'utf8');
111
+ }
112
+ async function crossNetworkResolution(detectedNames) {
113
+ const packages = Array.from(detectedNames).filter((x) => !x.includes('::'));
114
+ const types = Array.from(detectedNames).filter((x) => x.includes('::'));
115
+ const [mainnetPackages, mainnetTypes, testnetPackages, testnetTypes] = await Promise.all([
116
+ resolvePackages(packages, args['url-mainnet']),
117
+ resolveTypes(types, args['url-mainnet']),
118
+ resolvePackages(packages, args['url-testnet']),
119
+ resolveTypes(types, args['url-testnet']),
120
+ ]);
121
+ return {
122
+ mainnet: {
123
+ packages: mainnetPackages,
124
+ types: mainnetTypes,
125
+ },
126
+ testnet: {
127
+ packages: testnetPackages,
128
+ types: testnetTypes,
129
+ },
130
+ };
131
+ }
132
+ async function resolvePackages(packages, apiUrl) {
133
+ const batches = batch(packages, 50);
134
+ const results = {};
135
+ await Promise.all(batches.map(async (batch) => {
136
+ const response = await fetch(`${apiUrl}/v1/resolution/bulk`, {
137
+ method: 'POST',
138
+ headers: { 'Content-Type': 'application/json' },
139
+ body: JSON.stringify({
140
+ names: batch,
141
+ }),
142
+ });
143
+ if (!response.ok) {
144
+ const errorBody = await response.json().catch(() => ({}));
145
+ throw new Error(`Failed to resolve packages: ${errorBody?.message}`);
146
+ }
147
+ const data = await response.json();
148
+ if (!data?.resolution)
149
+ return;
150
+ for (const pkg of Object.keys(data?.resolution)) {
151
+ const pkgData = data.resolution[pkg]?.package_id;
152
+ if (!pkgData)
153
+ continue;
154
+ results[pkg] = pkgData;
155
+ }
156
+ }));
157
+ return results;
158
+ }
159
+ // TODO: Switch to `/struct-definition/bulk` endpoint when released,
160
+ // as this endpoint will be the right one for "non-nested" struct resolution.
161
+ // The current endpoint will fail with "generic" parameter lookups (which are not existent)
162
+ // on this parser.
163
+ async function resolveTypes(types, apiUrl) {
164
+ const batches = batch(types, 50);
165
+ const results = {};
166
+ await Promise.all(batches.map(async (batch) => {
167
+ const response = await fetch(`${apiUrl}/v1/struct-definition/bulk`, {
168
+ method: 'POST',
169
+ headers: { 'Content-Type': 'application/json' },
170
+ body: JSON.stringify({
171
+ types: batch,
172
+ }),
173
+ });
174
+ if (!response.ok) {
175
+ const errorBody = await response.json().catch(() => ({}));
176
+ throw new Error(`Failed to resolve types: ${errorBody?.message}`);
177
+ }
178
+ const data = await response.json();
179
+ if (!data?.resolution)
180
+ return;
181
+ for (const type of Object.keys(data?.resolution)) {
182
+ const typeData = data.resolution[type]?.type_tag;
183
+ if (!typeData)
184
+ continue;
185
+ results[type] = typeData;
186
+ }
187
+ }));
188
+ return results;
189
+ }
190
+ /**
191
+ * Finds all the MVR names in the given directory.
192
+ * @param directory - The directory to search for MVR names.
193
+ * @returns A set of all the MVR names found in the directory.
194
+ */
195
+ async function findNames({ directory = args.directory, include = args.include, exclude = args.exclude, depth = parseInt(args.depth), output = args.output, }) {
196
+ const detectedNames = new Set();
197
+ const excluded = [...exclude, output];
198
+ const files = glob_1.glob.sync(include, {
199
+ ignore: excluded,
200
+ cwd: directory,
201
+ maxDepth: depth,
202
+ absolute: true,
203
+ });
204
+ // We batch the files to avoid trying to open too many files at once.
205
+ const batches = batch(files);
206
+ for (const batch of batches) {
207
+ await processFilesBatch(batch, detectedNames);
208
+ }
209
+ return detectedNames;
210
+ }
211
+ /**
212
+ * Finds all the MVR names in the given files.
213
+ */
214
+ async function processFilesBatch(files, detectedNames) {
215
+ await Promise.all(files.map(async (file) => {
216
+ const content = await (0, promises_1.readFile)(file, 'utf8');
217
+ extractMvrNames(content).forEach((name) => detectedNames.add(name));
218
+ }));
219
+ }
220
+ /**
221
+ * Extracts all the MVR names from the given file's data (content).
222
+ */
223
+ function extractMvrNames(content) {
224
+ const relevantNames = new Set();
225
+ // find all "fully qualified" matches.
226
+ const fullQualifiedMatches = [...content.matchAll(TYPES_AND_TARGET_MATCHES)];
227
+ fullQualifiedMatches.forEach((match) => {
228
+ const [pkg] = match[0].split('::');
229
+ if (!(0, utils_1.isValidNamedPackage)(pkg))
230
+ return;
231
+ relevantNames.add(match[0]);
232
+ });
233
+ // find all "plain" name matches
234
+ const plainNameMatches = [...content.matchAll(MVR_NAME_MATCHES)];
235
+ plainNameMatches.forEach((match) => {
236
+ const [pkg] = match[0].split('::');
237
+ if (!(0, utils_1.isValidNamedPackage)(pkg))
238
+ return;
239
+ relevantNames.add(pkg);
240
+ });
241
+ return relevantNames;
242
+ }
243
+ /**
244
+ * Batch the given array into smaller arrays of the given size.
245
+ */
246
+ function batch(array, batchSize = MAX_BATCH_SIZE) {
247
+ const result = [];
248
+ for (let i = 0; i < array.length; i += batchSize) {
249
+ result.push(array.slice(i, i + batchSize)); // Create batches
250
+ }
251
+ return result;
252
+ }
253
+ function isSupportedFile(filePath) {
254
+ const ext = (0, path_1.extname)(filePath).toLowerCase();
255
+ return ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].includes(ext);
256
+ }
257
+ //# sourceMappingURL=parsing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsing.js","sourceRoot":"","sources":["../src/parsing.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@haneullabs/mvr-static",
3
+ "author": "Haneul Labs <build@haneullabs.com>",
4
+ "description": "The static generation tool for Move Registry (mvr)",
5
+ "homepage": "https://sdk.haneullabs.com",
6
+ "version": "0.1.0",
7
+ "license": "Apache-2.0",
8
+ "files": [
9
+ "CHANGELOG.md",
10
+ "LICENSE",
11
+ "README.md",
12
+ "dist",
13
+ "src"
14
+ ],
15
+ "type": "commonjs",
16
+ "main": "./dist/cjs/index.js",
17
+ "module": "./dist/esm/index.js",
18
+ "types": "./dist/cjs/index.d.ts",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/GeunhwaJeong/haneul-ts-sdks.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/MystenLabs/mvr/issues/new"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "devDependencies": {
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^4.0.15",
32
+ "@haneullabs/build-scripts": "0.1.0"
33
+ },
34
+ "dependencies": {
35
+ "@types/node": "^24.10.1",
36
+ "enquirer": "^2.4.1",
37
+ "glob": "^13.0.0",
38
+ "prettier": "^3.7.3",
39
+ "@haneullabs/haneul": "0.1.0"
40
+ },
41
+ "sideEffects": false,
42
+ "bin": "./bin/parser.js",
43
+ "scripts": {
44
+ "clean": "rm -rf tsconfig.tsbuildinfo ./dist",
45
+ "build": "tsc --build",
46
+ "prettier:check": "prettier -c --ignore-unknown .",
47
+ "prettier:fix": "prettier -w --ignore-unknown .",
48
+ "eslint:check": "eslint --max-warnings=0 .",
49
+ "eslint:fix": "pnpm run eslint:check --fix",
50
+ "lint": "pnpm run eslint:check && pnpm run prettier:check",
51
+ "lint:fix": "pnpm run eslint:fix && pnpm run prettier:fix",
52
+ "test": "vitest run"
53
+ }
54
+ }
package/src/execute.ts ADDED
@@ -0,0 +1,5 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { parser } from './parsing.js';
4
+
5
+ parser();
package/src/parsing.ts ADDED
@@ -0,0 +1,320 @@
1
+ // Copyright (c) Mysten Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
4
+ import { readFile } from 'fs/promises';
5
+ import { dirname, extname, isAbsolute, join } from 'path';
6
+ import { parseArgs } from 'util';
7
+ import type { NamedPackagesOverrides } from '@haneullabs/haneul/src/transactions';
8
+ import { isValidNamedPackage } from '@haneullabs/haneul/utils';
9
+ import { prompt } from 'enquirer';
10
+ import { glob } from 'glob';
11
+ import { format } from 'prettier';
12
+
13
+ const TYPES_AND_TARGET_MATCHES = /[@a-zA-Z0-9/.-]+::[a-zA-Z0-9_]+::[a-zA-Z0-9_]+/g;
14
+ const MVR_NAME_MATCHES = /[@a-zA-Z0-9/.-]+::/g;
15
+
16
+ const DEFAULT_INCLUDE_PATTERNS = ['**/*.{js,ts,jsx,tsx,mjs,cjs}'];
17
+ const DEFAULT_EXCLUDE_PATTERNS = ['node_modules/**', '**/.*'];
18
+ const DEFAULT_FILE_NAME = `mvr.ts`;
19
+
20
+ const MAX_BATCH_SIZE = 25; // files to process per batch.
21
+ const MAINNET_API_URL = 'https://mainnet.mvr.haneullabs.com';
22
+ const TESTNET_API_URL = 'https://testnet.mvr.haneullabs.com';
23
+
24
+ const WARNING_MESSAGE = `/**
25
+ * This file is automatically generated by the mvr SDK.
26
+ * You can edit this file, but it will be overwritten on the next run.
27
+ * You should check this file in your version control system.
28
+ *
29
+ * Run this script before building your project to ensure that the mvr.ts file stays up to date.
30
+ *
31
+ * You can use this pre-built cache when initializing your "NamedPackagesPlugin" by calling
32
+ * \`getMvrCache("mainnet")\` or \`getMvrCache("testnet")\`
33
+ */
34
+ `;
35
+
36
+ const { values: args } = parseArgs({
37
+ options: {
38
+ directory: {
39
+ type: 'string',
40
+ default: '.',
41
+ short: 'd',
42
+ },
43
+ output: {
44
+ type: 'string',
45
+ default: DEFAULT_FILE_NAME,
46
+ short: 'o',
47
+ },
48
+ depth: {
49
+ type: 'string',
50
+ default: '10',
51
+ short: 'd',
52
+ },
53
+ 'url-mainnet': {
54
+ type: 'string',
55
+ default: MAINNET_API_URL,
56
+ },
57
+ 'url-testnet': {
58
+ type: 'string',
59
+ default: TESTNET_API_URL,
60
+ },
61
+ include: {
62
+ type: 'string',
63
+ multiple: true,
64
+ default: DEFAULT_INCLUDE_PATTERNS,
65
+ short: 'i',
66
+ },
67
+ exclude: {
68
+ type: 'string',
69
+ multiple: true,
70
+ default: DEFAULT_EXCLUDE_PATTERNS,
71
+ short: 'e',
72
+ },
73
+ force: {
74
+ type: 'boolean',
75
+ default: false,
76
+ short: 'f',
77
+ },
78
+ },
79
+ });
80
+
81
+ export async function parser() {
82
+ const path = isAbsolute(args.output) ? args.output : join(process.cwd(), args.output);
83
+ const dir = dirname(path);
84
+
85
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
86
+
87
+ if (!isSupportedFile(path))
88
+ throw new Error(
89
+ `Unsupported file type: ${path}. Please use a .ts (or equivalent) file name for the output.`,
90
+ );
91
+
92
+ if (existsSync(path) && !args.force) {
93
+ const { overwrite } = (await prompt({
94
+ type: 'confirm',
95
+ name: 'overwrite',
96
+ message: `The file ${path} already exists. Do you want to overwrite it?`,
97
+ })) as { overwrite: boolean };
98
+
99
+ console.log(`Skipping generation of MVR file.`);
100
+ if (!overwrite) return process.exit(1);
101
+ }
102
+
103
+ console.log(`Generating ${args.output}...`);
104
+
105
+ const detectedNames = await findNames({});
106
+
107
+ const { mainnet, testnet } = await crossNetworkResolution(detectedNames);
108
+
109
+ await writeOutputFile(path, mainnet, testnet);
110
+ }
111
+
112
+ async function writeOutputFile(
113
+ outDir: string,
114
+ mainnet: NamedPackagesOverrides,
115
+ testnet: NamedPackagesOverrides,
116
+ ) {
117
+ const outputFile = `${WARNING_MESSAGE}
118
+ const mainnetResolution = ${JSON.stringify(mainnet, null, 2)}
119
+ const testnetResolution = ${JSON.stringify(testnet, null, 2)}
120
+
121
+ export function getMvrCache(network: 'mainnet' | 'testnet') {
122
+ return network === 'mainnet' ? mainnetResolution : testnetResolution;
123
+ }\n
124
+ `;
125
+
126
+ writeFileSync(outDir, await format(outputFile, { parser: 'typescript' }), 'utf8');
127
+ }
128
+
129
+ export async function crossNetworkResolution(detectedNames: Set<string>) {
130
+ const packages = Array.from(detectedNames).filter((x) => !x.includes('::'));
131
+ const types = Array.from(detectedNames).filter((x) => x.includes('::'));
132
+
133
+ const [mainnetPackages, mainnetTypes, testnetPackages, testnetTypes] = await Promise.all([
134
+ resolvePackages(packages, args['url-mainnet']),
135
+ resolveTypes(types, args['url-mainnet']),
136
+ resolvePackages(packages, args['url-testnet']),
137
+ resolveTypes(types, args['url-testnet']),
138
+ ]);
139
+
140
+ return {
141
+ mainnet: {
142
+ packages: mainnetPackages,
143
+ types: mainnetTypes,
144
+ },
145
+ testnet: {
146
+ packages: testnetPackages,
147
+ types: testnetTypes,
148
+ },
149
+ };
150
+ }
151
+
152
+ async function resolvePackages(packages: string[], apiUrl: string) {
153
+ const batches = batch(packages, 50);
154
+
155
+ const results: Record<string, string> = {};
156
+
157
+ await Promise.all(
158
+ batches.map(async (batch) => {
159
+ const response = await fetch(`${apiUrl}/v1/resolution/bulk`, {
160
+ method: 'POST',
161
+ headers: { 'Content-Type': 'application/json' },
162
+ body: JSON.stringify({
163
+ names: batch,
164
+ }),
165
+ });
166
+
167
+ if (!response.ok) {
168
+ const errorBody = await response.json().catch(() => ({}));
169
+ throw new Error(`Failed to resolve packages: ${errorBody?.message}`);
170
+ }
171
+
172
+ const data = await response.json();
173
+
174
+ if (!data?.resolution) return;
175
+
176
+ for (const pkg of Object.keys(data?.resolution)) {
177
+ const pkgData = data.resolution[pkg]?.package_id;
178
+
179
+ if (!pkgData) continue;
180
+
181
+ results[pkg] = pkgData;
182
+ }
183
+ }),
184
+ );
185
+
186
+ return results;
187
+ }
188
+
189
+ // TODO: Switch to `/struct-definition/bulk` endpoint when released,
190
+ // as this endpoint will be the right one for "non-nested" struct resolution.
191
+ // The current endpoint will fail with "generic" parameter lookups (which are not existent)
192
+ // on this parser.
193
+ async function resolveTypes(types: string[], apiUrl: string) {
194
+ const batches = batch(types, 50);
195
+
196
+ const results: Record<string, string> = {};
197
+
198
+ await Promise.all(
199
+ batches.map(async (batch) => {
200
+ const response = await fetch(`${apiUrl}/v1/struct-definition/bulk`, {
201
+ method: 'POST',
202
+ headers: { 'Content-Type': 'application/json' },
203
+ body: JSON.stringify({
204
+ types: batch,
205
+ }),
206
+ });
207
+
208
+ if (!response.ok) {
209
+ const errorBody = await response.json().catch(() => ({}));
210
+ throw new Error(`Failed to resolve types: ${errorBody?.message}`);
211
+ }
212
+
213
+ const data = await response.json();
214
+
215
+ if (!data?.resolution) return;
216
+
217
+ for (const type of Object.keys(data?.resolution)) {
218
+ const typeData = data.resolution[type]?.type_tag;
219
+ if (!typeData) continue;
220
+
221
+ results[type] = typeData;
222
+ }
223
+ }),
224
+ );
225
+
226
+ return results;
227
+ }
228
+
229
+ /**
230
+ * Finds all the MVR names in the given directory.
231
+ * @param directory - The directory to search for MVR names.
232
+ * @returns A set of all the MVR names found in the directory.
233
+ */
234
+ export async function findNames({
235
+ directory = args.directory,
236
+ include = args.include,
237
+ exclude = args.exclude,
238
+ depth = parseInt(args.depth),
239
+ output = args.output,
240
+ }: {
241
+ directory?: string;
242
+ include?: string[];
243
+ exclude?: string[];
244
+ depth?: number;
245
+ output?: string;
246
+ }) {
247
+ const detectedNames = new Set<string>();
248
+ const excluded = [...exclude, output];
249
+
250
+ const files = glob.sync(include, {
251
+ ignore: excluded,
252
+ cwd: directory,
253
+ maxDepth: depth,
254
+ absolute: true,
255
+ });
256
+
257
+ // We batch the files to avoid trying to open too many files at once.
258
+ const batches = batch(files);
259
+
260
+ for (const batch of batches) {
261
+ await processFilesBatch(batch, detectedNames);
262
+ }
263
+
264
+ return detectedNames;
265
+ }
266
+
267
+ /**
268
+ * Finds all the MVR names in the given files.
269
+ */
270
+ async function processFilesBatch(files: string[], detectedNames: Set<string>) {
271
+ await Promise.all(
272
+ files.map(async (file) => {
273
+ const content = await readFile(file, 'utf8');
274
+ extractMvrNames(content).forEach((name) => detectedNames.add(name));
275
+ }),
276
+ );
277
+ }
278
+
279
+ /**
280
+ * Extracts all the MVR names from the given file's data (content).
281
+ */
282
+ function extractMvrNames(content: string) {
283
+ const relevantNames = new Set<string>();
284
+ // find all "fully qualified" matches.
285
+ const fullQualifiedMatches = [...content.matchAll(TYPES_AND_TARGET_MATCHES)];
286
+ fullQualifiedMatches.forEach((match) => {
287
+ const [pkg] = match[0].split('::');
288
+
289
+ if (!isValidNamedPackage(pkg)) return;
290
+
291
+ relevantNames.add(match[0]);
292
+ });
293
+
294
+ // find all "plain" name matches
295
+ const plainNameMatches = [...content.matchAll(MVR_NAME_MATCHES)];
296
+ plainNameMatches.forEach((match) => {
297
+ const [pkg] = match[0].split('::');
298
+ if (!isValidNamedPackage(pkg)) return;
299
+
300
+ relevantNames.add(pkg);
301
+ });
302
+
303
+ return relevantNames;
304
+ }
305
+
306
+ /**
307
+ * Batch the given array into smaller arrays of the given size.
308
+ */
309
+ function batch<T>(array: T[], batchSize: number = MAX_BATCH_SIZE) {
310
+ const result = [];
311
+ for (let i = 0; i < array.length; i += batchSize) {
312
+ result.push(array.slice(i, i + batchSize)); // Create batches
313
+ }
314
+ return result;
315
+ }
316
+
317
+ function isSupportedFile(filePath: string) {
318
+ const ext = extname(filePath).toLowerCase();
319
+ return ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'].includes(ext);
320
+ }