@effectweb/compiler 0.3.0 → 0.4.0
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/README.md +19 -16
- package/dist/compile.d.ts +4 -1
- package/dist/compile.js +9 -1
- package/dist/files.d.ts +1 -0
- package/dist/files.js +3 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/oxlint.d.ts +3 -4
- package/dist/oxlint.js +14 -10
- package/dist/vite.js +4 -2
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -11,28 +11,33 @@ export default defineConfig({ plugins: [effectweb()] });
|
|
|
11
11
|
|
|
12
12
|
Install `effectweb` and its required Effect version in the application. Set TypeScript `jsx` to `preserve` and `jsxImportSource` to `effectweb`.
|
|
13
13
|
|
|
14
|
-
For direct compilation, import `compile` from `@effectweb/compiler`; the result contains generated code, a source map, and diagnostics. The Vite plugin reports diagnostics and enables development instrumentation during serve.
|
|
14
|
+
For direct compilation, import `compile` from `@effectweb/compiler`; the result contains generated code, a source map, and diagnostics. The Vite plugin reports syntax diagnostics and enables development instrumentation during serve.
|
|
15
|
+
|
|
16
|
+
The compiler lowers JSX syntax. Calls, callbacks, local variables, control flow, and JSX helpers retain ordinary JavaScript behavior. `view` is an executable runtime function; the compiler does not prove render purity, infer model dependencies, memoize helpers, or reinterpret `.map` as keyed rendering. Use the runtime's explicit `list(rows, render)` operation for keyed lists.
|
|
17
|
+
|
|
18
|
+
Files opt in by importing `effectweb` or one of its subpaths, or by declaring `/** @jsxImportSource effectweb */`. A different `@jsxImportSource` pragma leaves the file to its chosen JSX runtime. `compile` returns other files unchanged. `importSource` and `runtimeModule` options customize these module names. The package also supports the standard automatic JSX transform through `effectweb/jsx-runtime`; the native compiler adds source metadata in development.
|
|
15
19
|
|
|
16
20
|
Requires Node.js 22.14+. Optional packages provide binaries for glibc Linux x64/arm64, macOS x64/arm64, and Windows x64. Keep optional dependencies enabled. Installation does not compile Rust. Framework contributors build from source using Rust 1.96+.
|
|
17
21
|
|
|
18
22
|
See [EffectWeb](https://github.com/DerpyCrabs/EffectWeb) for authoring and development instructions.
|
|
19
23
|
|
|
20
|
-
For editor and CI diagnostics, add `@effectweb/compiler/oxlint` to Oxlint's `jsPlugins
|
|
24
|
+
For editor and CI diagnostics, add `@effectweb/compiler/oxlint` to Oxlint's `jsPlugins`. `effectweb/valid-view` checks supported JSX syntax, and `diagnose` exposes the same structured diagnostics without emitting code. Parser failures throw.
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
`effectweb/render-safety` is an optional heuristic lint rule for suspicious render work and captures. The separate `lint` API exposes these checks. They never participate in compilation or change generated code, and they are not a proof of purity. The former `whole-model-dependency` rule and collection-identity inference have been removed.
|
|
27
|
+
|
|
28
|
+
The runtime freezes published plain objects and arrays in every build without changing their identity or introducing proxies. Opaque mutable resources retain their own lifecycle. Development instrumentation labels actual text and attribute expressions and their evaluated values; production builds omit that metadata. It does not derive model-field dependency paths.
|
|
23
29
|
|
|
24
30
|
Diagnostics include `code`, `category`, `severity`, source `file`/`line`/`column` (one-based UTF-16 columns), and an actionable `remedy`:
|
|
25
31
|
|
|
26
|
-
| Code | Category | Meaning and remedy
|
|
27
|
-
| ------ | --------------------- |
|
|
28
|
-
| EW1000 | correctness | Lint could not parse
|
|
29
|
-
| EW1001 | correctness |
|
|
30
|
-
|
|
|
31
|
-
| EW2001 | unprovable-dependency |
|
|
32
|
-
| EW2002 | unprovable-dependency |
|
|
33
|
-
| EW3001 | performance | A helper depends on the entire model; optionally pass the individual fields it uses. |
|
|
32
|
+
| Code | Category | Meaning and remedy |
|
|
33
|
+
| ------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
34
|
+
| EW1000 | correctness | Lint could not parse the file or load the native compiler. Fix syntax or installation. |
|
|
35
|
+
| EW1001 | correctness | Unsupported intrinsic JSX syntax, such as `key`, `ref`, or `innerHTML`. Use explicit lists or owned DOM bindings. |
|
|
36
|
+
| EW1003 | correctness | Optional render-safety lint found potentially impure work. Review it and move side effects into owned work. |
|
|
37
|
+
| EW2001 | unprovable-dependency | Optional render-safety lint found a potentially mutable capture. Review its ownership; compilation itself accepts ordinary JavaScript captures. |
|
|
38
|
+
| EW2002 | unprovable-dependency | Query-key lint found a custom `key`. Remove it; every request argument participates in cache identity. The public query types and runtime also reject custom keys. |
|
|
34
39
|
|
|
35
|
-
`effectweb/
|
|
40
|
+
`effectweb/query-key` recognizes imported `query` definitions, including aliases and `effectweb/query`, with literal custom keys. Types and the runtime cover definitions assembled outside that lint analysis. Supply service instances through the Effect environment. For example:
|
|
36
41
|
|
|
37
42
|
```json
|
|
38
43
|
{
|
|
@@ -40,11 +45,9 @@ Diagnostics include `code`, `category`, `severity`, source `file`/`line`/`column
|
|
|
40
45
|
"rules": {
|
|
41
46
|
"effectweb/valid-view": "error",
|
|
42
47
|
"effectweb/query-key": "error",
|
|
43
|
-
"effectweb/
|
|
48
|
+
"effectweb/render-safety": "warn"
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
```
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Query checks recognize imported `query` (including aliases and `effectweb/query`) and reject literal definitions containing `key`. TypeScript and the runtime also reject custom keys, including definitions assembled outside the compiler's static analysis. Pass all request data as arguments and supply services through the Effect environment.
|
|
53
|
+
Remove `effectweb/render-safety` when heuristic advice is not wanted. TypeScript checks props, snapshots, and Effect service/error contracts; the compiler does not load or check the consumer's TypeScript project. See the [0.4.0 migration guide](https://github.com/DerpyCrabs/EffectWeb/blob/main/docs/migration-0.4.0.md) for list and lifecycle changes.
|
package/dist/compile.d.ts
CHANGED
|
@@ -21,5 +21,8 @@ export interface CompilerResult {
|
|
|
21
21
|
readonly diagnostics: readonly Diagnostic[];
|
|
22
22
|
}
|
|
23
23
|
export declare function compile(source: string, filename: string, options?: CompilerOptions): CompilerResult;
|
|
24
|
-
/**
|
|
24
|
+
/** Collect compiler syntax diagnostics without emitting code. */
|
|
25
25
|
export declare function diagnose(source: string, filename: string, options?: Omit<CompilerOptions, 'onDiagnostic'>): readonly Diagnostic[];
|
|
26
|
+
export type LintOptions = Pick<CompilerOptions, 'importSource'>;
|
|
27
|
+
/** Optional heuristic lint checks. These never participate in compilation. */
|
|
28
|
+
export declare function lint(source: string, filename: string, options?: LintOptions): readonly Diagnostic[];
|
package/dist/compile.js
CHANGED
|
@@ -6,12 +6,20 @@ export function compile(source, filename, options = {}) {
|
|
|
6
6
|
onDiagnostic?.(diagnostic);
|
|
7
7
|
return result;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
9
|
+
/** Collect compiler syntax diagnostics without emitting code. */
|
|
10
10
|
export function diagnose(source, filename, options = {}) {
|
|
11
|
+
return diagnostics(source, filename, options, false);
|
|
12
|
+
}
|
|
13
|
+
/** Optional heuristic lint checks. These never participate in compilation. */
|
|
14
|
+
export function lint(source, filename, options = {}) {
|
|
15
|
+
return diagnostics(source, filename, options, true);
|
|
16
|
+
}
|
|
17
|
+
function diagnostics(source, filename, options, lint) {
|
|
11
18
|
return JSON.parse(nativeCompile(source, filename, JSON.stringify({
|
|
12
19
|
importSource: 'effectweb',
|
|
13
20
|
...options,
|
|
14
21
|
development: true,
|
|
15
22
|
diagnosticsOnly: true,
|
|
23
|
+
lint,
|
|
16
24
|
}))).diagnostics;
|
|
17
25
|
}
|
package/dist/files.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isCompilerFile(filename: string): boolean;
|
package/dist/files.js
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { compile, diagnose, type CompilerOptions, type CompilerResult, type Diagnostic, } from './compile.js';
|
|
1
|
+
export { compile, diagnose, lint, type LintOptions, type CompilerOptions, type CompilerResult, type Diagnostic, } from './compile.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { compile, diagnose, } from './compile.js';
|
|
1
|
+
export { compile, diagnose, lint, } from './compile.js';
|
package/dist/oxlint.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
import { type CompilerOptions } from './compile.js';
|
|
1
2
|
type Source = {
|
|
2
3
|
text: string;
|
|
3
4
|
};
|
|
4
5
|
type Context = {
|
|
5
6
|
filename: string;
|
|
6
7
|
sourceCode: Source;
|
|
7
|
-
options: readonly
|
|
8
|
-
importSource?: string;
|
|
9
|
-
}[];
|
|
8
|
+
options: readonly Pick<CompilerOptions, 'importSource'>[];
|
|
10
9
|
report: (diagnostic: {
|
|
11
10
|
loc: {
|
|
12
11
|
line: number;
|
|
@@ -37,7 +36,7 @@ declare const _default: {
|
|
|
37
36
|
Program(): void;
|
|
38
37
|
};
|
|
39
38
|
};
|
|
40
|
-
'
|
|
39
|
+
'render-safety': {
|
|
41
40
|
meta: {
|
|
42
41
|
type: "problem" | "suggestion";
|
|
43
42
|
schema: {
|
package/dist/oxlint.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { diagnose } from './compile.js';
|
|
1
|
+
import { diagnose, lint } from './compile.js';
|
|
2
|
+
import { isCompilerFile } from './files.js';
|
|
2
3
|
const results = new WeakMap();
|
|
3
4
|
function rule(category) {
|
|
4
5
|
return {
|
|
@@ -15,7 +16,7 @@ function rule(category) {
|
|
|
15
16
|
create(context) {
|
|
16
17
|
return {
|
|
17
18
|
Program() {
|
|
18
|
-
if (
|
|
19
|
+
if (!isCompilerFile(context.filename))
|
|
19
20
|
return;
|
|
20
21
|
const importSource = context.options[0]?.importSource ?? 'effectweb';
|
|
21
22
|
let cached = results.get(context.sourceCode);
|
|
@@ -23,11 +24,12 @@ function rule(category) {
|
|
|
23
24
|
cached = { text: context.sourceCode.text, diagnostics: new Map() };
|
|
24
25
|
results.set(context.sourceCode, cached);
|
|
25
26
|
}
|
|
26
|
-
const
|
|
27
|
+
const heuristic = category === 'render-safety' || category === 'unprovable-dependency';
|
|
28
|
+
const key = `${context.filename}\0${importSource}\0${heuristic}`;
|
|
27
29
|
let diagnostics = cached.diagnostics.get(key);
|
|
28
30
|
if (!diagnostics) {
|
|
29
31
|
try {
|
|
30
|
-
diagnostics = diagnose(context.sourceCode.text, context.filename, { importSource });
|
|
32
|
+
diagnostics = (heuristic ? lint : diagnose)(context.sourceCode.text, context.filename, { importSource });
|
|
31
33
|
}
|
|
32
34
|
catch (error) {
|
|
33
35
|
// Parser failures and unavailable native binaries must not silently pass lint.
|
|
@@ -47,11 +49,13 @@ function rule(category) {
|
|
|
47
49
|
cached.diagnostics.set(key, diagnostics);
|
|
48
50
|
}
|
|
49
51
|
for (const diagnostic of diagnostics) {
|
|
50
|
-
const selected = category === '
|
|
51
|
-
?
|
|
52
|
-
: category === '
|
|
53
|
-
? diagnostic.
|
|
54
|
-
:
|
|
52
|
+
const selected = category === 'render-safety'
|
|
53
|
+
? ['EW1000', 'EW1003', 'EW2001'].includes(diagnostic.code)
|
|
54
|
+
: category === 'unprovable-dependency'
|
|
55
|
+
? diagnostic.code === 'EW2002' || diagnostic.code === 'EW1000'
|
|
56
|
+
: category === 'errors'
|
|
57
|
+
? diagnostic.severity === 'error'
|
|
58
|
+
: diagnostic.category === category;
|
|
55
59
|
if (!selected)
|
|
56
60
|
continue;
|
|
57
61
|
context.report({
|
|
@@ -68,7 +72,7 @@ export default {
|
|
|
68
72
|
meta: { name: 'effectweb' },
|
|
69
73
|
rules: {
|
|
70
74
|
'valid-view': rule('errors'),
|
|
71
|
-
'
|
|
75
|
+
'render-safety': rule('render-safety'),
|
|
72
76
|
'query-key': rule('unprovable-dependency'),
|
|
73
77
|
},
|
|
74
78
|
};
|
package/dist/vite.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { compile } from './compile.js';
|
|
2
|
+
import { isCompilerFile } from './files.js';
|
|
2
3
|
export function effectweb(options = {}) {
|
|
3
4
|
let development = false;
|
|
4
5
|
return {
|
|
5
6
|
config(_config, environment) {
|
|
6
7
|
return {
|
|
7
8
|
define: { __EFFECTWEB_DEV__: JSON.stringify(environment.command === 'serve') },
|
|
8
|
-
resolve: { dedupe: ['effect'] },
|
|
9
|
+
resolve: { dedupe: ['effect', 'effectweb'] },
|
|
10
|
+
optimizeDeps: { exclude: ['effectweb'] },
|
|
9
11
|
};
|
|
10
12
|
},
|
|
11
13
|
configResolved(config) {
|
|
@@ -15,7 +17,7 @@ export function effectweb(options = {}) {
|
|
|
15
17
|
enforce: 'pre',
|
|
16
18
|
transform(code, id) {
|
|
17
19
|
const filename = id.split('?')[0];
|
|
18
|
-
if (!filename ||
|
|
20
|
+
if (!filename || !isCompilerFile(filename))
|
|
19
21
|
return;
|
|
20
22
|
const result = compile(code, filename, {
|
|
21
23
|
...options,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effectweb/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Native Oxc compiler and Vite plugin for effectweb",
|
|
5
5
|
"homepage": "https://github.com/DerpyCrabs/EffectWeb",
|
|
6
6
|
"bugs": {
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"optionalDependencies": {
|
|
49
|
-
"@effectweb/compiler-darwin-arm64": "0.
|
|
50
|
-
"@effectweb/compiler-darwin-x64": "0.
|
|
51
|
-
"@effectweb/compiler-linux-arm64-gnu": "0.
|
|
52
|
-
"@effectweb/compiler-linux-x64-gnu": "0.
|
|
53
|
-
"@effectweb/compiler-win32-x64-msvc": "0.
|
|
49
|
+
"@effectweb/compiler-darwin-arm64": "0.4.0",
|
|
50
|
+
"@effectweb/compiler-darwin-x64": "0.4.0",
|
|
51
|
+
"@effectweb/compiler-linux-arm64-gnu": "0.4.0",
|
|
52
|
+
"@effectweb/compiler-linux-x64-gnu": "0.4.0",
|
|
53
|
+
"@effectweb/compiler-win32-x64-msvc": "0.4.0"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=22.14"
|