@farm.js/plugin 0.1.0-beta.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.
Files changed (51) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +11 -0
  3. package/dist/api/index.d.ts +42 -0
  4. package/dist/api/index.d.ts.map +1 -0
  5. package/dist/api/index.js +567 -0
  6. package/dist/context/index.d.ts +61 -0
  7. package/dist/context/index.d.ts.map +1 -0
  8. package/dist/context/index.js +75 -0
  9. package/dist/index.d.ts +43 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +49 -0
  12. package/dist/middleware/index.d.ts +97 -0
  13. package/dist/middleware/index.d.ts.map +1 -0
  14. package/dist/middleware/index.js +469 -0
  15. package/dist/observability/index.d.ts +190 -0
  16. package/dist/observability/index.d.ts.map +1 -0
  17. package/dist/observability/index.js +399 -0
  18. package/dist/rsc/build-paths.d.ts +3 -0
  19. package/dist/rsc/build-paths.d.ts.map +1 -0
  20. package/dist/rsc/build-paths.js +8 -0
  21. package/dist/rsc/entries/client.d.ts +14 -0
  22. package/dist/rsc/entries/client.d.ts.map +1 -0
  23. package/dist/rsc/entries/client.js +283 -0
  24. package/dist/rsc/entries/rsc.d.ts +13 -0
  25. package/dist/rsc/entries/rsc.d.ts.map +1 -0
  26. package/dist/rsc/entries/rsc.js +932 -0
  27. package/dist/rsc/entries/ssr.d.ts +13 -0
  28. package/dist/rsc/entries/ssr.d.ts.map +1 -0
  29. package/dist/rsc/entries/ssr.js +245 -0
  30. package/dist/rsc/index.d.ts +78 -0
  31. package/dist/rsc/index.d.ts.map +1 -0
  32. package/dist/rsc/index.js +1368 -0
  33. package/dist/rsc/nitro-build.d.ts +36 -0
  34. package/dist/rsc/nitro-build.d.ts.map +1 -0
  35. package/dist/rsc/nitro-build.js +396 -0
  36. package/dist/rsc/optimized-boundary.d.ts +20 -0
  37. package/dist/rsc/optimized-boundary.d.ts.map +1 -0
  38. package/dist/rsc/optimized-boundary.js +15 -0
  39. package/dist/rsc/server-fn-transform.d.ts +6 -0
  40. package/dist/rsc/server-fn-transform.d.ts.map +1 -0
  41. package/dist/rsc/server-fn-transform.js +152 -0
  42. package/dist/rsc/types.d.ts +123 -0
  43. package/dist/rsc/types.d.ts.map +1 -0
  44. package/dist/rsc/types.js +1 -0
  45. package/dist/rsc/vite-plugin-nitro.d.ts +33 -0
  46. package/dist/rsc/vite-plugin-nitro.d.ts.map +1 -0
  47. package/dist/rsc/vite-plugin-nitro.js +163 -0
  48. package/package.json +94 -0
  49. package/scripts/build.js +7 -0
  50. package/scripts/clean.js +6 -0
  51. package/scripts/run-nitro.mjs +18 -0
