@esportsplus/reactivity 0.23.0 → 0.23.2
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/build/transformer/detector.js +38 -0
- package/build/transformer/index.d.ts +9 -0
- package/build/transformer/{core/index.js → index.js} +9 -18
- package/build/transformer/plugins/esbuild.d.ts +1 -3
- package/build/transformer/plugins/esbuild.js +5 -4
- package/build/transformer/plugins/tsc.js +1 -1
- package/build/transformer/plugins/vite.d.ts +1 -3
- package/build/transformer/plugins/vite.js +4 -4
- package/build/transformer/{core/transforms/reactive-array.d.ts → transforms/array.d.ts} +1 -1
- package/build/transformer/transforms/array.js +93 -0
- package/build/transformer/{core/transforms/reactive-object.d.ts → transforms/object.d.ts} +1 -1
- package/build/transformer/transforms/object.js +163 -0
- package/build/transformer/{core/transforms/reactive-primitives.d.ts → transforms/primitives.d.ts} +1 -1
- package/build/transformer/transforms/primitives.js +335 -0
- package/build/transformer/{core/transforms → transforms}/utilities.d.ts +1 -2
- package/build/transformer/transforms/utilities.js +73 -0
- package/build/types.d.ts +1 -4
- package/package.json +8 -12
- package/readme.md +0 -24
- package/src/transformer/detector.ts +65 -0
- package/src/transformer/{core/index.ts → index.ts} +10 -25
- package/src/transformer/plugins/esbuild.ts +5 -6
- package/src/transformer/plugins/tsc.ts +1 -1
- package/src/transformer/plugins/vite.ts +4 -8
- package/src/transformer/transforms/array.ts +143 -0
- package/src/transformer/transforms/object.ts +251 -0
- package/src/transformer/transforms/primitives.ts +461 -0
- package/src/transformer/transforms/utilities.ts +119 -0
- package/src/types.ts +0 -5
- package/build/transformer/core/detector.js +0 -6
- package/build/transformer/core/index.d.ts +0 -10
- package/build/transformer/core/transforms/auto-dispose.d.ts +0 -3
- package/build/transformer/core/transforms/auto-dispose.js +0 -116
- package/build/transformer/core/transforms/reactive-array.js +0 -89
- package/build/transformer/core/transforms/reactive-object.js +0 -155
- package/build/transformer/core/transforms/reactive-primitives.js +0 -325
- package/build/transformer/core/transforms/utilities.js +0 -57
- package/src/transformer/core/detector.ts +0 -12
- package/src/transformer/core/transforms/auto-dispose.ts +0 -194
- package/src/transformer/core/transforms/reactive-array.ts +0 -140
- package/src/transformer/core/transforms/reactive-object.ts +0 -244
- package/src/transformer/core/transforms/reactive-primitives.ts +0 -459
- package/src/transformer/core/transforms/utilities.ts +0 -95
- /package/build/transformer/{core/detector.d.ts → detector.d.ts} +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { mightNeedTransform as checkTransform } from '@esportsplus/typescript/transformer';
|
|
2
|
+
import ts from 'typescript';
|
|
3
|
+
const REACTIVE_REGEX = /\breactive\b/;
|
|
4
|
+
function visit(ctx, node) {
|
|
5
|
+
if (ctx.hasImport && ctx.hasUsage) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if (ts.isImportDeclaration(node) &&
|
|
9
|
+
node.importClause?.namedBindings &&
|
|
10
|
+
ts.isNamedImports(node.importClause.namedBindings)) {
|
|
11
|
+
let elements = node.importClause.namedBindings.elements;
|
|
12
|
+
for (let i = 0, n = elements.length; i < n; i++) {
|
|
13
|
+
let el = elements[i], name = el.propertyName?.text ?? el.name.text;
|
|
14
|
+
if (name === 'reactive') {
|
|
15
|
+
ctx.hasImport = true;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (ts.isCallExpression(node) &&
|
|
21
|
+
ts.isIdentifier(node.expression) &&
|
|
22
|
+
node.expression.text === 'reactive') {
|
|
23
|
+
ctx.hasUsage = true;
|
|
24
|
+
}
|
|
25
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
26
|
+
}
|
|
27
|
+
const mightNeedTransform = (code) => {
|
|
28
|
+
if (!checkTransform(code, { regex: REACTIVE_REGEX })) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
let ctx = {
|
|
32
|
+
hasImport: false,
|
|
33
|
+
hasUsage: false
|
|
34
|
+
};
|
|
35
|
+
visit(ctx, ts.createSourceFile('detect.ts', code, ts.ScriptTarget.Latest, false));
|
|
36
|
+
return ctx.hasImport && ctx.hasUsage;
|
|
37
|
+
};
|
|
38
|
+
export { mightNeedTransform };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TransformResult } from '../types.js';
|
|
2
|
+
import { mightNeedTransform } from './detector.js';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
declare const createTransformer: () => ts.TransformerFactory<ts.SourceFile>;
|
|
5
|
+
declare const transform: (sourceFile: ts.SourceFile) => TransformResult;
|
|
6
|
+
export { createTransformer, mightNeedTransform, transform };
|
|
7
|
+
export { transformReactiveArrays } from './transforms/array.js';
|
|
8
|
+
export { transformReactiveObjects } from './transforms/object.js';
|
|
9
|
+
export { transformReactivePrimitives } from './transforms/primitives.js';
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { injectAutoDispose } from './transforms/auto-dispose.js';
|
|
2
1
|
import { mightNeedTransform } from './detector.js';
|
|
3
|
-
import { transformReactiveArrays } from './transforms/
|
|
4
|
-
import { transformReactiveObjects } from './transforms/
|
|
5
|
-
import { transformReactivePrimitives } from './transforms/
|
|
2
|
+
import { transformReactiveArrays } from './transforms/array.js';
|
|
3
|
+
import { transformReactiveObjects } from './transforms/object.js';
|
|
4
|
+
import { transformReactivePrimitives } from './transforms/primitives.js';
|
|
6
5
|
import ts from 'typescript';
|
|
7
|
-
const createTransformer = (
|
|
6
|
+
const createTransformer = () => {
|
|
8
7
|
return () => {
|
|
9
8
|
return (sourceFile) => {
|
|
10
|
-
let result = transform(sourceFile
|
|
9
|
+
let result = transform(sourceFile);
|
|
11
10
|
return result.transformed ? result.sourceFile : sourceFile;
|
|
12
11
|
};
|
|
13
12
|
};
|
|
14
13
|
};
|
|
15
|
-
const transform = (sourceFile
|
|
14
|
+
const transform = (sourceFile) => {
|
|
16
15
|
let bindings = new Map(), code = sourceFile.getFullText(), current = sourceFile, original = code, result;
|
|
17
16
|
if (!mightNeedTransform(code)) {
|
|
18
17
|
return { code, sourceFile, transformed: false };
|
|
@@ -32,13 +31,6 @@ const transform = (sourceFile, options) => {
|
|
|
32
31
|
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
33
32
|
code = result;
|
|
34
33
|
}
|
|
35
|
-
if (options?.autoDispose) {
|
|
36
|
-
result = injectAutoDispose(current);
|
|
37
|
-
if (result !== code) {
|
|
38
|
-
current = ts.createSourceFile(sourceFile.fileName, result, sourceFile.languageVersion, true);
|
|
39
|
-
code = result;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
34
|
if (code === original) {
|
|
43
35
|
return { code, sourceFile, transformed: false };
|
|
44
36
|
}
|
|
@@ -49,7 +41,6 @@ const transform = (sourceFile, options) => {
|
|
|
49
41
|
};
|
|
50
42
|
};
|
|
51
43
|
export { createTransformer, mightNeedTransform, transform };
|
|
52
|
-
export {
|
|
53
|
-
export {
|
|
54
|
-
export {
|
|
55
|
-
export { transformReactivePrimitives } from './transforms/reactive-primitives.js';
|
|
44
|
+
export { transformReactiveArrays } from './transforms/array.js';
|
|
45
|
+
export { transformReactiveObjects } from './transforms/object.js';
|
|
46
|
+
export { transformReactivePrimitives } from './transforms/primitives.js';
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { Plugin } from 'esbuild';
|
|
2
|
-
|
|
3
|
-
declare const _default: (options?: TransformOptions) => Plugin;
|
|
2
|
+
declare const _default: () => Plugin;
|
|
4
3
|
export default _default;
|
|
5
|
-
export type { TransformOptions as PluginOptions };
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TRANSFORM_PATTERN } from '@esportsplus/typescript/transformer';
|
|
2
|
+
import { mightNeedTransform, transform } from '../../transformer/index.js';
|
|
2
3
|
import fs from 'fs';
|
|
3
4
|
import ts from 'typescript';
|
|
4
|
-
export default (
|
|
5
|
+
export default () => {
|
|
5
6
|
return {
|
|
6
7
|
name: '@esportsplus/reactivity/plugin-esbuild',
|
|
7
8
|
setup(build) {
|
|
8
|
-
build.onLoad({ filter:
|
|
9
|
+
build.onLoad({ filter: TRANSFORM_PATTERN }, async (args) => {
|
|
9
10
|
let code = await fs.promises.readFile(args.path, 'utf8');
|
|
10
11
|
if (!mightNeedTransform(code)) {
|
|
11
12
|
return null;
|
|
12
13
|
}
|
|
13
14
|
try {
|
|
14
|
-
let sourceFile = ts.createSourceFile(args.path, code, ts.ScriptTarget.Latest, true), result = transform(sourceFile
|
|
15
|
+
let sourceFile = ts.createSourceFile(args.path, code, ts.ScriptTarget.Latest, true), result = transform(sourceFile);
|
|
15
16
|
if (!result.transformed) {
|
|
16
17
|
return null;
|
|
17
18
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
|
-
|
|
3
|
-
declare const _default: (options?: TransformOptions) => Plugin;
|
|
2
|
+
declare const _default: () => Plugin;
|
|
4
3
|
export default _default;
|
|
5
|
-
export type { TransformOptions as PluginOptions };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TRANSFORM_PATTERN } from '@esportsplus/typescript/transformer';
|
|
2
|
+
import { mightNeedTransform, transform } from '../../transformer/index.js';
|
|
2
3
|
import ts from 'typescript';
|
|
3
|
-
|
|
4
|
-
export default (options) => {
|
|
4
|
+
export default () => {
|
|
5
5
|
return {
|
|
6
6
|
enforce: 'pre',
|
|
7
7
|
name: '@esportsplus/reactivity/plugin-vite',
|
|
@@ -13,7 +13,7 @@ export default (options) => {
|
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
16
|
-
let sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true), result = transform(sourceFile
|
|
16
|
+
let sourceFile = ts.createSourceFile(id, code, ts.ScriptTarget.Latest, true), result = transform(sourceFile);
|
|
17
17
|
if (!result.transformed) {
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { applyReplacements } from './utilities.js';
|
|
2
|
+
import ts from 'typescript';
|
|
3
|
+
function getExpressionName(node) {
|
|
4
|
+
if (ts.isIdentifier(node)) {
|
|
5
|
+
return node.text;
|
|
6
|
+
}
|
|
7
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
8
|
+
return getPropertyPath(node);
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
function getPropertyPath(node) {
|
|
13
|
+
let current = node, parts = [];
|
|
14
|
+
while (ts.isPropertyAccessExpression(current)) {
|
|
15
|
+
parts.unshift(current.name.text);
|
|
16
|
+
current = current.expression;
|
|
17
|
+
}
|
|
18
|
+
if (ts.isIdentifier(current)) {
|
|
19
|
+
parts.unshift(current.text);
|
|
20
|
+
return parts.join('.');
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function isAssignmentTarget(node) {
|
|
25
|
+
let parent = node.parent;
|
|
26
|
+
if ((ts.isBinaryExpression(parent) && parent.left === node) ||
|
|
27
|
+
ts.isPostfixUnaryExpression(parent) ||
|
|
28
|
+
ts.isPrefixUnaryExpression(parent)) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
function visit(ctx, node) {
|
|
34
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
|
|
35
|
+
if (ts.isIdentifier(node.initializer) && ctx.bindings.get(node.initializer.text) === 'array') {
|
|
36
|
+
ctx.bindings.set(node.name.text, 'array');
|
|
37
|
+
}
|
|
38
|
+
if (ts.isPropertyAccessExpression(node.initializer)) {
|
|
39
|
+
let path = getPropertyPath(node.initializer);
|
|
40
|
+
if (path && ctx.bindings.get(path) === 'array') {
|
|
41
|
+
ctx.bindings.set(node.name.text, 'array');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if ((ts.isFunctionDeclaration(node) || ts.isArrowFunction(node)) && node.parameters) {
|
|
46
|
+
for (let i = 0, n = node.parameters.length; i < n; i++) {
|
|
47
|
+
let param = node.parameters[i];
|
|
48
|
+
if ((ts.isIdentifier(param.name) && param.type) &&
|
|
49
|
+
ts.isTypeReferenceNode(param.type) &&
|
|
50
|
+
ts.isIdentifier(param.type.typeName) &&
|
|
51
|
+
param.type.typeName.text === 'ReactiveArray') {
|
|
52
|
+
ctx.bindings.set(param.name.text, 'array');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (ts.isPropertyAccessExpression(node) &&
|
|
57
|
+
node.name.text === 'length' &&
|
|
58
|
+
!isAssignmentTarget(node)) {
|
|
59
|
+
let name = getExpressionName(node.expression);
|
|
60
|
+
if (name && ctx.bindings.get(name) === 'array') {
|
|
61
|
+
let objText = node.expression.getText(ctx.sourceFile);
|
|
62
|
+
ctx.replacements.push({
|
|
63
|
+
end: node.end,
|
|
64
|
+
newText: `${objText}.$length()`,
|
|
65
|
+
start: node.pos
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (ts.isBinaryExpression(node) &&
|
|
70
|
+
node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
71
|
+
ts.isElementAccessExpression(node.left)) {
|
|
72
|
+
let elemAccess = node.left, objName = getExpressionName(elemAccess.expression);
|
|
73
|
+
if (objName && ctx.bindings.get(objName) === 'array') {
|
|
74
|
+
let indexText = elemAccess.argumentExpression.getText(ctx.sourceFile), objText = elemAccess.expression.getText(ctx.sourceFile), valueText = node.right.getText(ctx.sourceFile);
|
|
75
|
+
ctx.replacements.push({
|
|
76
|
+
end: node.end,
|
|
77
|
+
newText: `${objText}.$set(${indexText}, ${valueText})`,
|
|
78
|
+
start: node.pos
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
83
|
+
}
|
|
84
|
+
const transformReactiveArrays = (sourceFile, bindings) => {
|
|
85
|
+
let code = sourceFile.getFullText(), ctx = {
|
|
86
|
+
bindings,
|
|
87
|
+
replacements: [],
|
|
88
|
+
sourceFile
|
|
89
|
+
};
|
|
90
|
+
visit(ctx, sourceFile);
|
|
91
|
+
return applyReplacements(code, ctx.replacements);
|
|
92
|
+
};
|
|
93
|
+
export { transformReactiveArrays };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { uid } from '@esportsplus/typescript/transformer';
|
|
2
|
+
import { addMissingImports, applyReplacements } from './utilities.js';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
const CLASS_NAME_REGEX = /class (\w+)/;
|
|
5
|
+
const EXTRA_IMPORTS = [
|
|
6
|
+
{ module: '@esportsplus/reactivity/constants', specifier: 'REACTIVE_OBJECT' },
|
|
7
|
+
{ module: '@esportsplus/reactivity/reactive/array', specifier: 'ReactiveArray' }
|
|
8
|
+
];
|
|
9
|
+
function analyzeProperty(prop, sourceFile) {
|
|
10
|
+
if (!ts.isPropertyAssignment(prop)) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
let key;
|
|
14
|
+
if (ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name)) {
|
|
15
|
+
key = prop.name.text;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
let value = prop.initializer, valueText = value.getText(sourceFile);
|
|
21
|
+
if (ts.isArrowFunction(value) || ts.isFunctionExpression(value)) {
|
|
22
|
+
return { key, type: 'computed', valueText };
|
|
23
|
+
}
|
|
24
|
+
if (ts.isArrayLiteralExpression(value)) {
|
|
25
|
+
return { key, type: 'array', valueText };
|
|
26
|
+
}
|
|
27
|
+
return { key, type: 'signal', valueText };
|
|
28
|
+
}
|
|
29
|
+
function buildClassCode(className, properties) {
|
|
30
|
+
let accessors = [], disposeStatements = [], fields = [];
|
|
31
|
+
fields.push(`[REACTIVE_OBJECT] = true;`);
|
|
32
|
+
for (let i = 0, n = properties.length; i < n; i++) {
|
|
33
|
+
let { key, type, valueText } = properties[i];
|
|
34
|
+
if (type === 'signal') {
|
|
35
|
+
let param = uid('v');
|
|
36
|
+
fields.push(`#${key} = signal(${valueText});`);
|
|
37
|
+
accessors.push(`get ${key}() { return read(this.#${key}); }`);
|
|
38
|
+
accessors.push(`set ${key}(${param}) { set(this.#${key}, ${param}); }`);
|
|
39
|
+
}
|
|
40
|
+
else if (type === 'array') {
|
|
41
|
+
let elements = valueText.slice(1, -1);
|
|
42
|
+
fields.push(`${key} = new ReactiveArray(${elements});`);
|
|
43
|
+
disposeStatements.push(`this.${key}.dispose();`);
|
|
44
|
+
}
|
|
45
|
+
else if (type === 'computed') {
|
|
46
|
+
fields.push(`#${key}: Computed<unknown> | null = null;`);
|
|
47
|
+
accessors.push(`get ${key}() { return read(this.#${key} ??= computed(${valueText})); }`);
|
|
48
|
+
disposeStatements.push(`if (this.#${key}) dispose(this.#${key});`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return `
|
|
52
|
+
class ${className} {
|
|
53
|
+
${fields.join('\n')}
|
|
54
|
+
${accessors.join('\n')}
|
|
55
|
+
|
|
56
|
+
dispose() {
|
|
57
|
+
${disposeStatements.length > 0 ? disposeStatements.join('\n') : ''}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
function visit(ctx, node) {
|
|
63
|
+
if (ts.isImportDeclaration(node)) {
|
|
64
|
+
ctx.lastImportEnd = node.end;
|
|
65
|
+
if (ts.isStringLiteral(node.moduleSpecifier) &&
|
|
66
|
+
node.moduleSpecifier.text.includes('@esportsplus/reactivity')) {
|
|
67
|
+
let clause = node.importClause;
|
|
68
|
+
if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings)) {
|
|
69
|
+
let elements = clause.namedBindings.elements;
|
|
70
|
+
for (let i = 0, n = elements.length; i < n; i++) {
|
|
71
|
+
if (elements[i].name.text === 'reactive') {
|
|
72
|
+
ctx.hasReactiveImport = true;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (ctx.hasReactiveImport &&
|
|
80
|
+
ts.isCallExpression(node) &&
|
|
81
|
+
ts.isIdentifier(node.expression) &&
|
|
82
|
+
node.expression.text === 'reactive') {
|
|
83
|
+
let arg = node.arguments[0];
|
|
84
|
+
if (arg && ts.isObjectLiteralExpression(arg)) {
|
|
85
|
+
let varName = null;
|
|
86
|
+
if (ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
87
|
+
varName = node.parent.name.text;
|
|
88
|
+
ctx.bindings.set(varName, 'object');
|
|
89
|
+
}
|
|
90
|
+
let needsImports = new Set(), properties = [];
|
|
91
|
+
needsImports.add('REACTIVE_OBJECT');
|
|
92
|
+
let props = arg.properties;
|
|
93
|
+
for (let i = 0, n = props.length; i < n; i++) {
|
|
94
|
+
let prop = props[i];
|
|
95
|
+
if (ts.isSpreadAssignment(prop)) {
|
|
96
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
let analyzed = analyzeProperty(prop, ctx.sourceFile);
|
|
100
|
+
if (!analyzed) {
|
|
101
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
properties.push(analyzed);
|
|
105
|
+
if (analyzed.type === 'signal') {
|
|
106
|
+
needsImports.add('read');
|
|
107
|
+
needsImports.add('set');
|
|
108
|
+
needsImports.add('signal');
|
|
109
|
+
}
|
|
110
|
+
else if (analyzed.type === 'array') {
|
|
111
|
+
needsImports.add('ReactiveArray');
|
|
112
|
+
if (varName) {
|
|
113
|
+
ctx.bindings.set(`${varName}.${analyzed.key}`, 'array');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (analyzed.type === 'computed') {
|
|
117
|
+
needsImports.add('computed');
|
|
118
|
+
needsImports.add('dispose');
|
|
119
|
+
needsImports.add('read');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
needsImports.forEach(imp => ctx.allNeededImports.add(imp));
|
|
123
|
+
ctx.calls.push({
|
|
124
|
+
end: node.end,
|
|
125
|
+
generatedClass: buildClassCode(uid('ReactiveObject'), properties),
|
|
126
|
+
needsImports,
|
|
127
|
+
start: node.pos,
|
|
128
|
+
varName
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
ts.forEachChild(node, n => visit(ctx, n));
|
|
133
|
+
}
|
|
134
|
+
const transformReactiveObjects = (sourceFile, bindings) => {
|
|
135
|
+
let code = sourceFile.getFullText(), ctx = {
|
|
136
|
+
allNeededImports: new Set(),
|
|
137
|
+
bindings,
|
|
138
|
+
calls: [],
|
|
139
|
+
hasReactiveImport: false,
|
|
140
|
+
lastImportEnd: 0,
|
|
141
|
+
sourceFile
|
|
142
|
+
};
|
|
143
|
+
visit(ctx, sourceFile);
|
|
144
|
+
if (ctx.calls.length === 0) {
|
|
145
|
+
return code;
|
|
146
|
+
}
|
|
147
|
+
let replacements = [];
|
|
148
|
+
replacements.push({
|
|
149
|
+
end: ctx.lastImportEnd,
|
|
150
|
+
newText: code.substring(0, ctx.lastImportEnd) + '\n' + ctx.calls.map(c => c.generatedClass).join('\n') + '\n',
|
|
151
|
+
start: 0
|
|
152
|
+
});
|
|
153
|
+
for (let i = 0, n = ctx.calls.length; i < n; i++) {
|
|
154
|
+
let call = ctx.calls[i], classMatch = call.generatedClass.match(CLASS_NAME_REGEX);
|
|
155
|
+
replacements.push({
|
|
156
|
+
end: call.end,
|
|
157
|
+
newText: ` new ${classMatch ? classMatch[1] : 'ReactiveObject'}()`,
|
|
158
|
+
start: call.start
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return addMissingImports(applyReplacements(code, replacements), ctx.allNeededImports, EXTRA_IMPORTS);
|
|
162
|
+
};
|
|
163
|
+
export { transformReactiveObjects };
|
package/build/transformer/{core/transforms/reactive-primitives.d.ts → transforms/primitives.d.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Bindings } from '
|
|
1
|
+
import type { Bindings } from '../../types.js';
|
|
2
2
|
import ts from 'typescript';
|
|
3
3
|
declare const transformReactivePrimitives: (sourceFile: ts.SourceFile, bindings: Bindings) => string;
|
|
4
4
|
export { transformReactivePrimitives };
|