bonescript-compiler 0.5.8 → 0.6.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 (56) hide show
  1. package/dist/ast.d.ts +2 -0
  2. package/dist/cli.js +52 -8
  3. package/dist/cli.js.map +1 -1
  4. package/dist/emit_admin.d.ts +5 -0
  5. package/dist/emit_admin.js +340 -35
  6. package/dist/emit_admin.js.map +1 -1
  7. package/dist/emit_audit.js +38 -4
  8. package/dist/emit_audit.js.map +1 -1
  9. package/dist/emit_capability.js +14 -0
  10. package/dist/emit_capability.js.map +1 -1
  11. package/dist/emit_full.js +10 -2
  12. package/dist/emit_full.js.map +1 -1
  13. package/dist/emit_maintenance.js +35 -3
  14. package/dist/emit_maintenance.js.map +1 -1
  15. package/dist/emit_nakama.js +36 -36
  16. package/dist/emit_notify.js +30 -2
  17. package/dist/emit_notify.js.map +1 -1
  18. package/dist/emit_runtime.d.ts +18 -1
  19. package/dist/emit_runtime.js +265 -85
  20. package/dist/emit_runtime.js.map +1 -1
  21. package/dist/emit_websocket.js +22 -2
  22. package/dist/emit_websocket.js.map +1 -1
  23. package/dist/emit_zod.js +12 -1
  24. package/dist/emit_zod.js.map +1 -1
  25. package/dist/formatter.d.ts +1 -0
  26. package/dist/formatter.js +10 -2
  27. package/dist/formatter.js.map +1 -1
  28. package/dist/ir.d.ts +2 -0
  29. package/dist/lexer.d.ts +1 -0
  30. package/dist/lexer.js +4 -0
  31. package/dist/lexer.js.map +1 -1
  32. package/dist/lowering.js +2 -0
  33. package/dist/lowering.js.map +1 -1
  34. package/dist/parse_decls.js +36 -1
  35. package/dist/parse_decls.js.map +1 -1
  36. package/dist/typechecker.js +9 -0
  37. package/dist/typechecker.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/ast.ts +2 -0
  40. package/src/cli.ts +58 -10
  41. package/src/emit_admin.ts +342 -35
  42. package/src/emit_audit.ts +40 -4
  43. package/src/emit_capability.ts +13 -0
  44. package/src/emit_full.ts +9 -2
  45. package/src/emit_maintenance.ts +35 -3
  46. package/src/emit_nakama.ts +576 -576
  47. package/src/emit_notify.ts +30 -2
  48. package/src/emit_runtime.ts +955 -763
  49. package/src/emit_websocket.ts +22 -2
  50. package/src/emit_zod.ts +11 -1
  51. package/src/formatter.ts +9 -2
  52. package/src/ir.ts +2 -0
  53. package/src/lexer.ts +2 -0
  54. package/src/lowering.ts +5 -3
  55. package/src/parse_decls.ts +31 -1
  56. package/src/typechecker.ts +10 -0
@@ -31,7 +31,32 @@ export function emitNotifyService(system: IR.IRSystem): string {
31
31
  lines.push(` body: string;`);
32
32
  lines.push(`}`);
33
33
  lines.push(``);
34
+ // HTML-escape helper. Used to render arbitrary event payload data inside an
35
+ // HTML email body without enabling HTML/JS injection in clients that render
36
+ // it. Subject lines are also escaped for consistency.
37
+ lines.push(`function escapeHtml(s: string): string {`);
38
+ lines.push(` return s`);
39
+ lines.push(` .replace(/&/g, "&")`);
40
+ lines.push(` .replace(/</g, "&lt;")`);
41
+ lines.push(` .replace(/>/g, "&gt;")`);
42
+ lines.push(` .replace(/"/g, "&quot;")`);
43
+ lines.push(` .replace(/'/g, "&#39;");`);
44
+ lines.push(`}`);
45
+ lines.push(``);
46
+ // Conservative email validation. Rejects empty input, multiple addresses,
47
+ // and CRLF that would let a caller inject extra headers into the request body
48
+ // sent to Resend / SendGrid.
49
+ lines.push(`const __EMAIL_RE = /^[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}$/;`);
50
+ lines.push(`function isValidEmail(addr: string): boolean {`);
51
+ lines.push(` if (!addr || addr.length > 254) return false;`);
52
+ lines.push(` if (/[\\r\\n]/.test(addr)) return false;`);
53
+ lines.push(` return __EMAIL_RE.test(addr);`);
54
+ lines.push(`}`);
55
+ lines.push(``);
34
56
  lines.push(`async function sendEmail(msg: NotifyMessage): Promise<void> {`);
57
+ lines.push(` if (!isValidEmail(msg.to)) {`);
58
+ lines.push(" throw new Error(`Invalid recipient address: ${msg.to.slice(0, 64)}`);");
59
+ lines.push(` }`);
35
60
  lines.push(` if (PROVIDER === "log") {`);
36
61
  lines.push(` console.log(\`[notify] \${msg.subject} → \${msg.to}\`);`);
37
62
  lines.push(` return;`);
@@ -57,15 +82,18 @@ export function emitNotifyService(system: IR.IRSystem): string {
57
82
  lines.push(`}`);
58
83
  lines.push(``);
59
84
 
60
- // Per-event handlers
85
+ // Per-event handlers — payload is JSON-stringified and HTML-escaped before
86
+ // being placed inside <pre> so payload values like "<script>..." can't break
87
+ // out of the body.
61
88
  for (const event of system.events) {
62
89
  const eventName = toPascalCase(event.name);
63
90
  lines.push(`// Handler for ${eventName}`);
64
91
  lines.push(`export async function notify${eventName}(event: SystemEvent, recipientEmail: string): Promise<void> {`);
92
+ lines.push(` const __payload = escapeHtml(JSON.stringify(event.payload, null, 2));`);
65
93
  lines.push(` await sendEmail({`);
66
94
  lines.push(` to: recipientEmail,`);
67
95
  lines.push(` subject: "${eventName} notification",`);
68
- lines.push(` body: \`<p>Event <strong>${eventName}</strong> occurred.</p><pre>\${JSON.stringify(event.payload, null, 2)}</pre>\`,`);
96
+ lines.push(" body: `<p>Event <strong>${escapeHtml(\"" + eventName + "\")}</strong> occurred.</p><pre>${__payload}</pre>`,");
69
97
  lines.push(` });`);
70
98
  lines.push(`}`);
71
99
  lines.push(``);