zero-com 0.0.2 → 0.0.3
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/index.js +123 -0
- package/package.json +1 -1
package/index.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ZeroComWebpackPlugin = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const minimatch_1 = require("minimatch");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const ts_morph_1 = require("ts-morph");
|
|
11
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
12
|
+
class ZeroComWebpackPlugin {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = Object.assign(Object.assign({ development: true }, options), { patterns: Object.assign({}, options.patterns) });
|
|
15
|
+
this.compilationId = String(Math.floor(Math.random() * 1000000));
|
|
16
|
+
this.clientPattern = this.options.patterns.client;
|
|
17
|
+
this.serverPattern = this.options.patterns.server;
|
|
18
|
+
}
|
|
19
|
+
apply(compiler) {
|
|
20
|
+
const ZERO_COM_CLIENT_SEND = 'ZERO_COM_CLIENT_SEND';
|
|
21
|
+
const ZERO_COM_SERVER_REGISTRY = 'ZERO_COM_SERVER_REGISTRY';
|
|
22
|
+
const pluginName = ZeroComWebpackPlugin.name;
|
|
23
|
+
const { webpack } = compiler;
|
|
24
|
+
const { RawSource } = webpack.sources;
|
|
25
|
+
compiler.hooks.normalModuleFactory.tap(pluginName, (nmf) => {
|
|
26
|
+
nmf.hooks.beforeResolve.tap(pluginName, (resolveData) => {
|
|
27
|
+
const absolutePath = path_1.default.resolve(resolveData.context, resolveData.request);
|
|
28
|
+
const isServerFile = (0, minimatch_1.minimatch)(absolutePath, path_1.default.join(compiler.context, this.serverPattern));
|
|
29
|
+
if (!isServerFile)
|
|
30
|
+
return;
|
|
31
|
+
const requestedFromClient = (0, minimatch_1.minimatch)(resolveData.contextInfo.issuer, path_1.default.join(compiler.context, this.clientPattern));
|
|
32
|
+
const tsPath = absolutePath + '.ts';
|
|
33
|
+
const jsPath = absolutePath + '.js';
|
|
34
|
+
const mjsPath = absolutePath + '.mjs';
|
|
35
|
+
let resolvedPath = '';
|
|
36
|
+
if (fs_1.default.existsSync(tsPath)) {
|
|
37
|
+
resolvedPath = tsPath;
|
|
38
|
+
}
|
|
39
|
+
else if (fs_1.default.existsSync(jsPath)) {
|
|
40
|
+
resolvedPath = jsPath;
|
|
41
|
+
}
|
|
42
|
+
else if (fs_1.default.existsSync(mjsPath)) {
|
|
43
|
+
resolvedPath = mjsPath;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new Error('Unable to resolve: ' + absolutePath);
|
|
47
|
+
}
|
|
48
|
+
const originalContent = fs_1.default.readFileSync(resolvedPath, 'utf8');
|
|
49
|
+
const project = new ts_morph_1.Project({
|
|
50
|
+
compilerOptions: {
|
|
51
|
+
target: typescript_1.default.ScriptTarget.ES2017,
|
|
52
|
+
module: typescript_1.default.ModuleKind.ESNext,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
const sourceFile = project.createSourceFile(absolutePath, originalContent, { overwrite: true });
|
|
56
|
+
let newModuleContent = '';
|
|
57
|
+
if (requestedFromClient) {
|
|
58
|
+
const generatedFunctions = [];
|
|
59
|
+
sourceFile.getFunctions().forEach(func => {
|
|
60
|
+
if (func.isExported() && func.isAsync()) {
|
|
61
|
+
const funcName = String(func.getName());
|
|
62
|
+
const lineNumber = func.getStartLineNumber();
|
|
63
|
+
const funcParams = func.getParameters().map(p => p.getName()).join(', ');
|
|
64
|
+
const method = formatMethodName(funcName, path_1.default.relative(compiler.context, absolutePath), lineNumber);
|
|
65
|
+
const newFunctionBody = `return window.${ZERO_COM_CLIENT_SEND}({method: '${method}', params: [${funcParams}]})`;
|
|
66
|
+
func.setBodyText(newFunctionBody);
|
|
67
|
+
generatedFunctions.push(func.getText());
|
|
68
|
+
console.log('client:', method);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
newModuleContent = generatedFunctions.join('\n\n');
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const chunks = [];
|
|
75
|
+
sourceFile.getFunctions().forEach(func => {
|
|
76
|
+
if (func.isExported() && func.isAsync()) {
|
|
77
|
+
const funcName = String(func.getName());
|
|
78
|
+
const lineNumber = func.getStartLineNumber();
|
|
79
|
+
const method = formatMethodName(funcName, path_1.default.relative(compiler.context, absolutePath), lineNumber);
|
|
80
|
+
chunks.push(`global.${ZERO_COM_SERVER_REGISTRY}['${method}'] = ${funcName}`);
|
|
81
|
+
console.log('server:', method);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
newModuleContent = `${originalContent} if (!global.${ZERO_COM_SERVER_REGISTRY}) global.${ZERO_COM_SERVER_REGISTRY} = Object.create(null); ${chunks.join(',')}`;
|
|
85
|
+
}
|
|
86
|
+
project.createSourceFile(absolutePath + '.ts', newModuleContent, { overwrite: true });
|
|
87
|
+
const result = project.emitToMemory();
|
|
88
|
+
const newContent = result.getFiles()[0].text;
|
|
89
|
+
const inlineLoader = `data:text/javascript,${encodeURIComponent(newContent)}`;
|
|
90
|
+
resolveData.request = inlineLoader;
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
if (this.options.development)
|
|
94
|
+
return;
|
|
95
|
+
const replacements = [
|
|
96
|
+
{ target: ZERO_COM_CLIENT_SEND, replacement: `__ZERO_COM_CLIENT_SEND_${this.compilationId}` },
|
|
97
|
+
{ target: ZERO_COM_SERVER_REGISTRY, replacement: `__ZERO_COM_SERVER_REGISTRY_${this.compilationId}` }
|
|
98
|
+
];
|
|
99
|
+
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
|
|
100
|
+
compilation.hooks.processAssets.tap({ name: pluginName, stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE }, (assets) => {
|
|
101
|
+
for (const assetName in assets) {
|
|
102
|
+
if (assetName.endsWith('.js')) {
|
|
103
|
+
let assetSource = String(assets[assetName].source());
|
|
104
|
+
let modified = false;
|
|
105
|
+
replacements.forEach(({ target, replacement }) => {
|
|
106
|
+
if (assetSource.includes(target)) {
|
|
107
|
+
assetSource = assetSource.replaceAll(target, replacement);
|
|
108
|
+
modified = true;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (modified) {
|
|
112
|
+
compilation.updateAsset(assetName, new RawSource(assetSource));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.ZeroComWebpackPlugin = ZeroComWebpackPlugin;
|
|
121
|
+
const formatMethodName = (funcName, path, line) => {
|
|
122
|
+
return `${funcName}@${path}:${line}`;
|
|
123
|
+
};
|