@flink-app/flink 2.0.0-alpha.58 → 2.0.0-alpha.60

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @flink-app/flink
2
2
 
3
+ ## 2.0.0-alpha.60
4
+
5
+ ## 2.0.0-alpha.59
6
+
7
+ ### Minor Changes
8
+
9
+ - dbc2119: feat: add generic compiler extension system and @flink-app/inbound-email-plugin
10
+
11
+ Add `compilerPlugins` to `FlinkConfig` and `FlinkCompilerPlugin` interface so plugins can declare custom scan directories for auto-discovery. The TypeScript compiler reads these at build time, generates the corresponding `.flink/generatedXxx.ts` registration files, and includes them in the start script.
12
+
13
+ Introduce `@flink-app/inbound-email-plugin` as the first consumer of this system. It starts an SMTP server and automatically routes inbound emails to matching `EmailHandler` files discovered in `src/email-handlers/`. User and permission context are injected via `AsyncLocalStorage` for seamless integration with Flink tools and agents.
14
+
3
15
  ## 2.0.0-alpha.58
4
16
 
5
17
  ### Patch Changes
package/cli/cli-utils.ts CHANGED
@@ -116,6 +116,7 @@ export async function compile(opts: CompileOptions): Promise<void> {
116
116
  await compiler.parseTools();
117
117
  await compiler.parseAgents();
118
118
  await compiler.parseJobs();
119
+ await compiler.parseAllExtensionDirs();
119
120
  await compiler.parseHandlers();
120
121
  await compiler.generateStartScript(entry);
121
122
  await compiler.generateAllSchemas();
package/cli/dev.ts CHANGED
@@ -6,6 +6,7 @@ import { existsSync } from "fs";
6
6
  import { parseArgs, hasFlag, getOption, normalizeEntry, printHelp, compile, forkApp } from "./cli-utils";
7
7
  import { FlinkLogFactory } from "../src/FlinkLogFactory";
8
8
  import { loadFlinkConfig } from "../src/utils/loadFlinkConfig";
9
+ import { loadEnvFiles } from "./loadEnvFiles";
9
10
 
10
11
  // Load config BEFORE creating logger
11
12
  const flinkConfig = loadFlinkConfig();
@@ -16,6 +17,19 @@ const logger = FlinkLogFactory.createLogger("flink.dev");
16
17
  module.exports = async function dev(args: string[]) {
17
18
  const parsed = parseArgs(args);
18
19
 
20
+ // Load .env files before anything else so all env vars are available at startup.
21
+ // NODE_ENV defaults to "development" when not explicitly set.
22
+ if (!process.env.NODE_ENV) {
23
+ process.env.NODE_ENV = "development";
24
+ }
25
+
26
+ const initLogger = FlinkLogFactory.createLogger("flink.init");
27
+ const { loaded, injected } = loadEnvFiles(parsed.dir, "development");
28
+
29
+ if (loaded.length > 0) {
30
+ initLogger.info(`Loaded env files: ${loaded.join(", ")} (${injected} vars injected)`);
31
+ }
32
+
19
33
  if (hasFlag(parsed, "help")) {
20
34
  printHelp({
21
35
  description:
@@ -181,15 +195,24 @@ function startTscWatch(dir: string): ChildProcess {
181
195
 
182
196
  if (!trimmed) continue;
183
197
 
184
- if (trimmed.includes("Starting compilation") || trimmed.includes("File change detected")) {
198
+ // Filter out noisy watch-mode status lines
199
+ if (
200
+ trimmed.includes("Starting compilation") ||
201
+ trimmed.includes("File change detected") ||
202
+ trimmed.match(/^\[\d+:\d+:\d+\s+[AP]M\] Watching for file changes/)
203
+ ) {
185
204
  continue;
186
205
  }
187
206
 
188
207
  if (trimmed.includes("Found 0 errors")) {
189
208
  console.log(`[tsc] ✓ No type errors`);
190
- } else if (trimmed.includes("Found") && trimmed.includes("error")) {
191
- console.log(`[tsc] ${trimmed}`);
192
- } else if (trimmed.includes("error TS")) {
209
+ } else if (trimmed.match(/Found \d+ errors?/)) {
210
+ // Pretty-print the error count summary
211
+ const match = trimmed.match(/Found (\d+) errors?/);
212
+ const count = match?.[1];
213
+ console.log(`[tsc] ❌ Found ${count} type error${count === "1" ? "" : "s"} — see details above`);
214
+ } else {
215
+ // Show everything else: error details, file paths, code context, etc.
193
216
  console.log(`[tsc] ${trimmed}`);
194
217
  }
195
218
  }
@@ -0,0 +1,116 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { resolve, join } from "path";
3
+
4
+ /**
5
+ * Parse the contents of a .env file into a key/value map.
6
+ *
7
+ * Rules:
8
+ * - Empty lines and lines starting with # are skipped
9
+ * - "export FOO=bar" is treated the same as "FOO=bar"
10
+ * - Quoted values (single or double) are unquoted, and their content is used as-is
11
+ * - Unquoted values have inline comments stripped: FOO=bar # comment → "bar"
12
+ */
13
+ export function parseEnvContent(content: string): Record<string, string> {
14
+ const result: Record<string, string> = {};
15
+
16
+ for (const rawLine of content.split("\n")) {
17
+ let line = rawLine.trim();
18
+
19
+ // Skip empty lines and full-line comments
20
+ if (!line || line.startsWith("#")) continue;
21
+
22
+ // Strip "export " prefix
23
+ if (line.startsWith("export ")) {
24
+ line = line.slice(7).trim();
25
+ }
26
+
27
+ const eqIdx = line.indexOf("=");
28
+ if (eqIdx === -1) continue;
29
+
30
+ const key = line.slice(0, eqIdx).trim();
31
+ if (!key) continue;
32
+
33
+ let value = line.slice(eqIdx + 1);
34
+
35
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
36
+ // Quoted value — strip quotes, preserve content as-is
37
+ value = value.slice(1, -1);
38
+ } else {
39
+ // Unquoted — strip inline comments (" # ...") and trim
40
+ const commentIdx = value.search(/ #/);
41
+ if (commentIdx !== -1) {
42
+ value = value.slice(0, commentIdx);
43
+ }
44
+ value = value.trim();
45
+ }
46
+
47
+ result[key] = value;
48
+ }
49
+
50
+ return result;
51
+ }
52
+
53
+ function readEnvFile(filepath: string): Record<string, string> | null {
54
+ if (!existsSync(filepath)) return null;
55
+ try {
56
+ return parseEnvContent(readFileSync(filepath, "utf-8"));
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ export interface LoadEnvFilesResult {
63
+ /** Relative filenames that were found and loaded, in load order */
64
+ loaded: string[];
65
+ /** Number of variables injected into process.env (excludes already-set vars) */
66
+ injected: number;
67
+ }
68
+
69
+ /**
70
+ * Load .env files in Next.js-compatible order.
71
+ *
72
+ * Priority (highest wins):
73
+ * 1. process.env (already-set variables are never overridden)
74
+ * 2. .env.[environment].local
75
+ * 3. .env.local (skipped when environment === "test")
76
+ * 4. .env.[environment]
77
+ * 5. .env
78
+ *
79
+ * @param dir Root directory of the Flink app (where .env files live)
80
+ * @param environment "development" | "production" | "test"
81
+ */
82
+ export function loadEnvFiles(dir: string, environment: "development" | "production" | "test"): LoadEnvFilesResult {
83
+ const absoluteDir = resolve(dir);
84
+
85
+ // Files listed from lowest to highest priority so that Object.assign
86
+ // naturally lets later files override earlier ones.
87
+ const candidates: string[] = [
88
+ ".env",
89
+ `.env.${environment}`,
90
+ // .env.local is intentionally skipped in test (matches Next.js behaviour)
91
+ ...(environment !== "test" ? [".env.local"] : []),
92
+ `.env.${environment}.local`,
93
+ ];
94
+
95
+ const loaded: string[] = [];
96
+ const merged: Record<string, string> = {};
97
+
98
+ for (const filename of candidates) {
99
+ const parsed = readEnvFile(join(absoluteDir, filename));
100
+ if (parsed !== null) {
101
+ loaded.push(filename);
102
+ Object.assign(merged, parsed);
103
+ }
104
+ }
105
+
106
+ // Inject into process.env — existing values always win
107
+ let injected = 0;
108
+ for (const [key, value] of Object.entries(merged)) {
109
+ if (!(key in process.env)) {
110
+ process.env[key] = value;
111
+ injected++;
112
+ }
113
+ }
114
+
115
+ return { loaded, injected };
116
+ }
package/cli/run.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  import { parseArgs, hasFlag, getOption, normalizeEntry, printHelp, compile, forkApp } from "./cli-utils";
3
3
  import { FlinkLogFactory } from "../src/FlinkLogFactory";
4
4
  import { loadFlinkConfig } from "../src/utils/loadFlinkConfig";
5
+ import { loadEnvFiles } from "./loadEnvFiles";
5
6
 
6
7
  // Load config BEFORE creating logger
7
8
  const flinkConfig = loadFlinkConfig();
@@ -10,6 +11,19 @@ FlinkLogFactory.configure(flinkConfig?.logging);
10
11
  module.exports = async function run(args: string[]) {
11
12
  const parsed = parseArgs(args);
12
13
 
14
+ // Load .env files before anything else so all env vars are available at startup.
15
+ // NODE_ENV defaults to "production" when not explicitly set.
16
+ if (!process.env.NODE_ENV) {
17
+ process.env.NODE_ENV = "production";
18
+ }
19
+
20
+ const initLogger = FlinkLogFactory.createLogger("flink.init");
21
+ const { loaded, injected } = loadEnvFiles(parsed.dir, "production");
22
+
23
+ if (loaded.length > 0) {
24
+ initLogger.info(`Loaded env files: ${loaded.join(", ")} (${injected} vars injected)`);
25
+ }
26
+
13
27
  if (hasFlag(parsed, "help")) {
14
28
  printHelp({
15
29
  description: "Compiles and starts the application.",
@@ -125,17 +125,20 @@ function compile(opts) {
125
125
  return [4 /*yield*/, compiler.parseJobs()];
126
126
  case 5:
127
127
  _c.sent();
128
- return [4 /*yield*/, compiler.parseHandlers()];
128
+ return [4 /*yield*/, compiler.parseAllExtensionDirs()];
129
129
  case 6:
130
130
  _c.sent();
131
- return [4 /*yield*/, compiler.generateStartScript(entry)];
131
+ return [4 /*yield*/, compiler.parseHandlers()];
132
132
  case 7:
133
133
  _c.sent();
134
- return [4 /*yield*/, compiler.generateAllSchemas()];
134
+ return [4 /*yield*/, compiler.generateStartScript(entry)];
135
135
  case 8:
136
136
  _c.sent();
137
- return [4 /*yield*/, compiler.saveAllModifiedFiles()];
137
+ return [4 /*yield*/, compiler.generateAllSchemas()];
138
138
  case 9:
139
+ _c.sent();
140
+ return [4 /*yield*/, compiler.saveAllModifiedFiles()];
141
+ case 10:
139
142
  _c.sent();
140
143
  if (typeCheck) {
141
144
  stepStart = Date.now();
@@ -145,14 +148,14 @@ function compile(opts) {
145
148
  time("Type checking (getPreEmitDiagnostics)", stepStart);
146
149
  }
147
150
  stepStart = Date.now();
148
- if (!(process.env.FLINK_USE_TSC === "true")) return [3 /*break*/, 10];
151
+ if (!(process.env.FLINK_USE_TSC === "true")) return [3 /*break*/, 11];
149
152
  compiler.emitWithTsc();
150
- return [3 /*break*/, 12];
151
- case 10: return [4 /*yield*/, compiler.emit()];
152
- case 11:
153
- _c.sent();
154
- _c.label = 12;
153
+ return [3 /*break*/, 13];
154
+ case 11: return [4 /*yield*/, compiler.emit()];
155
155
  case 12:
156
+ _c.sent();
157
+ _c.label = 13;
158
+ case 13:
156
159
  time("Transpilation (".concat(process.env.FLINK_USE_TSC === "true" ? "tsc" : "swc", ")"), stepStart);
157
160
  if (timingLogs) {
158
161
  console.log("Compilation done in ".concat(Date.now() - start, "ms"));
package/dist/cli/dev.js CHANGED
@@ -47,18 +47,29 @@ var fs_1 = require("fs");
47
47
  var cli_utils_1 = require("./cli-utils");
48
48
  var FlinkLogFactory_1 = require("../src/FlinkLogFactory");
49
49
  var loadFlinkConfig_1 = require("../src/utils/loadFlinkConfig");
50
+ var loadEnvFiles_1 = require("./loadEnvFiles");
50
51
  // Load config BEFORE creating logger
51
52
  var flinkConfig = (0, loadFlinkConfig_1.loadFlinkConfig)();
52
53
  FlinkLogFactory_1.FlinkLogFactory.configure(flinkConfig === null || flinkConfig === void 0 ? void 0 : flinkConfig.logging);
53
54
  var logger = FlinkLogFactory_1.FlinkLogFactory.createLogger("flink.dev");
54
55
  module.exports = function dev(args) {
55
56
  return __awaiter(this, void 0, void 0, function () {
56
- var parsed, dir, entry, typecheck, noTypecheck, serverProcess, tscProcess, isRebuilding, pendingRebuild, watcher;
57
+ var parsed, initLogger, _a, loaded, injected, dir, entry, typecheck, noTypecheck, serverProcess, tscProcess, isRebuilding, pendingRebuild, watcher;
57
58
  var _this = this;
58
- return __generator(this, function (_a) {
59
- switch (_a.label) {
59
+ return __generator(this, function (_b) {
60
+ switch (_b.label) {
60
61
  case 0:
61
62
  parsed = (0, cli_utils_1.parseArgs)(args);
63
+ // Load .env files before anything else so all env vars are available at startup.
64
+ // NODE_ENV defaults to "development" when not explicitly set.
65
+ if (!process.env.NODE_ENV) {
66
+ process.env.NODE_ENV = "development";
67
+ }
68
+ initLogger = FlinkLogFactory_1.FlinkLogFactory.createLogger("flink.init");
69
+ _a = (0, loadEnvFiles_1.loadEnvFiles)(parsed.dir, "development"), loaded = _a.loaded, injected = _a.injected;
70
+ if (loaded.length > 0) {
71
+ initLogger.info("Loaded env files: ".concat(loaded.join(", "), " (").concat(injected, " vars injected)"));
72
+ }
62
73
  if ((0, cli_utils_1.hasFlag)(parsed, "help")) {
63
74
  (0, cli_utils_1.printHelp)({
64
75
  description: "Starts development mode with watch and auto-reload.\n Fast rebuilds with swc (skips type checking by default).\n Runs background tsc --watch for async type error reporting.",
@@ -81,7 +92,7 @@ module.exports = function dev(args) {
81
92
  console.log("\uD83D\uDCE6 Initial build ".concat(typecheck ? "(with type checking)" : "(fast mode, skipping type check)", "..."));
82
93
  return [4 /*yield*/, (0, cli_utils_1.compile)({ dir: dir, entry: entry, typeCheck: typecheck })];
83
94
  case 1:
84
- _a.sent();
95
+ _b.sent();
85
96
  serverProcess = null;
86
97
  tscProcess = null;
87
98
  isRebuilding = false;
@@ -215,16 +226,23 @@ function startTscWatch(dir) {
215
226
  var trimmed = line.replace(/\x1Bc/g, "").trim();
216
227
  if (!trimmed)
217
228
  continue;
218
- if (trimmed.includes("Starting compilation") || trimmed.includes("File change detected")) {
229
+ // Filter out noisy watch-mode status lines
230
+ if (trimmed.includes("Starting compilation") ||
231
+ trimmed.includes("File change detected") ||
232
+ trimmed.match(/^\[\d+:\d+:\d+\s+[AP]M\] Watching for file changes/)) {
219
233
  continue;
220
234
  }
221
235
  if (trimmed.includes("Found 0 errors")) {
222
236
  console.log("[tsc] \u2713 No type errors");
223
237
  }
224
- else if (trimmed.includes("Found") && trimmed.includes("error")) {
225
- console.log("[tsc] ".concat(trimmed));
238
+ else if (trimmed.match(/Found \d+ errors?/)) {
239
+ // Pretty-print the error count summary
240
+ var match = trimmed.match(/Found (\d+) errors?/);
241
+ var count = match === null || match === void 0 ? void 0 : match[1];
242
+ console.log("[tsc] \u274C Found ".concat(count, " type error").concat(count === "1" ? "" : "s", " \u2014 see details above"));
226
243
  }
227
- else if (trimmed.includes("error TS")) {
244
+ else {
245
+ // Show everything else: error details, file paths, code context, etc.
228
246
  console.log("[tsc] ".concat(trimmed));
229
247
  }
230
248
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Parse the contents of a .env file into a key/value map.
3
+ *
4
+ * Rules:
5
+ * - Empty lines and lines starting with # are skipped
6
+ * - "export FOO=bar" is treated the same as "FOO=bar"
7
+ * - Quoted values (single or double) are unquoted, and their content is used as-is
8
+ * - Unquoted values have inline comments stripped: FOO=bar # comment → "bar"
9
+ */
10
+ export declare function parseEnvContent(content: string): Record<string, string>;
11
+ export interface LoadEnvFilesResult {
12
+ /** Relative filenames that were found and loaded, in load order */
13
+ loaded: string[];
14
+ /** Number of variables injected into process.env (excludes already-set vars) */
15
+ injected: number;
16
+ }
17
+ /**
18
+ * Load .env files in Next.js-compatible order.
19
+ *
20
+ * Priority (highest wins):
21
+ * 1. process.env (already-set variables are never overridden)
22
+ * 2. .env.[environment].local
23
+ * 3. .env.local (skipped when environment === "test")
24
+ * 4. .env.[environment]
25
+ * 5. .env
26
+ *
27
+ * @param dir Root directory of the Flink app (where .env files live)
28
+ * @param environment "development" | "production" | "test"
29
+ */
30
+ export declare function loadEnvFiles(dir: string, environment: "development" | "production" | "test"): LoadEnvFilesResult;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
3
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
4
+ if (ar || !(i in from)) {
5
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6
+ ar[i] = from[i];
7
+ }
8
+ }
9
+ return to.concat(ar || Array.prototype.slice.call(from));
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.parseEnvContent = parseEnvContent;
13
+ exports.loadEnvFiles = loadEnvFiles;
14
+ var fs_1 = require("fs");
15
+ var path_1 = require("path");
16
+ /**
17
+ * Parse the contents of a .env file into a key/value map.
18
+ *
19
+ * Rules:
20
+ * - Empty lines and lines starting with # are skipped
21
+ * - "export FOO=bar" is treated the same as "FOO=bar"
22
+ * - Quoted values (single or double) are unquoted, and their content is used as-is
23
+ * - Unquoted values have inline comments stripped: FOO=bar # comment → "bar"
24
+ */
25
+ function parseEnvContent(content) {
26
+ var result = {};
27
+ for (var _i = 0, _a = content.split("\n"); _i < _a.length; _i++) {
28
+ var rawLine = _a[_i];
29
+ var line = rawLine.trim();
30
+ // Skip empty lines and full-line comments
31
+ if (!line || line.startsWith("#"))
32
+ continue;
33
+ // Strip "export " prefix
34
+ if (line.startsWith("export ")) {
35
+ line = line.slice(7).trim();
36
+ }
37
+ var eqIdx = line.indexOf("=");
38
+ if (eqIdx === -1)
39
+ continue;
40
+ var key = line.slice(0, eqIdx).trim();
41
+ if (!key)
42
+ continue;
43
+ var value = line.slice(eqIdx + 1);
44
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
45
+ // Quoted value — strip quotes, preserve content as-is
46
+ value = value.slice(1, -1);
47
+ }
48
+ else {
49
+ // Unquoted — strip inline comments (" # ...") and trim
50
+ var commentIdx = value.search(/ #/);
51
+ if (commentIdx !== -1) {
52
+ value = value.slice(0, commentIdx);
53
+ }
54
+ value = value.trim();
55
+ }
56
+ result[key] = value;
57
+ }
58
+ return result;
59
+ }
60
+ function readEnvFile(filepath) {
61
+ if (!(0, fs_1.existsSync)(filepath))
62
+ return null;
63
+ try {
64
+ return parseEnvContent((0, fs_1.readFileSync)(filepath, "utf-8"));
65
+ }
66
+ catch (_a) {
67
+ return null;
68
+ }
69
+ }
70
+ /**
71
+ * Load .env files in Next.js-compatible order.
72
+ *
73
+ * Priority (highest wins):
74
+ * 1. process.env (already-set variables are never overridden)
75
+ * 2. .env.[environment].local
76
+ * 3. .env.local (skipped when environment === "test")
77
+ * 4. .env.[environment]
78
+ * 5. .env
79
+ *
80
+ * @param dir Root directory of the Flink app (where .env files live)
81
+ * @param environment "development" | "production" | "test"
82
+ */
83
+ function loadEnvFiles(dir, environment) {
84
+ var absoluteDir = (0, path_1.resolve)(dir);
85
+ // Files listed from lowest to highest priority so that Object.assign
86
+ // naturally lets later files override earlier ones.
87
+ var candidates = __spreadArray(__spreadArray([
88
+ ".env",
89
+ ".env.".concat(environment)
90
+ ], (environment !== "test" ? [".env.local"] : []), true), [
91
+ ".env.".concat(environment, ".local"),
92
+ ], false);
93
+ var loaded = [];
94
+ var merged = {};
95
+ for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) {
96
+ var filename = candidates_1[_i];
97
+ var parsed = readEnvFile((0, path_1.join)(absoluteDir, filename));
98
+ if (parsed !== null) {
99
+ loaded.push(filename);
100
+ Object.assign(merged, parsed);
101
+ }
102
+ }
103
+ // Inject into process.env — existing values always win
104
+ var injected = 0;
105
+ for (var _a = 0, _b = Object.entries(merged); _a < _b.length; _a++) {
106
+ var _c = _b[_a], key = _c[0], value = _c[1];
107
+ if (!(key in process.env)) {
108
+ process.env[key] = value;
109
+ injected++;
110
+ }
111
+ }
112
+ return { loaded: loaded, injected: injected };
113
+ }
package/dist/cli/run.js CHANGED
@@ -40,16 +40,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  var cli_utils_1 = require("./cli-utils");
41
41
  var FlinkLogFactory_1 = require("../src/FlinkLogFactory");
42
42
  var loadFlinkConfig_1 = require("../src/utils/loadFlinkConfig");
43
+ var loadEnvFiles_1 = require("./loadEnvFiles");
43
44
  // Load config BEFORE creating logger
44
45
  var flinkConfig = (0, loadFlinkConfig_1.loadFlinkConfig)();
45
46
  FlinkLogFactory_1.FlinkLogFactory.configure(flinkConfig === null || flinkConfig === void 0 ? void 0 : flinkConfig.logging);
46
47
  module.exports = function run(args) {
47
48
  return __awaiter(this, void 0, void 0, function () {
48
- var parsed, entry;
49
- return __generator(this, function (_a) {
50
- switch (_a.label) {
49
+ var parsed, initLogger, _a, loaded, injected, entry;
50
+ return __generator(this, function (_b) {
51
+ switch (_b.label) {
51
52
  case 0:
52
53
  parsed = (0, cli_utils_1.parseArgs)(args);
54
+ // Load .env files before anything else so all env vars are available at startup.
55
+ // NODE_ENV defaults to "production" when not explicitly set.
56
+ if (!process.env.NODE_ENV) {
57
+ process.env.NODE_ENV = "production";
58
+ }
59
+ initLogger = FlinkLogFactory_1.FlinkLogFactory.createLogger("flink.init");
60
+ _a = (0, loadEnvFiles_1.loadEnvFiles)(parsed.dir, "production"), loaded = _a.loaded, injected = _a.injected;
61
+ if (loaded.length > 0) {
62
+ initLogger.info("Loaded env files: ".concat(loaded.join(", "), " (").concat(injected, " vars injected)"));
63
+ }
53
64
  if ((0, cli_utils_1.hasFlag)(parsed, "help")) {
54
65
  (0, cli_utils_1.printHelp)({
55
66
  description: "Compiles and starts the application.",
@@ -80,7 +91,7 @@ module.exports = function run(args) {
80
91
  typeCheck: true,
81
92
  })];
82
93
  case 1:
83
- _a.sent();
94
+ _b.sent();
84
95
  (0, cli_utils_1.forkApp)({
85
96
  dir: parsed.dir,
86
97
  args: args,
@@ -1,4 +1,5 @@
1
1
  import { SourceFile } from "ts-morph";
2
+ import { FlinkCompilerPlugin } from "./utils/loadFlinkConfig";
2
3
  declare class TypeScriptCompiler {
3
4
  private cwd;
4
5
  private project;
@@ -24,6 +25,14 @@ declare class TypeScriptCompiler {
24
25
  * Tool ID registry for agent validation (built during segmentation)
25
26
  */
26
27
  private toolIdRegistry;
28
+ /**
29
+ * Compiler plugins loaded from flink.config.js
30
+ */
31
+ private compilerPlugins;
32
+ /**
33
+ * Extension files collected during segmentation, keyed by generatedFile name
34
+ */
35
+ private extensionFiles;
27
36
  /**
28
37
  * Generates a schema $id from a file path and type name using the same algorithm
29
38
  * as the schema generator's defineId callback.
@@ -206,5 +215,16 @@ declare class TypeScriptCompiler {
206
215
  * Scans project for jobs so they can be registered during start.
207
216
  */
208
217
  parseJobs(): Promise<SourceFile>;
218
+ /**
219
+ * Generates a .flink/generatedXxx.ts file for a single compiler plugin extension.
220
+ * Mirrors the same namespace-import + spread pattern used by parseJobs.
221
+ */
222
+ parseExtensionDir(ext: FlinkCompilerPlugin): Promise<SourceFile>;
223
+ /**
224
+ * Iterates all compilerPlugins from flink.config.js and generates
225
+ * a .flink/generatedXxx.ts file for each one.
226
+ * Call this after parseJobs() and before generateStartScript().
227
+ */
228
+ parseAllExtensionDirs(): Promise<void>;
209
229
  }
210
230
  export default TypeScriptCompiler;