@govela/compiler 0.0.0-stage → 0.4.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 abullo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,33 @@
1
- # Temporary Holding Version
1
+ # @govela/compiler
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Vela compiler for JavaScript toolchains: `npm i -D @govela/compiler` installs
4
+ the `vela` command with a prebuilt binary for this platform, no Go
5
+ toolchain needed. Install `@govela/runtime` of the same version for
6
+ bundled applications.
7
+
8
+ ```sh
9
+ npx vela --project src --out build --runtime-import=bare
10
+ npx vela check --project src
11
+ ```
12
+
13
+ ## JavaScript API
14
+
15
+ ```js
16
+ import { compile, startService } from '@govela/compiler';
17
+
18
+ const result = await compile({ path: 'src/App.vela' });
19
+ // result.ok, result.js, result.css, result.map, result.diagnostics, result.imports
20
+
21
+ const service = await startService(); // one `vela serve --stdio` process
22
+ const a = await service.compile({ path: 'src/App.vela', source, options: { sourcemap: true } });
23
+ await service.close();
24
+ ```
25
+
26
+ Requests, results and options are those of the compiler service protocol
27
+ (`docs/TOOLING_PROTOCOL.md` in the compiler repository). `startService`
28
+ rejects a binary that speaks another protocol or has another version.
29
+
30
+ Supported platforms: linux x64/arm64, macOS x64/arm64, Windows x64. Set
31
+ `VELA_BINARY` to the path of a `vela` binary to use another build.
32
+
33
+ License: MIT.
package/bin/vela.js ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ // The `vela` command of @govela/compiler: runs the binary of this platform
3
+ // with the arguments, standard streams and exit code of the command.
4
+ import { spawnSync } from 'node:child_process';
5
+ import { binaryPath } from '../index.js';
6
+
7
+ let binary;
8
+ try {
9
+ binary = binaryPath();
10
+ } catch (error) {
11
+ console.error(error.message);
12
+ process.exit(1);
13
+ }
14
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit', windowsHide: true });
15
+ if (result.error) {
16
+ console.error(`vela: cannot run ${binary}: ${result.error.message}`);
17
+ process.exit(1);
18
+ }
19
+ if (result.signal) {
20
+ process.kill(process.pid, result.signal);
21
+ }
22
+ process.exit(result.status ?? 1);
package/index.d.ts ADDED
@@ -0,0 +1,91 @@
1
+ // Types of the compiler service protocol (docs/TOOLING_PROTOCOL.md).
2
+
3
+ export declare const version: string;
4
+ export declare const protocol: 1;
5
+
6
+ /** The file options of a request; each is the build flag of the same name. */
7
+ export interface CompileOptions {
8
+ minify?: boolean;
9
+ css?: 'inject' | 'external';
10
+ sourcemap?: boolean;
11
+ target?: 'permissive' | 'browser' | 'worker' | 'node' | 'ssr';
12
+ unavailableCapabilities?: string[];
13
+ strict?: boolean;
14
+ hydrationVerify?: 'repair' | 'fail' | 'off';
15
+ mode?: 'development' | 'production';
16
+ runtimeImport?: 'relative' | 'bare';
17
+ checkDeps?: boolean;
18
+ /** 'vela' keeps `.vela` specifiers of component imports, for bundler plugins. */
19
+ componentImports?: 'js' | 'vela';
20
+ }
21
+
22
+ export interface CompileRequest {
23
+ /** The component, absolute or relative to the service's working directory. */
24
+ path: string;
25
+ /** The text to compile; without it the service reads path. */
26
+ source?: string;
27
+ options?: CompileOptions;
28
+ }
29
+
30
+ export interface Diagnostic {
31
+ severity: 'error' | 'warning' | 'hint';
32
+ code?: string;
33
+ file?: string;
34
+ line: number;
35
+ column: number;
36
+ endLine: number;
37
+ endColumn: number;
38
+ message: string;
39
+ suggestion?: string;
40
+ }
41
+
42
+ export interface ModuleImport {
43
+ specifier: string;
44
+ kind: 'component' | 'module' | 'runtime' | 'package' | 'url';
45
+ resolved?: string;
46
+ }
47
+
48
+ export interface CompileResult {
49
+ ok: boolean;
50
+ js?: string;
51
+ css?: string;
52
+ /** A v3 source map with options.sourcemap. */
53
+ map?: object;
54
+ diagnostics: Diagnostic[];
55
+ imports: ModuleImport[];
56
+ error?: string;
57
+ }
58
+
59
+ export interface Handshake {
60
+ protocol: number;
61
+ compilerVersion: string;
62
+ runtimePackage: string;
63
+ runtimeContract: string;
64
+ }
65
+
66
+ export interface ServiceOptions {
67
+ /** Working directory of the service: paths and vela.config.json resolve against it. */
68
+ cwd?: string;
69
+ /** A configuration file instead of vela.config.json in cwd. */
70
+ config?: string;
71
+ /** Further flags of `vela serve`, e.g. ['--target', 'browser']. */
72
+ args?: string[];
73
+ /** A vela binary instead of the platform package's. */
74
+ binary?: string;
75
+ }
76
+
77
+ export interface Service {
78
+ handshake(): Handshake;
79
+ compile(request: CompileRequest): Promise<CompileResult>;
80
+ /** Ends the input; resolves when the service has answered every request and exited. */
81
+ close(): Promise<void>;
82
+ }
83
+
84
+ /** The vela binary: VELA_BINARY, else the binary of the platform package. */
85
+ export declare function binaryPath(): string;
86
+
87
+ /** Starts `vela serve --stdio`; rejects a binary of another protocol or version. */
88
+ export declare function startService(options?: ServiceOptions): Promise<Service>;
89
+
90
+ /** Compiles one component with a short-lived service. */
91
+ export declare function compile(request: CompileRequest, options?: ServiceOptions): Promise<CompileResult>;
package/index.js ADDED
@@ -0,0 +1,144 @@
1
+ // The JavaScript API of @govela/compiler: the binary of this platform, and
2
+ // the compiler service protocol (docs/TOOLING_PROTOCOL.md) over
3
+ // `vela serve --stdio`.
4
+ import { spawn } from 'node:child_process';
5
+ import { readFileSync } from 'node:fs';
6
+ import { createRequire } from 'node:module';
7
+ import { createInterface } from 'node:readline';
8
+
9
+ const require = createRequire(import.meta.url);
10
+ const manifest = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'));
11
+
12
+ /** The version of this package; the binary must have the same version. */
13
+ export const version = manifest.version;
14
+
15
+ /** The service protocol version this package speaks. */
16
+ export const protocol = 1;
17
+
18
+ const platforms = {
19
+ 'linux-x64': 'bin/vela',
20
+ 'linux-arm64': 'bin/vela',
21
+ 'darwin-x64': 'bin/vela',
22
+ 'darwin-arm64': 'bin/vela',
23
+ 'win32-x64': 'bin/vela.exe',
24
+ };
25
+
26
+ function velaError(code, message) {
27
+ const error = new Error(message);
28
+ error.code = code;
29
+ return error;
30
+ }
31
+
32
+ /**
33
+ * The path of the vela binary: VELA_BINARY when it is set, else the binary
34
+ * of the installed platform package.
35
+ */
36
+ export function binaryPath() {
37
+ if (process.env.VELA_BINARY) {
38
+ return process.env.VELA_BINARY;
39
+ }
40
+ const platform = `${process.platform}-${process.arch}`;
41
+ const file = platforms[platform];
42
+ const name = `${manifest.name}-${platform}`;
43
+ if (!file) {
44
+ throw velaError('VELA_PLATFORM', `vela: no prebuilt binary for ${platform}; supported: ${Object.keys(platforms).join(', ')}. Install the compiler with \`go install github.com/elauven/vela@v${version}\` and set VELA_BINARY to it.`);
45
+ }
46
+ try {
47
+ return require.resolve(`${name}/${file}`);
48
+ } catch {
49
+ throw velaError('VELA_BINARY', `vela: the package ${name} is not installed. It is an optional dependency of ${manifest.name}; reinstall without --no-optional / --omit=optional, or set VELA_BINARY to a vela binary.`);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Starts `vela serve --stdio`. Resolves when the compiler has answered the
55
+ * handshake with this package's protocol and version.
56
+ */
57
+ export function startService({ cwd, config, args = [], binary } = {}) {
58
+ const command = binary ?? binaryPath();
59
+ const argv = ['serve', '--stdio', '--protocol', String(protocol), ...(config ? ['--config', config] : []), ...args];
60
+ const child = spawn(command, argv, { cwd, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
61
+ const lines = createInterface({ input: child.stdout });
62
+ const pending = new Map();
63
+ let stderr = '';
64
+ let nextId = 1;
65
+ let closed = false;
66
+ child.stderr.on('data', (chunk) => { stderr += chunk; });
67
+
68
+ return new Promise((resolve, reject) => {
69
+ let handshake = null;
70
+ const fail = (error) => {
71
+ for (const { reject: rejectRequest } of pending.values()) rejectRequest(error);
72
+ pending.clear();
73
+ if (!handshake) reject(error);
74
+ };
75
+ child.on('error', (error) => fail(velaError('VELA_BINARY', `vela: cannot run ${command}: ${error.message}`)));
76
+ // 'close' comes after the last output line, unlike 'exit'.
77
+ child.on('close', (code, signal) => {
78
+ closed = true;
79
+ if (pending.size > 0 || !handshake) {
80
+ fail(velaError('VELA_EXIT', `vela serve exited (${signal ?? code})${stderr ? `: ${stderr.trim()}` : ''}`));
81
+ }
82
+ });
83
+ lines.on('line', (line) => {
84
+ let message;
85
+ try {
86
+ message = JSON.parse(line);
87
+ } catch {
88
+ fail(velaError('VELA_PROTOCOL', `vela serve wrote a line that is not JSON: ${line}`));
89
+ return;
90
+ }
91
+ if (!handshake) {
92
+ handshake = message;
93
+ if (message.error || message.protocol !== protocol) {
94
+ child.kill();
95
+ reject(velaError('VELA_PROTOCOL', `vela: ${message.error ?? `the compiler speaks protocol ${message.protocol}, ${manifest.name} ${version} speaks ${protocol}`}`));
96
+ return;
97
+ }
98
+ if (message.compilerVersion !== version) {
99
+ child.kill();
100
+ reject(velaError('VELA_VERSION', `vela: the binary ${command} is version ${message.compilerVersion}, ${manifest.name} is ${version}; install matching versions${process.env.VELA_BINARY ? ' or unset VELA_BINARY' : ''}`));
101
+ return;
102
+ }
103
+ resolve(service);
104
+ return;
105
+ }
106
+ const request = pending.get(JSON.stringify(message.id));
107
+ if (request) {
108
+ pending.delete(JSON.stringify(message.id));
109
+ request.resolve(message);
110
+ }
111
+ });
112
+
113
+ const service = {
114
+ handshake: () => handshake,
115
+ compile(request) {
116
+ if (closed) {
117
+ return Promise.reject(velaError('VELA_EXIT', 'vela serve is closed'));
118
+ }
119
+ const id = nextId++;
120
+ return new Promise((resolveRequest, rejectRequest) => {
121
+ pending.set(JSON.stringify(id), { resolve: resolveRequest, reject: rejectRequest });
122
+ child.stdin.write(JSON.stringify({ ...request, id }) + '\n');
123
+ });
124
+ },
125
+ close() {
126
+ if (closed) return Promise.resolve();
127
+ return new Promise((resolveClose) => {
128
+ child.once('close', () => resolveClose());
129
+ child.stdin.end();
130
+ });
131
+ },
132
+ };
133
+ });
134
+ }
135
+
136
+ /** Compiles one component with a short-lived service. */
137
+ export async function compile(request, serviceOptions) {
138
+ const service = await startService(serviceOptions);
139
+ try {
140
+ return await service.compile(request);
141
+ } finally {
142
+ await service.close();
143
+ }
144
+ }
package/package.json CHANGED
@@ -1,6 +1,39 @@
1
1
  {
2
2
  "name": "@govela/compiler",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.5",
4
+ "description": "The Vela compiler: single-file components to ES modules, and Go server renderers. Manifest generated by the compiler repository; do not edit.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/elauven/vela.git",
9
+ "directory": "packages/compiler"
10
+ },
11
+ "type": "module",
12
+ "bin": {
13
+ "vela": "bin/vela.js"
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "types": "./index.d.ts",
18
+ "default": "./index.js"
19
+ },
20
+ "./package.json": "./package.json"
21
+ },
22
+ "types": "index.d.ts",
23
+ "files": [
24
+ "bin/vela.js",
25
+ "index.js",
26
+ "index.d.ts",
27
+ "LICENSE"
28
+ ],
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "optionalDependencies": {
33
+ "@govela/compiler-darwin-arm64": "0.4.5",
34
+ "@govela/compiler-darwin-x64": "0.4.5",
35
+ "@govela/compiler-linux-arm64": "0.4.5",
36
+ "@govela/compiler-linux-x64": "0.4.5",
37
+ "@govela/compiler-win32-x64": "0.4.5"
38
+ }
39
+ }