gofront 1.0.0 → 1.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.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/cli-core.js +65 -0
  4. package/src/codegen/expressions.js +3 -0
  5. package/src/codegen/statements.js +3 -0
  6. package/src/codegen/stdlib/builder.js +3 -0
  7. package/src/codegen/stdlib/bytes.js +3 -0
  8. package/src/codegen/stdlib/errors.js +3 -0
  9. package/src/codegen/stdlib/fmt.js +3 -0
  10. package/src/codegen/stdlib/gom.js +3 -0
  11. package/src/codegen/stdlib/html.js +3 -0
  12. package/src/codegen/stdlib/index.js +3 -0
  13. package/src/codegen/stdlib/io.js +3 -0
  14. package/src/codegen/stdlib/maps.js +3 -0
  15. package/src/codegen/stdlib/math.js +3 -0
  16. package/src/codegen/stdlib/os.js +3 -0
  17. package/src/codegen/stdlib/path.js +3 -0
  18. package/src/codegen/stdlib/rand.js +3 -0
  19. package/src/codegen/stdlib/regexp.js +3 -0
  20. package/src/codegen/stdlib/slices.js +3 -0
  21. package/src/codegen/stdlib/sort.js +3 -0
  22. package/src/codegen/stdlib/strconv.js +3 -0
  23. package/src/codegen/stdlib/strings.js +3 -0
  24. package/src/codegen/stdlib/time.js +3 -0
  25. package/src/codegen/stdlib/unicode.js +3 -0
  26. package/src/codegen/stdlib/utf8.js +3 -0
  27. package/src/codegen/templ.js +3 -0
  28. package/src/compiler.js +63 -4
  29. package/src/index.js +32 -126
  30. package/src/parser/declarations.js +347 -0
  31. package/src/parser/index.js +3 -346
  32. package/src/typechecker/assignability.js +3 -0
  33. package/src/typechecker/expressions.js +9 -0
  34. package/src/typechecker/index.js +2 -1
  35. package/src/typechecker/resolve.js +9 -2
  36. package/src/typechecker/statements.js +3 -0
  37. package/src/typechecker/termination.js +3 -0
  38. package/src/typechecker/types.js +1 -0
package/README.md CHANGED
@@ -634,7 +634,7 @@ Design documents for planned features are organised by release under `docs/v*/`
634
634
  ## Tests
635
635
 
