@signaltree/callable-syntax 6.0.0 → 6.0.1

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.
@@ -0,0 +1 @@
1
+
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { DEFAULT_ROOT_IDENTIFIERS, transformCode } from './lib/ast-transform.js';
2
+ export { signalTreeSyntaxTransform } from './lib/vite-plugin.js';
3
+ export { SignalTreeSyntaxWebpackPlugin } from './lib/webpack-plugin.js';
@@ -0,0 +1,74 @@
1
+ import generate from '@babel/generator';
2
+ import { parse } from '@babel/parser';
3
+ import traverse from '@babel/traverse';
4
+ import * as t from '@babel/types';
5
+
6
+ const DEFAULT_ROOT_IDENTIFIERS = ['tree'];
7
+ function transformCode(source, options = {}) {
8
+ var _a;
9
+ const rootIds = ((_a = options.rootIdentifiers) === null || _a === void 0 ? void 0 : _a.length) ? options.rootIdentifiers : DEFAULT_ROOT_IDENTIFIERS;
10
+ const ast = parseSourceCode(source);
11
+ let transformCount = 0;
12
+ traverse(ast, {
13
+ CallExpression(path) {
14
+ const {
15
+ node
16
+ } = path;
17
+ if (!t.isCallExpression(node)) return;
18
+ if (shouldTransformCallExpression(node, rootIds)) {
19
+ const transformedCall = createTransformedCall(node);
20
+ path.replaceWith(transformedCall);
21
+ transformCount++;
22
+ }
23
+ }
24
+ });
25
+ const output = generate(ast, {
26
+ retainLines: false,
27
+ comments: true
28
+ }, source);
29
+ if (options.debug && transformCount > 0) {
30
+ console.log(`[signaltree callable-syntax] transformed ${transformCount} calls`);
31
+ }
32
+ return {
33
+ code: output.code,
34
+ transformed: transformCount
35
+ };
36
+ }
37
+ function parseSourceCode(source) {
38
+ return parse(source, {
39
+ sourceType: 'module',
40
+ plugins: ['typescript', 'jsx']
41
+ });
42
+ }
43
+ function shouldTransformCallExpression(node, rootIds) {
44
+ if (!t.isMemberExpression(node.callee)) return false;
45
+ if (node.arguments.length === 0) return false;
46
+ if (isAlreadyTransformed(node.callee)) return false;
47
+ return isRootedSignalAccess(node.callee, rootIds);
48
+ }
49
+ function isAlreadyTransformed(callee) {
50
+ return t.isIdentifier(callee.property) && (callee.property.name === 'set' || callee.property.name === 'update');
51
+ }
52
+ function createTransformedCall(node) {
53
+ const callee = node.callee;
54
+ const method = determineMethod(node.arguments[0]);
55
+ return t.callExpression(t.memberExpression(callee, t.identifier(method)), node.arguments);
56
+ }
57
+ function determineMethod(firstArg) {
58
+ if (t.isFunctionExpression(firstArg) || t.isArrowFunctionExpression(firstArg)) {
59
+ return 'update';
60
+ }
61
+ return 'set';
62
+ }
63
+ function isRootedSignalAccess(expr, roots) {
64
+ let current = expr;
65
+ while (t.isMemberExpression(current)) {
66
+ if (t.isIdentifier(current.object)) {
67
+ return roots.includes(current.object.name);
68
+ }
69
+ current = current.object;
70
+ }
71
+ return false;
72
+ }
73
+
74
+ export { DEFAULT_ROOT_IDENTIFIERS, transformCode };
@@ -0,0 +1,25 @@
1
+ import { transformCode } from './ast-transform.js';
2
+
3
+ function signalTreeSyntaxTransform(options = {}) {
4
+ var _a, _b;
5
+ const include = (_a = options.include) !== null && _a !== void 0 ? _a : /src\/.*\.(t|j)sx?$/;
6
+ const exclude = (_b = options.exclude) !== null && _b !== void 0 ? _b : /node_modules|\.spec\.|\.test\./;
7
+ return {
8
+ name: 'signaltree-callable-syntax',
9
+ enforce: 'pre',
10
+ transform(code, id) {
11
+ if (!include.test(id) || exclude.test(id)) return null;
12
+ const result = transformCode(code, {
13
+ rootIdentifiers: options.rootIdentifiers,
14
+ debug: options.debug
15
+ });
16
+ if (result.transformed === 0) return null;
17
+ return {
18
+ code: result.code,
19
+ map: null
20
+ };
21
+ }
22
+ };
23
+ }
24
+
25
+ export { signalTreeSyntaxTransform };
@@ -0,0 +1,44 @@
1
+ import { transformCode } from './ast-transform.js';
2
+
3
+ class SignalTreeSyntaxWebpackPlugin {
4
+ constructor(options = {}) {
5
+ this.options = options;
6
+ }
7
+ apply(compiler) {
8
+ var _a, _b;
9
+ const test = (_a = this.options.test) !== null && _a !== void 0 ? _a : /src\/.*\.(t|j)sx?$/;
10
+ const exclude = (_b = this.options.exclude) !== null && _b !== void 0 ? _b : /node_modules|\.spec\.|\.test\./;
11
+ compiler.hooks.emit.tapAsync('SignalTreeSyntaxWebpackPlugin', (compilation, cb) => {
12
+ for (const filename of Object.keys(compilation.assets)) {
13
+ if (!test.test(filename) || exclude.test(filename)) continue;
14
+ const asset = compilation.assets[filename];
15
+ const raw = asset.source();
16
+ let source;
17
+ if (typeof raw === 'string') {
18
+ source = raw;
19
+ } else if (Buffer.isBuffer(raw)) {
20
+ source = raw.toString('utf8');
21
+ } else {
22
+ source = String(raw);
23
+ }
24
+ const {
25
+ code,
26
+ transformed
27
+ } = transformCode(source, {
28
+ rootIdentifiers: this.options.rootIdentifiers,
29
+ debug: this.options.debug
30
+ });
31
+ if (transformed > 0) {
32
+ const updated = code;
33
+ compilation.assets[filename] = {
34
+ source: () => updated,
35
+ size: () => Buffer.byteLength(updated, 'utf8')
36
+ };
37
+ }
38
+ }
39
+ cb();
40
+ });
41
+ }
42
+ }
43
+
44
+ export { SignalTreeSyntaxWebpackPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaltree/callable-syntax",
3
- "version": "6.0.0",
3
+ "version": "6.0.1",
4
4
  "description": "Optional zero-runtime callable syntax transform for SignalTree unified leaf API.",
5
5
  "license": "BSL-1.1",
6
6
  "type": "module",
@@ -1,10 +1 @@
1
- import '@angular/core';
2
-
3
- // Augment Angular WritableSignal so leaves support callable set/update like NodeAccessor.
4
- // Getter signature already exists on WritableSignal.
5
- declare module '@angular/core' {
6
- interface WritableSignal<T> {
7
- (value: T extends (...args: unknown[]) => unknown ? never : T): void;
8
- (updater: (current: T) => T): void;
9
- }
10
- }
1
+ export {};
package/src/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './lib/ast-transform';
2
+ export * from './lib/vite-plugin';
3
+ export * from './lib/webpack-plugin';
4
+ export * from './augmentation';
@@ -0,0 +1,10 @@
1
+ export interface TransformOptions {
2
+ readonly rootIdentifiers?: string[];
3
+ readonly debug?: boolean;
4
+ }
5
+ export interface TransformResult {
6
+ code: string;
7
+ transformed: number;
8
+ }
9
+ export declare const DEFAULT_ROOT_IDENTIFIERS: string[];
10
+ export declare function transformCode(source: string, options?: TransformOptions): TransformResult;
@@ -0,0 +1 @@
1
+ export declare const syntaxTransform: () => string;
@@ -0,0 +1,16 @@
1
+ type Plugin = {
2
+ name: string;
3
+ enforce?: 'pre' | 'post';
4
+ transform?: (code: string, id: string) => {
5
+ code: string;
6
+ map: null;
7
+ } | null;
8
+ };
9
+ export interface SignalTreeVitePluginOptions {
10
+ include?: RegExp;
11
+ exclude?: RegExp;
12
+ rootIdentifiers?: string[];
13
+ debug?: boolean;
14
+ }
15
+ export declare function signalTreeSyntaxTransform(options?: SignalTreeVitePluginOptions): Plugin;
16
+ export {};
@@ -0,0 +1,25 @@
1
+ interface CompilationLike {
2
+ assets: Record<string, {
3
+ source(): unknown;
4
+ size(): number;
5
+ }>;
6
+ }
7
+ interface CompilerLike {
8
+ hooks: {
9
+ emit: {
10
+ tapAsync(name: string, cb: (compilation: CompilationLike, done: (err?: Error) => void) => void): void;
11
+ };
12
+ };
13
+ }
14
+ export interface SignalTreeWebpackPluginOptions {
15
+ test?: RegExp;
16
+ exclude?: RegExp;
17
+ rootIdentifiers?: string[];
18
+ debug?: boolean;
19
+ }
20
+ export declare class SignalTreeSyntaxWebpackPlugin {
21
+ private readonly options;
22
+ constructor(options?: SignalTreeWebpackPluginOptions);
23
+ apply(compiler: CompilerLike): void;
24
+ }
25
+ export {};