motoko 2.0.10 → 3.0.0-beta0

Sign up to get free protection for your applications and to get access to all the features.
package/src/package.ts CHANGED
@@ -9,11 +9,24 @@ export interface PackageInfo {
9
9
  name: string;
10
10
  repo: string;
11
11
  version: string;
12
- dir: string;
12
+ dir?: string;
13
13
  branch?: string | undefined;
14
14
  }
15
15
 
16
- async function fetchPackage(mo: Motoko, info: PackageInfo) {
16
+ export interface Package {
17
+ name: string;
18
+ version: string;
19
+ files: PackageFiles;
20
+ }
21
+
22
+ export type PackageFiles = Record<string, PackageFile>;
23
+
24
+ export interface PackageFile {
25
+ content: string;
26
+ }
27
+
28
+ // TODO: call `fetchPackage` instead of deprecated functions
29
+ async function loadPackage(mo: Motoko, info: PackageInfo) {
17
30
  if (
18
31
  !info.repo.startsWith('https://github.com/') ||
19
32
  !info.repo.endsWith('.git')
@@ -27,26 +40,27 @@ async function fetchPackage(mo: Motoko, info: PackageInfo) {
27
40
  branch: info.version,
28
41
  dir: info.dir || 'src',
29
42
  };
30
- const result = await fetchGithub(mo, repo, info.name);
43
+ const result = await fetchGithub_(mo, repo, info.name);
31
44
  if (result) {
32
45
  mo.addPackage(info.name, info.name + '/');
33
46
  }
34
47
  return result ? true : false;
35
48
  }
36
49
 
37
- async function fetchGithub(mo: Motoko, info: PackageInfo, directory = '') {
50
+ /** @deprecated */
51
+ async function fetchGithub_(mo: Motoko, info: PackageInfo, directory = '') {
38
52
  const possiblyCDN = !(
39
53
  (info.branch.length % 2 === 0 && /^[A-F0-9]+$/i.test(info.branch)) ||
40
54
  info.branch === 'master' ||
41
55
  info.branch === 'main'
42
56
  );
43
57
  if (possiblyCDN) {
44
- const result = await fetchFromCDN(mo, info, directory);
58
+ const result = await fetchFromCDN_(mo, info, directory);
45
59
  if (result) {
46
60
  return result;
47
61
  }
48
62
  }
49
- return await fetchFromGithub(mo, info, directory);
63
+ return await fetchFromGithub_(mo, info, directory);
50
64
  }
51
65
 
52
66
  // function saveWorkplaceToMotoko(mo, files) {
@@ -56,7 +70,8 @@ async function fetchGithub(mo: Motoko, info: PackageInfo, directory = '') {
56
70
  // }
57
71
  // }
58
72
 
59
- async function fetchFromCDN(mo: Motoko, info: PackageInfo, directory = '') {
73
+ /** @deprecated */
74
+ async function fetchFromCDN_(mo: Motoko, info: PackageInfo, directory = '') {
60
75
  const meta_url = `https://data.jsdelivr.com/v1/package/gh/${info.repo}@${info.branch}/flat`;
61
76
  const base_url = `https://cdn.jsdelivr.net/gh/${info.repo}@${info.branch}`;
62
77
  const response = await fetch(meta_url);
@@ -87,7 +102,8 @@ async function fetchFromCDN(mo: Motoko, info: PackageInfo, directory = '') {
87
102
  });
88
103
  }
89
104
 
90
- async function fetchFromGithub(
105
+ /** @deprecated */
106
+ async function fetchFromGithub_(
91
107
  mo: Motoko,
92
108
  info: PackageInfo,
93
109
  directory: string = '',
@@ -129,14 +145,7 @@ async function fetchFromGithub(
129
145
  });
130
146
  }
131
147
 
132
- // async function resolve(path) {
133
-
134
- // }
135
-
136
- function parseGithubPackage(
137
- path: string | PackageInfo,
138
- name: string,
139
- ): PackageInfo {
148
+ function parseGithubPackageInfo(path: string | PackageInfo): PackageInfo {
140
149
  if (!path) {
141
150
  return;
142
151
  }
@@ -151,35 +160,152 @@ function parseGithubPackage(
151
160
  return;
152
161
  }
153
162
  } catch (err) {
154
- console.warn(err);
163
+ // console.warn(err);
164
+ return;
155
165
  }
156
166
 
157
- const { name: repoName, filepath, branch, owner } = result;
158
-
167
+ const { name, filepath, branch, owner } = result;
159
168
  return {
160
- name: name || repoName,
161
- repo: `https://github.com/${owner}/${repoName}.git`,
169
+ name,
170
+ repo: `https://github.com/${owner}/${name}.git`,
162
171
  version: branch,
163
172
  dir: filepath,
173
+ branch,
164
174
  // homepage: ,
165
175
  };
166
176
  }
167
177
 
178
+ async function fetchPackageFiles(
179
+ info: PackageInfo,
180
+ ): Promise<PackageFiles | undefined> {
181
+ const prefix = 'https://github.com/';
182
+ const suffix = '.git';
183
+ if (!info.repo.startsWith(prefix) || !info.repo.endsWith(suffix)) {
184
+ return;
185
+ }
186
+ const repoPart = info.repo.slice(prefix.length, -suffix.length);
187
+
188
+ // TODO: modify condition?
189
+ const possiblyCDN = !(
190
+ (info.branch &&
191
+ info.branch.length % 2 === 0 &&
192
+ /^[A-F0-9]+$/i.test(info.branch)) ||
193
+ info.branch === 'master' ||
194
+ info.branch === 'main'
195
+ );
196
+ if (possiblyCDN) {
197
+ const result = await fetchFromService(
198
+ info,
199
+ 'CDN',
200
+ `https://data.jsdelivr.com/v1/package/gh/${repoPart}@${info.branch}/flat`,
201
+ `https://cdn.jsdelivr.net/gh/${repoPart}@${info.branch}`,
202
+ 'files',
203
+ 'name',
204
+ );
205
+ if (result?.length) {
206
+ return result;
207
+ }
208
+ }
209
+ return await fetchFromService(
210
+ info,
211
+ 'GitHub',
212
+ `https://api.github.com/repos/${repoPart}/git/trees/${info.branch}?recursive=1`,
213
+ `https://raw.githubusercontent.com/${repoPart}/${info.branch}/`,
214
+ 'tree',
215
+ 'path',
216
+ (file) => file.type === 'blob',
217
+ );
218
+ }
219
+
220
+ async function fetchFromService(
221
+ info: PackageInfo,
222
+ serviceName: string,
223
+ metaUrl: string,
224
+ baseUrl: string,
225
+ resultProperty: string,
226
+ pathProperty: string,
227
+ condition?: (file: any) => boolean,
228
+ ): Promise<PackageFiles | undefined> {
229
+ const response = await fetch(metaUrl);
230
+ if (!response.ok) {
231
+ throw Error(
232
+ response.statusText ||
233
+ `Could not fetch from ${serviceName}: ${info.repo}`,
234
+ );
235
+ }
236
+ const json = await response.json();
237
+ if (!json.hasOwnProperty(resultProperty)) {
238
+ throw new Error(`Unexpected response from ${serviceName}`);
239
+ }
240
+ // Remove leading and trailing '/' from directory
241
+ let directory = info.dir
242
+ ? info.dir.replace(/^\//, '').replace(/\/$/, '')
243
+ : '';
244
+ const files: Record<string, PackageFile> = {};
245
+ await Promise.all(
246
+ (<any[]>json[resultProperty])
247
+ .filter((file) => {
248
+ return (
249
+ (!directory ||
250
+ file[pathProperty].startsWith(
251
+ file[pathProperty].startsWith('/')
252
+ ? `/${directory}`
253
+ : directory,
254
+ )) &&
255
+ (!condition || condition(file)) &&
256
+ /\.mo$/.test(file[pathProperty])
257
+ );
258
+ })
259
+ .map(async (file) => {
260
+ const response = await fetch(`${baseUrl}${file[pathProperty]}`);
261
+ if (!response.ok) {
262
+ throw Error(response.statusText);
263
+ }
264
+ const content = await response.text();
265
+ let path = file[pathProperty];
266
+ if (path.startsWith('/')) {
267
+ path = path.slice(1);
268
+ }
269
+ if (directory) {
270
+ // Remove directory prefix
271
+ path = path.slice(directory.length + 1);
272
+ }
273
+ files[path] = {
274
+ content,
275
+ };
276
+ }),
277
+ );
278
+ return files;
279
+ }
280
+
281
+ export async function fetchPackage(
282
+ info: string | PackageInfo,
283
+ ): Promise<Package | undefined> {
284
+ if (typeof info === 'string') {
285
+ info = parseGithubPackageInfo(info);
286
+ }
287
+ const files = await fetchPackageFiles(info);
288
+ if (!files) {
289
+ return;
290
+ }
291
+ return {
292
+ name: info.name,
293
+ version: info.version,
294
+ files,
295
+ };
296
+ }
297
+
168
298
  export async function loadPackages(
169
299
  mo: Motoko,
170
300
  packages: Record<string, string | PackageInfo>,
171
301
  ) {
172
302
  await Promise.all(
173
303
  Object.entries(packages).map(([name, path]) => {
174
- const info = parseGithubPackage(path, name);
175
- return fetchPackage(mo, info);
304
+ const info = {
305
+ ...parseGithubPackageInfo(path),
306
+ name,
307
+ };
308
+ return loadPackage(mo, info);
176
309
  }),
177
310
  );
178
311
  }
179
-
180
- // export async function findPackage(package) {
181
- // if (typeof package === 'string') {
182
- // return resolve(package);
183
- // }
184
- // return package;
185
- // },
@@ -1,4 +1,4 @@
1
- import getMotoko from '..';
1
+ import wrapMotoko from '..';
2
2
  const { Motoko } = require('../../versions/latest/moc_interpreter.min');
3
3
 
4
- export default getMotoko(Motoko, 'latest/interpreter');
4
+ export default wrapMotoko(Motoko, 'latest/interpreter');
@@ -1,4 +1,4 @@
1
- import getMotoko from '..';
1
+ import wrapMotoko from '..';
2
2
  const { Motoko } = require('../../versions/latest/moc.min');
3
3
 
4
- export default getMotoko(Motoko, 'latest');
4
+ export default wrapMotoko(Motoko, 'latest');