forked from alibaba/lowcode-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstandalone-loader.ts
More file actions
133 lines (109 loc) · 3.41 KB
/
standalone-loader.ts
File metadata and controls
133 lines (109 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import fetch from 'node-fetch';
import type { ProjectSchema, ResultDir } from '@alilc/lowcode-types';
import type { FlattenFile } from './types/file';
declare const Worker: any;
declare const self: any;
declare const __PACKAGE_VERSION__: string;
const packageVersion = __PACKAGE_VERSION__ || 'latest';
export const DEFAULT_WORKER_JS = `https://unpkg.com/@alilc/lowcode-code-generator@${packageVersion}/dist/standalone-worker.min.js`;
export const DEFAULT_TIMEOUT_IN_MS = 60 * 1000;
const workerJsCache = new Map<string, { content: string; url: string }>();
export async function init({
workerJsUrl = DEFAULT_WORKER_JS,
}: {
workerJsUrl?: string;
} = {}) {
await loadWorkerJs(workerJsUrl);
}
export type Result = ResultDir | FlattenFile[];
export async function generateCode(options: {
solution: 'icejs' | 'rax';
schema: ProjectSchema;
flattenResult?: boolean;
workerJsUrl?: string;
timeoutInMs?: number;
}): Promise<Result> {
if (typeof self !== 'object') {
throw new Error('self is not defined');
}
if (typeof Worker !== 'function') {
throw new Error('Worker is not supported');
}
const workerJsUrl = options.workerJsUrl || DEFAULT_WORKER_JS;
const workerJs = await loadWorkerJs(workerJsUrl);
const worker = new Worker(workerJs.url, {
type: 'classic',
credentials: 'omit',
});
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('timeout'));
worker.terminate();
}, options.timeoutInMs || DEFAULT_TIMEOUT_IN_MS);
worker.onmessage = (event: any) => {
const msg = event.data;
switch (msg.type) {
case 'ready':
print('worker is ready.');
break;
case 'run:begin':
print('worker is running...');
break;
case 'run:end':
print('worker is done.');
resolve(msg.result);
clearTimeout(timer);
worker.terminate();
break;
case 'run:error':
printErr(`worker error: ${msg.errorMsg}`);
clearTimeout(timer);
reject(new Error(msg.errorMsg || 'unknown error'));
worker.terminate();
break;
default:
print('got unknown msg: %o', msg);
break;
}
};
worker.onerror = (err: any) => {
printErr('worker error: %o', err);
clearTimeout(timer);
reject(err);
worker.terminate();
};
worker.postMessage({
type: 'run',
solution: options.solution,
schema: options.schema,
flattenResult: options.flattenResult,
});
});
}
async function loadWorkerJs(workerJsUrl: string) {
const cached = workerJsCache.get(workerJsUrl);
if (cached) {
return cached;
}
const workerJsContent = await fetch(workerJsUrl)
.then((res) => res.text())
.catch((err) => {
throw new Error(`Failed to fetch worker js: ${err}`);
});
const workerJs = {
content: workerJsContent,
url: self.URL.createObjectURL(
new self.Blob([workerJsContent], { type: 'application/javascript' }),
),
};
workerJsCache.set(workerJsUrl, workerJs);
return workerJs;
}
function print(msg: string, ...args: unknown[]) {
// eslint-disable-next-line no-console
console.debug(`[code-generator/loader]: ${msg}`, ...args);
}
function printErr(msg: string, ...args: unknown[]) {
// eslint-disable-next-line no-console
console.debug(`[code-generator/loader]: %c${msg}`, 'color:red', ...args);
}