@asterflow/fs 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  </div>
12
12
 
13
- > Generates a static route manifest from a file-based `routes/` directory and registers it on an AsterFlow app as a plugin.
13
+ > File-based routing for AsterFlow - dynamic (scan a directory at startup) or static (a pre-generated manifest, bundler-safe) - registered as a plugin.
14
14
 
15
15
  ## 📦 Installation
16
16
 
@@ -18,7 +18,19 @@
18
18
  bun install @asterflow/fs
19
19
  ```
20
20
 
21
- Register the plugin with a generated route manifest:
21
+ `fsRoutingPlugin` supports two mutually exclusive modes, picked automatically from which config key you pass:
22
+
23
+ **Dynamic** - point it at a directory, no codegen step required. Simplest for dev/unbundled runs (`bun run src/index.ts`), but the `import()` path is fully computed at runtime, so a bundler can't trace it - don't use this for a bundled/production build.
24
+
25
+ ```ts
26
+ import { AsterFlow } from 'asterflow'
27
+ import { fsRoutingPlugin } from '@asterflow/fs'
28
+
29
+ const app = new AsterFlow()
30
+ .use(fsRoutingPlugin, { path: './src/routes' })
31
+ ```
32
+
33
+ **Static** - a pre-generated manifest of literal imports, safe for bundling. Generate it once (via `asterflow generate`, `--watch`, or `generateRouteManifest` in a build script) and pass the result in:
22
34
 
23
35
  ```ts
24
36
  import { AsterFlow } from 'asterflow'
@@ -29,16 +41,19 @@ const app = new AsterFlow()
29
41
  .use(fsRoutingPlugin, { routes })
30
42
  ```
31
43
 
44
+ Passing both `routes` and `path` is ambiguous - the plugin logs a warning and uses `path`.
45
+
32
46
  ### ✨ Features
33
47
 
34
- - **Static manifest, not runtime scanning**: `generateRouteManifest` walks a routes directory once and writes a file with one literal `import` per route plus a default-exported array - a bundler can follow these imports, unlike the old `await import(dynamicPath)` approach.
35
- - **File-to-URL conventions**: `index.ts` becomes `/`, `users/index.ts` becomes `/users`, and a `$`-prefixed segment like `$id.ts` becomes a `:id` param.
36
- - **Auto path assignment**: in the generated manifest, any route whose `default export` has no explicit `path` gets one assigned from its file location.
37
- - **Safe registration**: `fsRoutingPlugin` registers every entry in `routes` with `instance.controller(route)` on `beforeInitialize`, and skips (with a warning) any entry that isn't a `Method`/`Router` instance instead of throwing.
48
+ - **Two loading modes, one plugin**: `path` scans and `import()`s the directory at `beforeInitialize` (via `loadRoutesFromDir`) - no manifest file needed. `routes` takes a pre-generated array instead, for when the app gets bundled.
49
+ - **Static manifest generation**: `generateRouteManifest` walks a routes directory once and writes a file with one literal `import` per route plus a default-exported array, so a bundler can follow it - unlike a fully-dynamic `import(path)`, which bundlers can't resolve at all.
50
+ - **File-to-URL conventions** (both modes): `index.ts` becomes `/`, `users/index.ts` becomes `/users`, and a `$`-prefixed segment like `$id.ts` becomes a `:id` param.
51
+ - **Auto path assignment**: any route whose `default export` has no explicit `path` gets one assigned from its file location.
52
+ - **Safe registration**: `fsRoutingPlugin` registers every resolved route with `instance.controller(route)` on `beforeInitialize`, and skips (with a warning) any entry that isn't a `Method`/`Router` instance instead of throwing.
38
53
 
39
54
  ## ❓ How to Use
40
55
 
41
- Generate the manifest ahead of time, usually via the `asterflow generate` CLI command, or by calling the generator directly from a build script:
56
+ For a static manifest, generate it ahead of time, usually via the `asterflow generate` CLI command, or by calling the generator directly from a build script:
42
57
 
43
58
  ```ts
44
59
  import { generateRouteManifest } from '@asterflow/fs'
