@jk2908/solas 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +2 -0
  3. package/dist/cli.js +77 -83
  4. package/dist/error-boundary.d.ts +1 -1
  5. package/dist/error-boundary.js +1 -1
  6. package/dist/index.d.ts +3 -3
  7. package/dist/index.js +10 -14
  8. package/dist/internal/build.d.ts +1 -1
  9. package/dist/internal/build.js +4 -4
  10. package/dist/internal/codegen/config.d.ts +1 -1
  11. package/dist/internal/codegen/config.js +20 -11
  12. package/dist/internal/codegen/environments.js +25 -21
  13. package/dist/internal/codegen/manifest.d.ts +1 -1
  14. package/dist/internal/codegen/manifest.js +7 -8
  15. package/dist/internal/codegen/maps.d.ts +1 -1
  16. package/dist/internal/codegen/maps.js +35 -28
  17. package/dist/internal/codegen/utils.d.ts +30 -0
  18. package/dist/internal/codegen/utils.js +165 -1
  19. package/dist/internal/env/browser.js +20 -16
  20. package/dist/internal/env/request-context.d.ts +2 -2
  21. package/dist/internal/env/request-context.js +1 -1
  22. package/dist/internal/env/rsc.d.ts +8 -22
  23. package/dist/internal/env/rsc.js +38 -117
  24. package/dist/internal/env/ssr.js +9 -9
  25. package/dist/internal/env/utils.js +2 -2
  26. package/dist/internal/metadata.d.ts +2 -2
  27. package/dist/internal/metadata.js +18 -6
  28. package/dist/internal/navigation/http-exception-boundary.d.ts +2 -2
  29. package/dist/internal/navigation/http-exception-boundary.js +1 -1
  30. package/dist/internal/navigation/link.js +1 -1
  31. package/dist/internal/navigation/redirect-boundary.d.ts +1 -1
  32. package/dist/internal/navigation/redirect-boundary.js +1 -1
  33. package/dist/internal/navigation/redirect.js +1 -1
  34. package/dist/internal/navigation/use-search-params.d.ts +11 -1
  35. package/dist/internal/navigation/use-search-params.js +24 -3
  36. package/dist/internal/prerender.d.ts +10 -1
  37. package/dist/internal/prerender.js +55 -5
  38. package/dist/internal/render/head.d.ts +4 -1
  39. package/dist/internal/render/head.js +37 -18
  40. package/dist/internal/render/tree.d.ts +1 -1
  41. package/dist/internal/render/tree.js +3 -3
  42. package/dist/internal/router/create-router.d.ts +2 -2
  43. package/dist/internal/router/create-router.js +1 -1
  44. package/dist/internal/router/prefetcher.d.ts +1 -1
  45. package/dist/internal/router/prefetcher.js +8 -3
  46. package/dist/internal/router/resolver.d.ts +29 -29
  47. package/dist/internal/router/resolver.js +4 -4
  48. package/dist/internal/router/router-context.d.ts +4 -0
  49. package/dist/internal/router/router-context.js +1 -0
  50. package/dist/internal/router/router-provider.d.ts +6 -2
  51. package/dist/internal/router/router-provider.js +38 -22
  52. package/dist/internal/router/router.d.ts +1 -1
  53. package/dist/internal/router/router.js +4 -4
  54. package/dist/internal/router/use-router.d.ts +5 -1
  55. package/dist/internal/router/use-router.js +1 -1
  56. package/dist/internal/router/utils.d.ts +1 -1
  57. package/dist/internal/server/actions.d.ts +30 -0
  58. package/dist/internal/server/actions.js +107 -0
  59. package/dist/internal/server/cookies.d.ts +1 -1
  60. package/dist/internal/server/cookies.js +3 -3
  61. package/dist/internal/server/dynamic.js +2 -2
  62. package/dist/internal/server/headers.js +2 -2
  63. package/dist/internal/server/url.js +14 -3
  64. package/dist/internal/ui/defaults/error.d.ts +1 -1
  65. package/dist/internal/ui/error-boundary.d.ts +1 -1
  66. package/dist/internal/ui/error-boundary.js +1 -1
  67. package/dist/navigation.d.ts +6 -6
  68. package/dist/navigation.js +6 -6
  69. package/dist/prerender.d.ts +1 -1
  70. package/dist/prerender.js +1 -1
  71. package/dist/router.d.ts +4 -4
  72. package/dist/router.js +4 -4
  73. package/dist/server.d.ts +4 -4
  74. package/dist/server.js +4 -4
  75. package/dist/solas.d.ts +1 -1
  76. package/dist/solas.js +1 -0
  77. package/dist/types.d.ts +6 -6
  78. package/dist/types.js +1 -1
  79. package/dist/utils/context.js +1 -1
  80. package/dist/utils/logger.js +2 -2
  81. package/package.json +3 -1
  82. package/dist/utils/format.d.ts +0 -6
  83. package/dist/utils/format.js +0 -72
