Skip to content

Commit 4faac77

Browse files
committed
0.3.2
1 parent 398cb65 commit 4faac77

3 files changed

Lines changed: 109 additions & 3 deletions

File tree

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@orgsoft/dsbuild",
3-
"version": "0.3.1",
3+
"version": "0.3.2",
44
"exports": "./mod.ts",
55
"compilerOptions": {
66
"lib": ["dom", "dom.iterable", "dom.asynciterable", "esnext", "deno.ns"],

plugin-main.ts

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { exists } from "jsr:@std/fs@^1";
2-
import { dirname, esbuild, parseJsonc } from "./deps.ts";
2+
import { dirname, esbuild, isAbsolute, parseJsonc } from "./deps.ts";
33

44
import {
55
denoPlugin,
@@ -10,7 +10,14 @@ import {
1010
resolve,
1111
} from "./deps.ts";
1212
import { serve, setServeDir } from "./serve.ts";
13-
import { DEFAULT_SERVE_DIR, IS_DEV, omitKeys } from "./stuff.ts";
13+
import {
14+
DEFAULT_SERVE_DIR,
15+
DenoTempFile,
16+
IS_DEV,
17+
omitKeys,
18+
REACT_STATIC_TS_CONFIG,
19+
REACT_STATIC_TS_CONFIG_DEV,
20+
} from "./stuff.ts";
1421

1522
/**
1623
* Options for configuring the build process
@@ -79,6 +86,71 @@ export type BuildOptions = {
7986

8087
let isFirstBuild = true;
8188

89+
/**
90+
* Configuration resource for managing TypeScript/JSX config conformance
91+
*/
92+
type ConformedConfig = {
93+
readonly path: string | undefined;
94+
[Symbol.dispose](): void;
95+
};
96+
97+
/**
98+
* Creates a conformed config with automatic resource cleanup
99+
* @param options - Config options
100+
* @returns Resource-managed config object
101+
*/
102+
async function withConformedConfig({
103+
configPath,
104+
inFiles,
105+
isDev
106+
}: {
107+
configPath?: string;
108+
inFiles?: string[];
109+
isDev: boolean;
110+
}): Promise<ConformedConfig> {
111+
// Check if input files contain JSX/TSX
112+
const isJsx = inFiles?.find((file) =>
113+
file.endsWith(".jsx") || file.endsWith(".tsx")
114+
);
115+
116+
const finalConfig = configPath
117+
? parseJsonc(await Deno.readTextFile(configPath)) as Record<string, any>
118+
: isJsx
119+
? isDev ? REACT_STATIC_TS_CONFIG_DEV : REACT_STATIC_TS_CONFIG
120+
: undefined;
121+
122+
// Adjust JSX compiler options based on dev mode
123+
if (finalConfig && "compilerOptions" in finalConfig) {
124+
if (!isDev && finalConfig["compilerOptions"]?.["jsx"] === "react-jsxdev") {
125+
finalConfig["compilerOptions"]["jsx"] = "react-jsx";
126+
}
127+
if (isDev && finalConfig["compilerOptions"]?.["jsx"] === "react-jsx") {
128+
finalConfig["compilerOptions"]["jsx"] = "react-jsxdev";
129+
}
130+
}
131+
132+
if (finalConfig && configPath && "importMap" in finalConfig) {
133+
// Convert to absolute path if not already
134+
if (finalConfig["importMap"] && !isAbsolute(finalConfig["importMap"])) {
135+
finalConfig["importMap"] = resolve(dirname(configPath), finalConfig["importMap"] as string);
136+
}
137+
}
138+
139+
140+
const tmpFile = finalConfig
141+
? new DenoTempFile(JSON.stringify(finalConfig))
142+
: undefined;
143+
144+
const finalConfigPath = tmpFile ? tmpFile.getPath() : configPath;
145+
146+
return {
147+
path: finalConfigPath,
148+
[Symbol.dispose]() {
149+
tmpFile?.[Symbol.dispose]();
150+
}
151+
};
152+
}
153+
82154
/**
83155
* Builds a project using esbuild
84156
* @param options - Build options
@@ -136,6 +208,15 @@ export const build = async (options: BuildOptions): Promise<void> => {
136208
}
137209
}
138210

211+
// Conform config json to match needed JSX config
212+
using config = await withConformedConfig({
213+
configPath: finalConfigPath,
214+
inFiles: inFiles,
215+
isDev: IS_DEV
216+
});
217+
218+
finalConfigPath = config.path;
219+
139220
const opts: esbuild.BuildOptions = {
140221
plugins: [
141222
denoPlugin({

stuff.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,29 @@ export function omitKeys<T, TKey extends keyof T>(
6565
delete result[key];
6666
}
6767
return result;
68+
}
69+
70+
/**
71+
* A temporary file that is automatically deleted when the object is disposed.
72+
*/
73+
export class DenoTempFile {
74+
private path: string;
75+
private disposed = false;
76+
77+
[Symbol.dispose]() {
78+
if (this.disposed) {
79+
return;
80+
}
81+
this.disposed = true;
82+
return Deno.remove(this.path);
83+
}
84+
85+
constructor(text: string) {
86+
this.path = Deno.makeTempFileSync();
87+
Deno.writeTextFileSync(this.path, text);
88+
}
89+
90+
getPath() {
91+
return this.path;
92+
}
6893
}

0 commit comments

Comments
 (0)