@@ -49,7 +64,7 @@ await generateRouteManifest({
49
64
  })
50
65
  ```
51
66
 
52
- Route files just export a `Method` or `Router` - the `path` is filled in by the generator from the file's location, so `src/routes/users/$id.ts` becomes `/users/:id`:
67
+ Route files just export a `Method` or `Router` - the `path` is filled in from the file's location (whichever mode you use), so `src/routes/users/$id.ts` becomes `/users/:id`:
53
68
 
54
69
  ```ts
55
70
  // src/routes/users/$id.ts
@@ -1,107 +1,130 @@
1
1
  "use strict";
2
- var f = Object.defineProperty;
3
- var T = Object.getOwnPropertyDescriptor;
4
- var P = Object.getOwnPropertyNames;
5
- var S = Object.prototype.hasOwnProperty;
6
- var O = (e, r) => {
7
- for (var s in r)
8
- f(e, s, { get: r[s], enumerable: !0 });
9
- }, I = (e, r, s, t) => {
10
- if (r && typeof r == "object" || typeof r == "function")
11
- for (let o of P(r))
12
- !S.call(e, o) && o !== s && f(e, o, { get: () => r[o], enumerable: !(t = T(r, o)) || t.enumerable });
13
- return e;
2
+ var h = Object.defineProperty;
3
+ var I = Object.getOwnPropertyDescriptor;
4
+ var N = Object.getOwnPropertyNames;
5
+ var U = Object.prototype.hasOwnProperty;
6
+ var M = (t, e) => {
7
+ for (var r in e)
8
+ h(t, r, { get: e[r], enumerable: !0 });
9
+ }, W = (t, e, r, o) => {
10
+ if (e && typeof e == "object" || typeof e == "function")
11
+ for (let s of N(e))
12
+ !U.call(t, s) && s !== r && h(t, s, { get: () => e[s], enumerable: !(o = I(e, s)) || o.enumerable });
13
+ return t;
14
14
  };
15
- var M = (e) => I(f({}, "__esModule", { value: !0 }), e);
15
+ var _ = (t) => W(h({}, "__esModule", { value: !0 }), t);
16
16
  // plugins/fs/src/index.ts
17
- var _ = {};
18
- O(_, {
19
- default: () => D,
20
- fsRoutingPlugin: () => F,
21
- generateRouteManifest: () => U,
22
- getFilesRecursively: () => c,
23
- transformPathToUrl: () => m
17
+ var C = {};
18
+ M(C, {
19
+ default: () => X,
20
+ fsRoutingPlugin: () => T,
21
+ generateRouteManifest: () => L,
22
+ getFilesRecursively: () => a,
23
+ loadRoutesFromDir: () => y,
24
+ transformPathToUrl: () => p
24
25
  });
25
- module.exports = M(_);
26
- var $ = require("@asterflow/plugin"), u = require("@asterflow/router");
26
+ module.exports = _(C);
27
+ var b = require("@asterflow/plugin"), d = require("@asterflow/router");
27
28
  // plugins/fs/package.json
28
- var y = "2.0.1";
29
+ var R = "2.1.0";
30
+ // plugins/fs/src/utils/loader.ts
31
+ var j = require("path"), v = require("url");
32
+ // plugins/fs/src/utils/constants.ts
33
+ var f = new Set([".ts", ".tsx", ".js", ".jsx"]);
34
+ // plugins/fs/src/utils/format.ts
35
+ var F = require("path");
36
+ function p(t, e) {
37
+ let o = (0, F.relative)(e, t).replace(/\.(ts|js)$/, "");
38
+ return o.endsWith("/index") ? o = o.slice(0, -6) : o === "index" && (o = ""), o = o.replace(/\$/g, ":"), `/${o}`;
39
+ }
40
+ // plugins/fs/src/utils/glob.ts
41
+ var A = require("fs/promises"), E = require("path");
42
+ async function a(t) {
43
+ let e = await (0, A.readdir)(t, { withFileTypes: !0 });
44
+ return (await Promise.all(
45
+ e.map(async (o) => {
46
+ let s = (0, E.join)(t, o.name);
47
+ return o.isDirectory() ? a(s) : s;
48
+ })
49
+ )).flat();
50
+ }
51
+ // plugins/fs/src/utils/loader.ts
52
+ async function y(t) {
53
+ let r = (await a(t)).filter((s) => f.has((0, j.extname)(s)) && !s.endsWith(".d.ts")).sort(), o = [];
54
+ for (let s of r) {
55
+ let n = (await import((0, v.pathToFileURL)(s).href)).default;
56
+ n != null && (n.path || (n.path = p(s, t)), o.push(n));
57
+ }
58
+ return o;
59
+ }
29
60
  // plugins/fs/src/utils/log.ts
30
- var l = {
61
+ var c = {
31
62
  reset: "\x1B[0m",
32
63
  red: "\x1B[31m",
33
64
  yellow: "\x1B[33m",
34
65
  cyan: "\x1B[36m"
35
66
  };
36
- function w(e, r) {
37
- console.warn(`${l.yellow}%s %s${l.reset}`, "[AsterFlow]", e), console.group();
38
- for (let [s, t] of Object.entries(r))
39
- console.log(`${l.cyan}%s:${l.reset} %s`, s, t);
67
+ function w(t, e) {
68
+ console.warn(`${c.yellow}%s %s${c.reset}`, "[AsterFlow]", t), console.group();
69
+ for (let [r, o] of Object.entries(e))
70
+ console.log(`${c.cyan}%s:${c.reset} %s`, r, o);
40
71
  console.groupEnd(), console.log();
41
72
  }
42
73
  // plugins/fs/src/utils/codegen.ts
43
- var p = require("fs/promises"), i = require("path");
44
- // plugins/fs/src/utils/format.ts
45
- var h = require("path");
46
- function m(e, r) {
47
- let t = (0, h.relative)(r, e).replace(/\.(ts|js)$/, "");
48
- return t.endsWith("/index") ? t = t.slice(0, -6) : t === "index" && (t = ""), t = t.replace(/\$/g, ":"), `/${t}`;
49
- }
50
- // plugins/fs/src/utils/glob.ts
51
- var R = require("fs/promises"), j = require("path");
52
- async function c(e) {
53
- let r = await (0, R.readdir)(e, { withFileTypes: !0 });
54
- return (await Promise.all(
55
- r.map(async (t) => {
56
- let o = (0, j.join)(e, t.name);
57
- return t.isDirectory() ? c(o) : o;
58
- })
59
- )).flat();
60
- }
61
- // plugins/fs/src/utils/codegen.ts
62
- var N = new Set([".ts", ".tsx", ".js", ".jsx"]);
63
- async function U({ routesDir: e, outFile: r }) {
64
- let t = (await c(e)).filter((n) => N.has((0, i.extname)(n)) && !n.endsWith(".d.ts")).sort(), o = (0, i.dirname)(r), g = [], d = [], x = [];
65
- t.forEach((n, v) => {
66
- let a = `Route${v}`, E = A((0, i.relative)(o, n)), k = m(n, e);
67
- g.push(`import ${a} from '${E}'`), d.push(`if (!${a}.path) ${a}.path = ${JSON.stringify(k)}`), x.push(a);
74
+ var m = require("fs/promises"), i = require("path");
75
+ async function L({ routesDir: t, outFile: e }) {
76
+ let o = (await a(t)).filter((l) => f.has((0, i.extname)(l)) && !l.endsWith(".d.ts")).sort(), s = (0, i.dirname)(e), g = [], n = [], x = [];
77
+ o.forEach((l, k) => {
78
+ let u = `Route${k}`, O = $((0, i.relative)(s, l)), P = p(l, t);
79
+ g.push(`import ${u} from '${O}'`), n.push(`if (!${u}.path) ${u}.path = ${JSON.stringify(P)}`), x.push(u);
68
80
  });
69
- let b = [
81
+ let S = [
70
82
  "// AUTO-GENERATED by `asterflow generate` - do not edit directly.",
71
- `// Source directory: ${A((0, i.relative)(o, e))}`,
83
+ `// Source directory: ${$((0, i.relative)(s, t))}`,
72
84
  ...g,
73
85
  "",
74
- ...d,
86
+ ...n,
75
87
  "",
76
88
  `export default [${x.join(", ")}]`,
77
89
  ""
78
90
  ].join(`
79
91
  `);
80
- await (0, p.mkdir)(o, { recursive: !0 }), await (0, p.writeFile)(r, b);
92
+ await (0, m.mkdir)(s, { recursive: !0 }), await (0, m.writeFile)(e, S);
81
93
  }
82
- function A(e) {
83
- let s = e.replace(/\.(ts|tsx|js|jsx)$/, "").split(i.sep).join("/");
84
- return s.startsWith(".") ? s : `./${s}`;
94
+ function $(t) {
95
+ let r = t.replace(/\.(ts|tsx|js|jsx)$/, "").split(i.sep).join("/");
96
+ return r.startsWith(".") ? r : `./${r}`;
85
97
  }
86
98
  // plugins/fs/src/index.ts
87
- var F = $.Plugin.create({ name: "fs-routing" }).decorate("creator", "Ashu11-A").decorate("version", y).config({ routes: [] }).extends((e, r) => ({
88
- registerRoutes(s) {
89
- for (let t of s.routes) {
90
- if (!(t instanceof u.Method || t instanceof u.Router)) {
99
+ var T = b.Plugin.create({ name: "fs-routing" }).decorate("creator", "Ashu11-A").decorate("version", R).config({
100
+ routes: void 0,
101
+ path: void 0
102
+ }).extends((t, e) => ({
103
+ registerRoutes(r) {
104
+ for (let o of r) {
105
+ if (!(o instanceof d.Method || o instanceof d.Router)) {
91
106
  w("Route Skipped: Invalid Entry", {
92
- "Exported Type": typeof t,
93
- Reason: "An entry in the generated route manifest is not a Router/Method instance.",
94
- Solution: "Re-run `asterflow generate` - if the problem persists, check the route file's default export."
107
+ "Exported Type": typeof o,
108
+ Reason: "An entry in the route list is not a Router/Method instance.",
109
+ Solution: "Check the route file's default export - if using a static manifest, re-run `asterflow generate`."
95
110
  });
96
111
  continue;
97
112
  }
98
- e.controller(t);
113
+ t.controller(o);
99
114
  }
100
115
  }
101
- })).on("beforeInitialize", (e, r) => e.registerRoutes(r)), D = F;
116
+ })).on("beforeInitialize", async (t, e) => {
117
+ e.path && e.routes && w("Ambiguous fs-routing Config", {
118
+ Reason: "Both `routes` and `path` were provided.",
119
+ Solution: "Pass only one: `path` for dynamic (dev) loading, or `routes` for a pre-generated static manifest. `path` will be used."
120
+ });
121
+ let r = e.path ? await y(e.path) : e.routes ?? [];
122
+ t.registerRoutes(r);
123
+ }), X = T;
102
124
  0 && (module.exports = {
103
125
  fsRoutingPlugin,
104
126
  generateRouteManifest,
105
127
  getFilesRecursively,
128
+ loadRoutesFromDir,
106
129
  transformPathToUrl
107
130
  });
package/dist/mjs/index.js CHANGED
@@ -1,87 +1,110 @@
1
1
  // plugins/fs/src/index.ts
2
- import { Plugin as O } from "@asterflow/plugin";
3
- import { Method as I, Router as M } from "@asterflow/router";
2
+ import { Plugin as U } from "@asterflow/plugin";
3
+ import { Method as M, Router as W } from "@asterflow/router";
4
4
  // plugins/fs/package.json
5
- var f = "2.0.1";
6
- // plugins/fs/src/utils/log.ts
7
- var a = {
8
- reset: "\x1B[0m",
9
- red: "\x1B[31m",
10
- yellow: "\x1B[33m",
11
- cyan: "\x1B[36m"
12
- };
13
- function m(t, r) {
14
- console.warn(`${a.yellow}%s %s${a.reset}`, "[AsterFlow]", t), console.group();
15
- for (let [s, e] of Object.entries(r))
16
- console.log(`${a.cyan}%s:${a.reset} %s`, s, e);
17
- console.groupEnd(), console.log();
18
- }
19
- // plugins/fs/src/utils/codegen.ts
20
- import { mkdir as v, writeFile as E } from "fs/promises";
21
- import { dirname as k, extname as T, relative as d, sep as P } from "path";
5
+ var g = "2.1.0";
6
+ // plugins/fs/src/utils/loader.ts
7
+ import { extname as T } from "path";
8
+ import { pathToFileURL as S } from "url";
9
+ // plugins/fs/src/utils/constants.ts
10
+ var p = new Set([".ts", ".tsx", ".js", ".jsx"]);
22
11
  // plugins/fs/src/utils/format.ts
23
- import { relative as $ } from "path";
24
- function g(t, r) {
25
- let e = $(r, t).replace(/\.(ts|js)$/, "");
26
- return e.endsWith("/index") ? e = e.slice(0, -6) : e === "index" && (e = ""), e = e.replace(/\$/g, ":"), `/${e}`;
12
+ import { relative as v } from "path";
13
+ function u(e, o) {
14
+ let t = v(o, e).replace(/\.(ts|js)$/, "");
15
+ return t.endsWith("/index") ? t = t.slice(0, -6) : t === "index" && (t = ""), t = t.replace(/\$/g, ":"), `/${t}`;
27
16
  }
28
17
  // plugins/fs/src/utils/glob.ts
29
- import { readdir as F } from "fs/promises";
18
+ import { readdir as $ } from "fs/promises";
30
19
  import { join as b } from "path";
31
- async function l(t) {
32
- let r = await F(t, { withFileTypes: !0 });
20
+ async function a(e) {
21
+ let o = await $(e, { withFileTypes: !0 });
33
22
  return (await Promise.all(
34
- r.map(async (e) => {
35
- let o = b(t, e.name);
36
- return e.isDirectory() ? l(o) : o;
23
+ o.map(async (t) => {
24
+ let s = b(e, t.name);
25
+ return t.isDirectory() ? a(s) : s;
37
26
  })
38
27
  )).flat();
39
28
  }
29
+ // plugins/fs/src/utils/loader.ts
30
+ async function h(e) {
31
+ let r = (await a(e)).filter((s) => p.has(T(s)) && !s.endsWith(".d.ts")).sort(), t = [];
32
+ for (let s of r) {
33
+ let i = (await import(S(s).href)).default;
34
+ i != null && (i.path || (i.path = u(s, e)), t.push(i));
35
+ }
36
+ return t;
37
+ }
38
+ // plugins/fs/src/utils/log.ts
39
+ var f = {
40
+ reset: "\x1B[0m",
41
+ red: "\x1B[31m",
42
+ yellow: "\x1B[33m",
43
+ cyan: "\x1B[36m"
44
+ };
45
+ function m(e, o) {
46
+ console.warn(`${f.yellow}%s %s${f.reset}`, "[AsterFlow]", e), console.group();
47
+ for (let [r, t] of Object.entries(o))
48
+ console.log(`${f.cyan}%s:${f.reset} %s`, r, t);
49
+ console.groupEnd(), console.log();
50
+ }
40
51
  // plugins/fs/src/utils/codegen.ts
41
- var S = new Set([".ts", ".tsx", ".js", ".jsx"]);
42
- async function B({ routesDir: t, outFile: r }) {
43
- let e = (await l(t)).filter((i) => S.has(T(i)) && !i.endsWith(".d.ts")).sort(), o = k(r), c = [], p = [], u = [];
44
- e.forEach((i, w) => {
45
- let n = `Route${w}`, h = x(d(o, i)), R = g(i, t);
46
- c.push(`import ${n} from '${h}'`), p.push(`if (!${n}.path) ${n}.path = ${JSON.stringify(R)}`), u.push(n);
52
+ import { mkdir as k, writeFile as O } from "fs/promises";
53
+ import { dirname as P, extname as I, relative as y, sep as N } from "path";
54
+ async function rt({ routesDir: e, outFile: o }) {
55
+ let t = (await a(e)).filter((n) => p.has(I(n)) && !n.endsWith(".d.ts")).sort(), s = P(o), c = [], i = [], d = [];
56
+ t.forEach((n, R) => {
57
+ let l = `Route${R}`, F = w(y(s, n)), A = u(n, e);
58
+ c.push(`import ${l} from '${F}'`), i.push(`if (!${l}.path) ${l}.path = ${JSON.stringify(A)}`), d.push(l);
47
59
  });
48
- let y = [
60
+ let x = [
49
61
  "// AUTO-GENERATED by `asterflow generate` - do not edit directly.",
50
- `// Source directory: ${x(d(o, t))}`,
62
+ `// Source directory: ${w(y(s, e))}`,
51
63
  ...c,
52
64
  "",
53
- ...p,
65
+ ...i,
54
66
  "",
55
- `export default [${u.join(", ")}]`,
67
+ `export default [${d.join(", ")}]`,
56
68
  ""
57
69
  ].join(`
58
70
  `);
59
- await v(o, { recursive: !0 }), await E(r, y);
71
+ await k(s, { recursive: !0 }), await O(o, x);
60
72
  }
61
- function x(t) {
62
- let s = t.replace(/\.(ts|tsx|js|jsx)$/, "").split(P).join("/");
63
- return s.startsWith(".") ? s : `./${s}`;
73
+ function w(e) {
74
+ let r = e.replace(/\.(ts|tsx|js|jsx)$/, "").split(N).join("/");
75
+ return r.startsWith(".") ? r : `./${r}`;
64
76
  }
65
77
  // plugins/fs/src/index.ts
66
- var W = O.create({ name: "fs-routing" }).decorate("creator", "Ashu11-A").decorate("version", f).config({ routes: [] }).extends((t, r) => ({
67
- registerRoutes(s) {
68
- for (let e of s.routes) {
69
- if (!(e instanceof I || e instanceof M)) {
78
+ var _ = U.create({ name: "fs-routing" }).decorate("creator", "Ashu11-A").decorate("version", g).config({
79
+ routes: void 0,
80
+ path: void 0
81
+ }).extends((e, o) => ({
82
+ registerRoutes(r) {
83
+ for (let t of r) {
84
+ if (!(t instanceof M || t instanceof W)) {
70
85
  m("Route Skipped: Invalid Entry", {
71
- "Exported Type": typeof e,
72
- Reason: "An entry in the generated route manifest is not a Router/Method instance.",
73
- Solution: "Re-run `asterflow generate` - if the problem persists, check the route file's default export."
86
+ "Exported Type": typeof t,
87
+ Reason: "An entry in the route list is not a Router/Method instance.",
88
+ Solution: "Check the route file's default export - if using a static manifest, re-run `asterflow generate`."
74
89
  });
75
90
  continue;
76
91
  }
77
- t.controller(e);
92
+ e.controller(t);
78
93
  }
79
94
  }
80
- })).on("beforeInitialize", (t, r) => t.registerRoutes(r)), V = W;
95
+ })).on("beforeInitialize", async (e, o) => {
96
+ o.path && o.routes && m("Ambiguous fs-routing Config", {
97
+ Reason: "Both `routes` and `path` were provided.",
98
+ Solution: "Pass only one: `path` for dynamic (dev) loading, or `routes` for a pre-generated static manifest. `path` will be used."
99
+ });
100
+ let r = o.path ? await h(o.path) : o.routes ?? [];
101
+ e.registerRoutes(r);
102
+ }), pt = _;
81
103
  export {
82
- V as default,
83
- W as fsRoutingPlugin,
84
- B as generateRouteManifest,
85
- l as getFilesRecursively,
86
- g as transformPathToUrl
104
+ pt as default,
105
+ _ as fsRoutingPlugin,
106
+ rt as generateRouteManifest,
107
+ a as getFilesRecursively,
108
+ h as loadRoutesFromDir,
109
+ u as transformPathToUrl
87
110
  };
@@ -3,6 +3,7 @@ import { type AnyRouter } from '@asterflow/router';
3
3
  export * from './utils/codegen';
4
4
  export * from './utils/format';
5
5
  export * from './utils/glob';
6
+ export * from './utils/loader';
6
7
  export * from './types/asterflow.d';
7
8
  export declare const fsRoutingPlugin: Plugin<{
8
9
  decorate: {
@@ -10,23 +11,18 @@ export declare const fsRoutingPlugin: Plugin<{
10
11
  version: string;
11
12
  };
12
13
  config: {
13
- routes: AnyRouter[];
14
+ routes: AnyRouter[] | undefined;
15
+ path: string | undefined;
14
16
  defaultConfig: {
15
- routes: AnyRouter[];
17
+ routes: AnyRouter[] | undefined;
18
+ path: string | undefined;
16
19
  };
17
20
  };
18
21
  path: "fs-routing";
19
22
  instance: import("asterflow").AnyAsterflow;
20
23
  derive: {};
21
24
  extension: {
22
- registerRoutes: (context: {
23
- routes: AnyRouter[];
24
- defaultConfig: {
25
- routes: AnyRouter[];
26
- };
27
- creator: string;
28
- version: string;
29
- }) => void;
25
+ registerRoutes: (routes: AnyRouter[]) => void;
30
26
  };
31
27
  }>;
32
28
  export default fsRoutingPlugin;
@@ -7,9 +7,11 @@ export interface GenerateRouteManifestOptions {
7
7
  /**
8
8
  * Scans `routesDir` once and writes a manifest file at `outFile` containing a
9
9
  * static `import` per route file plus a default-exported `AnyRouter[]`. Meant
10
- * to run at build/dev time (the `asterflow generate` CLI command), not at
11
- * request time - the resulting imports are literal specifiers a bundler can
12
- * follow, unlike `fsRoutingPlugin`'s old `await import(file)` with a
13
- * fully-dynamic path, which bundlers can't statically resolve at all.
10
+ * to run at build time (the `asterflow generate` CLI command, or a bundler
11
+ * plugin) - the resulting imports are literal specifiers a bundler can
12
+ * follow, unlike `loadRoutesFromDir`'s fully-dynamic `import(file)`, which
13
+ * bundlers can't statically resolve at all. Use this for bundled/production
14
+ * builds; `loadRoutesFromDir` (passed to `fsRoutingPlugin` as `routesDir`)
15
+ * covers unbundled dev runs where no codegen step is wanted.
14
16
  */
15
17
  export declare function generateRouteManifest({ routesDir, outFile }: GenerateRouteManifestOptions): Promise<void>;
@@ -0,0 +1 @@
1
+ export declare const ROUTE_FILE_EXTENSIONS: Set<string>;
@@ -0,0 +1,10 @@
1
+ import type { AnyRouter } from '@asterflow/router';
2
+ /**
3
+ * Scans `routesDir` and `import()`s every route file at call time, assigning
4
+ * `path` from the file location when a route doesn't set one explicitly.
5
+ * Meant for unbundled dev/runtime use (no codegen step required) - the
6
+ * `import()` path is fully dynamic, so a bundler can't trace it. Bundled
7
+ * builds should use `generateRouteManifest` + a static `routes` array
8
+ * instead.
9
+ */
10
+ export declare function loadRoutesFromDir(routesDir: string): Promise<AnyRouter[]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asterflow/fs",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "Generates a static route manifest from a file-based routes/ directory and registers it on an AsterFlow app as a plugin.",
5
5
  "keywords": [
6
6
  "asterflow",
@@ -34,11 +34,11 @@
34
34
  "node": ">=20"
35
35
  },
36
36
  "dependencies": {
37
- "@asterflow/plugin": "^2.0.1",
38
- "@asterflow/router": "^2.0.1",
37
+ "@asterflow/plugin": "^2.1.0",
38
+ "@asterflow/router": "^2.1.0",
39
39
  "@asterflow/url-parser": "^4.1.1"
40
40
  },
41
41
  "devDependencies": {
42
- "asterflow": "^2.0.1"
42
+ "asterflow": "^2.1.0"
43
43
  }
44
44
  }