motoko 1.0.1 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
package/lib/index.js ADDED
@@ -0,0 +1,120 @@
1
+ 'use strict';
2
+
3
+ const { file } = require('./file');
4
+ const { /* findPackage, */ loadPackages } = require('./package');
5
+
6
+ module.exports = (compiler, version) => {
7
+ const debug = require('debug')(version ? `motoko:${version}` : 'motoko');
8
+
9
+ const invoke = (key, unwrap, args) => {
10
+ if (!compiler) {
11
+ throw new Error(
12
+ 'Please load a Motoko compiler before running this function',
13
+ );
14
+ }
15
+ if (typeof compiler[key] !== 'function') {
16
+ throw new Error(`Unknown compiler function: '${key}'`);
17
+ }
18
+ let result;
19
+ try {
20
+ result = compiler[key](...args);
21
+ } catch (err) {
22
+ if (err instanceof Error) {
23
+ throw err;
24
+ }
25
+ throw new Error(
26
+ `Unable to execute ${key}(${[...args]
27
+ .map((x) => typeof x)
28
+ .join(', ')}):\n${JSON.stringify(err)}`,
29
+ );
30
+ }
31
+ if (!unwrap) {
32
+ return result;
33
+ }
34
+ if (!result.code) {
35
+ throw new Error(
36
+ result.diagnostics
37
+ ? result.diagnostics
38
+ .map(({ message }) => message)
39
+ .join('; ')
40
+ : '(no diagnostics)',
41
+ );
42
+ }
43
+ return result.code;
44
+ };
45
+
46
+ const mo = {
47
+ version,
48
+ compiler,
49
+ file(path) {
50
+ return file(mo, path);
51
+ },
52
+ // findPackage,
53
+ async loadPackages(packages) {
54
+ return loadPackages(mo, packages);
55
+ },
56
+ read(path) {
57
+ return invoke('readFile', false, [path]);
58
+ },
59
+ write(path, content = '') {
60
+ if (typeof content !== 'string') {
61
+ throw new Error('Non-string file content');
62
+ }
63
+ debug('+file', path);
64
+ invoke('saveFile', false, [path, content]);
65
+ },
66
+ rename(path, newPath) {
67
+ invoke('renameFile', false, [path, newPath]);
68
+ },
69
+ delete(path) {
70
+ debug('-file', path);
71
+ invoke('removeFile', false, [path]);
72
+ },
73
+ list(directory) {
74
+ return invoke('readDir', false, [directory]);
75
+ },
76
+ addPackage(name, directory) {
77
+ debug('+package', name, directory);
78
+ invoke('addPackage', false, [name, directory]);
79
+ },
80
+ clearPackages() {
81
+ debug('-packages');
82
+ invoke('clearPackage', false, []);
83
+ },
84
+ setAliases(aliases) {
85
+ debug('aliases', aliases);
86
+ invoke('setActorAliases', false, [Object.entries(aliases)]);
87
+ },
88
+ setMetadata(values) {
89
+ invoke('setPublicMetadata', false, [values]);
90
+ },
91
+ check(path) {
92
+ const result = invoke('check', false, [path]);
93
+ return result.diagnostics;
94
+ },
95
+ run(path, libPaths) {
96
+ return invoke('run', false, [libPaths || [], path]);
97
+ },
98
+ candid(path) {
99
+ return invoke('candid', true, [path]);
100
+ },
101
+ wasm(path, mode) {
102
+ if (!mode) {
103
+ mode = 'ic';
104
+ } else if (mode !== 'ic' && mode !== 'wasi') {
105
+ throw new Error(`Invalid WASM format: ${mode}`);
106
+ }
107
+ return invoke('compileWasm', true, [mode, path]);
108
+ },
109
+ parseMotoko(content) {
110
+ const ast = invoke('parseMotoko', true, [content]);
111
+ return ast;
112
+ },
113
+ parseCandid(content) {
114
+ const ast = invoke('parseCandid', true, [content]);
115
+ return ast;
116
+ },
117
+ };
118
+ return mo;
119
+ };
120
+ exports.default = exports;
package/lib/package.js ADDED
@@ -0,0 +1,163 @@
1
+ 'use strict';
2
+ // Derived from: https://github.com/dfinity/motoko-playground/blob/main/src/workers/file.ts
3
+
4
+ const parse = require('isomorphic-parse-github-url');
5
+ const fetch = require('cross-fetch');
6
+
7
+ async function fetchPackage(mo, info) {
8
+ if (
9
+ !info.repo.startsWith('https://github.com/') ||
10
+ !info.repo.endsWith('.git')
11
+ ) {
12
+ return false;
13
+ }
14
+ const repo = {
15
+ repo: info.repo.slice(0, -4).replace(/^(https:\/\/github.com\/)/, ''),
16
+ branch: info.version,
17
+ dir: info.dir || 'src',
18
+ };
19
+ const result = await fetchGithub(mo, repo, info.name);
20
+ if (result) {
21
+ mo.addPackage(info.name, info.name + '/');
22
+ }
23
+ return result ? true : false;
24
+ }
25
+
26
+ async function fetchGithub(mo, repo, directory = '') {
27
+ const possiblyCDN = !(
28
+ (repo.branch.length % 2 === 0 && /^[A-F0-9]+$/i.test(repo.branch)) ||
29
+ repo.branch === 'master' ||
30
+ repo.branch === 'main'
31
+ );
32
+ if (possiblyCDN) {
33
+ const result = await fetchFromCDN(repo, directory);
34
+ if (result) {
35
+ return result;
36
+ }
37
+ }
38
+ return await fetchFromGithub(mo, repo, directory);
39
+ }
40
+
41
+ // function saveWorkplaceToMotoko(mo, files) {
42
+ // for (const [name, code] of Object.entries(files)) {
43
+ // if (!name.endsWith('mo')) continue;
44
+ // mo.addFile(name, code);
45
+ // }
46
+ // }
47
+
48
+ async function fetchFromCDN(mo, repo, directory = '') {
49
+ const meta_url = `https://data.jsdelivr.com/v1/package/gh/${repo.repo}@${repo.branch}/flat`;
50
+ const base_url = `https://cdn.jsdelivr.net/gh/${repo.repo}@${repo.branch}`;
51
+ const response = await fetch(meta_url);
52
+ const json = await response.json();
53
+ if (!json.hasOwnProperty('files')) {
54
+ throw new Error(json.message || `Could not fetch from CDN: ${repo}`);
55
+ }
56
+ const promises = [];
57
+ const files = {};
58
+ for (const f of json.files) {
59
+ if (f.name.startsWith(`/${repo.dir}/`) && /\.mo$/.test(f.name)) {
60
+ const promise = (async () => {
61
+ const content = await (await fetch(base_url + f.name)).text();
62
+ const stripped =
63
+ directory +
64
+ f.name.slice(repo.dir ? repo.dir.length + 1 : 0);
65
+ mo.write(stripped, content);
66
+ files[stripped] = content;
67
+ })();
68
+ promises.push(promise);
69
+ }
70
+ }
71
+ if (!promises.length) {
72
+ return;
73
+ }
74
+ return Promise.all(promises).then(() => {
75
+ return files;
76
+ });
77
+ }
78
+
79
+ async function fetchFromGithub(mo, repo, directory = '') {
80
+ const meta_url = `https://api.github.com/repos/${repo.repo}/git/trees/${repo.branch}?recursive=1`;
81
+ const base_url = `https://raw.githubusercontent.com/${repo.repo}/${repo.branch}/`;
82
+ const response = await fetch(meta_url);
83
+ const json = await response.json();
84
+ if (!json.hasOwnProperty('tree')) {
85
+ throw new Error(
86
+ json.message || `Could not fetch from GitHub repository: ${repo}`,
87
+ );
88
+ }
89
+ const promises = [];
90
+ const files = {};
91
+ for (const f of json.tree) {
92
+ if (
93
+ f.path.startsWith(repo.dir ? `${repo.dir}/` : '') &&
94
+ f.type === 'blob' &&
95
+ /\.mo$/.test(f.path)
96
+ ) {
97
+ const promise = (async () => {
98
+ const content = await (await fetch(base_url + f.path)).text();
99
+ const stripped =
100
+ directory +
101
+ (directory ? '/' : '') +
102
+ f.path.slice(repo.dir ? repo.dir.length + 1 : 0);
103
+ mo.write(stripped, content);
104
+ files[stripped] = content;
105
+ })();
106
+ promises.push(promise);
107
+ }
108
+ }
109
+ if (!promises.length) {
110
+ return;
111
+ }
112
+ return Promise.all(promises).then(() => {
113
+ return files;
114
+ });
115
+ }
116
+
117
+ // async function resolve(path) {
118
+
119
+ // }
120
+
121
+ function parseGithubPackage(path, name) {
122
+ if (!path) {
123
+ return;
124
+ }
125
+ if (typeof path === 'object') {
126
+ return path;
127
+ }
128
+
129
+ let result;
130
+ try {
131
+ result = parse(path);
132
+ if (!result) {
133
+ return;
134
+ }
135
+ } catch (err) {
136
+ console.warn(err);
137
+ }
138
+
139
+ const { name: repoName, filepath, branch, owner } = result;
140
+
141
+ return {
142
+ name: name || repoName,
143
+ repo: `https://github.com/${owner}/${repoName}.git`,
144
+ version: branch,
145
+ dir: filepath,
146
+ // homepage: ,
147
+ };
148
+ }
149
+
150
+ module.exports = {
151
+ // async findPackage(package) {
152
+ // if (typeof package === 'string') {
153
+ // return resolve(package);
154
+ // }
155
+ // return package;
156
+ // },
157
+ loadPackages: async (mo, packages) => {
158
+ for (const [name, path] of Object.entries(packages)) {
159
+ const info = parseGithubPackage(path, name);
160
+ return fetchPackage(mo, info);
161
+ }
162
+ },
163
+ };
package/package.json CHANGED
@@ -1,12 +1,53 @@
1
1
  {
2
- "name": "motoko",
3
- "version": "1.0.1",
4
- "description": "",
5
- "main": "motoko.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
- },
9
- "keywords": [],
10
- "author": "",
11
- "license": "ISC"
2
+ "name": "motoko",
3
+ "version": "2.0.4",
4
+ "description": "Compile Motoko smart contracts in Node.js and the browser.",
5
+ "author": "Ryan Vandersmith (https://github.com/rvanasa)",
6
+ "license": "Apache-2.0",
7
+ "main": "./index.js",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/dfinity/node-motoko.git"
11
+ },
12
+ "scripts": {
13
+ "generate": "node utils/generate",
14
+ "test": "jest"
15
+ },
16
+ "dependencies": {
17
+ "cross-fetch": "3.1.5",
18
+ "isomorphic-parse-github-url": "1.0.2"
19
+ },
20
+ "devDependencies": {
21
+ "@wasmer/wasi": "^1.0.2",
22
+ "cross-env": "^7.0.3",
23
+ "jest": "^28.1.3",
24
+ "prettier": "^2.7.1"
25
+ },
26
+ "directories": {
27
+ "lib": "lib",
28
+ "example": "examples"
29
+ },
30
+ "files": [
31
+ "index.js",
32
+ "interpreter.js",
33
+ "lib",
34
+ "contrib",
35
+ "versions/latest"
36
+ ],
37
+ "keywords": [
38
+ "motoko",
39
+ "language",
40
+ "programming-language",
41
+ "dfinity",
42
+ "smart-contract",
43
+ "canister",
44
+ "browser",
45
+ "ic",
46
+ "icp",
47
+ "internet-computer",
48
+ "blockchain",
49
+ "cryptocurrency",
50
+ "nft",
51
+ "token"
52
+ ]
12
53
  }