bun-assemblyscript 0.1.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.
@@ -0,0 +1,32 @@
1
+ {
2
+ "AssemblyScript Export": {
3
+ "prefix": "asexport",
4
+ "scope": "typescript",
5
+ "body": [
6
+ "export function ${1:name}(${2:a}: ${3:i32}): ${4:i32} {",
7
+ " $0",
8
+ "}"
9
+ ],
10
+ "description": "Exported function for AssemblyScript"
11
+ },
12
+ "AssemblyScript Class": {
13
+ "prefix": "asclass",
14
+ "scope": "typescript",
15
+ "body": [
16
+ "export class ${1:Name} {",
17
+ " constructor() {",
18
+ " $0",
19
+ " }",
20
+ "}"
21
+ ],
22
+ "description": "Exported class with constructor for AssemblyScript"
23
+ },
24
+ "AssemblyScript Import": {
25
+ "prefix": "asimport",
26
+ "scope": "typescript",
27
+ "body": [
28
+ "import { ${2:func} } from \"${1:./module.as}\";$0"
29
+ ],
30
+ "description": "Import pattern from an .as file"
31
+ }
32
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "recommendations": [
3
+ "saulecabrera.vscode-assemblyscript"
4
+ ]
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "files.associations": {
3
+ "*.as": "typescript"
4
+ }
5
+ }
package/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # bun-assemblyscript
2
+
3
+ [![npm version](https://badge.fury.io/js/bun-assemblyscript.svg)](https://badge.fury.io/js/bun-assemblyscript)
4
+ [![Bun](https://img.shields.io/badge/Bun-%23000000.svg?logo=bun&logoColor=white)](https://bun.sh)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ ## Why
8
+ Le développement avec WebAssembly dans Bun nécessite souvent des étapes de compilation manuelles et fastidieuses. `bun-assemblyscript` élimine cette friction en permettant l'importation directe de fichiers `.as` dans vos projets Bun. Profitez de la performance de WebAssembly avec l'expérience développeur de TypeScript.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ bun add -d bun-assemblyscript assemblyscript
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```typescript
19
+ import { add } from "./math.as";
20
+ console.log(add(1, 2)); // 3
21
+ ```
22
+
23
+ ## How it works
24
+ Le plugin compile le code WebAssembly à la volée selon ce pipeline :
25
+ `.as → asc → .wasm → .d.ts → import natif`
26
+
27
+ ## Configuration
28
+ Les options de compilation suivantes sont supportées :
29
+ - `embedMode` : Définit la méthode d'intégration du binaire wasm (ex: inline en base64).
30
+ - `runtime` : Spécifie le runtime AssemblyScript à intégrer (stub, minimal, etc.).
31
+ - `optimizeLevel` : Niveau d'optimisation de `asc` (1 à 3).
32
+
33
+ ## Roadmap
34
+ Notre objectif principal pour le futur est d'obtenir une **intégration CLI Bun** native et complète pour ce plugin.
package/app.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { add } from "./test/fixtures/math.as";
2
+ console.log("Result from WASM in bundled app:", add(5, 7));
@@ -0,0 +1,113 @@
1
+ /**
2
+ * ============================================================
3
+ * AssemblyScript Primitive Types — Advanced TypeScript Bindings
4
+ * ============================================================
5
+ * Branded types pour distinguer les primitives AS à la compilation,
6
+ * éviter les mélanges implicites (ex: i32 ≠ f64), et offrir
7
+ * une meilleure expérience IntelliSense dans l'éditeur.
8
+ */
9
+
10
+ // ─── Branding utility ────────────────────────────────────────
11
+ declare const __brand: unique symbol;
12
+ type Brand<T, B extends string> = T & { readonly [__brand]: B };
13
+
14
+ // ─── Integers signés ─────────────────────────────────────────
15
+ declare type i8 = Brand<number, "i8">;
16
+ declare type i16 = Brand<number, "i16">;
17
+ declare type i32 = Brand<number, "i32">;
18
+ declare type i64 = Brand<bigint, "i64">;
19
+ declare type isize = Brand<number, "isize">;
20
+
21
+ // ─── Integers non-signés ─────────────────────────────────────
22
+ declare type u8 = Brand<number, "u8">;
23
+ declare type u16 = Brand<number, "u16">;
24
+ declare type u32 = Brand<number, "u32">;
25
+ declare type u64 = Brand<bigint, "u64">;
26
+ declare type usize = Brand<number, "usize">;
27
+
28
+ // ─── Flottants ───────────────────────────────────────────────
29
+ declare type f32 = Brand<number, "f32">;
30
+ declare type f64 = Brand<number, "f64">;
31
+
32
+ // ─── Booléen ─────────────────────────────────────────────────
33
+ declare type bool = Brand<boolean, "bool">;
34
+
35
+ // ─── SIMD / Références ───────────────────────────────────────
36
+ declare type v128 = Brand<never, "v128">;
37
+ declare type anyref = Brand<object, "anyref">;
38
+ declare type externref = Brand<object, "externref">;
39
+
40
+ // ─── Helpers de cast (narrowing explicite) ───────────────────
41
+ declare function as_i32(v: number): i32;
42
+ declare function as_u32(v: number): u32;
43
+ declare function as_f64(v: number): f64;
44
+ declare function as_i64(v: bigint): i64;
45
+ declare function as_u64(v: bigint): u64;
46
+ declare function as_bool(v: boolean): bool;
47
+
48
+ // ─── Groupes utilitaires ─────────────────────────────────────
49
+ /** Tout entier AS signé */
50
+ type ASSignedInt = i8 | i16 | i32 | i64 | isize;
51
+ /** Tout entier AS non-signé */
52
+ type ASUnsignedInt = u8 | u16 | u32 | u64 | usize;
53
+ /** Tout entier AS */
54
+ type ASInteger = ASSignedInt | ASUnsignedInt;
55
+ /** Tout flottant AS */
56
+ type ASFloat = f32 | f64;
57
+ /** Tout numérique AS */
58
+ type ASNumeric = ASInteger | ASFloat;
59
+ /** Toute primitive AS */
60
+ type ASPrimitive = ASNumeric | bool | v128 | anyref | externref;
61
+
62
+ // ─── Tailles en bits (métadonnée statique) ───────────────────
63
+ type BitWidth = 8 | 16 | 32 | 64 | 128;
64
+
65
+ interface ASTypeInfo<T extends ASPrimitive, W extends BitWidth> {
66
+ readonly type: T;
67
+ readonly bits: W;
68
+ readonly signed: boolean;
69
+ readonly floating: boolean;
70
+ }
71
+
72
+ type ASTypeMap = {
73
+ i8: ASTypeInfo<i8, 8>;
74
+ i16: ASTypeInfo<i16, 16>;
75
+ i32: ASTypeInfo<i32, 32>;
76
+ i64: ASTypeInfo<i64, 64>;
77
+ u8: ASTypeInfo<u8, 8>;
78
+ u16: ASTypeInfo<u16, 16>;
79
+ u32: ASTypeInfo<u32, 32>;
80
+ u64: ASTypeInfo<u64, 64>;
81
+ f32: ASTypeInfo<f32, 32>;
82
+ f64: ASTypeInfo<f64, 64>;
83
+ v128: ASTypeInfo<v128, 128>;
84
+ };
85
+
86
+ // ─── Exports d'un module .as ─────────────────────────────────
87
+
88
+ /** Fonction exportée depuis un module AssemblyScript */
89
+ type ASFunction = (...args: ASPrimitive[]) => ASPrimitive | void;
90
+
91
+ /** Mémoire linéaire exportée */
92
+ interface ASMemory {
93
+ readonly buffer: ArrayBuffer;
94
+ grow(pages: u32): i32;
95
+ }
96
+
97
+ /** Table WebAssembly exportée */
98
+ interface ASTable<T extends ASFunction = ASFunction> {
99
+ readonly length: u32;
100
+ get(index: u32): T | null;
101
+ }
102
+
103
+ /** Forme typée des exports d'un module .as */
104
+ interface ASModuleExports {
105
+ readonly memory?: ASMemory;
106
+ readonly table?: ASTable;
107
+ [exportName: string]: ASFunction | ASMemory | ASTable | ASPrimitive | undefined;
108
+ }
109
+
110
+ declare module "*.as" {
111
+ const exports: ASModuleExports;
112
+ export default exports;
113
+ }
package/build-app.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { assemblyScriptPlugin } from "./src/plugin";
2
+
3
+ await Bun.build({
4
+ entrypoints: ["./app.ts"],
5
+ outdir: "./dist",
6
+ plugins: [assemblyScriptPlugin()],
7
+ target: "node",
8
+ minify: true // forces production optimizations
9
+ });
10
+ console.log("Build OK");
package/bun.lock ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "workspaces": {
4
+ "": {
5
+ "name": "bun-assemblyscript",
6
+ "devDependencies": {
7
+ "bun-types": "^1.3.11",
8
+ },
9
+ "peerDependencies": {
10
+ "assemblyscript": "^0.28.10",
11
+ "bun": ">=1.0.0",
12
+ },
13
+ },
14
+ },
15
+ "packages": {
16
+ "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/8IzqSu4/OWGRs7Fs2ROzGVwJMFTBQkgAp6sAthkBYoN7OiM4rY/CpPVs2X9w9N1W61CHSkEdNKi8HrLZKfK3g=="],
17
+
18
+ "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-TT7eUihnAzxM2tlZesusuC75PAOYKvUBgVU/Nm/lakZ/DpyuqhNkzUfcxSgmmK9IjVWzMmezLIGZl16XGCGJng=="],
19
+
20
+ "@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.3.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-CYjIHWaQG7T4phfjErHr6BiXRs0K/9DqMeiohJmuYSBF+H2m56vFslOenLCguGYQL9jeiiCZBeoVCpwjxZrMgQ=="],
21
+
22
+ "@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.3.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-8XMLyRNxHF4jfLajkWt+F8UDxsWbzysyxQVMZKUXwoeGvaxB0rVd07r3YbgDtG8U6khhRFM3oaGp+CQ0whwmdA=="],
23
+
24
+ "@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.3.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-jBwYCLG5Eb+PqtFrc3Wp2WMYlw1Id75gUcsdP+ApCOpf5oQhHxkFWCjZmcDoioDmEhMWAiM3wtwSrTlPg+sI6Q=="],
25
+
26
+ "@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.3.11", "", { "os": "linux", "cpu": "x64" }, "sha512-z3GFCk1UBzDOOiEBHL32lVP7Edi26BhOjKb6bIc0nRyabbRiyON4++GR0zmd/H5zM5S0+UcXFgCGnD+b8avTLw=="],
27
+
28
+ "@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.3.11", "", { "os": "linux", "cpu": "x64" }, "sha512-KZlf1jKtf4jai8xiQv/0XRjxVVhHnw/HtUKtLdOeQpTOQ1fQFhLoz2FGGtVRd0LVa/yiRbSz9HlWIzWlmJClng=="],
29
+
30
+ "@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.3.11", "", { "os": "linux", "cpu": "x64" }, "sha512-ADImD4yCHNpqZu718E2chWcCaAHvua90yhmpzzV6fF4zOhwkGGbPCgUWmKyJ83uz+DXaPdYxX0ttDvtolrzx3Q=="],
31
+
32
+ "@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.3.11", "", { "os": "linux", "cpu": "x64" }, "sha512-J+qz4Al05PrNIOdj7xsWVTyx0c/gjUauG5nKV3Rrx0Q+5JO+1pPVlnfNmWbOF9pKG4f3IGad8KXJUfGMORld+Q=="],
33
+
34
+ "@oven/bun-windows-aarch64": ["@oven/bun-windows-aarch64@1.3.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UOdkwScHRkGPz+n9ZJU7sTkTvqV7rD1SLCLaru1xH8WRsV7tDorPqNCzEN1msOIiPRK825nvAtEm9UsomO1GsA=="],
35
+
36
+ "@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.3.11", "", { "os": "win32", "cpu": "x64" }, "sha512-E51tyWDP1l0CbjZYhiUxhDGPaY8Hf5YBREx0PHBff1LM1/q3qsJ6ZvRUa8YbbOO0Ax9QP6GHjD9vf3n6bXZ7QA=="],
37
+
38
+ "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.11", "", { "os": "win32", "cpu": "x64" }, "sha512-cCsXK9AQ9Zf18QlVnbrFu2IKfr4sf2sfbErkF2jfCzyCO9Bnhl0KRx63zlN+Ni1xU7gcBLAssgcui5R400N2eA=="],
39
+
40
+ "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
41
+
42
+ "assemblyscript": ["assemblyscript@0.28.10", "", { "dependencies": { "binaryen": "123.0.0-nightly.20250530", "long": "^5.2.4" }, "bin": { "asc": "bin/asc.js", "asinit": "bin/asinit.js" } }, "sha512-MGqjjNlPMmcWjfnme3cGFKmbBY/rj0bmE4M1Wg8tNqmHusA1PAjOMgWK67KWBK63lmvotFDoP8e5N0URxKlR/Q=="],
43
+
44
+ "binaryen": ["binaryen@123.0.0-nightly.20250530", "", { "bin": { "wasm-as": "bin/wasm-as", "wasm2js": "bin/wasm2js", "wasm-dis": "bin/wasm-dis", "wasm-opt": "bin/wasm-opt", "wasm-merge": "bin/wasm-merge", "wasm-shell": "bin/wasm-shell", "wasm-reduce": "bin/wasm-reduce", "wasm-metadce": "bin/wasm-metadce", "wasm-ctor-eval": "bin/wasm-ctor-eval" } }, "sha512-d1zPHBN5YlOd3Ff+OUxvVExuFeh8heSnqe+X3bjItFxGLvn4VGBKmrvv7pgy/cRhrIUGuPW138iaWfDhwjyDqg=="],
45
+
46
+ "bun": ["bun@1.3.11", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.11", "@oven/bun-darwin-x64": "1.3.11", "@oven/bun-darwin-x64-baseline": "1.3.11", "@oven/bun-linux-aarch64": "1.3.11", "@oven/bun-linux-aarch64-musl": "1.3.11", "@oven/bun-linux-x64": "1.3.11", "@oven/bun-linux-x64-baseline": "1.3.11", "@oven/bun-linux-x64-musl": "1.3.11", "@oven/bun-linux-x64-musl-baseline": "1.3.11", "@oven/bun-windows-aarch64": "1.3.11", "@oven/bun-windows-x64": "1.3.11", "@oven/bun-windows-x64-baseline": "1.3.11" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-AvXWYFO6j/ZQ7bhGm4X6eilq2JHsDVC90ZM32k2B7/srhC2gs3Sdki1QTbwrdRCo8o7eT+167vcB1yzOvPdbjA=="],
47
+
48
+ "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
49
+
50
+ "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
51
+
52
+ "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
53
+ }
54
+ }
package/bunfig.toml ADDED
@@ -0,0 +1,9 @@
1
+ # bunfig.toml — Configuration Bun pour bun-assemblyscript
2
+
3
+ [test]
4
+ # Précharger le plugin avant les tests pour que les imports .as fonctionnent
5
+ preload = ["./preload.ts", "bun-plugin-assemblyscript"]
6
+
7
+ [run]
8
+ # Précharger le plugin pour bun run <script>
9
+ preload = ["./preload.ts"]
package/debug_asc.ts ADDED
@@ -0,0 +1,11 @@
1
+ // Script de debug isolé — à lancer via: bun run /tmp/debug_asc.ts
2
+ import { compile } from "./src/compiler";
3
+ import { resolve } from "path";
4
+
5
+ const file = resolve("test/fixtures/math.as");
6
+ console.log("Compiling:", file);
7
+
8
+ const result = await compile(file, { optimizeLevel: 0, runtime: "stub" });
9
+ console.log("success:", result.success);
10
+ console.log("wasmBytes length:", result.wasmBytes?.byteLength ?? null);
11
+ console.log("errors:", result.errors);
package/dist/app.js ADDED
@@ -0,0 +1 @@
1
+ var c=Uint8Array.from(atob("AGFzbQEAAAABBwFgAn9/AX8DBAMAAAAFAwEAAAcmBANhZGQAAAhtdWx0aXBseQABCHN1YnRyYWN0AAIGbWVtb3J5AgAKGQMHACAAIAFqCwcAIAAgAWwLBwAgACABaws="),(t)=>t.charCodeAt(0)),A=new WebAssembly.Memory({initial:1});function s(t,n){if(n===0)return"";let r=new DataView(t.buffer).getInt32(n-4,!0)>>>1;if(r<=0)return"";return String.fromCharCode(...new Uint16Array(t.buffer,n,r))}var m={env:{memory:A,abort(t,n,e,r){let i=s(A,t),b=s(A,n);throw new Error(`AbortError: ${i||"(no)"} — ${b}:${e}:${r}`)}}},{instance:o}=await WebAssembly.instantiate(c,m),a=o.exports.add,u=o.exports.multiply,d=o.exports.subtract;console.log("Result from WASM in bundled app:",a(5,7));
package/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * bun-assemblyscript
3
+ * Plugin Bun pour importer des fichiers AssemblyScript (.as) directement.
4
+ */
5
+
6
+ // Plugin principal
7
+ export { assemblyScriptPlugin } from "./src/plugin";
8
+ export type { PluginOptions } from "./src/plugin";
9
+
10
+ // Compilateur
11
+ export { compile } from "./src/compiler";
12
+ export type { CompilerOptions, CompilerResult } from "./src/compiler";
13
+
14
+ // Instantiateur
15
+ export { instantiate, AbortError } from "./src/instantiator";
16
+ export type { ASExports } from "./src/instantiator";
17
+
18
+ // Export par défaut
19
+ export { assemblyScriptPlugin as default } from "./src/plugin";
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "bun-assemblyscript",
3
+ "version": "0.1.0",
4
+ "main": "./dist/index.js",
5
+ "module": "./dist/index.mjs",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.mjs",
10
+ "require": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ },
13
+ "./loader": {
14
+ "import": "./dist/loader.mjs",
15
+ "require": "./dist/loader.js",
16
+ "types": "./dist/loader.d.ts"
17
+ }
18
+ },
19
+ "bin": {
20
+ "bun-as": "./src/bin/watch.ts"
21
+ },
22
+ "peerDependencies": {
23
+ "assemblyscript": "^0.28.10",
24
+ "bun": ">=1.0.0"
25
+ },
26
+ "scripts": {
27
+ "build": "bun run build.ts",
28
+ "test": "bun test",
29
+ "postinstall": "bun run ./src/install/index.ts"
30
+ },
31
+ "devDependencies": {
32
+ "bun-types": "^1.3.11"
33
+ }
34
+ }
package/preload.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { plugin } from "bun";
2
+ import { assemblyScriptPlugin } from "./src/plugin";
3
+
4
+ plugin(assemblyScriptPlugin());
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bun
2
+ import { startWatcher, startBuild } from "../watcher/index";
3
+
4
+ const args = process.argv.slice(2);
5
+ const command = args[0] || "watch";
6
+
7
+ if (command === "watch") {
8
+ startWatcher();
9
+ } else if (command === "build") {
10
+ startBuild().then(() => process.exit(0));
11
+ } else {
12
+ console.log("Usage: bun-as [watch|build]");
13
+ process.exit(1);
14
+ }
@@ -0,0 +1,135 @@
1
+ import { join, basename } from "path";
2
+ import { existsSync } from "fs";
3
+
4
+ export interface CacheMeta {
5
+ hash: string;
6
+ compiledAt: number;
7
+ ascVersion: string;
8
+ }
9
+
10
+ export interface CacheEntry {
11
+ wasmBytes: Uint8Array;
12
+ dtsContent: string;
13
+ }
14
+
15
+ const CACHE_DIR = join(process.cwd(), ".cache", "bun-as");
16
+ const ASC_VERSION = "0.28.10"; // Version fixée par l'instruction d'installation
17
+
18
+ /**
19
+ * Calcule le SHA256 d'un contenu de fichier via Bun.CryptoHasher.
20
+ */
21
+ export async function computeHash(content: string): Promise<string> {
22
+ const hasher = new Bun.CryptoHasher("sha256");
23
+ hasher.update(content);
24
+ return hasher.digest("hex");
25
+ }
26
+
27
+ /**
28
+ * Assure que le cache Bun AssemblyScript est dans le .gitignore du projet.
29
+ */
30
+ async function checkGitignore() {
31
+ const gitignorePath = join(process.cwd(), ".gitignore");
32
+ try {
33
+ const content = await Bun.file(gitignorePath).text();
34
+ if (!content.includes(".cache/bun-as")) {
35
+ await Bun.write(
36
+ gitignorePath,
37
+ content + "\n# bun-assemblyscript cache\n.cache/bun-as/\n"
38
+ );
39
+ }
40
+ } catch (err) {
41
+ // Si .gitignore n'existe pas, on le créé
42
+ await Bun.write(gitignorePath, ".cache/bun-as/\n");
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Crée récursivement le dossier de cache spécifique au fichier.
48
+ */
49
+ async function ensureCacheDir(fileName: string) {
50
+ const dir = join(CACHE_DIR, fileName);
51
+ const fs = await import("fs/promises");
52
+ await fs.mkdir(dir, { recursive: true });
53
+ await checkGitignore();
54
+ return dir;
55
+ }
56
+
57
+ /**
58
+ * Récupère une entrée du cache si le hash et la version asc correspondent.
59
+ */
60
+ export async function get(
61
+ filePath: string,
62
+ currentHash: string
63
+ ): Promise<CacheEntry | null> {
64
+ const baseName = basename(filePath);
65
+ const dir = join(CACHE_DIR, baseName);
66
+ const metaPath = join(dir, "meta.json");
67
+
68
+ if (!existsSync(metaPath)) return null;
69
+
70
+ try {
71
+ const meta: CacheMeta = await Bun.file(metaPath).json();
72
+
73
+ // Si la version d'asc a changé, le cache est totalement invalide
74
+ if (meta.ascVersion !== ASC_VERSION) {
75
+ await invalidate(filePath);
76
+ return null;
77
+ }
78
+
79
+ // Si le hash a changé, le cache n'est pas le bon
80
+ if (meta.hash !== currentHash) {
81
+ return null;
82
+ }
83
+
84
+ const wasmPath = join(dir, `${currentHash}.wasm`);
85
+ const dtsPath = join(dir, `${currentHash}.d.ts`);
86
+
87
+ if (!existsSync(wasmPath) || !existsSync(dtsPath)) return null;
88
+
89
+ const wasmBytes = new Uint8Array(await Bun.file(wasmPath).arrayBuffer());
90
+ const dtsContent = await Bun.file(dtsPath).text();
91
+
92
+ return { wasmBytes, dtsContent };
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Enregistre une entrée WASM + DTS dans le cache.
100
+ */
101
+ export async function set(
102
+ filePath: string,
103
+ currentHash: string,
104
+ wasmBytes: Uint8Array,
105
+ dtsContent: string
106
+ ) {
107
+ const baseName = basename(filePath);
108
+ const dir = await ensureCacheDir(baseName);
109
+
110
+ const wasmPath = join(dir, `${currentHash}.wasm`);
111
+ const dtsPath = join(dir, `${currentHash}.d.ts`);
112
+ const metaPath = join(dir, "meta.json");
113
+
114
+ const meta: CacheMeta = {
115
+ hash: currentHash,
116
+ compiledAt: Date.now(),
117
+ ascVersion: ASC_VERSION,
118
+ };
119
+
120
+ await Bun.write(wasmPath, wasmBytes);
121
+ await Bun.write(dtsPath, dtsContent);
122
+ await Bun.write(metaPath, JSON.stringify(meta, null, 2));
123
+ }
124
+
125
+ /**
126
+ * Invalide manuellement le cache d'un fichier.
127
+ */
128
+ export async function invalidate(filePath: string) {
129
+ const baseName = basename(filePath);
130
+ const dir = join(CACHE_DIR, baseName);
131
+ try {
132
+ const fs = await import("fs/promises");
133
+ await fs.rm(dir, { recursive: true, force: true });
134
+ } catch {}
135
+ }