zero-com 0.0.5 → 0.0.7-s
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.d.ts +1 -0
- package/lib/common.d.ts +10 -0
- package/lib/index.d.ts +11 -0
- package/lib/rollup.d.ts +3 -0
- package/lib/rollup.js +23 -6
- package/lib/webpack.d.ts +15 -0
- package/lib/webpack.js +25 -6
- package/package.json +4 -3
- package/index.ts +0 -1
- package/lib/common.ts +0 -14
- package/lib/index.ts +0 -19
- package/lib/rollup.ts +0 -155
- package/lib/webpack.ts +0 -167
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/index';
|
package/lib/common.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Options = {
|
|
2
|
+
development?: boolean;
|
|
3
|
+
patterns: {
|
|
4
|
+
client: string;
|
|
5
|
+
server: string;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export declare const ZERO_COM_CLIENT_SEND = "ZERO_COM_CLIENT_SEND";
|
|
9
|
+
export declare const ZERO_COM_SERVER_REGISTRY = "ZERO_COM_SERVER_REGISTRY";
|
|
10
|
+
export declare const formatFuncIdName: (funcName: string, path: string, line: number) => string;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
var ZERO_COM_SERVER_REGISTRY: {
|
|
3
|
+
[funcId: string]: (...args: any[]) => any;
|
|
4
|
+
};
|
|
5
|
+
var ZERO_COM_CLIENT_SEND: (...args: any[]) => Promise<any>;
|
|
6
|
+
}
|
|
7
|
+
export declare const serverFn: <Ctx, Rest extends any[], R>(sfn: (ctx: Ctx, ...rest: Rest) => R) => {
|
|
8
|
+
(...rest: Rest): R;
|
|
9
|
+
serverFn: (ctx: Ctx, ...rest: Rest) => R;
|
|
10
|
+
};
|
|
11
|
+
export declare const execServerFn: (sfn: ReturnType<typeof serverFn>, ctx: any, args: any[]) => ReturnType<typeof sfn>;
|
package/lib/rollup.d.ts
ADDED
package/lib/rollup.js
CHANGED
|
@@ -92,14 +92,29 @@ function zeroComRollupPlugin(options) {
|
|
|
92
92
|
});
|
|
93
93
|
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
94
94
|
const initializer = decl.getInitializer();
|
|
95
|
-
if (initializer
|
|
96
|
-
|
|
95
|
+
if (!initializer || !decl.isExported())
|
|
96
|
+
return;
|
|
97
|
+
if (initializer instanceof ts_morph_1.ArrowFunction && initializer.isAsync()) {
|
|
98
|
+
const funcName = decl.getName();
|
|
99
|
+
const lineNumber = decl.getStartLineNumber();
|
|
100
|
+
const funcParams = initializer.getParameters().map(p => p.getName()).join(', ');
|
|
101
|
+
const funcId = (0, common_1.formatFuncIdName)(funcName, path_1.default.relative(process.cwd(), id), lineNumber);
|
|
102
|
+
const newFunctionBody = `return window.${common_1.ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`;
|
|
103
|
+
initializer.setBodyText(newFunctionBody);
|
|
104
|
+
}
|
|
105
|
+
else if (initializer.getKind() === typescript_1.default.SyntaxKind.CallExpression && initializer.getExpression().getText() === 'serverFn') {
|
|
106
|
+
const call = initializer;
|
|
107
|
+
const arg = call.getArguments()[0];
|
|
108
|
+
if (arg && arg instanceof ts_morph_1.ArrowFunction) {
|
|
97
109
|
const funcName = decl.getName();
|
|
98
110
|
const lineNumber = decl.getStartLineNumber();
|
|
99
|
-
const funcParams =
|
|
111
|
+
const funcParams = arg.getParameters().map(p => p.getName()).join(', ');
|
|
100
112
|
const funcId = (0, common_1.formatFuncIdName)(funcName, path_1.default.relative(process.cwd(), id), lineNumber);
|
|
101
113
|
const newFunctionBody = `return window.${common_1.ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`;
|
|
102
|
-
|
|
114
|
+
// Create a new arrow function string
|
|
115
|
+
const newArrowFunc = `(${funcParams}) => { ${newFunctionBody} }`;
|
|
116
|
+
// Replace the serverFn call with the new arrow function
|
|
117
|
+
decl.setInitializer(newArrowFunc);
|
|
103
118
|
}
|
|
104
119
|
}
|
|
105
120
|
});
|
|
@@ -116,8 +131,10 @@ function zeroComRollupPlugin(options) {
|
|
|
116
131
|
});
|
|
117
132
|
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
118
133
|
const initializer = decl.getInitializer();
|
|
119
|
-
if (initializer
|
|
120
|
-
|
|
134
|
+
if (initializer) {
|
|
135
|
+
const isServerFn = initializer.getKind() === typescript_1.default.SyntaxKind.CallExpression && initializer.getExpression().getText() === 'serverFn';
|
|
136
|
+
if ((initializer instanceof ts_morph_1.ArrowFunction && decl.isExported() && initializer.isAsync()) ||
|
|
137
|
+
(isServerFn && decl.isExported())) {
|
|
121
138
|
const funcName = decl.getName();
|
|
122
139
|
const lineNumber = decl.getStartLineNumber();
|
|
123
140
|
const funcId = (0, common_1.formatFuncIdName)(funcName, path_1.default.relative(process.cwd(), id), lineNumber);
|
package/lib/webpack.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Compiler } from 'webpack';
|
|
2
|
+
import { Options } from './common';
|
|
3
|
+
export type Message = {
|
|
4
|
+
funcId: string;
|
|
5
|
+
params: any[];
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
};
|
|
8
|
+
export declare class ZeroComWebpackPlugin {
|
|
9
|
+
private options;
|
|
10
|
+
private compilationId;
|
|
11
|
+
private clientPattern;
|
|
12
|
+
private serverPattern;
|
|
13
|
+
constructor(options: Options);
|
|
14
|
+
apply(compiler: Compiler): void;
|
|
15
|
+
}
|
package/lib/webpack.js
CHANGED
|
@@ -69,14 +69,31 @@ class ZeroComWebpackPlugin {
|
|
|
69
69
|
});
|
|
70
70
|
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
71
71
|
const initializer = decl.getInitializer();
|
|
72
|
-
if (initializer
|
|
73
|
-
|
|
72
|
+
if (!initializer || !decl.isExported())
|
|
73
|
+
return;
|
|
74
|
+
if (initializer instanceof ts_morph_1.ArrowFunction && initializer.isAsync()) {
|
|
75
|
+
const funcName = decl.getName();
|
|
76
|
+
const lineNumber = decl.getStartLineNumber();
|
|
77
|
+
const funcParams = initializer.getParameters().map(p => p.getName()).join(', ');
|
|
78
|
+
const funcId = (0, common_1.formatFuncIdName)(funcName, path_1.default.relative(compiler.context, absolutePath), lineNumber);
|
|
79
|
+
const newFunctionBody = `return window.${common_1.ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`;
|
|
80
|
+
initializer.setBodyText(newFunctionBody);
|
|
81
|
+
generatedFunctions.push(decl.getVariableStatementOrThrow().getText());
|
|
82
|
+
console.log('client:', funcId);
|
|
83
|
+
}
|
|
84
|
+
else if (initializer.getKind() === typescript_1.default.SyntaxKind.CallExpression && initializer.getExpression().getText() === 'serverFn') {
|
|
85
|
+
const call = initializer;
|
|
86
|
+
const arg = call.getArguments()[0];
|
|
87
|
+
if (arg && arg instanceof ts_morph_1.ArrowFunction) {
|
|
74
88
|
const funcName = decl.getName();
|
|
75
89
|
const lineNumber = decl.getStartLineNumber();
|
|
76
|
-
const funcParams =
|
|
90
|
+
const funcParams = arg.getParameters().map(p => p.getName()).join(', ');
|
|
77
91
|
const funcId = (0, common_1.formatFuncIdName)(funcName, path_1.default.relative(compiler.context, absolutePath), lineNumber);
|
|
78
92
|
const newFunctionBody = `return window.${common_1.ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`;
|
|
79
|
-
|
|
93
|
+
// Create a new arrow function string
|
|
94
|
+
const newArrowFunc = `(${funcParams}) => { ${newFunctionBody} }`;
|
|
95
|
+
// Replace the serverFn call with the new arrow function
|
|
96
|
+
decl.setInitializer(newArrowFunc);
|
|
80
97
|
generatedFunctions.push(decl.getVariableStatementOrThrow().getText());
|
|
81
98
|
console.log('client:', funcId);
|
|
82
99
|
}
|
|
@@ -97,8 +114,10 @@ class ZeroComWebpackPlugin {
|
|
|
97
114
|
});
|
|
98
115
|
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
99
116
|
const initializer = decl.getInitializer();
|
|
100
|
-
if (initializer
|
|
101
|
-
|
|
117
|
+
if (initializer) {
|
|
118
|
+
const isServerFn = initializer.getKind() === typescript_1.default.SyntaxKind.CallExpression && initializer.getExpression().getText() === 'serverFn';
|
|
119
|
+
if ((initializer instanceof ts_morph_1.ArrowFunction && decl.isExported() && initializer.isAsync()) ||
|
|
120
|
+
(isServerFn && decl.isExported())) {
|
|
102
121
|
const funcName = decl.getName();
|
|
103
122
|
const lineNumber = decl.getStartLineNumber();
|
|
104
123
|
const funcId = (0, common_1.formatFuncIdName)(funcName, path_1.default.relative(compiler.context, absolutePath), lineNumber);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zero-com",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7s",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"repository": "https://github.com/yosbelms/zero-com",
|
|
6
6
|
"keywords": [
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
"client"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build": "npx tsc",
|
|
16
|
-
"
|
|
15
|
+
"build": "npx tsc -d",
|
|
16
|
+
"clean": "find . -type f \\( -name \"*.js\" -o -name \"*.js.map\" -o -name \"*.d.ts\" -o -name \"*.d.ts.map\" \\) | grep -v \"./node_modules\" | xargs rm",
|
|
17
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
17
18
|
},
|
|
18
19
|
"author": "",
|
|
19
20
|
"license": "MIT",
|
package/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './lib/index'
|
package/lib/common.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export type Options = {
|
|
2
|
-
development?: boolean,
|
|
3
|
-
patterns: {
|
|
4
|
-
client: string,
|
|
5
|
-
server: string,
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const ZERO_COM_CLIENT_SEND = 'ZERO_COM_CLIENT_SEND'
|
|
10
|
-
export const ZERO_COM_SERVER_REGISTRY = 'ZERO_COM_SERVER_REGISTRY'
|
|
11
|
-
|
|
12
|
-
export const formatFuncIdName = (funcName: string, path: string, line: number): string => {
|
|
13
|
-
return `${funcName}@${path}:${line}`
|
|
14
|
-
}
|
package/lib/index.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
declare global {
|
|
3
|
-
var ZERO_COM_SERVER_REGISTRY: { [funcId: string]: (...args: any[]) => any }
|
|
4
|
-
var ZERO_COM_CLIENT_SEND: (...args: any[]) => Promise<any>
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const serverFn = <Ctx, Rest extends any[], R>(sfn: (ctx: Ctx, ...rest: Rest) => R) => {
|
|
8
|
-
const clonedSfn = (...rest: Rest): R => sfn(null as Ctx, ...rest)
|
|
9
|
-
clonedSfn.serverFn = sfn
|
|
10
|
-
return clonedSfn
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const execServerFn = (sfn: ReturnType<typeof serverFn>, ctx: any, args: any[]): ReturnType<typeof sfn> => {
|
|
14
|
-
if (sfn.serverFn) {
|
|
15
|
-
return sfn.serverFn.call(null, ctx, ...args)
|
|
16
|
-
} else {
|
|
17
|
-
return sfn.call(null, ...args)
|
|
18
|
-
}
|
|
19
|
-
}
|
package/lib/rollup.ts
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import { minimatch } from 'minimatch'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import { ArrowFunction, Project } from 'ts-morph'
|
|
5
|
-
import ts from 'typescript'
|
|
6
|
-
import {
|
|
7
|
-
Plugin,
|
|
8
|
-
PluginContext,
|
|
9
|
-
ResolveIdResult,
|
|
10
|
-
LoadResult,
|
|
11
|
-
NormalizedOutputOptions,
|
|
12
|
-
RenderedChunk
|
|
13
|
-
} from 'rollup'
|
|
14
|
-
import { Options, ZERO_COM_CLIENT_SEND, ZERO_COM_SERVER_REGISTRY, formatFuncIdName } from './common'
|
|
15
|
-
|
|
16
|
-
export function zeroComRollupPlugin(options: Options): Plugin {
|
|
17
|
-
const { development = true, patterns } = options
|
|
18
|
-
const compilationId = String(Math.floor(Math.random() * 1000000))
|
|
19
|
-
const clientPattern = patterns.client
|
|
20
|
-
const serverPattern = patterns.server
|
|
21
|
-
|
|
22
|
-
const replacements = [
|
|
23
|
-
{ target: ZERO_COM_CLIENT_SEND, replacement: `__ZERO_COM_CLIENT_SEND_${compilationId}` },
|
|
24
|
-
{ target: ZERO_COM_SERVER_REGISTRY, replacement: `__ZERO_COM_SERVER_REGISTRY_${compilationId}` }
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
name: 'zero-com-rollup-plugin',
|
|
29
|
-
|
|
30
|
-
async resolveId(this: PluginContext, source: string, importer: string | undefined, options: { isEntry: boolean }): Promise<ResolveIdResult> {
|
|
31
|
-
if (!importer) return null
|
|
32
|
-
|
|
33
|
-
const resolveResult = await this.resolve(source, importer, { ...options, skipSelf: true })
|
|
34
|
-
if (!resolveResult) return null
|
|
35
|
-
|
|
36
|
-
const absolutePath = resolveResult.id
|
|
37
|
-
const isServerFile = minimatch(absolutePath, path.join(process.cwd(), serverPattern))
|
|
38
|
-
if (!isServerFile) return null
|
|
39
|
-
|
|
40
|
-
const requestedFromClient = minimatch(importer, path.join(process.cwd(), clientPattern))
|
|
41
|
-
|
|
42
|
-
const tsPath = absolutePath + '.ts'
|
|
43
|
-
const jsPath = absolutePath + '.js'
|
|
44
|
-
const mjsPath = absolutePath + '.mjs'
|
|
45
|
-
let resolvedPath = ''
|
|
46
|
-
|
|
47
|
-
if (fs.existsSync(tsPath)) {
|
|
48
|
-
resolvedPath = tsPath
|
|
49
|
-
} else if (fs.existsSync(jsPath)) {
|
|
50
|
-
resolvedPath = jsPath
|
|
51
|
-
} else if (fs.existsSync(mjsPath)) {
|
|
52
|
-
resolvedPath = mjsPath
|
|
53
|
-
} else {
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
id: resolvedPath,
|
|
59
|
-
meta: {
|
|
60
|
-
isClient: requestedFromClient,
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
load(this: PluginContext, id: string): LoadResult {
|
|
66
|
-
const meta = this.getModuleInfo(id)?.meta
|
|
67
|
-
if (meta === undefined || meta.isClient === undefined) return null
|
|
68
|
-
|
|
69
|
-
const originalContent = fs.readFileSync(id, 'utf8')
|
|
70
|
-
const project = new Project({
|
|
71
|
-
compilerOptions: {
|
|
72
|
-
target: ts.ScriptTarget.ES2017,
|
|
73
|
-
module: ts.ModuleKind.ESNext,
|
|
74
|
-
},
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
const sourceFile = project.createSourceFile(id, originalContent, { overwrite: true })
|
|
78
|
-
|
|
79
|
-
if (meta.isClient) {
|
|
80
|
-
sourceFile.getFunctions().forEach(func => {
|
|
81
|
-
if (func.isExported() && func.isAsync()) {
|
|
82
|
-
const funcName = String(func.getName())
|
|
83
|
-
const lineNumber = func.getStartLineNumber()
|
|
84
|
-
const funcParams = func.getParameters().map(p => p.getName()).join(', ')
|
|
85
|
-
const funcId = formatFuncIdName(funcName, path.relative(process.cwd(), id), lineNumber)
|
|
86
|
-
const newFunctionBody = `return window.${ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`
|
|
87
|
-
func.setBodyText(newFunctionBody)
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
91
|
-
const initializer = decl.getInitializer()
|
|
92
|
-
if (initializer && initializer instanceof ArrowFunction) {
|
|
93
|
-
if (decl.isExported() && initializer.isAsync()) {
|
|
94
|
-
const funcName = decl.getName()
|
|
95
|
-
const lineNumber = decl.getStartLineNumber()
|
|
96
|
-
const funcParams = initializer.getParameters().map(p => p.getName()).join(', ')
|
|
97
|
-
const funcId = formatFuncIdName(funcName, path.relative(process.cwd(), id), lineNumber)
|
|
98
|
-
const newFunctionBody = `return window.${ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`
|
|
99
|
-
initializer.setBodyText(newFunctionBody)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
} else {
|
|
104
|
-
const chunks: string[] = []
|
|
105
|
-
sourceFile.getFunctions().forEach(func => {
|
|
106
|
-
if (func.isExported() && func.isAsync()) {
|
|
107
|
-
const funcName = String(func.getName())
|
|
108
|
-
const lineNumber = func.getStartLineNumber()
|
|
109
|
-
const funcId = formatFuncIdName(funcName, path.relative(process.cwd(), id), lineNumber)
|
|
110
|
-
chunks.push(`global.${ZERO_COM_SERVER_REGISTRY}['${funcId}'] = ${funcName}`)
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
114
|
-
const initializer = decl.getInitializer()
|
|
115
|
-
if (initializer && initializer instanceof ArrowFunction) {
|
|
116
|
-
if (decl.isExported() && initializer.isAsync()) {
|
|
117
|
-
const funcName = decl.getName()
|
|
118
|
-
const lineNumber = decl.getStartLineNumber()
|
|
119
|
-
const funcId = formatFuncIdName(funcName, path.relative(process.cwd(), id), lineNumber)
|
|
120
|
-
chunks.push(`global.${ZERO_COM_SERVER_REGISTRY}['${funcId}'] = ${funcName}`)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
if (chunks.length > 0) {
|
|
126
|
-
const textToAdd = `\nif (!global.${ZERO_COM_SERVER_REGISTRY}) global.${ZERO_COM_SERVER_REGISTRY} = Object.create(null); ${chunks.join(',')}`
|
|
127
|
-
sourceFile.insertText(sourceFile.getEnd(), textToAdd);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const result = project.emitToMemory()
|
|
132
|
-
const newContent = result.getFiles()[0].text
|
|
133
|
-
return newContent
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
renderChunk(this: PluginContext, code: string, chunk: RenderedChunk, options: NormalizedOutputOptions) {
|
|
137
|
-
if (development) return null
|
|
138
|
-
|
|
139
|
-
let modified = false
|
|
140
|
-
let newCode = code
|
|
141
|
-
replacements.forEach(({ target, replacement }) => {
|
|
142
|
-
if (newCode.includes(target)) {
|
|
143
|
-
newCode = newCode.replaceAll(target, replacement)
|
|
144
|
-
modified = true
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
if (modified) {
|
|
149
|
-
return { code: newCode, map: null }
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return null
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
package/lib/webpack.ts
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import { minimatch } from 'minimatch'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import { ArrowFunction, Project } from 'ts-morph'
|
|
5
|
-
import ts from 'typescript'
|
|
6
|
-
import { Compiler } from 'webpack'
|
|
7
|
-
import { Options, ZERO_COM_CLIENT_SEND, ZERO_COM_SERVER_REGISTRY, formatFuncIdName } from './common'
|
|
8
|
-
|
|
9
|
-
export type Message = {
|
|
10
|
-
funcId: string,
|
|
11
|
-
params: any[],
|
|
12
|
-
[key: string]: any
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class ZeroComWebpackPlugin {
|
|
16
|
-
private options: Options
|
|
17
|
-
private compilationId: string
|
|
18
|
-
private clientPattern: string
|
|
19
|
-
private serverPattern: string
|
|
20
|
-
|
|
21
|
-
constructor(options: Options) {
|
|
22
|
-
this.options = {
|
|
23
|
-
development: true,
|
|
24
|
-
...options,
|
|
25
|
-
patterns: {
|
|
26
|
-
...options.patterns
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
this.compilationId = String(Math.floor(Math.random() * 1000000))
|
|
30
|
-
this.clientPattern = this.options.patterns.client
|
|
31
|
-
this.serverPattern = this.options.patterns.server
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
apply(compiler: Compiler) {
|
|
35
|
-
const pluginName = ZeroComWebpackPlugin.name
|
|
36
|
-
const { webpack } = compiler
|
|
37
|
-
const { RawSource } = webpack.sources
|
|
38
|
-
|
|
39
|
-
compiler.hooks.normalModuleFactory.tap(pluginName, (nmf) => {
|
|
40
|
-
nmf.hooks.beforeResolve.tap(pluginName, (resolveData) => {
|
|
41
|
-
const absolutePath = path.resolve(resolveData.context, resolveData.request)
|
|
42
|
-
const isServerFile = minimatch(absolutePath, path.join(compiler.context, this.serverPattern))
|
|
43
|
-
if (!isServerFile) return
|
|
44
|
-
|
|
45
|
-
const requestedFromClient = minimatch(resolveData.contextInfo.issuer, path.join(compiler.context, this.clientPattern))
|
|
46
|
-
|
|
47
|
-
const tsPath = absolutePath + '.ts'
|
|
48
|
-
const jsPath = absolutePath + '.js'
|
|
49
|
-
const mjsPath = absolutePath + '.mjs'
|
|
50
|
-
let resolvedPath = ''
|
|
51
|
-
|
|
52
|
-
if (fs.existsSync(tsPath)) {
|
|
53
|
-
resolvedPath = tsPath
|
|
54
|
-
} else if (fs.existsSync(jsPath)) {
|
|
55
|
-
resolvedPath = jsPath
|
|
56
|
-
} else if (fs.existsSync(mjsPath)) {
|
|
57
|
-
resolvedPath = mjsPath
|
|
58
|
-
} else {
|
|
59
|
-
throw new Error('Unable to resolve: ' + absolutePath)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const originalContent = fs.readFileSync(resolvedPath, 'utf8')
|
|
63
|
-
|
|
64
|
-
const project = new Project({
|
|
65
|
-
compilerOptions: {
|
|
66
|
-
target: ts.ScriptTarget.ES2017,
|
|
67
|
-
module: ts.ModuleKind.ESNext,
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const sourceFile = project.createSourceFile(absolutePath, originalContent, { overwrite: true })
|
|
72
|
-
let newModuleContent = ''
|
|
73
|
-
|
|
74
|
-
if (requestedFromClient) {
|
|
75
|
-
const generatedFunctions: string[] = []
|
|
76
|
-
sourceFile.getFunctions().forEach(func => {
|
|
77
|
-
if (func.isExported() && func.isAsync()) {
|
|
78
|
-
const funcName = String(func.getName())
|
|
79
|
-
const lineNumber = func.getStartLineNumber()
|
|
80
|
-
const funcParams = func.getParameters().map(p => p.getName()).join(', ')
|
|
81
|
-
const funcId = formatFuncIdName(funcName, path.relative(compiler.context, absolutePath), lineNumber)
|
|
82
|
-
const newFunctionBody = `return window.${ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`
|
|
83
|
-
func.setBodyText(newFunctionBody)
|
|
84
|
-
generatedFunctions.push(func.getText())
|
|
85
|
-
console.log('client:', funcId)
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
89
|
-
const initializer = decl.getInitializer()
|
|
90
|
-
if (initializer && initializer instanceof ArrowFunction) {
|
|
91
|
-
if (decl.isExported() && initializer.isAsync()) {
|
|
92
|
-
const funcName = decl.getName()
|
|
93
|
-
const lineNumber = decl.getStartLineNumber()
|
|
94
|
-
const funcParams = initializer.getParameters().map(p => p.getName()).join(', ')
|
|
95
|
-
const funcId = formatFuncIdName(funcName, path.relative(compiler.context, absolutePath), lineNumber)
|
|
96
|
-
const newFunctionBody = `return window.${ZERO_COM_CLIENT_SEND}({funcId: '${funcId}', params: [${funcParams}]})`
|
|
97
|
-
initializer.setBodyText(newFunctionBody)
|
|
98
|
-
generatedFunctions.push(decl.getVariableStatementOrThrow().getText())
|
|
99
|
-
console.log('client:', funcId)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
newModuleContent = generatedFunctions.join('\n\n')
|
|
104
|
-
} else {
|
|
105
|
-
const chunks: string[] = []
|
|
106
|
-
sourceFile.getFunctions().forEach(func => {
|
|
107
|
-
if (func.isExported() && func.isAsync()) {
|
|
108
|
-
const funcName = String(func.getName())
|
|
109
|
-
const lineNumber = func.getStartLineNumber()
|
|
110
|
-
const funcId = formatFuncIdName(funcName, path.relative(compiler.context, absolutePath), lineNumber)
|
|
111
|
-
chunks.push(`global.${ZERO_COM_SERVER_REGISTRY}['${funcId}'] = ${funcName}`)
|
|
112
|
-
console.log('server:', funcId)
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
sourceFile.getVariableDeclarations().forEach(decl => {
|
|
116
|
-
const initializer = decl.getInitializer()
|
|
117
|
-
if (initializer && initializer instanceof ArrowFunction) {
|
|
118
|
-
if (decl.isExported() && initializer.isAsync()) {
|
|
119
|
-
const funcName = decl.getName()
|
|
120
|
-
const lineNumber = decl.getStartLineNumber()
|
|
121
|
-
const funcId = formatFuncIdName(funcName, path.relative(compiler.context, absolutePath), lineNumber)
|
|
122
|
-
chunks.push(`global.${ZERO_COM_SERVER_REGISTRY}['${funcId}'] = ${funcName}`)
|
|
123
|
-
console.log('server:', funcId)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
newModuleContent = `${originalContent} if (!global.${ZERO_COM_SERVER_REGISTRY}) global.${ZERO_COM_SERVER_REGISTRY} = Object.create(null); ${chunks.join(',')}`
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
project.createSourceFile(absolutePath + '.ts', newModuleContent, { overwrite: true })
|
|
131
|
-
const result = project.emitToMemory()
|
|
132
|
-
const newContent = result.getFiles()[0].text
|
|
133
|
-
const inlineLoader = `data:text/javascript,${encodeURIComponent(newContent)}`
|
|
134
|
-
resolveData.request = inlineLoader
|
|
135
|
-
})
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
if (this.options.development) return
|
|
139
|
-
|
|
140
|
-
const replacements = [
|
|
141
|
-
{ target: ZERO_COM_CLIENT_SEND, replacement: `__ZERO_COM_CLIENT_SEND_${this.compilationId}` },
|
|
142
|
-
{ target: ZERO_COM_SERVER_REGISTRY, replacement: `__ZERO_COM_SERVER_REGISTRY_${this.compilationId}` }
|
|
143
|
-
]
|
|
144
|
-
|
|
145
|
-
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
|
|
146
|
-
compilation.hooks.processAssets.tap({ name: pluginName, stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE }, (assets) => {
|
|
147
|
-
for (const assetName in assets) {
|
|
148
|
-
if (assetName.endsWith('.js')) {
|
|
149
|
-
let assetSource = String(assets[assetName].source())
|
|
150
|
-
let modified = false
|
|
151
|
-
replacements.forEach(({ target, replacement }) => {
|
|
152
|
-
if (assetSource.includes(target)) {
|
|
153
|
-
assetSource = assetSource.replaceAll(target, replacement)
|
|
154
|
-
modified = true
|
|
155
|
-
}
|
|
156
|
-
})
|
|
157
|
-
if (modified) {
|
|
158
|
-
compilation.updateAsset(assetName, new RawSource(assetSource))
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
})
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
}
|