@timo9378/flow2code 0.1.3 → 0.1.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/dist/compiler.cjs CHANGED
@@ -2093,7 +2093,7 @@ function generateNodeChainDAG(writer, triggerId, context) {
2093
2093
  generateNodeBody(writer, node, context);
2094
2094
  });
2095
2095
  writer.writeLine(`)();`);
2096
- writer.writeLine(`${promiseVar}.catch(() => {});`);
2096
+ writer.writeLine(`${promiseVar}.catch((err) => { console.error("[Flow2Code DAG Error]", err); });`);
2097
2097
  writer.blankLine();
2098
2098
  }
2099
2099
  if (dagNodeIds.length > 0) {
@@ -2166,7 +2166,18 @@ function generateNodeBody(writer, node, context) {
2166
2166
  const plugin = context.pluginRegistry.get(node.nodeType);
2167
2167
  if (plugin) {
2168
2168
  const pluginCtx = createPluginContext(context);
2169
- plugin.generate(node, writer, pluginCtx);
2169
+ try {
2170
+ plugin.generate(node, writer, pluginCtx);
2171
+ } catch (err) {
2172
+ const errMsg = err instanceof Error ? err.message : String(err);
2173
+ const stack = err instanceof Error ? err.stack : void 0;
2174
+ throw new Error(
2175
+ `[flow2code] Plugin "${node.nodeType}" threw an error while generating node "${node.label}" (${node.id}):
2176
+ ${errMsg}` + (stack ? `
2177
+ Stack: ${stack}` : ""),
2178
+ { cause: err }
2179
+ );
2180
+ }
2170
2181
  } else {
2171
2182
  throw new Error(
2172
2183
  `[flow2code] Unsupported node type: "${node.nodeType}". Register a plugin via pluginRegistry.register() or use a built-in node type.`
@@ -2174,6 +2185,13 @@ function generateNodeBody(writer, node, context) {
2174
2185
  }
2175
2186
  }
2176
2187
  function createPluginContext(context) {
2188
+ const pendingChildBlockIds = [];
2189
+ const applyChildBlockRegistration = (nodeId) => {
2190
+ pendingChildBlockIds.push(nodeId);
2191
+ context.childBlockNodeIds.add(nodeId);
2192
+ context.symbolTableExclusions.add(nodeId);
2193
+ context.generatedBlockNodeIds.add(nodeId);
2194
+ };
2177
2195
  return {
2178
2196
  ir: context.ir,
2179
2197
  nodeMap: context.nodeMap,
@@ -2199,9 +2217,7 @@ function createPluginContext(context) {
2199
2217
  return resolveEnvVars(url, context);
2200
2218
  },
2201
2219
  generateChildNode(writer, node) {
2202
- context.childBlockNodeIds.add(node.id);
2203
- context.symbolTableExclusions.add(node.id);
2204
- context.generatedBlockNodeIds.add(node.id);
2220
+ applyChildBlockRegistration(node.id);
2205
2221
  writer.writeLine(`// --- ${node.label} (${node.nodeType}) [${node.id}] ---`);
2206
2222
  generateNodeBody(writer, node, context);
2207
2223
  generateBlockContinuation(writer, node.id, context);
@@ -2245,27 +2261,27 @@ function collectRequiredPackages(ir, context) {
2245
2261
  function buildSourceMap(code, ir, filePath) {
2246
2262
  const lines = code.split("\n");
2247
2263
  const mappings = {};
2248
- const nodeMarkerRegex = /^[\s]*\/\/ --- .+? \(.+?\) \[(.+?)\] ---$/;
2264
+ const validNodeIds = new Set(ir.nodes.map((n) => n.id));
2249
2265
  let currentNodeId = null;
2250
2266
  let currentStartLine = 0;
2251
2267
  for (let i = 0; i < lines.length; i++) {
2252
2268
  const lineNum = i + 1;
2253
- const match = lines[i].match(nodeMarkerRegex);
2254
- if (match) {
2255
- if (currentNodeId) {
2256
- mappings[currentNodeId] = {
2257
- startLine: currentStartLine,
2258
- endLine: lineNum - 1
2259
- };
2260
- }
2261
- const [, nodeId] = match;
2262
- if (ir.nodes.some((n) => n.id === nodeId)) {
2263
- currentNodeId = nodeId;
2264
- currentStartLine = lineNum;
2265
- } else {
2266
- currentNodeId = null;
2267
- }
2269
+ const line = lines[i];
2270
+ const bracketOpen = line.indexOf("[");
2271
+ const bracketClose = line.indexOf("] ---", bracketOpen);
2272
+ if (bracketOpen === -1 || bracketClose === -1) continue;
2273
+ const trimmed = line.trimStart();
2274
+ if (!trimmed.startsWith("//")) continue;
2275
+ const candidateId = line.slice(bracketOpen + 1, bracketClose);
2276
+ if (!validNodeIds.has(candidateId)) continue;
2277
+ if (currentNodeId) {
2278
+ mappings[currentNodeId] = {
2279
+ startLine: currentStartLine,
2280
+ endLine: lineNum - 1
2281
+ };
2268
2282
  }
2283
+ currentNodeId = candidateId;
2284
+ currentStartLine = lineNum;
2269
2285
  }
2270
2286
  if (currentNodeId) {
2271
2287
  mappings[currentNodeId] = {
@@ -2960,9 +2976,13 @@ function buildEdges(ctx) {
2960
2976
  }
2961
2977
  }
2962
2978
  }
2979
+ const resolveTargetPort = (targetNodeId, fallback) => {
2980
+ const tgt = ctx.nodes.get(targetNodeId);
2981
+ return tgt?.inputs?.[0]?.id ?? fallback;
2982
+ };
2963
2983
  for (const [parentId, children] of ctx.controlFlowChildren) {
2964
2984
  for (const child of children) {
2965
- addEdge(parentId, child.portId, child.nodeId, "input");
2985
+ addEdge(parentId, child.portId, child.nodeId, resolveTargetPort(child.nodeId, "input"));
2966
2986
  connectedTargets.add(child.nodeId);
2967
2987
  }
2968
2988
  }
@@ -2971,7 +2991,7 @@ function buildEdges(ctx) {
2971
2991
  const predNode = ctx.nodes.get(predId);
2972
2992
  if (!predNode) continue;
2973
2993
  const sourcePort = predNode.outputs[0]?.id ?? "output";
2974
- addEdge(predId, sourcePort, nodeId, "input");
2994
+ addEdge(predId, sourcePort, nodeId, resolveTargetPort(nodeId, "input"));
2975
2995
  }
2976
2996
  }
2977
2997
  function computeAuditHints(ctx) {
@@ -3103,7 +3123,9 @@ function trackVariableUses(nodeId, expression, ctx) {
3103
3123
  if (seen.has(ident)) continue;
3104
3124
  seen.add(ident);
3105
3125
  if (ctx.varDefs.has(ident)) {
3106
- uses.push({ nodeId, portId: "input", varName: ident });
3126
+ const targetNode = ctx.nodes.get(nodeId);
3127
+ const portId = targetNode?.inputs?.[0]?.id ?? "input";
3128
+ uses.push({ nodeId, portId, varName: ident });
3107
3129
  }
3108
3130
  }
3109
3131
  if (uses.length > 0) {
package/dist/compiler.js CHANGED
@@ -2026,7 +2026,7 @@ function generateNodeChainDAG(writer, triggerId, context) {
2026
2026
  generateNodeBody(writer, node, context);
2027
2027
  });
2028
2028
  writer.writeLine(`)();`);
2029
- writer.writeLine(`${promiseVar}.catch(() => {});`);
2029
+ writer.writeLine(`${promiseVar}.catch((err) => { console.error("[Flow2Code DAG Error]", err); });`);
2030
2030
  writer.blankLine();
2031
2031
  }
2032
2032
  if (dagNodeIds.length > 0) {
@@ -2099,7 +2099,18 @@ function generateNodeBody(writer, node, context) {
2099
2099
  const plugin = context.pluginRegistry.get(node.nodeType);
2100
2100
  if (plugin) {
2101
2101
  const pluginCtx = createPluginContext(context);
2102
- plugin.generate(node, writer, pluginCtx);
2102
+ try {
2103
+ plugin.generate(node, writer, pluginCtx);
2104
+ } catch (err) {
2105
+ const errMsg = err instanceof Error ? err.message : String(err);
2106
+ const stack = err instanceof Error ? err.stack : void 0;
2107
+ throw new Error(
2108
+ `[flow2code] Plugin "${node.nodeType}" threw an error while generating node "${node.label}" (${node.id}):
2109
+ ${errMsg}` + (stack ? `
2110
+ Stack: ${stack}` : ""),
2111
+ { cause: err }
2112
+ );
2113
+ }
2103
2114
  } else {
2104
2115
  throw new Error(
2105
2116
  `[flow2code] Unsupported node type: "${node.nodeType}". Register a plugin via pluginRegistry.register() or use a built-in node type.`
@@ -2107,6 +2118,13 @@ function generateNodeBody(writer, node, context) {
2107
2118
  }
2108
2119
  }
2109
2120
  function createPluginContext(context) {
2121
+ const pendingChildBlockIds = [];
2122
+ const applyChildBlockRegistration = (nodeId) => {
2123
+ pendingChildBlockIds.push(nodeId);
2124
+ context.childBlockNodeIds.add(nodeId);
2125
+ context.symbolTableExclusions.add(nodeId);
2126
+ context.generatedBlockNodeIds.add(nodeId);
2127
+ };
2110
2128
  return {
2111
2129
  ir: context.ir,
2112
2130
  nodeMap: context.nodeMap,
@@ -2132,9 +2150,7 @@ function createPluginContext(context) {
2132
2150
  return resolveEnvVars(url, context);
2133
2151
  },
2134
2152
  generateChildNode(writer, node) {
2135
- context.childBlockNodeIds.add(node.id);
2136
- context.symbolTableExclusions.add(node.id);
2137
- context.generatedBlockNodeIds.add(node.id);
2153
+ applyChildBlockRegistration(node.id);
2138
2154
  writer.writeLine(`// --- ${node.label} (${node.nodeType}) [${node.id}] ---`);
2139
2155
  generateNodeBody(writer, node, context);
2140
2156
  generateBlockContinuation(writer, node.id, context);
@@ -2178,27 +2194,27 @@ function collectRequiredPackages(ir, context) {
2178
2194
  function buildSourceMap(code, ir, filePath) {
2179
2195
  const lines = code.split("\n");
2180
2196
  const mappings = {};
2181
- const nodeMarkerRegex = /^[\s]*\/\/ --- .+? \(.+?\) \[(.+?)\] ---$/;
2197
+ const validNodeIds = new Set(ir.nodes.map((n) => n.id));
2182
2198
  let currentNodeId = null;
2183
2199
  let currentStartLine = 0;
2184
2200
  for (let i = 0; i < lines.length; i++) {
2185
2201
  const lineNum = i + 1;
2186
- const match = lines[i].match(nodeMarkerRegex);
2187
- if (match) {
2188
- if (currentNodeId) {
2189
- mappings[currentNodeId] = {
2190
- startLine: currentStartLine,
2191
- endLine: lineNum - 1
2192
- };
2193
- }
2194
- const [, nodeId] = match;
2195
- if (ir.nodes.some((n) => n.id === nodeId)) {
2196
- currentNodeId = nodeId;
2197
- currentStartLine = lineNum;
2198
- } else {
2199
- currentNodeId = null;
2200
- }
2202
+ const line = lines[i];
2203
+ const bracketOpen = line.indexOf("[");
2204
+ const bracketClose = line.indexOf("] ---", bracketOpen);
2205
+ if (bracketOpen === -1 || bracketClose === -1) continue;
2206
+ const trimmed = line.trimStart();
2207
+ if (!trimmed.startsWith("//")) continue;
2208
+ const candidateId = line.slice(bracketOpen + 1, bracketClose);
2209
+ if (!validNodeIds.has(candidateId)) continue;
2210
+ if (currentNodeId) {
2211
+ mappings[currentNodeId] = {
2212
+ startLine: currentStartLine,
2213
+ endLine: lineNum - 1
2214
+ };
2201
2215
  }
2216
+ currentNodeId = candidateId;
2217
+ currentStartLine = lineNum;
2202
2218
  }
2203
2219
  if (currentNodeId) {
2204
2220
  mappings[currentNodeId] = {
@@ -2896,9 +2912,13 @@ function buildEdges(ctx) {
2896
2912
  }
2897
2913
  }
2898
2914
  }
2915
+ const resolveTargetPort = (targetNodeId, fallback) => {
2916
+ const tgt = ctx.nodes.get(targetNodeId);
2917
+ return tgt?.inputs?.[0]?.id ?? fallback;
2918
+ };
2899
2919
  for (const [parentId, children] of ctx.controlFlowChildren) {
2900
2920
  for (const child of children) {
2901
- addEdge(parentId, child.portId, child.nodeId, "input");
2921
+ addEdge(parentId, child.portId, child.nodeId, resolveTargetPort(child.nodeId, "input"));
2902
2922
  connectedTargets.add(child.nodeId);
2903
2923
  }
2904
2924
  }
@@ -2907,7 +2927,7 @@ function buildEdges(ctx) {
2907
2927
  const predNode = ctx.nodes.get(predId);
2908
2928
  if (!predNode) continue;
2909
2929
  const sourcePort = predNode.outputs[0]?.id ?? "output";
2910
- addEdge(predId, sourcePort, nodeId, "input");
2930
+ addEdge(predId, sourcePort, nodeId, resolveTargetPort(nodeId, "input"));
2911
2931
  }
2912
2932
  }
2913
2933
  function computeAuditHints(ctx) {
@@ -3039,7 +3059,9 @@ function trackVariableUses(nodeId, expression, ctx) {
3039
3059
  if (seen.has(ident)) continue;
3040
3060
  seen.add(ident);
3041
3061
  if (ctx.varDefs.has(ident)) {
3042
- uses.push({ nodeId, portId: "input", varName: ident });
3062
+ const targetNode = ctx.nodes.get(nodeId);
3063
+ const portId = targetNode?.inputs?.[0]?.id ?? "input";
3064
+ uses.push({ nodeId, portId, varName: ident });
3043
3065
  }
3044
3066
  }
3045
3067
  if (uses.length > 0) {
package/dist/server.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/server/index.ts
4
4
  import { createServer } from "http";
5
5
  import { readFile, stat } from "fs/promises";
6
- import { join as join2, extname, dirname as dirname2 } from "path";
6
+ import { join as join2, extname, dirname as dirname2, resolve as resolve2 } from "path";
7
7
  import { fileURLToPath } from "url";
8
8
  import { existsSync as existsSync2 } from "fs";
9
9
 
@@ -1979,7 +1979,7 @@ function generateNodeChainDAG(writer, triggerId, context) {
1979
1979
  generateNodeBody(writer, node, context);
1980
1980
  });
1981
1981
  writer.writeLine(`)();`);
1982
- writer.writeLine(`${promiseVar}.catch(() => {});`);
1982
+ writer.writeLine(`${promiseVar}.catch((err) => { console.error("[Flow2Code DAG Error]", err); });`);
1983
1983
  writer.blankLine();
1984
1984
  }
1985
1985
  if (dagNodeIds.length > 0) {
@@ -2052,7 +2052,18 @@ function generateNodeBody(writer, node, context) {
2052
2052
  const plugin = context.pluginRegistry.get(node.nodeType);
2053
2053
  if (plugin) {
2054
2054
  const pluginCtx = createPluginContext(context);
2055
- plugin.generate(node, writer, pluginCtx);
2055
+ try {
2056
+ plugin.generate(node, writer, pluginCtx);
2057
+ } catch (err) {
2058
+ const errMsg = err instanceof Error ? err.message : String(err);
2059
+ const stack = err instanceof Error ? err.stack : void 0;
2060
+ throw new Error(
2061
+ `[flow2code] Plugin "${node.nodeType}" threw an error while generating node "${node.label}" (${node.id}):
2062
+ ${errMsg}` + (stack ? `
2063
+ Stack: ${stack}` : ""),
2064
+ { cause: err }
2065
+ );
2066
+ }
2056
2067
  } else {
2057
2068
  throw new Error(
2058
2069
  `[flow2code] Unsupported node type: "${node.nodeType}". Register a plugin via pluginRegistry.register() or use a built-in node type.`
@@ -2060,6 +2071,13 @@ function generateNodeBody(writer, node, context) {
2060
2071
  }
2061
2072
  }
2062
2073
  function createPluginContext(context) {
2074
+ const pendingChildBlockIds = [];
2075
+ const applyChildBlockRegistration = (nodeId) => {
2076
+ pendingChildBlockIds.push(nodeId);
2077
+ context.childBlockNodeIds.add(nodeId);
2078
+ context.symbolTableExclusions.add(nodeId);
2079
+ context.generatedBlockNodeIds.add(nodeId);
2080
+ };
2063
2081
  return {
2064
2082
  ir: context.ir,
2065
2083
  nodeMap: context.nodeMap,
@@ -2085,9 +2103,7 @@ function createPluginContext(context) {
2085
2103
  return resolveEnvVars(url, context);
2086
2104
  },
2087
2105
  generateChildNode(writer, node) {
2088
- context.childBlockNodeIds.add(node.id);
2089
- context.symbolTableExclusions.add(node.id);
2090
- context.generatedBlockNodeIds.add(node.id);
2106
+ applyChildBlockRegistration(node.id);
2091
2107
  writer.writeLine(`// --- ${node.label} (${node.nodeType}) [${node.id}] ---`);
2092
2108
  generateNodeBody(writer, node, context);
2093
2109
  generateBlockContinuation(writer, node.id, context);
@@ -2131,27 +2147,27 @@ function collectRequiredPackages(ir, context) {
2131
2147
  function buildSourceMap(code, ir, filePath) {
2132
2148
  const lines = code.split("\n");
2133
2149
  const mappings = {};
2134
- const nodeMarkerRegex = /^[\s]*\/\/ --- .+? \(.+?\) \[(.+?)\] ---$/;
2150
+ const validNodeIds = new Set(ir.nodes.map((n) => n.id));
2135
2151
  let currentNodeId = null;
2136
2152
  let currentStartLine = 0;
2137
2153
  for (let i = 0; i < lines.length; i++) {
2138
2154
  const lineNum = i + 1;
2139
- const match = lines[i].match(nodeMarkerRegex);
2140
- if (match) {
2141
- if (currentNodeId) {
2142
- mappings[currentNodeId] = {
2143
- startLine: currentStartLine,
2144
- endLine: lineNum - 1
2145
- };
2146
- }
2147
- const [, nodeId] = match;
2148
- if (ir.nodes.some((n) => n.id === nodeId)) {
2149
- currentNodeId = nodeId;
2150
- currentStartLine = lineNum;
2151
- } else {
2152
- currentNodeId = null;
2153
- }
2155
+ const line = lines[i];
2156
+ const bracketOpen = line.indexOf("[");
2157
+ const bracketClose = line.indexOf("] ---", bracketOpen);
2158
+ if (bracketOpen === -1 || bracketClose === -1) continue;
2159
+ const trimmed = line.trimStart();
2160
+ if (!trimmed.startsWith("//")) continue;
2161
+ const candidateId = line.slice(bracketOpen + 1, bracketClose);
2162
+ if (!validNodeIds.has(candidateId)) continue;
2163
+ if (currentNodeId) {
2164
+ mappings[currentNodeId] = {
2165
+ startLine: currentStartLine,
2166
+ endLine: lineNum - 1
2167
+ };
2154
2168
  }
2169
+ currentNodeId = candidateId;
2170
+ currentStartLine = lineNum;
2155
2171
  }
2156
2172
  if (currentNodeId) {
2157
2173
  mappings[currentNodeId] = {
@@ -2709,9 +2725,13 @@ function buildEdges(ctx) {
2709
2725
  }
2710
2726
  }
2711
2727
  }
2728
+ const resolveTargetPort = (targetNodeId, fallback) => {
2729
+ const tgt = ctx.nodes.get(targetNodeId);
2730
+ return tgt?.inputs?.[0]?.id ?? fallback;
2731
+ };
2712
2732
  for (const [parentId, children] of ctx.controlFlowChildren) {
2713
2733
  for (const child of children) {
2714
- addEdge(parentId, child.portId, child.nodeId, "input");
2734
+ addEdge(parentId, child.portId, child.nodeId, resolveTargetPort(child.nodeId, "input"));
2715
2735
  connectedTargets.add(child.nodeId);
2716
2736
  }
2717
2737
  }
@@ -2720,7 +2740,7 @@ function buildEdges(ctx) {
2720
2740
  const predNode = ctx.nodes.get(predId);
2721
2741
  if (!predNode) continue;
2722
2742
  const sourcePort = predNode.outputs[0]?.id ?? "output";
2723
- addEdge(predId, sourcePort, nodeId, "input");
2743
+ addEdge(predId, sourcePort, nodeId, resolveTargetPort(nodeId, "input"));
2724
2744
  }
2725
2745
  }
2726
2746
  function computeAuditHints(ctx) {
@@ -2852,7 +2872,9 @@ function trackVariableUses(nodeId, expression, ctx) {
2852
2872
  if (seen.has(ident)) continue;
2853
2873
  seen.add(ident);
2854
2874
  if (ctx.varDefs.has(ident)) {
2855
- uses.push({ nodeId, portId: "input", varName: ident });
2875
+ const targetNode = ctx.nodes.get(nodeId);
2876
+ const portId = targetNode?.inputs?.[0]?.id ?? "input";
2877
+ uses.push({ nodeId, portId, varName: ident });
2856
2878
  }
2857
2879
  }
2858
2880
  if (uses.length > 0) {
@@ -3681,6 +3703,66 @@ function handleDecompile(body) {
3681
3703
  }
3682
3704
  }
3683
3705
 
3706
+ // src/lib/logger.ts
3707
+ import pc from "picocolors";
3708
+ var LEVEL_ORDER = {
3709
+ debug: 0,
3710
+ info: 1,
3711
+ warn: 2,
3712
+ error: 3,
3713
+ silent: 4
3714
+ };
3715
+ var Logger = class {
3716
+ /** Minimum log level (default: "info"). Set to "silent" to suppress all output. */
3717
+ level = "info";
3718
+ /** Prefix for all log lines (default: "[flow2code]") */
3719
+ prefix = "[flow2code]";
3720
+ shouldLog(level) {
3721
+ return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level];
3722
+ }
3723
+ debug(...args) {
3724
+ if (!this.shouldLog("debug")) return;
3725
+ console.log(pc.gray(`${this.prefix} ${pc.dim("DEBUG")}`), ...args);
3726
+ }
3727
+ info(...args) {
3728
+ if (!this.shouldLog("info")) return;
3729
+ console.log(pc.blue(`${this.prefix}`), ...args);
3730
+ }
3731
+ success(...args) {
3732
+ if (!this.shouldLog("info")) return;
3733
+ console.log(pc.green(`${this.prefix} \u2705`), ...args);
3734
+ }
3735
+ warn(...args) {
3736
+ if (!this.shouldLog("warn")) return;
3737
+ console.warn(pc.yellow(`${this.prefix} \u26A0\uFE0F`), ...args);
3738
+ }
3739
+ error(...args) {
3740
+ if (!this.shouldLog("error")) return;
3741
+ console.error(pc.red(`${this.prefix} \u274C`), ...args);
3742
+ }
3743
+ /** Print a blank line (respects silent mode) */
3744
+ blank() {
3745
+ if (!this.shouldLog("info")) return;
3746
+ console.log();
3747
+ }
3748
+ /** Print raw text without prefix (respects silent mode) */
3749
+ raw(...args) {
3750
+ if (!this.shouldLog("info")) return;
3751
+ console.log(...args);
3752
+ }
3753
+ /** Formatted key-value line for startup banners */
3754
+ kv(key, value) {
3755
+ if (!this.shouldLog("info")) return;
3756
+ console.log(` ${pc.dim("\u251C\u2500")} ${pc.bold(key)} ${value}`);
3757
+ }
3758
+ /** Last key-value line (uses └─) */
3759
+ kvLast(key, value) {
3760
+ if (!this.shouldLog("info")) return;
3761
+ console.log(` ${pc.dim("\u2514\u2500")} ${pc.bold(key)} ${value}`);
3762
+ }
3763
+ };
3764
+ var logger = new Logger();
3765
+
3684
3766
  // src/server/index.ts
3685
3767
  var __filename = fileURLToPath(import.meta.url);
3686
3768
  var __dirname = dirname2(__filename);
@@ -3762,7 +3844,7 @@ function sendJson(res, status, body) {
3762
3844
  }
3763
3845
  var MAX_BODY_SIZE = 2 * 1024 * 1024;
3764
3846
  async function readBody(req) {
3765
- return new Promise((resolve2, reject) => {
3847
+ return new Promise((resolve3, reject) => {
3766
3848
  const chunks = [];
3767
3849
  let totalSize = 0;
3768
3850
  req.on("data", (chunk) => {
@@ -3774,7 +3856,7 @@ async function readBody(req) {
3774
3856
  }
3775
3857
  chunks.push(chunk);
3776
3858
  });
3777
- req.on("end", () => resolve2(Buffer.concat(chunks).toString("utf-8")));
3859
+ req.on("end", () => resolve3(Buffer.concat(chunks).toString("utf-8")));
3778
3860
  req.on("error", reject);
3779
3861
  });
3780
3862
  }
@@ -3783,7 +3865,13 @@ async function parseJsonBody(req) {
3783
3865
  return JSON.parse(raw);
3784
3866
  }
3785
3867
  async function serveStatic(staticDir, pathname, res) {
3786
- let filePath = join2(staticDir, pathname === "/" ? "index.html" : pathname);
3868
+ const decodedPath = decodeURIComponent(pathname);
3869
+ let filePath = join2(staticDir, decodedPath === "/" ? "index.html" : decodedPath);
3870
+ const resolvedPath = resolve2(filePath);
3871
+ const resolvedStaticDir = resolve2(staticDir);
3872
+ if (!resolvedPath.startsWith(resolvedStaticDir + (resolvedStaticDir.endsWith("/") || resolvedStaticDir.endsWith("\\") ? "" : process.platform === "win32" ? "\\" : "/"))) {
3873
+ return false;
3874
+ }
3787
3875
  if (!extname(filePath)) {
3788
3876
  filePath += ".html";
3789
3877
  }
@@ -3871,7 +3959,7 @@ function startServer(options = {}) {
3871
3959
  const projectRoot = options.projectRoot ?? process.cwd();
3872
3960
  const server = createServer((req, res) => {
3873
3961
  handleRequest(req, res, staticDir, projectRoot).catch((err) => {
3874
- console.error("[flow2code] Internal error:", err);
3962
+ logger.error("Internal error:", err);
3875
3963
  res.writeHead(500, { "Content-Type": "text/plain" });
3876
3964
  res.end("Internal Server Error");
3877
3965
  });
@@ -3882,20 +3970,20 @@ function startServer(options = {}) {
3882
3970
  if (options.onReady) {
3883
3971
  options.onReady(url);
3884
3972
  } else {
3885
- console.log(`
3886
- \u{1F680} Flow2Code Dev Server`);
3887
- console.log(` \u251C\u2500 Local: ${url}`);
3888
- console.log(` \u251C\u2500 API: ${url}/api/compile`);
3889
- console.log(` \u251C\u2500 Static: ${staticDir}`);
3890
- console.log(` \u2514\u2500 Project: ${projectRoot}`);
3973
+ logger.blank();
3974
+ logger.info("Flow2Code Dev Server");
3975
+ logger.kv("Local:", url);
3976
+ logger.kv("API:", `${url}/api/compile`);
3977
+ logger.kv("Static:", staticDir);
3978
+ logger.kvLast("Project:", projectRoot);
3891
3979
  if (!hasUI) {
3892
- console.log();
3893
- console.log(` \u26A0\uFE0F UI files not found (out/index.html missing).`);
3894
- console.log(` The API endpoints still work, but the visual editor won't load.`);
3895
- console.log(` To fix: run "pnpm build:ui" in the flow2code source directory,`);
3896
- console.log(` or reinstall from npm: npm i @timo9378/flow2code@latest`);
3980
+ logger.blank();
3981
+ logger.warn("UI files not found (out/index.html missing).");
3982
+ logger.raw(" The API endpoints still work, but the visual editor won't load.");
3983
+ logger.raw(' To fix: run "pnpm build:ui" in the flow2code source directory,');
3984
+ logger.raw(" or reinstall from npm: npm i @timo9378/flow2code@latest");
3897
3985
  }
3898
- console.log();
3986
+ logger.blank();
3899
3987
  }
3900
3988
  });
3901
3989
  return server;
package/out/404.html CHANGED
@@ -1 +1 @@
1
- <!DOCTYPE html><!--gs3QpnA696kN6tOSlwt6o--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/c8a26302d935bf6e.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/b6e8711267bccbbd.js"/><script src="/_next/static/chunks/fbca595129527827.js" async=""></script><script src="/_next/static/chunks/ab8888d4b78b94be.js" async=""></script><script src="/_next/static/chunks/turbopack-576234c945ffdc44.js" async=""></script><script src="/_next/static/chunks/acf223168ac429f7.js" async=""></script><script src="/_next/static/chunks/b163b5d7cccbcf42.js" async=""></script><script src="/_next/static/chunks/6b84376656bd9887.js" async=""></script><script src="/_next/static/chunks/b112c2f519e4b429.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Flow2Code | Visual AST Compiler</title><meta name="description" content="Visual backend logic generator: compile canvas nodes directly into native TypeScript code"/><link rel="manifest" href="/site.webmanifest"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="antialiased overflow-hidden"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/b6e8711267bccbbd.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[46798,[\"/_next/static/chunks/acf223168ac429f7.js\"],\"TooltipProvider\"]\n3:I[95731,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"default\"]\n4:I[58298,[\"/_next/static/chunks/acf223168ac429f7.js\",\"/_next/static/chunks/b112c2f519e4b429.js\"],\"default\"]\n5:I[32294,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"default\"]\n6:I[5806,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\n9:I[5806,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"ViewportBoundary\"]\nb:I[5806,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"MetadataBoundary\"]\nd:I[63491,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"default\"]\n:HL[\"/_next/static/chunks/c8a26302d935bf6e.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"gs3QpnA696kN6tOSlwt6o\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/c8a26302d935bf6e.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/acf223168ac429f7.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"antialiased overflow-hidden\",\"children\":[\"$\",\"$L2\",null,{\"delayDuration\":200,\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$4\",\"errorStyles\":[],\"errorScripts\":[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/b112c2f519e4b429.js\",\"async\":true}]],\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L9\",null,{\"children\":\"$La\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lb\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lc\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$d\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"e:I[22192,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"IconMark\"]\n8:null\nc:[[\"$\",\"title\",\"0\",{\"children\":\"Flow2Code | Visual AST Compiler\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Visual backend logic generator: compile canvas nodes directly into native TypeScript code\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/site.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$Le\",\"7\",{}]]\n"])</script></body></html>
1
+ <!DOCTYPE html><!--qqgjMH_XFks_bLx9gn_yB--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/83ab8820627f8bfe.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/b6e8711267bccbbd.js"/><script src="/_next/static/chunks/fbca595129527827.js" async=""></script><script src="/_next/static/chunks/ab8888d4b78b94be.js" async=""></script><script src="/_next/static/chunks/turbopack-576234c945ffdc44.js" async=""></script><script src="/_next/static/chunks/acf223168ac429f7.js" async=""></script><script src="/_next/static/chunks/b163b5d7cccbcf42.js" async=""></script><script src="/_next/static/chunks/6b84376656bd9887.js" async=""></script><script src="/_next/static/chunks/b112c2f519e4b429.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Flow2Code | Visual AST Compiler</title><meta name="description" content="Visual backend logic generator: compile canvas nodes directly into native TypeScript code"/><link rel="manifest" href="/site.webmanifest"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="antialiased overflow-hidden"><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/b6e8711267bccbbd.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[46798,[\"/_next/static/chunks/acf223168ac429f7.js\"],\"TooltipProvider\"]\n3:I[95731,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"default\"]\n4:I[58298,[\"/_next/static/chunks/acf223168ac429f7.js\",\"/_next/static/chunks/b112c2f519e4b429.js\"],\"default\"]\n5:I[32294,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"default\"]\n6:I[5806,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\n9:I[5806,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"ViewportBoundary\"]\nb:I[5806,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"MetadataBoundary\"]\nd:I[63491,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"default\"]\n:HL[\"/_next/static/chunks/83ab8820627f8bfe.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"qqgjMH_XFks-bLx9gn_yB\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/83ab8820627f8bfe.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/acf223168ac429f7.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"antialiased overflow-hidden\",\"children\":[\"$\",\"$L2\",null,{\"delayDuration\":200,\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$4\",\"errorStyles\":[],\"errorScripts\":[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/b112c2f519e4b429.js\",\"async\":true}]],\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L9\",null,{\"children\":\"$La\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lb\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lc\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$d\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"e:I[22192,[\"/_next/static/chunks/b163b5d7cccbcf42.js\",\"/_next/static/chunks/6b84376656bd9887.js\"],\"IconMark\"]\n8:null\nc:[[\"$\",\"title\",\"0\",{\"children\":\"Flow2Code | Visual AST Compiler\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Visual backend logic generator: compile canvas nodes directly into native TypeScript code\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/site.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$Le\",\"7\",{}]]\n"])</script></body></html>
@@ -1,10 +1,10 @@
1
1
  1:"$Sreact.fragment"
2
2
  2:I[55026,["/_next/static/chunks/b163b5d7cccbcf42.js","/_next/static/chunks/6b84376656bd9887.js"],"ClientPageRoot"]
3
- 3:I[52683,["/_next/static/chunks/acf223168ac429f7.js","/_next/static/chunks/5f1a9fec0e69c483.js","/_next/static/chunks/993eabba22c07d39.js"],"default"]
3
+ 3:I[52683,["/_next/static/chunks/acf223168ac429f7.js","/_next/static/chunks/5f1a9fec0e69c483.js","/_next/static/chunks/2be31674b47c1089.js"],"default"]
4
4
  6:I[5806,["/_next/static/chunks/b163b5d7cccbcf42.js","/_next/static/chunks/6b84376656bd9887.js"],"OutletBoundary"]
5
5
  7:"$Sreact.suspense"
6
6
  :HL["/_next/static/chunks/8a5bd6fe3abc8091.css","style"]
7
- 0:{"buildId":"gs3QpnA696kN6tOSlwt6o","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/8a5bd6fe3abc8091.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/5f1a9fec0e69c483.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/993eabba22c07d39.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
7
+ 0:{"buildId":"qqgjMH_XFks-bLx9gn_yB","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/8a5bd6fe3abc8091.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/5f1a9fec0e69c483.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/2be31674b47c1089.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
8
8
  4:{}
9
9
  5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
10
10
  8:null