636
636
  ```sh
637
- npm run test:unit # unit tests only (~1118 tests, no browser required)
637
+ npm run test:unit # unit tests only (~1100 tests, no browser required)
638
638
  npm run test:e2e # E2E tests (Playwright, headless Chromium)
639
639
  npm run test:all # both
640
640
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gofront",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "author": "Luuk van Venrooij",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,65 @@
1
+ // CLI compilation core — extracted for direct import in tests.
2
+ // index.js retains only arg parsing, file I/O, watch mode, and process.exit.
3
+
4
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
5
+ import { basename, dirname, join, resolve } from "node:path";
6
+ import { compileDir, compileSingleFile } from "./compiler.js";
7
+ import { minify } from "./minifier.js";
8
+
9
+ export function runCompile(inputPath, isDir, options) {
10
+ const {
11
+ sourceMap = false,
12
+ outputFile = null,
13
+ dumpTokens = false,
14
+ dumpAst = false,
15
+ } = options ?? {};
16
+
17
+ if (isDir) {
18
+ const outputDir = outputFile ? dirname(resolve(outputFile)) : resolve(".");
19
+ return compileDir(inputPath, { sourceMap, outputDir });
20
+ }
21
+
22
+ return compileSingleFile(inputPath, {
23
+ sourceMap,
24
+ outputFile,
25
+ dumpTokens,
26
+ dumpAst,
27
+ });
28
+ }
29
+
30
+ export function maybeMinify(js, options) {
31
+ const {
32
+ minify: doMinify = false,
33
+ mangle = false,
34
+ sourceMap = false,
35
+ } = options ?? {};
36
+ if (!doMinify) return js;
37
+ if (sourceMap)
38
+ throw new Error("--source-map and --minify cannot be used together");
39
+ return minify(js, { mangle });
40
+ }
41
+
42
+ export function handleInit(targetDir) {
43
+ try {
44
+ mkdirSync(targetDir, { recursive: true });
45
+ } catch (e) {
46
+ throw new Error(`cannot create '${targetDir}': ${e.message}`);
47
+ }
48
+
49
+ const mainPath = join(targetDir, "main.go");
50
+ if (existsSync(mainPath)) {
51
+ throw new Error(`${mainPath} already exists — nothing written`);
52
+ }
53
+
54
+ const pkgName = basename(targetDir);
55
+ const safePkg = pkgName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^[0-9]/, "_");
56
+ const template = `package ${safePkg}\n\nfunc main() {\n\tconsole.log("Hello from GoFront!")\n}\n`;
57
+
58
+ try {
59
+ writeFileSync(mainPath, template);
60
+ } catch (e) {
61
+ throw new Error(`cannot write '${mainPath}': ${e.message}`);
62
+ }
63
+
64
+ return { mainPath };
65
+ }
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { ERROR, isComplex } from "../typechecker/types.js";
4
4
 
5
+ /** @typedef {import('./index.js').CodeGen} CodeGen */
6
+
5
7
  // Namespace constants: pkg.Field → JS literal
6
8
  const NS_CONSTANTS = {
7
9
  math: {
@@ -143,6 +145,7 @@ const EXPR_GEN_DELEGATE = {
143
145
  TypeAssertExpr: "_genTypeAssertExpr",
144
146
  };
145
147
 
148
+ /** @type {ThisType<CodeGen>} */
146
149
  export const expressionGenMethods = {
147
150
  genExpr(expr) {
148
151
  switch (expr.kind) {
@@ -2,6 +2,8 @@
2
2
 
3
3
  import { isComplex } from "../typechecker/types.js";
4
4
 
5
+ /** @typedef {import('./index.js').CodeGen} CodeGen */
6
+
5
7
  // Method-name dispatch for genStmt — string values add no static call edges.
6
8
  const STMT_GEN_DELEGATE = {
7
9
  VarDecl: "genVarDecl",
@@ -15,6 +17,7 @@ const STMT_GEN_DELEGATE = {
15
17
  BranchStmt: "_genBranchStmt",
16
18
  };
17
19
 
20
+ /** @type {ThisType<CodeGen>} */
18
21
  export const statementGenMethods = {
19
22
  genBlock(block) {
20
23
  for (const stmt of block.stmts) this.genStmt(stmt);
@@ -1,5 +1,7 @@
1
1
  // CodeGen for `strings.Builder` and `bytes.Buffer` method calls.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const BUILDER_STR = {
4
6
  WriteString: (b, a) => `(${b}._buf += ${a[0]}, [${a[0]}.length, null])`,
5
7
  WriteByte: (b, a) => `(${b}._buf += String.fromCodePoint(${a[0]}))`,
@@ -22,6 +24,7 @@ const BUILDER_COMMON = {
22
24
  Grow: () => "undefined",
23
25
  };
24
26
 
27
+ /** @type {ThisType<CodeGen>} */
25
28
  export const builderMethods = {
26
29
  _genBuilderCall(typeName, method, expr) {
27
30
  const recv = expr.func.expr;
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `bytes` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const __bs = `(b => String.fromCharCode(...b))`;
4
6
  const __sb = `(s => [...s].map(c => c.charCodeAt(0)))`;
5
7
 
@@ -54,6 +56,7 @@ const BYTES_DISPATCH = {
54
56
  `{_src: ${a[0]}, _pos: 0, Read(p) { const n = Math.min(p.length, this._src.length - this._pos); for (let i = 0; i < n; i++) p[i] = this._src[this._pos + i]; this._pos += n; return [n, n === 0 ? "EOF" : null]; }, Len() { return this._src.length - this._pos; }, Reset(b) { this._src = b; this._pos = 0; }}`,
55
57
  };
56
58
 
59
+ /** @type {ThisType<CodeGen>} */
57
60
  export const bytesMethods = {
58
61
  _genBytes(fn, a) {
59
62
  const gen = BYTES_DISPATCH[fn];
@@ -1,5 +1,8 @@
1
1
  // CodeGen for Go `errors` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
5
+ /** @type {ThisType<CodeGen>} */
3
6
  export const errorsMethods = {
4
7
  _genErrors(fn, a) {
5
8
  const args = a();
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `fmt` package — installed onto CodeGen.prototype via stdlibGenMethods.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const _SSCAN_LOOP =
4
6
  `let n = 0; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { ` +
5
7
  `const t = tokens[i]; const p = ptrs[i]; ` +
@@ -7,6 +9,7 @@ const _SSCAN_LOOP =
7
9
  `else if (typeof p.value === "boolean") p.value = t === "true"; ` +
8
10
  `else p.value = t; n++; }`;
9
11
 
12
+ /** @type {ThisType<CodeGen>} */
10
13
  export const fmtMethods = {
11
14
  _genFmt(fn, _a, expr) {
12
15
  const fmtArgs = expr.args.map((e) => this.genExpr(e)).join(", ");
@@ -1,5 +1,7 @@
1
1
  // CodeGen for the GoFront-built-in `gom` DOM-rendering package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const GOM_ELEMENT_TAGS = {
4
6
  Div: "div",
5
7
  Section: "section",
@@ -85,6 +87,7 @@ const GOM_PROP_SETTERS = {
85
87
  Placeholder: "placeholder",
86
88
  };
87
89
 
90
+ /** @type {ThisType<CodeGen>} */
88
91
  export const gomMethods = {
89
92
  _genGom(fn, expr) {
90
93
  const a = () =>
@@ -1,5 +1,8 @@
1
1
  // CodeGen for Go `html` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
5
+ /** @type {ThisType<CodeGen>} */
3
6
  export const htmlMethods = {
4
7
  _genHtml(fn, a) {
5
8
  switch (fn) {
@@ -22,6 +22,8 @@ import { timeMethods } from "./time.js";
22
22
  import { unicodeMethods } from "./unicode.js";
23
23
  import { utf8Methods } from "./utf8.js";
24
24
 
25
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
26
+
25
27
  // Stdlib namespace → handler method name. Used by _genStdlibCall to dispatch
26
28
  // dynamically without creating static call edges.
27
29
  const STDLIB_METHOD_MAP = {
@@ -70,6 +72,7 @@ const dispatchMethods = {
70
72
  },
71
73
  };
72
74
 
75
+ /** @type {ThisType<CodeGen>} */
73
76
  export const stdlibGenMethods = {
74
77
  ...builderMethods,
75
78
  ...bytesMethods,
@@ -1,5 +1,8 @@
1
1
  // CodeGen for Go `io` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
5
+ /** @type {ThisType<CodeGen>} */
3
6
  export const ioMethods = {
4
7
  _genIo(fn, _a, expr) {
5
8
  switch (fn) {
@@ -1,5 +1,8 @@
1
1
  // CodeGen for Go `maps` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
5
+ /** @type {ThisType<CodeGen>} */
3
6
  export const mapsMethods = {
4
7
  _genMaps(fn, a) {
5
8
  if (fn === "Equal") {
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `math` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const MATH1 = {
4
6
  Abs: "abs",
5
7
  Floor: "floor",
@@ -41,6 +43,7 @@ const MATH_EXTRA = {
41
43
  Remainder: ([x, y]) => `(${x} - Math.round(${x} / ${y}) * ${y})`,
42
44
  };
43
45
 
46
+ /** @type {ThisType<CodeGen>} */
44
47
  export const mathMethods = {
45
48
  _genMath(fn, a) {
46
49
  const args = a();
@@ -1,5 +1,8 @@
1
1
  // CodeGen for Go `os` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
5
+ /** @type {ThisType<CodeGen>} */
3
6
  export const osMethods = {
4
7
  _genOs(fn, a) {
5
8
  const args = a();
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `path` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const PATH_DISPATCH = {
4
6
  Base: (a) =>
5
7
  `((p) => { if (!p) return "."; const stripped = p.replace(/\\/+$/, ""); if (!stripped) return "/"; const i = stripped.lastIndexOf("/"); return i < 0 ? stripped : stripped.slice(i + 1) || "/"; })(${a[0]})`,
@@ -14,6 +16,7 @@ const PATH_DISPATCH = {
14
16
  `((pat, name) => { try { const sp=/[.+^$()|[\\]\\\\]/g; const re = new RegExp("^" + pat.replace(sp, "\\\\$&").replace(/\\*/g, "[^/]*").replace(/\\?/g, "[^/]") + "$"); return [re.test(name), null]; } catch(e) { return [false, "syntax error in pattern"]; } })(${a[0]}, ${a[1]})`,
15
17
  };
16
18
 
19
+ /** @type {ThisType<CodeGen>} */
17
20
  export const pathMethods = {
18
21
  _genPath(fn, a, expr) {
19
22
  if (fn === "Join") {
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `math/rand` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const RAND_DISPATCH = {
4
6
  Intn: (a) => `Math.floor(Math.random() * ${a[0]})`,
5
7
  Int63n: (a) => `Math.floor(Math.random() * ${a[0]})`,
@@ -16,6 +18,7 @@ const RAND_DISPATCH = {
16
18
  `((n) => { const a = Array.from({length: n}, (_, i) => i); for (let i = n - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; })(${a[0]})`,
17
19
  };
18
20
 
21
+ /** @type {ThisType<CodeGen>} */
19
22
  export const randMethods = {
20
23
  _genRand(fn, a) {
21
24
  const gen = RAND_DISPATCH[fn];
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `regexp` package and `*Regexp` methods.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const REGEXP_METHOD = {
4
6
  MatchString: (re, a) => `${re}.test(${a[0]})`,
5
7
  FindString: (re, a) => `(${re}.exec(${a[0]})?.[0] ?? "")`,
@@ -19,6 +21,7 @@ const REGEXP_METHOD = {
19
21
  String: (re) => `${re}.source`,
20
22
  };
21
23
 
24
+ /** @type {ThisType<CodeGen>} */
22
25
  export const regexpMethods = {
23
26
  _genRegexp(fn, a) {
24
27
  // Converts a Go regexp pattern string (which may contain inline flags like (?i))
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `slices` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const SLICES_DISPATCH = {
4
6
  Contains: (a) => `${a[0]}.includes(${a[1]})`,
5
7
  Index: (a) => `${a[0]}.indexOf(${a[1]})`,
@@ -35,6 +37,7 @@ const SLICES_DISPATCH = {
35
37
  Clip: (a) => `${a[0]}.slice()`,
36
38
  };
37
39
 
40
+ /** @type {ThisType<CodeGen>} */
38
41
  export const slicesMethods = {
39
42
  _genSlices(fn, a) {
40
43
  if (fn === "Equal") {
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `sort` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const SORT_DISPATCH = {
4
6
  Ints: (a) => `${a[0]}.sort((a, b) => a - b)`,
5
7
  Float64s: (a) => `${a[0]}.sort((a, b) => a - b)`,
@@ -20,6 +22,7 @@ const SORT_DISPATCH = {
20
22
  `(${a[0]}).every((v, i, a) => i === 0 || a[i - 1] <= v)`,
21
23
  };
22
24
 
25
+ /** @type {ThisType<CodeGen>} */
23
26
  export const sortMethods = {
24
27
  _genSort(fn, a) {
25
28
  const gen = SORT_DISPATCH[fn];
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `strconv` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const STRCONV_DISPATCH = {
4
6
  Itoa: (a) => `String(${a[0]})`,
5
7
  Atoi: (a) =>
@@ -22,6 +24,7 @@ const STRCONV_DISPATCH = {
22
24
  `[...(${a[0]}), ...new TextEncoder().encode(${a[1]}.toFixed(${a[3]} < 0 ? 6 : ${a[3]}))]`,
23
25
  };
24
26
 
27
+ /** @type {ThisType<CodeGen>} */
25
28
  export const strconvMethods = {
26
29
  _genStrconv(fn, a) {
27
30
  const gen = STRCONV_DISPATCH[fn];
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `strings` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const STRINGS_M1 = {
4
6
  ToUpper: "toUpperCase",
5
7
  ToLower: "toLowerCase",
@@ -71,6 +73,7 @@ const STRINGS_DISPATCH = {
71
73
  `((...pairs) => { const p = []; for (let i = 0; i < pairs.length; i += 2) p.push([pairs[i], pairs[i+1]]); return { _p: p, Replace(s) { let r = s; for (const [o, n] of this._p) r = r.split(o).join(n); return r; } }; })(${args.join(", ")})`,
72
74
  };
73
75
 
76
+ /** @type {ThisType<CodeGen>} */
74
77
  export const stringsMethods = {
75
78
  _genStrings(fn, a) {
76
79
  const args = a();
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `time` package — `time.Now`, `time.Since`, etc., plus `*Time` methods.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const TIME_METHOD_DISPATCH = {
4
6
  Year: (r) => `${r}._d.getFullYear()`,
5
7
  Month: (r) => `${r}._d.getMonth() + 1`,
@@ -26,6 +28,7 @@ const TIME_DISPATCH = {
26
28
  `{_d: new Date(${a[0]}, ${a[1]} - 1, ${a[2]}, ${a[3]}, ${a[4]}, ${a[5]})}`,
27
29
  };
28
30
 
31
+ /** @type {ThisType<CodeGen>} */
29
32
  export const timeMethods = {
30
33
  _genTimeMethodCall(method, expr) {
31
34
  const recv = expr.func.expr;
@@ -1,5 +1,8 @@
1
1
  // CodeGen for Go `unicode` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
5
+ /** @type {ThisType<CodeGen>} */
3
6
  export const unicodeMethods = {
4
7
  _genUnicode(fn, a) {
5
8
  const [arg] = a();
@@ -1,5 +1,7 @@
1
1
  // CodeGen for Go `unicode/utf8` package.
2
2
 
3
+ /** @typedef {import('../index.js').CodeGen} CodeGen */
4
+
3
5
  const UTF8_DISPATCH = {
4
6
  RuneCountInString: (a) => `[...(${a[0]})].length`,
5
7
  RuneLen: (a) =>
@@ -15,6 +17,7 @@ const UTF8_DISPATCH = {
15
17
  FullRuneInString: (a) => `(${a[0]}).length > 0`,
16
18
  };
17
19
 
20
+ /** @type {ThisType<CodeGen>} */
18
21
  export const utf8Methods = {
19
22
  _genUtf8(fn, a) {
20
23
  const gen = UTF8_DISPATCH[fn];
@@ -5,6 +5,9 @@
5
5
  import { Parser } from "../parser/index.js";
6
6
  import { T, Token } from "../tokens.js";
7
7
 
8
+ /** @typedef {import('./index.js').CodeGen} CodeGen */
9
+
10
+ /** @type {ThisType<CodeGen>} */
8
11
  export const templGenMethods = {
9
12
  genTemplDecl(decl) {
10
13
  const params = decl.params
package/src/compiler.js CHANGED
@@ -1,9 +1,11 @@
1
- // Multi-file GoFront package compiler.
1
+ // GoFront package compiler.
2
2
  //
3
- // compileDir(dir, options) — compile all *.go in a directory as one package
4
- // compileFiles(files, options) — compile an explicit list of .go files
3
+ // compileSingleFile(path, options) — compile one .go file
4
+ // compileDir(dir, options) — compile all *.go in a directory as one package
5
+ // compileFiles(files, options) — compile an explicit list of .go files
5
6
  //
6
- // Both return:
7
+ // compileSingleFile returns: { js } (or { tokens } / { ast } for debug modes)
8
+ // compileDir / compileFiles return:
7
9
  // {
8
10
  // pkgName: string,
9
11
  // js: string, // generated JS bundle (may include dep preamble)
@@ -146,6 +148,63 @@ export function resolveImports(
146
148
 
147
149
  // ── Main entry points ─────────────────────────────────────────
148
150
 
151
+ export function compileSingleFile(inputPath, options = {}) {
152
+ const {
153
+ sourceMap = false,
154
+ outputFile = null,
155
+ dumpTokens = false,
156
+ dumpAst = false,
157
+ } = options;
158
+
159
+ let source;
160
+ try {
161
+ source = readFileSync(inputPath, "utf8");
162
+ } catch (e) {
163
+ throw new Error(`cannot read '${inputPath}': ${e.message}`);
164
+ }
165
+
166
+ const tokens = new Lexer(source, basename(inputPath)).tokenize();
167
+ if (dumpTokens) return { tokens };
168
+
169
+ const ast = new Parser(tokens, basename(inputPath), source).parse();
170
+ ast._source = source;
171
+ if (dumpAst) return { ast };
172
+
173
+ const checker = new TypeChecker();
174
+ const jsImports = new Map();
175
+ const bundledPackages = new Set();
176
+ const preambles = [];
177
+
178
+ resolveImports(
179
+ [ast],
180
+ inputPath,
181
+ checker,
182
+ jsImports,
183
+ bundledPackages,
184
+ preambles,
185
+ );
186
+
187
+ const errors = checker.check(ast);
188
+ checker.reportUnusedImports();
189
+ if (errors.length > 0) {
190
+ throw new Error(errors.map((e) => e.message).join("\n"));
191
+ }
192
+
193
+ const cg = new CodeGen(checker, jsImports, bundledPackages);
194
+ let js = cg.generate(ast);
195
+
196
+ if (sourceMap) {
197
+ const outputDir = outputFile ? dirname(resolve(outputFile)) : resolve(".");
198
+ const srcPath = relative(outputDir, inputPath);
199
+ const map = cg.getSourceMap(srcPath, [source]);
200
+ const b64 = Buffer.from(map).toString("base64");
201
+ js += `\n//# sourceMappingURL=data:application/json;base64,${b64}`;
202
+ }
203
+
204
+ const output = preambles.length > 0 ? `${preambles.join("\n")}\n${js}` : js;
205
+ return { js: output };
206
+ }
207
+
149
208
  export function compileDir(dir, options = {}) {
150
209
  const files = gwFilesIn(dir);
151
210
  if (files.length === 0) throw new Error(`No .go files found in ${dir}`);