motoko 3.0.0-beta0 → 3.0.0-beta2

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.
@@ -17,24 +17,25 @@ declare const _default: {
17
17
  };
18
18
  candid(): string;
19
19
  wasm(mode: import("..").WasmMode): any;
20
- parseMotoko(): {
21
- ast: object;
22
- exportType: object;
23
- };
24
- parseCandid(): {
25
- ast: object;
20
+ parseMotoko(): import("../ast").Node;
21
+ parseMotokoTyped(): {
22
+ ast: import("../ast").Node;
23
+ type: import("../ast").Node;
26
24
  };
25
+ parseCandid(): object;
27
26
  };
28
27
  read(path: string): string;
29
28
  write(path: string, content?: string): void;
30
29
  rename(path: string, newPath: string): void;
31
30
  delete(path: string): void;
32
31
  list(directory: string): string[];
33
- fetchPackage(info: string | import("../package").PackageInfo): Promise<import("../package").Package>;
34
- loadPackages(packages: Record<string, string | import("../package").PackageInfo>): Promise<void>;
35
- addPackage(name: string, directory: string): void;
32
+ fetchPackage(name: string, info: string | import("../package").PackageInfo): Promise<import("../package").Package>;
33
+ installPackages(packages: Record<string, string | import("../package").PackageInfo>): Promise<void>;
34
+ loadPackage(pkg: import("../package").Package): void;
35
+ usePackage(name: string, directory: string): void;
36
36
  clearPackages(): void;
37
- setAliases(aliases: string): void;
37
+ validatePackage(pkg: import("../package").Package): void;
38
+ setAliases(aliases: Record<string, string>): void;
38
39
  setMetadata(values: string): void;
39
40
  check(path: string): import("..").Diagnostic[];