@@ -0,0 +1,61 @@
1
+ interface RequestLike {
2
+ url?: string;
3
+ headers: Record<string, string | string[] | undefined>;
4
+ }
5
+ interface PluginContextLike {
6
+ req: {
7
+ set: (key: string, value: any, options?: {
8
+ exposeToPage?: boolean;
9
+ }) => void;
10
+ get: <T = any>(key: string) => T | undefined;
11
+ };
12
+ }
13
+ interface ContextPluginLike {
14
+ name: string;
15
+ enforce?: "pre" | "post";
16
+ beforeRequest?: (req: RequestLike, res: unknown, context: PluginContextLike) => void | Promise<void>;
17
+ afterResponse?: (req: RequestLike, res: {
18
+ statusCode?: number;
19
+ } | unknown, context: PluginContextLike) => void | Promise<void>;
20
+ }
21
+ export interface ContextPluginOptions {
22
+ requestIdHeader?: string;
23
+ localeHeader?: string;
24
+ exposePathname?: boolean;
25
+ beforeRequest?: (payload: {
26
+ requestId: string;
27
+ locale: string;
28
+ pathname: string;
29
+ }) => void;
30
+ afterResponse?: (payload: {
31
+ requestId: string;
32
+ locale: string;
33
+ pathname: string;
34
+ statusCode: number;
35
+ durationMs: number;
36
+ }) => void;
37
+ }
38
+ /**
39
+ * Demo plugin that exposes request context to server page props as `props.context`.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * import { contextPlugin } from "@farm.js/plugin/context";
44
+ *
45
+ * export default defineConfig({
46
+ * plugins: [contextPlugin()],
47
+ * });
48
+ * ```
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * export default function Page(props: any) {
53
+ * const requestId = props.context?.data.get("requestId");
54
+ * const locale = props.context?.data.get("locale");
55
+ * return <div>{requestId} - {locale}</div>;
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function contextPlugin(options?: ContextPluginOptions): ContextPluginLike;
60
+ export {};
61
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;CACxD;AAED,UAAU,iBAAiB;IACzB,GAAG,EAAE;QACH,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;YAAE,YAAY,CAAC,EAAE,OAAO,CAAA;SAAE,KAAK,IAAI,CAAC;QAC7E,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC;KAC9C,CAAC;CACH;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,CACd,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,iBAAiB,KACvB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,aAAa,CAAC,EAAE,CACd,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,EACtC,OAAO,EAAE,iBAAiB,KACvB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3F,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,KAAK,IAAI,CAAC;CACZ;AAeD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,iBAAiB,CA0CnF"}
@@ -0,0 +1,75 @@
1
+ import { randomUUID } from "crypto";
2
+ function normalizeHeaderValue(value) {
3
+ if (!value)
4
+ return undefined;
5
+ if (Array.isArray(value))
6
+ return value[0];
7
+ return value;
8
+ }
9
+ function getHeader(req, name) {
10
+ const direct = normalizeHeaderValue(req.headers[name.toLowerCase()]);
11
+ if (direct)
12
+ return direct;
13
+ const fromRaw = normalizeHeaderValue(req.headers[name]);
14
+ return fromRaw;
15
+ }
16
+ /**
17
+ * Demo plugin that exposes request context to server page props as `props.context`.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { contextPlugin } from "@farm.js/plugin/context";
22
+ *
23
+ * export default defineConfig({
24
+ * plugins: [contextPlugin()],
25
+ * });
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * export default function Page(props: any) {
31
+ * const requestId = props.context?.data.get("requestId");
32
+ * const locale = props.context?.data.get("locale");
33
+ * return <div>{requestId} - {locale}</div>;
34
+ * }
35
+ * ```
36
+ */
37
+ export function contextPlugin(options = {}) {
38
+ const requestIdHeader = (options.requestIdHeader || "x-request-id").toLowerCase();
39
+ const localeHeader = (options.localeHeader || "x-locale").toLowerCase();
40
+ const exposePathname = options.exposePathname ?? true;
41
+ const beforeRequestCb = options.beforeRequest;
42
+ const afterResponseCb = options.afterResponse;
43
+ return {
44
+ name: "@farm.js/plugin-context",
45
+ enforce: "pre",
46
+ beforeRequest(req, _res, context) {
47
+ const pathname = req.url || "/";
48
+ const requestId = getHeader(req, requestIdHeader) || randomUUID();
49
+ const locale = getHeader(req, localeHeader) || "en";
50
+ context.req.set("requestId", requestId, { exposeToPage: true });
51
+ context.req.set("locale", locale, { exposeToPage: true });
52
+ if (exposePathname) {
53
+ context.req.set("pathname", pathname, { exposeToPage: true });
54
+ }
55
+ // Private value stays available only to plugin hooks.
56
+ context.req.set("internal:requestStart", Date.now());
57
+ if (beforeRequestCb) {
58
+ beforeRequestCb({ requestId, locale, pathname });
59
+ }
60
+ },
61
+ afterResponse(req, res, context) {
62
+ if (!afterResponseCb)
63
+ return;
64
+ const requestId = context.req.get("requestId") || "unknown";
65
+ const locale = context.req.get("locale") || "en";
66
+ const started = context.req.get("internal:requestStart");
67
+ const pathname = req.url || "/";
68
+ const durationMs = typeof started === "number" ? Date.now() - started : 0;
69
+ const statusCode = typeof res === "object" && res !== null && "statusCode" in res
70
+ ? Number(res.statusCode || 200)
71
+ : 200;
72
+ afterResponseCb({ requestId, locale, pathname, statusCode, durationMs });
73
+ },
74
+ };
75
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @farm.js/plugin - Official plugins for Farm.js framework
3
+ *
4
+ * This package provides official plugins that extend Farm.js functionality.
5
+ *
6
+ * Available plugins:
7
+ * - @farm.js/plugin/rsc - React Server Components support
8
+ * - @farm.js/plugin/middleware - Standalone middleware support
9
+ * - @farm.js/plugin/api - Standalone API routes support
10
+ * - @farm.js/plugin/observability - request/render/build observability lifecycle hooks
11
+ * - @farm.js/plugin/context - example request context exposure plugin
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Using RSC (includes middleware and API support)
16
+ * import { defineConfig } from '@farm.js/plugin/rsc'
17
+ *
18
+ * export default defineConfig({
19
+ * srcDir: 'src',
20
+ * experimental: {
21
+ * serverComponents: true,
22
+ * serverActions: true,
23
+ * },
24
+ * })
25
+ * ```
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // Using standalone plugins (without RSC)
30
+ * import { defineConfig } from 'vite'
31
+ * import { farmMiddleware } from '@farm.js/plugin/middleware'
32
+ * import { farmApi } from '@farm.js/plugin/api'
33
+ *
34
+ * export default defineConfig({
35
+ * plugins: [
36
+ * farmMiddleware({ srcDir: 'src', debug: true }),
37
+ * farmApi({ srcDir: 'src', debug: true }),
38
+ * ],
39
+ * })
40
+ * ```
41
+ */
42
+ export declare const version = "0.0.1";
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @farm.js/plugin - Official plugins for Farm.js framework
3
+ *
4
+ * This package provides official plugins that extend Farm.js functionality.
5
+ *
6
+ * Available plugins:
7
+ * - @farm.js/plugin/rsc - React Server Components support
8
+ * - @farm.js/plugin/middleware - Standalone middleware support
9
+ * - @farm.js/plugin/api - Standalone API routes support
10
+ * - @farm.js/plugin/observability - request/render/build observability lifecycle hooks
11
+ * - @farm.js/plugin/context - example request context exposure plugin
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Using RSC (includes middleware and API support)
16
+ * import { defineConfig } from '@farm.js/plugin/rsc'
17
+ *
18
+ * export default defineConfig({
19
+ * srcDir: 'src',
20
+ * experimental: {
21
+ * serverComponents: true,
22
+ * serverActions: true,
23
+ * },
24
+ * })
25
+ * ```
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // Using standalone plugins (without RSC)
30
+ * import { defineConfig } from 'vite'
31
+ * import { farmMiddleware } from '@farm.js/plugin/middleware'
32
+ * import { farmApi } from '@farm.js/plugin/api'
33
+ *
34
+ * export default defineConfig({
35
+ * plugins: [
36
+ * farmMiddleware({ srcDir: 'src', debug: true }),
37
+ * farmApi({ srcDir: 'src', debug: true }),
38
+ * ],
39
+ * })
40
+ * ```
41
+ */
42
+ export const version = "0.0.1";
43
+ // Note: Import plugins from their respective subpaths:
44
+ // - @farm.js/plugin/rsc
45
+ // - @farm.js/plugin/middleware
46
+ // - @farm.js/plugin/api
47
+ // - @farm.js/plugin/observability
48
+ // - @farm.js/plugin/context
49
+ // This avoids bundling unused code
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Farm.js Middleware Plugin
3
+ *
4
+ * Standalone middleware support that works with or without RSC.
5
+ * Discovers and executes middleware.ts files in the source directory.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { farmMiddleware } from '@farm.js/plugin/middleware'
10
+ *
11
+ * export default defineConfig({
12
+ * plugins: [farmMiddleware({ srcDir: 'src' })],
13
+ * })
14
+ * ```
15
+ */
16
+ import type { Plugin, ViteDevServer } from "vite";
17
+ import type { IncomingMessage, ServerResponse } from "http";
18
+ export interface FarmMiddlewareOptions {
19
+ /** Source directory containing middleware files (default: 'src') */
20
+ srcDir?: string;
21
+ /** Enable debug logging */
22
+ debug?: boolean;
23
+ }
24
+ /**
25
+ * Cookie options
26
+ */
27
+ export interface CookieOptions {
28
+ maxAge?: number;
29
+ expires?: Date;
30
+ path?: string;
31
+ domain?: string;
32
+ secure?: boolean;
33
+ httpOnly?: boolean;
34
+ sameSite?: "strict" | "lax" | "none";
35
+ }
36
+ /**
37
+ * Cookie management interface
38
+ */
39
+ export interface CookieJar {
40
+ get(name: string): string | undefined;
41
+ set(name: string, value: string, options?: CookieOptions): void;
42
+ delete(name: string): void;
43
+ getAll(): Record<string, string>;
44
+ }
45
+ /**
46
+ * Full middleware context - compatible with @farm.js/core/middleware
47
+ */
48
+ export interface MiddlewareContext {
49
+ request: IncomingMessage;
50
+ response: ServerResponse;
51
+ url: URL;
52
+ pathname: string;
53
+ searchParams: URLSearchParams;
54
+ method: string;
55
+ params: Record<string, string>;
56
+ route: string;
57
+ parent?: {
58
+ data: Map<string, any>;
59
+ headers: Record<string, string>;
60
+ };
61
+ vite: {
62
+ isDev: boolean;
63
+ hmr: boolean;
64
+ server?: ViteDevServer;
65
+ };
66
+ data: Map<string, any>;
67
+ headers: Map<string, string>;
68
+ cookies: CookieJar;
69
+ _handled: boolean;
70
+ _redirectUrl?: string;
71
+ _rewriteUrl?: string;
72
+ redirect(url: string, status?: number): void;
73
+ rewrite(url: string): void;
74
+ json(data: any, status?: number): void;
75
+ text(content: string, status?: number): void;
76
+ html(content: string, status?: number): void;
77
+ }
78
+ export type MiddlewareHandler = (ctx: MiddlewareContext, next: () => Promise<void>) => Promise<void> | void;
79
+ export interface DiscoveredMiddleware {
80
+ path: string;
81
+ filePath: string;
82
+ module: MiddlewareHandler | {
83
+ build: () => {
84
+ handlers: MiddlewareHandler[];
85
+ };
86
+ setBasePath?: (path: string) => void;
87
+ };
88
+ config?: {
89
+ matcher?: string[];
90
+ };
91
+ }
92
+ /**
93
+ * Farm.js Middleware Plugin
94
+ */
95
+ export default function farmMiddleware(options?: FarmMiddlewareOptions): Plugin;
96
+ export { farmMiddleware };
97
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"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"}