@@ -1,5 +1,9 @@
1
1
  export declare function useRouter(): {
2
- go: (to: string, opts?: import("./router-context").Navigation.GoOptions | undefined) => Promise<string>;
2
+ go: (to: string, opts?: import("./router-context.js").Navigation.GoOptions | undefined) => Promise<string>;
3
3
  prefetch: (path: string) => void;
4
4
  isNavigating: boolean;
5
+ url: {
6
+ pathname?: string | undefined;
7
+ search?: string | undefined;
8
+ };
5
9
  };
@@ -1,5 +1,5 @@
1
1
  import { use } from 'react';
2
- import { RouterContext } from './router-context';
2
+ import { RouterContext } from './router-context.js';
3
3
  export function useRouter() {
4
4
  return use(RouterContext);
5
5
  }
@@ -1,4 +1,4 @@
1
- import type { Route } from '../../types';
1
+ import type { Route } from '../../types.js';
2
2
  export type PathPattern = {
3
3
  path: string;
4
4
  wildcardNames: Set<string>;
@@ -0,0 +1,30 @@
1
+ import { ReactFormState } from 'react-dom/client';
2
+ import { SolasRequest } from '../../types.js';
3
+ /**
4
+ * Check if a request is an action request and reuse parsed FormData
5
+ * when multipart action detection already had to inspect the body
6
+ */
7
+ export declare function maybeAction(req: Request): Promise<{
8
+ action: boolean;
9
+ formData: null;
10
+ } | {
11
+ action: boolean;
12
+ formData: FormData;
13
+ }>;
14
+ /**
15
+ * Process an incoming action request, either from ReactClient.setServerCallback or a <form action={...}> submission
16
+ * @returns an object containing either the return value of the action or the form state, depending on the type
17
+ * of action request
18
+ */
19
+ export declare function processActionRequest(req: SolasRequest): Promise<{
20
+ returnValue: {
21
+ ok: boolean;
22
+ data: unknown;
23
+ } | undefined;
24
+ formState: ReactFormState | undefined;
25
+ temporaryReferences: unknown;
26
+ }>;
27
+ /**
28
+ * Check whether an action request came from the same origin as the target app
29
+ */
30
+ export declare function isTrustedActionRequest(req: Request): boolean;
@@ -0,0 +1,107 @@
1
+ import { createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction, } from '@vitejs/plugin-rsc/rsc';
2
+ import { Solas } from '../../solas.js';
3
+ import { HttpException } from '../navigation/http-exception.js';
4
+ /**
5
+ * Check if a request is an action request and reuse parsed FormData
6
+ * when multipart action detection already had to inspect the body
7
+ */
8
+ export async function maybeAction(req) {
9
+ if (req.method !== 'POST')
10
+ return { action: false, formData: null };
11
+ if (req.headers.has('x-rsc-action-id'))
12
+ return { action: true, formData: null };
13
+ const contentType = req.headers.get('content-type') ?? '';
14
+ if (!contentType.startsWith('multipart/form-data')) {
15
+ return { action: false, formData: null };
16
+ }
17
+ try {
18
+ const formData = await req.clone().formData();
19
+ for (const key of formData.keys()) {
20
+ if (key === '$ACTION_KEY' ||
21
+ key.startsWith('$ACTION_') ||
22
+ key.startsWith('$ACTION_REF_')) {
23
+ return { action: true, formData };
24
+ }
25
+ }
26
+ }
27
+ catch {
28
+ return { action: false, formData: null };
29
+ }
30
+ return { action: false, formData: null };
31
+ }
32
+ /**
33
+ * Process an incoming action request, either from ReactClient.setServerCallback or a <form action={...}> submission
34
+ * @returns an object containing either the return value of the action or the form state, depending on the type
35
+ * of action request
36
+ */
37
+ export async function processActionRequest(req) {
38
+ let returnValue;
39
+ let formState;
40
+ let temporaryReferences;
41
+ // reject cross-site action posts before any body decoding or action loading
42
+ if (!isTrustedActionRequest(req)) {
43
+ throw new HttpException(403, 'Cross-site action requests are forbidden');
44
+ }
45
+ const id = req.headers.get('x-rsc-action-id');
46
+ if (id) {
47
+ // x-rsc-action-id header exists when action is
48
+ // called via ReactClient.setServerCallback
49
+ const body = req.headers.get('content-type')?.startsWith('multipart/form-data')
50
+ ? await req.formData()
51
+ : await req.text();
52
+ temporaryReferences = createTemporaryReferenceSet();
53
+ const args = await decodeReply(body, {
54
+ temporaryReferences,
55
+ });
56
+ const action = await loadServerAction(id);
57
+ try {
58
+ const data = await action.apply(null, args);
59
+ returnValue = { ok: true, data };
60
+ }
61
+ catch (err) {
62
+ returnValue = { ok: false, data: err };
63
+ }
64
+ }
65
+ else {
66
+ // otherwise server function is called via
67
+ // <form action={...}>
68
+ // we might have already parsed FormData in the router for multipart action
69
+ // detection should be attached to the SolasRequest, so we can reuse that
70
+ // to avoid parsing twice
71
+ const parsedFormData = req[Solas.Config.REQUEST_META]?.parsedFormData;
72
+ const formData = parsedFormData ?? (await req.formData());
73
+ const decodedAction = await decodeAction(formData);
74
+ const result = await decodedAction();
75
+ formState = await decodeFormState(result, formData);
76
+ }
77
+ return { returnValue, formState, temporaryReferences };
78
+ }
79
+ /**
80
+ * Reduce Origin and Referer headers to a comparable origin string
81
+ */
82
+ function toOrigin(value) {
83
+ if (!value)
84
+ return null;
85
+ try {
86
+ return new URL(value).origin;
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ /**
93
+ * Check whether an action request came from the same origin as the target app
94
+ */
95
+ export function isTrustedActionRequest(req) {
96
+ const requestOrigin = toOrigin(req.url);
97
+ if (!requestOrigin)
98
+ return false;
99
+ const origin = toOrigin(req.headers.get('origin'));
100
+ if (origin)
101
+ return origin === requestOrigin;
102
+ // some user agents omit Origin on same-origin form posts, so fall back to Referer
103
+ const referer = toOrigin(req.headers.get('referer'));
104
+ if (referer)
105
+ return referer === requestOrigin;
106
+ return false;
107
+ }
@@ -1,4 +1,4 @@
1
- import { Cookies } from '../../utils/cookies';
1
+ import { Cookies } from '../../utils/cookies.js';
2
2
  /**
3
3
  * Get the request cookies as a Cookies instance
4
4
  * @returns a read-only Cookies instance containing the request cookies
@@ -1,6 +1,6 @@
1
- import { Cookies } from '../../utils/cookies';
2
- import { RequestContext } from '../env/request-context';
3
- import { dynamic } from './dynamic';
1
+ import { Cookies } from '../../utils/cookies.js';
2
+ import { RequestContext } from '../env/request-context.js';
3
+ import { dynamic } from './dynamic.js';
4
4
  /**
5
5
  * Get the request cookies as a Cookies instance
6
6
  * @returns a read-only Cookies instance containing the request cookies
@@ -1,5 +1,5 @@
1
- import { Logger } from '../../utils/logger';
2
- import { RequestContext } from '../env/request-context';
1
+ import { Logger } from '../../utils/logger.js';
2
+ import { RequestContext } from '../env/request-context.js';
3
3
  const logger = new Logger();
4
4
  const NEVER = new Promise(() => { });
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { RequestContext } from '../env/request-context';
2
- import { dynamic } from './dynamic';
1
+ import { RequestContext } from '../env/request-context.js';
2
+ import { dynamic } from './dynamic.js';
3
3
  /**
4
4
  * Get the request headers as a read-only map
5
5
  * @returns a read-only map of request headers
@@ -1,5 +1,7 @@
1
- import { RequestContext } from '../env/request-context';
2
- import { dynamic } from './dynamic';
1
+ import { Logger } from '../../utils/logger.js';
2
+ import { RequestContext } from '../env/request-context.js';
3
+ import { dynamic } from './dynamic.js';
4
+ const logger = new Logger();
3
5
  /**
4
6
  * Get the request url as a URL instance
5
7
  * @returns a URL instance containing the request url
@@ -11,7 +13,16 @@ export function url() {
11
13
  // without corrupting the cached instance shared across the request
12
14
  if (cache.url)
13
15
  return new URL(cache.url);
14
- const parsed = new URL(req.url);
16
+ let parsed;
17
+ try {
18
+ parsed = new URL(req.url);
19
+ }
20
+ catch (err) {
21
+ // if we throw the original error here, the rest of the code gets a messy parsing error
22
+ // instead of a simple 'invalid request url' failure
23
+ logger.error(`[url] invalid request url: ${req.url}`, err);
24
+ throw new Error('Invalid request url', { cause: err });
25
+ }
15
26
  cache.url = parsed;
16
27
  return new URL(parsed);
17
28
  }
@@ -1,4 +1,4 @@
1
- import type { HttpException } from '../../navigation/http-exception';
1
+ import type { HttpException } from '../../navigation/http-exception.js';
2
2
  export default function Err({ error }: {
3
3
  error: HttpException | Error;
4
4
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { Component } from 'react';
2
- import type { BoundaryError } from '../../types';
2
+ import type { BoundaryError } from '../../types.js';
3
3
  export type Props = {
4
4
  fallback: ((error: BoundaryError, reset: () => void) => React.ReactNode) | React.ReactNode;
5
5
  onError?: (error: BoundaryError) => void;
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { Component } from 'react';
3
- import { isKnownError } from '../env/utils';
3
+ import { isKnownError } from '../env/utils.js';
4
4
  /**
5
5
  * A component that catches synchronous errors in its child component tree and displays a fallback UI
6
6
  * @param props - the props for the component
@@ -1,6 +1,6 @@
1
- export { HttpException, abort, isHttpException, } from './internal/navigation/http-exception';
2
- export { HttpExceptionBoundary } from './internal/navigation/http-exception-boundary';
3
- export { Link } from './internal/navigation/link';
4
- export { Redirect, isRedirect, redirect } from './internal/navigation/redirect';
5
- export { RedirectBoundary } from './internal/navigation/redirect-boundary';
6
- export { useSearchParams } from './internal/navigation/use-search-params';
1
+ export { HttpExceptionBoundary } from './internal/navigation/http-exception-boundary.js';
2
+ export { HttpException, abort, isHttpException, } from './internal/navigation/http-exception.js';
3
+ export { Link } from './internal/navigation/link.js';
4
+ export { RedirectBoundary } from './internal/navigation/redirect-boundary.js';
5
+ export { Redirect, isRedirect, redirect } from './internal/navigation/redirect.js';
6
+ export { useSearchParams } from './internal/navigation/use-search-params.js';
@@ -1,6 +1,6 @@
1
- export { HttpException, abort, isHttpException, } from './internal/navigation/http-exception';
2
- export { HttpExceptionBoundary } from './internal/navigation/http-exception-boundary';
3
- export { Link } from './internal/navigation/link';
4
- export { Redirect, isRedirect, redirect } from './internal/navigation/redirect';
5
- export { RedirectBoundary } from './internal/navigation/redirect-boundary';
6
- export { useSearchParams } from './internal/navigation/use-search-params';
1
+ export { HttpExceptionBoundary } from './internal/navigation/http-exception-boundary.js';
2
+ export { HttpException, abort, isHttpException, } from './internal/navigation/http-exception.js';
3
+ export { Link } from './internal/navigation/link.js';
4
+ export { RedirectBoundary } from './internal/navigation/redirect-boundary.js';
5
+ export { Redirect, isRedirect, redirect } from './internal/navigation/redirect.js';
6
+ export { useSearchParams } from './internal/navigation/use-search-params.js';
@@ -1 +1 @@
1
- export { Prerender } from './internal/prerender';
1
+ export { Prerender } from './internal/prerender.js';
package/dist/prerender.js CHANGED
@@ -1 +1 @@
1
- export { Prerender } from './internal/prerender';
1
+ export { Prerender } from './internal/prerender.js';
package/dist/router.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createRouter } from './internal/router/create-router';
2
- export { Router } from './internal/router/router';
3
- export { RouterProvider } from './internal/router/router-provider';
4
- export { useRouter } from './internal/router/use-router';
1
+ export { createRouter } from './internal/router/create-router.js';
2
+ export { Router } from './internal/router/router.js';
3
+ export { RouterProvider } from './internal/router/router-provider.js';
4
+ export { useRouter } from './internal/router/use-router.js';
package/dist/router.js CHANGED
@@ -1,4 +1,4 @@
1
- export { createRouter } from './internal/router/create-router';
2
- export { Router } from './internal/router/router';
3
- export { RouterProvider } from './internal/router/router-provider';
4
- export { useRouter } from './internal/router/use-router';
1
+ export { createRouter } from './internal/router/create-router.js';
2
+ export { Router } from './internal/router/router.js';
3
+ export { RouterProvider } from './internal/router/router-provider.js';
4
+ export { useRouter } from './internal/router/use-router.js';
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { cookies } from './internal/server/cookies';
2
- export { dynamic } from './internal/server/dynamic';
3
- export { headers } from './internal/server/headers';
4
- export { url } from './internal/server/url';
1
+ export { cookies } from './internal/server/cookies.js';
2
+ export { dynamic } from './internal/server/dynamic.js';
3
+ export { headers } from './internal/server/headers.js';
4
+ export { url } from './internal/server/url.js';
package/dist/server.js CHANGED
@@ -1,4 +1,4 @@
1
- export { cookies } from './internal/server/cookies';
2
- export { dynamic } from './internal/server/dynamic';
3
- export { headers } from './internal/server/headers';
4
- export { url } from './internal/server/url';
1
+ export { cookies } from './internal/server/cookies.js';
2
+ export { dynamic } from './internal/server/dynamic.js';
3
+ export { headers } from './internal/server/headers.js';
4
+ export { url } from './internal/server/url.js';
package/dist/solas.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { PluginConfig } from './types';
1
+ import type { PluginConfig } from './types.js';
2
2
  export declare namespace Solas {
3
3
  namespace Config {
4
4
  const NAME = "Solas";
package/dist/solas.js CHANGED
@@ -19,6 +19,7 @@ var Solas;
19
19
  Config.PRERENDER_MODES = ['full', 'ppr', false];
20
20
  Config.TRAILING_SLASH_MODES = ['always', 'never', 'ignore'];
21
21
  const CONFIG_KEYS = new Set([
22
+ 'port',
22
23
  'logger',
23
24
  'metadata',
24
25
  'precompress',
package/dist/types.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  type BunRequest = Request & {
2
2
  params?: Record<string, string | string[]>;
3
3
  };
4
- import { Solas } from './solas';
5
- import { ExportReader } from './utils/export-reader';
6
- import type { Build } from './internal/build';
7
- import type { Metadata } from './internal/metadata';
8
- import type { HttpException } from './internal/navigation/http-exception';
9
- import type { Router } from './internal/router/router';
4
+ import { Solas } from './solas.js';
5
+ import { ExportReader } from './utils/export-reader.js';
6
+ import type { Build } from './internal/build.js';
7
+ import type { Metadata } from './internal/metadata.js';
8
+ import type { HttpException } from './internal/navigation/http-exception.js';
9
+ import type { Router } from './internal/router/router.js';
10
10
  export type LogLevel = (typeof Solas.Config.LOG_LEVELS)[number];
11
11
  type PluginConfigBase = {
12
12
  port?: number;
package/dist/types.js CHANGED
@@ -1 +1 @@
1
- import { Solas } from './solas';
1
+ import { Solas } from './solas.js';
@@ -1,5 +1,5 @@
1
1
  import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { Logger } from './logger';
2
+ import { Logger } from './logger.js';
3
3
  const logger = new Logger();
4
4
  export { Context };
5
5
  var Context;
@@ -1,5 +1,5 @@
1
- import { Solas } from '../solas';
2
- import { HttpException } from '../internal/navigation/http-exception';
1
+ import { Solas } from '../solas.js';
2
+ import { HttpException } from '../internal/navigation/http-exception.js';
3
3
  const LEVELS = {
4
4
  debug: 0,
5
5
  info: 1,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jk2908/solas",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "description": "A React Server Components meta-framework powered by Vite",
5
5
  "keywords": [
6
6
  "framework",
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "files": [
26
26
  "dist",
27
+ "CHANGELOG.md",
27
28
  "README.md",
28
29
  "LICENSE"
29
30
  ],
@@ -96,6 +97,7 @@
96
97
  "@types/bun": "^1.2.22",
97
98
  "@typescript/native-preview": "^7.0.0-dev.20260224.1",
98
99
  "network-information-types": "^0.1.1",
100
+ "oxfmt": "^0.35.0",
99
101
  "typescript": "^5.9.3"
100
102
  },
101
103
  "peerDependencies": {
@@ -1,6 +0,0 @@
1
- export declare namespace Format {
2
- /**
3
- * Format a file in-place using oxfmt with our preferred code style
4
- */
5
- function run(filePath: string): Promise<void>;
6
- }
@@ -1,72 +0,0 @@
1
- import path from 'node:path';
2
- import { format } from 'oxfmt';
3
- import { Logger } from './logger';
4
- const logger = new Logger();
5
- const BASE_OPTIONS = {
6
- useTabs: true,
7
- tabWidth: 2,
8
- printWidth: 90,
9
- singleQuote: true,
10
- jsxSingleQuote: false,
11
- quoteProps: 'as-needed',
12
- trailingComma: 'all',
13
- semi: false,
14
- arrowParens: 'avoid',
15
- bracketSameLine: true,
16
- bracketSpacing: true,
17
- endOfLine: 'lf',
18
- };
19
- const SUPPORTED_EXTENSIONS = new Set([
20
- '.js',
21
- '.jsx',
22
- '.ts',
23
- '.tsx',
24
- '.mjs',
25
- '.cjs',
26
- '.mts',
27
- '.cts',
28
- '.json',
29
- '.jsonc',
30
- '.json5',
31
- '.css',
32
- '.scss',
33
- '.less',
34
- '.md',
35
- '.mdx',
36
- '.html',
37
- '.yml',
38
- '.yaml',
39
- '.toml',
40
- ]);
41
- export { Format };
42
- var Format;
43
- (function (Format) {
44
- /**
45
- * Format a file in-place using oxfmt with our preferred code style
46
- */
47
- async function run(filePath) {
48
- try {
49
- const ext = path.extname(filePath).toLowerCase();
50
- if (!SUPPORTED_EXTENSIONS.has(ext)) {
51
- logger.warn(`[format] Skipping unsupported file type: ${filePath}`);
52
- return;
53
- }
54
- const file = Bun.file(filePath);
55
- const source = await file.text();
56
- const options = ext === '.json' ? { ...BASE_OPTIONS, trailingComma: 'none' } : BASE_OPTIONS;
57
- const result = await format(filePath, source, options);
58
- if (result.errors.length > 0) {
59
- logger.warn(`[format] oxfmt failed for ${filePath}: ${result.errors[0]?.message}`);
60
- return;
61
- }
62
- if (result.code === source)
63
- return;
64
- await Bun.write(filePath, result.code);
65
- logger.info(`[format] Formatted file: ${filePath}`);
66
- }
67
- catch (err) {
68
- logger.error(`[format] Failed to format file: ${filePath}`, err);
69
- }
70
- }
71
- Format.run = run;
72
- })(Format || (Format = {}));