40
41
  run(path: string, libPaths?: string[]): {
@@ -44,13 +45,14 @@ declare const _default: {
44
45
  };
45
46
  candid(path: string): string;
46
47
  wasm(path: string, mode: import("..").WasmMode): any;
47
- parseMotoko(content: string): {
48
- ast: object;
49
- exportType: object;
50
- };
51
- parseCandid(content: string): {
52
- ast: object;
48
+ parseMotoko(content: string): import("../ast").Node;
49
+ parseMotokoTyped(content: string): {
50
+ ast: import("../ast").Node;
51
+ type: import("../ast").Node;
53
52
  };
53
+ parseCandid(content: string): object;
54
+ resolveMain(directory?: string): string;
55
+ resolveLib(directory?: string): string;
54
56
  };
55
57
  export default _default;
56
58
  //# sourceMappingURL=interpreter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interpreter.d.ts","sourceRoot":"","sources":["../../src/versions/interpreter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,wBAAwD"}
1
+ {"version":3,"file":"interpreter.d.ts","sourceRoot":"","sources":["../../src/versions/interpreter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,wBAAwD"}
@@ -17,24 +17,25 @@ declare const _default: {
17
17
  };
18
18
  candid(): string;
19
19
  wasm(mode: import("..").WasmMode): any;
20
- parseMotoko(): {
21
- ast: object;
22
- exportType: object;
23
- };
24
- parseCandid(): {
25
- ast: object;
20
+ parseMotoko(): import("../ast").Node;
21
+ parseMotokoTyped(): {
22
+ ast: import("../ast").Node;
23
+ type: import("../ast").Node;
26
24
  };
25
+ parseCandid(): object;
27
26
  };
28
27
  read(path: string): string;
29
28
  write(path: string, content?: string): void;
30
29
  rename(path: string, newPath: string): void;
31
30
  delete(path: string): void;
32
31
  list(directory: string): string[];
33
- fetchPackage(info: string | import("../package").PackageInfo): Promise<import("../package").Package>;
34
- loadPackages(packages: Record<string, string | import("../package").PackageInfo>): Promise<void>;
35
- addPackage(name: string, directory: string): void;
32
+ fetchPackage(name: string, info: string | import("../package").PackageInfo): Promise<import("../package").Package>;
33
+ installPackages(packages: Record<string, string | import("../package").PackageInfo>): Promise<void>;
34
+ loadPackage(pkg: import("../package").Package): void;
35
+ usePackage(name: string, directory: string): void;
36
36
  clearPackages(): void;
37
- setAliases(aliases: string): void;
37
+ validatePackage(pkg: import("../package").Package): void;
38
+ setAliases(aliases: Record<string, string>): void;
38
39
  setMetadata(values: string): void;
39
40
  check(path: string): import("..").Diagnostic[];
40
41
  run(path: string, libPaths?: string[]): {
@@ -44,13 +45,14 @@ declare const _default: {
44
45
  };
45
46
  candid(path: string): string;
46
47
  wasm(path: string, mode: import("..").WasmMode): any;
47
- parseMotoko(content: string): {
48
- ast: object;
49
- exportType: object;
50
- };
51
- parseCandid(content: string): {
52
- ast: object;
48
+ parseMotoko(content: string): import("../ast").Node;
49
+ parseMotokoTyped(content: string): {
50
+ ast: import("../ast").Node;
51
+ type: import("../ast").Node;
53
52
  };
53
+ parseCandid(content: string): object;
54
+ resolveMain(directory?: string): string;
55
+ resolveLib(directory?: string): string;
54
56
  };
55
57
  export default _default;
56
58
  //# sourceMappingURL=moc.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"moc.d.ts","sourceRoot":"","sources":["../../src/versions/moc.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,wBAA4C"}
1
+ {"version":3,"file":"moc.d.ts","sourceRoot":"","sources":["../../src/versions/moc.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,wBAA4C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "motoko",
3
- "version": "3.0.0-beta0",
3
+ "version": "3.0.0-beta2",
4
4
  "description": "Compile and run Motoko smart contracts in Node.js or the browser.",
5
5
  "author": "Ryan Vandersmith (https://github.com/rvanasa)",
6
6
  "license": "Apache-2.0",
@@ -21,7 +21,8 @@
21
21
  "dependencies": {
22
22
  "cross-fetch": "3.1.5",
23
23
  "debug": "4.3.4",
24
- "isomorphic-parse-github-url": "1.0.2"
24
+ "isomorphic-parse-github-url": "1.0.2",
25
+ "sanitize-filename": "^1.6.3"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@types/jest": "^28.1.3",
package/src/ast.ts ADDED
@@ -0,0 +1,69 @@
1
+ export type CompilerAST = CompilerAST[] | CompilerNode | string | null;
2
+ export type CompilerSpan = { name: 'Pos'; args: [string, string, string] };
3
+
4
+ export interface CompilerNode {
5
+ name: string;
6
+ args: CompilerAST[];
7
+ }
8
+
9
+ export type Span = [number, number];
10
+ export type AST = AST[] | Node | string | null;
11
+
12
+ export interface Node {
13
+ name: string;
14
+ file?: string;
15
+ start?: Span;
16
+ end?: Span;
17
+ type?: Node;
18
+ args?: AST[];
19
+ }
20
+
21
+ // export type TypeAST = AST[] | Node | string | number | null;
22
+ // export type TypeNode = {
23
+ // name: string;
24
+ // args: TypeAST[];
25
+ // };
26
+
27
+ export function simplifyAST(ast: CompilerNode): Node;
28
+ export function simplifyAST(ast: CompilerAST[]): AST[];
29
+ export function simplifyAST<T extends CompilerAST>(ast: T): T;
30
+
31
+ export function simplifyAST(ast: CompilerAST): AST {
32
+ if (Array.isArray(ast)) {
33
+ return ast.map((a) => simplifyAST(a));
34
+ }
35
+ if (typeof ast !== 'object') {
36
+ return ast;
37
+ }
38
+ if (ast.name === '@') {
39
+ const [start, end, subAst] = ast.args as [
40
+ CompilerSpan,
41
+ CompilerSpan,
42
+ CompilerAST,
43
+ ];
44
+ return {
45
+ ...(typeof subAst === 'string'
46
+ ? { name: subAst }
47
+ : simplifyAST(subAst)),
48
+ file: start.args[0],
49
+ start: [+start.args[1], +start.args[2]],
50
+ end: [+end.args[1], +end.args[2]],
51
+ };
52
+ }
53
+ if (ast.name === ':') {
54
+ const [type, subAst] = ast.args as [CompilerNode, CompilerAST];
55
+ // console.log(subAst); ////
56
+ return {
57
+ ...(typeof subAst === 'string'
58
+ ? { name: subAst }
59
+ : simplifyAST(subAst)),
60
+ type: simplifyAST(type),
61
+ };
62
+ }
63
+ return {
64
+ name: ast.name,
65
+ args: simplifyAST(ast.args),
66
+ };
67
+ }
68
+
69
+ // export function getTypeString(type: Type) {}
package/src/file.ts CHANGED
@@ -60,6 +60,9 @@ export const file = (mo: Motoko, path: string) => {
60
60
  parseMotoko() {
61
61
  return mo.parseMotoko(result.read());
62
62
  },
63
+ parseMotokoTyped() {
64
+ return mo.parseMotokoTyped(result.read());
65
+ },
63
66
  parseCandid() {
64
67
  return mo.parseCandid(result.read());
65
68
  },
package/src/index.ts CHANGED
@@ -1,5 +1,13 @@
1
+ import { Node, simplifyAST } from './ast';
1
2
  import { file } from './file';
2
- import { fetchPackage, loadPackages, PackageInfo } from './package';
3
+ import {
4
+ fetchPackage,
5
+ installPackages,
6
+ Package,
7
+ PackageInfo,
8
+ validatePackage,
9
+ } from './package';
10
+ import { resolveMain, resolveLib } from './utils/resolveEntryPoint';
3
11
 
4
12
  export type Motoko = ReturnType<typeof wrapMotoko>;
5
13
 
@@ -21,7 +29,7 @@ export type Diagnostic = {
21
29
  export type WasmMode = 'ic' | 'wasi';
22
30
 
23
31
  export default function wrapMotoko(compiler: Compiler, version: string) {
24
- const debug = require('debug')(version ? `motoko:${version}` : 'motoko');
32
+ const debug = require('debug')(`motoko:${version}`);
25
33
 
26
34
  const invoke = (key: string, unwrap: boolean, args: any[]) => {
27
35
  if (!compiler) {
@@ -86,21 +94,36 @@ export default function wrapMotoko(compiler: Compiler, version: string) {
86
94
  list(directory: string): string[] {
87
95
  return invoke('readDir', false, [directory]);
88
96
  },
89
- async fetchPackage(info: string | PackageInfo) {
90
- return fetchPackage(info);
91
- },
92
- async loadPackages(packages: Record<string, string | PackageInfo>) {
93
- return loadPackages(mo, packages);
94
- },
95
- addPackage(name: string, directory: string) {
96
- debug('+package', name, directory);
97
+ async fetchPackage(name:string, info: string | PackageInfo) {
98
+ if(!info){
99
+ throw new Error('Please specify both a name and source');
100
+ }
101
+ return fetchPackage(name,info);
102
+ },
103
+ async installPackages(packages: Record<string, string | PackageInfo>) {
104
+ return installPackages(mo, packages);
105
+ },
106
+ loadPackage(pkg: Package) {
107
+ debug('+package', pkg.name);
108
+ mo.validatePackage(pkg);
109
+ const directory = `.node-motoko/${pkg.name}/${pkg.version}`;
110
+ Object.entries(pkg.files).forEach(([path, file]) => {
111
+ mo.write(`${directory}/${path}`, file.content);
112
+ });
113
+ mo.usePackage(pkg.name, directory);
114
+ },
115
+ usePackage(name: string, directory: string) {
116
+ debug('@package', name, directory);
97
117
  invoke('addPackage', false, [name, directory]);
98
118
  },
99
119
  clearPackages() {
100
120
  debug('-packages');
101
121
  invoke('clearPackage', false, []);
102
122
  },
103
- setAliases(aliases: string) {
123
+ validatePackage(pkg: Package) {
124
+ validatePackage(pkg);
125
+ },
126
+ setAliases(aliases: Record<string, string>) {
104
127
  debug('aliases', aliases);
105
128
  invoke('setActorAliases', false, [Object.entries(aliases)]);
106
129
  },
@@ -128,12 +151,26 @@ export default function wrapMotoko(compiler: Compiler, version: string) {
128
151
  }
129
152
  return invoke('compileWasm', true, [mode, path]);
130
153
  },
131
- parseMotoko(content: string): { ast: object; exportType: object } {
132
- return invoke('parseMotoko', true, [content]);
154
+ parseMotoko(content: string): Node {
155
+ const ast = invoke('parseMotoko', true, [content]);
156
+ return simplifyAST(ast);
133
157
  },
134
- parseCandid(content: string): { ast: object } {
158
+ parseMotokoTyped(content: string): { ast: Node; type: Node } {
159
+ const { ast, typ } = invoke('parseMotokoTyped', true, [content]);
160
+ return {
161
+ ast: simplifyAST(ast),
162
+ type: simplifyAST(typ),
163
+ };
164
+ },
165
+ parseCandid(content: string): object {
135
166
  return invoke('parseCandid', true, [content]);
136
167
  },
168
+ resolveMain(directory: string = ''): string | undefined {
169
+ return resolveMain(mo, directory);
170
+ },
171
+ resolveLib(directory: string = ''): string | undefined {
172
+ return resolveLib(mo, directory);
173
+ },
137
174
  };
138
175
  // @ts-ignore
139
176
  mo.default = mo;
package/src/package.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  import { default as parse } from 'isomorphic-parse-github-url';
5
5
  import fetch from 'cross-fetch';
6
6
  import { Motoko } from '.';
7
+ import sanitize from 'sanitize-filename';
7
8
 
8
9
  export interface PackageInfo {
9
10
  name: string;
@@ -42,7 +43,7 @@ async function loadPackage(mo: Motoko, info: PackageInfo) {
42
43
  };
43
44
  const result = await fetchGithub_(mo, repo, info.name);
44
45
  if (result) {
45
- mo.addPackage(info.name, info.name + '/');
46
+ mo.usePackage(info.name, info.name + '/');
46
47
  }
47
48
  return result ? true : false;
48
49
  }
@@ -279,6 +280,7 @@ async function fetchFromService(
279
280
  }
280
281
 
281
282
  export async function fetchPackage(
283
+ name: string,
282
284
  info: string | PackageInfo,
283
285
  ): Promise<Package | undefined> {
284
286
  if (typeof info === 'string') {
@@ -289,13 +291,13 @@ export async function fetchPackage(
289
291
  return;
290
292
  }
291
293
  return {
292
- name: info.name,
294
+ name,
293
295
  version: info.version,
294
296
  files,
295
297
  };
296
298
  }
297
299
 
298
- export async function loadPackages(
300
+ export async function installPackages(
299
301
  mo: Motoko,
300
302
  packages: Record<string, string | PackageInfo>,
301
303
  ) {
@@ -309,3 +311,54 @@ export async function loadPackages(
309
311
  }),
310
312
  );
311
313
  }
314
+
315
+ export function validatePackage(pkg: Package) {
316
+ function showValue(value: any) {
317
+ const string = JSON.stringify(value);
318
+ return string.length > 50 ? string.substring(0, 50) + '...' : string;
319
+ }
320
+ function getPackageDisplayName() {
321
+ return `(${pkg.name} / ${pkg.version})`;
322
+ }
323
+
324
+ if (typeof pkg !== 'object' || Array.isArray(pkg)) {
325
+ throw new Error(`Unexpected package: ${showValue(pkg)}`);
326
+ }
327
+ if (typeof pkg.name !== 'string' || sanitize(pkg.name) !== pkg.name) {
328
+ throw new Error(`Invalid package name ${getPackageDisplayName()}`);
329
+ }
330
+ if (
331
+ typeof pkg.version !== 'string' ||
332
+ sanitize(pkg.version) !== pkg.version
333
+ ) {
334
+ throw new Error(`Invalid package version ${getPackageDisplayName()}`);
335
+ }
336
+ if (typeof pkg.files !== 'object' || Array.isArray(pkg.files)) {
337
+ throw new Error(`Invalid package files: ${showValue(pkg.files)}`);
338
+ }
339
+
340
+ Object.entries(pkg.files).forEach(([path, file]) => {
341
+ if (
342
+ typeof path !== 'string' ||
343
+ path.split('/').some((p) => sanitize(p) !== p)
344
+ ) {
345
+ throw new Error(
346
+ `Invalid file path ${getPackageDisplayName()} [${path}]`,
347
+ );
348
+ }
349
+ if (typeof file !== 'object' || Array.isArray(file)) {
350
+ throw new Error(
351
+ `Invalid file ${getPackageDisplayName()} [${path}]: ${showValue(
352
+ file,
353
+ )}`,
354
+ );
355
+ }
356
+ if (typeof file.content !== 'string') {
357
+ throw new Error(
358
+ `Invalid file content ${getPackageDisplayName()} [${path}]: ${showValue(
359
+ file.content,
360
+ )}`,
361
+ );
362
+ }
363
+ });
364
+ }
@@ -0,0 +1,64 @@
1
+ import { Motoko } from '..';
2
+
3
+ // function getOne<T>(values: T[]): T | undefined {
4
+ // if (values.length) {
5
+ // return values[0];
6
+ // }
7
+ // }
8
+
9
+ function resolveEntryPoint(
10
+ mo: Motoko,
11
+ directory: string,
12
+ expected: string,
13
+ ): string {
14
+ directory = directory || '';
15
+ if (directory && !directory.endsWith('/')) {
16
+ directory += '/';
17
+ }
18
+
19
+ const moFiles = mo.list(directory).filter((f) => /\.mo$/i.test(f));
20
+ if (moFiles.length === 1) {
21
+ return moFiles[0];
22
+ } else if (moFiles.length === 0) {
23
+ throw new Error(
24
+ 'Could not find any Motoko files in the top-level directory',
25
+ );
26
+ }
27
+
28
+ const expectedFiles = moFiles.filter(
29
+ (f) => f.toLowerCase() === expected.toLowerCase(),
30
+ );
31
+ if (expectedFiles.length === 1) {
32
+ return expectedFiles[0];
33
+ } else if (expectedFiles.length > 1) {
34
+ throw new Error(
35
+ `Found ${expectedFiles.length} entry point files with different capitalization`,
36
+ );
37
+ }
38
+
39
+ throw new Error(
40
+ `Found ${moFiles.length} possible entry points. Please rename one of these files to '${expected}'`,
41
+ );
42
+
43
+ // TODO: evaluate whether we want to choose an entry point by parsing files
44
+
45
+ // const parsedFiles = moFiles.map((f) => {
46
+ // try {
47
+ // return mo.parseMotoko(mo.read(directory + f));
48
+ // } catch (err) {
49
+ // throw new Error(`Parse error in ${f}`);
50
+ // }
51
+ // });
52
+
53
+ // console.log(parsedFiles);
54
+
55
+ // return getOne(parsedFiles.filter());
56
+ }
57
+
58
+ export function resolveMain(mo: Motoko, directory: string): string {
59
+ return resolveEntryPoint(mo, directory, 'Main.mo');
60
+ }
61
+
62
+ export function resolveLib(mo: Motoko, directory: string): string {
63
+ return resolveEntryPoint(mo, directory, 'Lib.mo');
64
+ }