motoko 3.0.0-beta1 → 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.
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,8 +60,8 @@ export const file = (mo: Motoko, path: string) => {
60
60
  parseMotoko() {
61
61
  return mo.parseMotoko(result.read());
62
62
  },
63
- parseMotokoTypes() {
64
- return mo.parseMotokoTypes(result.read());
63
+ parseMotokoTyped() {
64
+ return mo.parseMotokoTyped(result.read());
65
65
  },
66
66
  parseCandid() {
67
67
  return mo.parseCandid(result.read());
package/src/index.ts CHANGED
@@ -1,5 +1,12 @@
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';
3
10
  import { resolveMain, resolveLib } from './utils/resolveEntryPoint';
4
11
 
5
12
  export type Motoko = ReturnType<typeof wrapMotoko>;
@@ -22,7 +29,7 @@ export type Diagnostic = {
22
29
  export type WasmMode = 'ic' | 'wasi';
23
30
 
24
31
  export default function wrapMotoko(compiler: Compiler, version: string) {
25
- const debug = require('debug')(version ? `motoko:${version}` : 'motoko');
32
+ const debug = require('debug')(`motoko:${version}`);
26
33
 
27
34
  const invoke = (key: string, unwrap: boolean, args: any[]) => {
28
35
  if (!compiler) {
@@ -87,21 +94,36 @@ export default function wrapMotoko(compiler: Compiler, version: string) {
87
94
  list(directory: string): string[] {
88
95
  return invoke('readDir', false, [directory]);
89
96
  },
90
- async fetchPackage(info: string | PackageInfo) {
91
- return fetchPackage(info);
92
- },
93
- async loadPackages(packages: Record<string, string | PackageInfo>) {
94
- return loadPackages(mo, packages);
95
- },
96
- addPackage(name: string, directory: string) {
97
- 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);
98
117
  invoke('addPackage', false, [name, directory]);
99
118
  },
100
119
  clearPackages() {
101
120
  debug('-packages');
102
121
  invoke('clearPackage', false, []);
103
122
  },
104
- setAliases(aliases: string) {
123
+ validatePackage(pkg: Package) {
124
+ validatePackage(pkg);
125
+ },
126
+ setAliases(aliases: Record<string, string>) {
105
127
  debug('aliases', aliases);
106
128
  invoke('setActorAliases', false, [Object.entries(aliases)]);
107
129
  },
@@ -129,11 +151,16 @@ export default function wrapMotoko(compiler: Compiler, version: string) {
129
151
  }
130
152
  return invoke('compileWasm', true, [mode, path]);
131
153
  },
132
- parseMotoko(content: string): object {
133
- return invoke('parseMotoko', true, [content]);
154
+ parseMotoko(content: string): Node {
155
+ const ast = invoke('parseMotoko', true, [content]);
156
+ return simplifyAST(ast);
134
157
  },
135
- parseMotokoTypes(content: string): { ast: object; outputType: object } {
136
- return invoke('parseMotokoTypes', true, [content]);
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
+ };
137
164
  },
138
165
  parseCandid(content: string): object {
139
166
  return invoke('parseCandid', true, [content]);
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
+ }
@@ -55,10 +55,10 @@ function resolveEntryPoint(
55
55
  // return getOne(parsedFiles.filter());
56
56
  }
57
57
 
58
- export function resolveMain(mo: Motoko, directory: string): string | undefined {
58
+ export function resolveMain(mo: Motoko, directory: string): string {
59
59
  return resolveEntryPoint(mo, directory, 'Main.mo');
60
60
  }
61
61
 
62
- export function resolveLib(mo: Motoko, directory: string): string | undefined {
62
+ export function resolveLib(mo: Motoko, directory: string): string {
63
63
  return resolveEntryPoint(mo, directory, 'Lib.mo');
64
64
  }