@dbx-tools/projen 0.9.51 → 0.9.54

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.
@@ -1,173 +0,0 @@
1
- import { Readable, Writable } from "node:stream";
2
-
3
- import * as promises from "./fs-promises.ts";
4
- import { pythonHost } from "./host.ts";
5
-
6
- type Callback<T = undefined> = (error: Error | null, value?: T) => void;
7
-
8
- function callback<T>(operation: Promise<T>, done: Callback<T>): void {
9
- void operation.then(
10
- (value) => done(null, value),
11
- (error) => done(error as Error),
12
- );
13
- }
14
-
15
- export function existsSync(path: string): boolean {
16
- return pythonHost().file.exists(String(path));
17
- }
18
-
19
- export function readFileSync(path: string, _encoding?: string): string {
20
- return pythonHost().file.readTextSync(String(path));
21
- }
22
-
23
- export function readdirSync(path: string, options: { withFileTypes?: boolean } = {}): unknown[] {
24
- const entries = pythonHost().file.readDirectorySync(String(path));
25
- if (!options.withFileTypes) return entries.map((entry) => entry.name);
26
- return entries.map((entry) => ({
27
- name: entry.name,
28
- isDirectory: () => entry.directory,
29
- isFile: () => entry.file,
30
- isSymbolicLink: () => false,
31
- }));
32
- }
33
-
34
- export function readlinkSync(path: string): string {
35
- return pythonHost().file.readLinkSync(String(path));
36
- }
37
-
38
- export function realpathSync(path: string): string {
39
- return pythonHost().file.realpathSync(String(path));
40
- }
41
-
42
- realpathSync.native = realpathSync;
43
-
44
- export function lstatSync(path: string): unknown {
45
- const value = pythonHost().file.statSync(String(path));
46
- return {
47
- mode: value.mode,
48
- mtime: new Date(value.mtimeMs),
49
- mtimeMs: value.mtimeMs,
50
- size: value.size,
51
- isDirectory: () => value.directory,
52
- isFile: () => value.file,
53
- isSymbolicLink: () => false,
54
- };
55
- }
56
-
57
- export function createReadStream(path: string): Readable {
58
- const stream = new Readable({ read() {} });
59
- void pythonHost()
60
- .file.readBytes(String(path))
61
- .then(
62
- (content) => {
63
- stream.push(Uint8Array.from(content));
64
- stream.push(null);
65
- },
66
- (error) => stream.destroy(error as Error),
67
- );
68
- return stream;
69
- }
70
-
71
- export function createWriteStream(path: string, options: { mode?: number } = {}): Writable {
72
- const chunks: number[] = [];
73
- return new Writable({
74
- write(chunk, _encoding, done) {
75
- chunks.push(...new Uint8Array(chunk));
76
- done();
77
- },
78
- final(done) {
79
- void pythonHost()
80
- .file.writeBytes(String(path), chunks, options.mode)
81
- .then(
82
- () => done(),
83
- (error) => done(error as Error),
84
- );
85
- },
86
- });
87
- }
88
-
89
- export function mkdir(path: string, options: object | Callback, done?: Callback): void {
90
- const settings = typeof options === "function" ? {} : (options as { recursive?: boolean });
91
- const callbackValue = typeof options === "function" ? options : done;
92
- callback(
93
- promises.mkdir(path, settings).then(() => undefined),
94
- callbackValue ?? (() => {}),
95
- );
96
- }
97
-
98
- export function realpath(path: string, done: Callback<string>): void {
99
- callback(promises.realpath(path), done);
100
- }
101
-
102
- export function stat(path: string, done: Callback<unknown>): void {
103
- callback(promises.stat(path), done);
104
- }
105
-
106
- export const lstat = stat;
107
-
108
- export function rmdir(path: string, done: Callback): void {
109
- callback(
110
- promises.rm(path).then(() => undefined),
111
- done,
112
- );
113
- }
114
-
115
- export function utimes(path: string, atime: Date, mtime: Date, done: Callback): void {
116
- callback(
117
- pythonHost()
118
- .file.touch(String(path), atime.getTime(), mtime.getTime())
119
- .then(() => undefined),
120
- done,
121
- );
122
- }
123
-
124
- export function open(_path: string, _flags: unknown, done: Callback<number>): void {
125
- done(
126
- Object.assign(new Error("File descriptors are unavailable in PythonMonkey"), {
127
- code: "ENOSYS",
128
- }),
129
- );
130
- }
131
-
132
- export function close(_fd: number, done: Callback): void {
133
- done(null);
134
- }
135
-
136
- export function openSync(): never {
137
- throw Object.assign(new Error("File descriptors are unavailable in PythonMonkey"), {
138
- code: "ENOSYS",
139
- });
140
- }
141
-
142
- export function closeSync(): void {}
143
-
144
- export const constants = {
145
- O_RDONLY: 0,
146
- O_WRONLY: 1,
147
- O_SYMLINK: 0,
148
- };
149
-
150
- export { promises };
151
-
152
- export default {
153
- close,
154
- closeSync,
155
- constants,
156
- createReadStream,
157
- createWriteStream,
158
- existsSync,
159
- lstat,
160
- mkdir,
161
- open,
162
- openSync,
163
- promises,
164
- readFileSync,
165
- readdirSync,
166
- realpath,
167
- realpathSync,
168
- readlinkSync,
169
- rmdir,
170
- stat,
171
- lstatSync,
172
- utimes,
173
- };
@@ -1,75 +0,0 @@
1
- export class PythonHeaders implements Iterable<[string, string]> {
2
- readonly #values = new Map<string, string[]>();
3
-
4
- constructor(init?: HeadersInit) {
5
- if (!init) return;
6
- if (Symbol.iterator in Object(init)) {
7
- for (const [name, value] of init as Iterable<[string, string]>) this.append(name, value);
8
- return;
9
- }
10
- for (const [name, value] of Object.entries(init)) this.set(name, String(value));
11
- }
12
-
13
- append(name: string, value: string): void {
14
- const key = normalizeName(name);
15
- const values = this.#values.get(key) ?? [];
16
- values.push(String(value));
17
- this.#values.set(key, values);
18
- }
19
-
20
- delete(name: string): void {
21
- this.#values.delete(normalizeName(name));
22
- }
23
-
24
- entries(): IterableIterator<[string, string]> {
25
- return this.#iterateEntries();
26
- }
27
-
28
- forEach(
29
- callback: (value: string, key: string, parent: PythonHeaders) => void,
30
- thisArg?: unknown,
31
- ): void {
32
- for (const [key, value] of this) callback.call(thisArg, value, key, this);
33
- }
34
-
35
- get(name: string): string | null {
36
- const values = this.#values.get(normalizeName(name));
37
- return values ? values.join(", ") : null;
38
- }
39
-
40
- getSetCookie(): string[] {
41
- return [...(this.#values.get("set-cookie") ?? [])];
42
- }
43
-
44
- has(name: string): boolean {
45
- return this.#values.has(normalizeName(name));
46
- }
47
-
48
- keys(): IterableIterator<string> {
49
- return this.#values.keys();
50
- }
51
-
52
- set(name: string, value: string): void {
53
- this.#values.set(normalizeName(name), [String(value)]);
54
- }
55
-
56
- values(): IterableIterator<string> {
57
- return this.#iterateValues();
58
- }
59
-
60
- [Symbol.iterator](): IterableIterator<[string, string]> {
61
- return this.entries();
62
- }
63
-
64
- *#iterateEntries(): IterableIterator<[string, string]> {
65
- for (const [name, values] of this.#values) yield [name, values.join(", ")];
66
- }
67
-
68
- *#iterateValues(): IterableIterator<string> {
69
- for (const [, value] of this) yield value;
70
- }
71
- }
72
-
73
- function normalizeName(name: string): string {
74
- return String(name).toLowerCase();
75
- }
@@ -1,341 +0,0 @@
1
- interface PythonBridge {
2
- eval(source: string): unknown;
3
- }
4
-
5
- interface PythonCompletedProcess {
6
- returncode: number;
7
- stdout: string | null;
8
- stderr: string | null;
9
- }
10
-
11
- interface PythonHttpResponse {
12
- status_code: number;
13
- headers: Record<string, string>;
14
- content: Iterable<number>;
15
- }
16
-
17
- export interface PythonFileHost {
18
- appendBytes(path: string, content: number[]): Promise<void>;
19
- chmod(path: string, mode: number): Promise<void>;
20
- copy(source: string, destination: string): Promise<void>;
21
- exists(path: string): boolean;
22
- mkdir(path: string, recursive: boolean): Promise<boolean>;
23
- mkdtemp(prefix: string): Promise<string>;
24
- readBytes(path: string): Promise<number[]>;
25
- readDirectory(path: string): Promise<{ name: string; directory: boolean; file: boolean }[]>;
26
- readTextSync(path: string): string;
27
- readDirectorySync(path: string): { name: string; directory: boolean; file: boolean }[];
28
- readLinkSync(path: string): string;
29
- realpath(path: string): Promise<string>;
30
- realpathSync(path: string): string;
31
- remove(path: string, recursive: boolean, force: boolean): Promise<void>;
32
- rename(source: string, destination: string): Promise<void>;
33
- stat(path: string): Promise<{
34
- directory: boolean;
35
- file: boolean;
36
- mode: number;
37
- mtimeMs: number;
38
- size: number;
39
- }>;
40
- statSync(path: string): {
41
- directory: boolean;
42
- file: boolean;
43
- mode: number;
44
- mtimeMs: number;
45
- size: number;
46
- };
47
- touch(path: string, atimeMs: number, mtimeMs: number): Promise<void>;
48
- writeBytes(path: string, content: number[], mode?: number): Promise<void>;
49
- }
50
-
51
- export interface PythonPathHost {
52
- basename(path: string): string;
53
- dirname(path: string): string;
54
- fileUrlToPath(url: string): string;
55
- isAbsolute(path: string): boolean;
56
- join(parts: string[]): string;
57
- relative(from: string, to: string): string;
58
- resolve(parts: string[]): string;
59
- }
60
-
61
- export interface PythonProcessResult {
62
- exitCode: number;
63
- stdout?: string;
64
- stderr?: string;
65
- }
66
-
67
- /** A started subprocess: await {@link wait} for its result, or {@link kill} it. */
68
- export interface PythonProcessHandle {
69
- /** Terminate the child (SIGKILL). No-op once it has already exited. */
70
- kill(): void;
71
- /** Resolve with the child's result once it exits (runs off the main thread). */
72
- wait(): Promise<PythonProcessResult>;
73
- }
74
-
75
- export interface PythonRuntimeHost {
76
- crypto: {
77
- digest(algorithm: string, content: number[], encoding?: "hex" | "base64"): string | number[];
78
- hashes(): string[];
79
- randomBytes(length: number): number[];
80
- };
81
- file: PythonFileHost;
82
- os: {
83
- homedir(): string;
84
- tmpdir(): string;
85
- };
86
- path: PythonPathHost;
87
- http: {
88
- fetch(
89
- url: string,
90
- method?: string,
91
- headers?: Record<string, string>,
92
- body?: string,
93
- timeoutMs?: number,
94
- ): Promise<{ status: number; headers: Record<string, string>; body: number[] }>;
95
- };
96
- process: {
97
- start(
98
- command: string,
99
- args: string[],
100
- environment: Record<string, string> | undefined,
101
- input: string | undefined,
102
- ): PythonProcessHandle;
103
- };
104
- }
105
-
106
- type PythonFunction = (...args: any[]) => any;
107
-
108
- const python = (globalThis as typeof globalThis & { python?: PythonBridge }).python;
109
- if (!python) throw new Error("PythonMonkey globalThis.python is unavailable");
110
-
111
- function evaluate<T extends PythonFunction>(source: string): T {
112
- return python!.eval(source) as T;
113
- }
114
-
115
- const toThread = evaluate<PythonFunction>("__import__('asyncio').to_thread");
116
- const osPath = {
117
- basename: evaluate<PythonFunction>("__import__('os').path.basename"),
118
- dirname: evaluate<PythonFunction>("__import__('os').path.dirname"),
119
- exists: evaluate<PythonFunction>("__import__('os').path.exists"),
120
- isAbsolute: evaluate<PythonFunction>("__import__('os').path.isabs"),
121
- join: evaluate<PythonFunction>("lambda parts: __import__('os').path.join(*list(parts))"),
122
- realpath: evaluate<PythonFunction>("__import__('os').path.realpath"),
123
- relative: evaluate<PythonFunction>("__import__('os').path.relpath"),
124
- resolve: evaluate<PythonFunction>(
125
- "lambda parts: __import__('os').path.abspath(__import__('os').path.join(*list(parts))) if list(parts) else __import__('os').getcwd()",
126
- ),
127
- };
128
- const readBytes = evaluate<PythonFunction>("lambda path: list(open(path, 'rb').read())");
129
- const readText = evaluate<PythonFunction>("lambda path: open(path, encoding='utf-8').read()");
130
- const writeBytes = evaluate<PythonFunction>(
131
- "lambda path, content: open(path, 'wb').write(bytes(int(value) for value in content))",
132
- );
133
- const appendBytes = evaluate<PythonFunction>(
134
- "lambda path, content: open(path, 'ab').write(bytes(int(value) for value in content))",
135
- );
136
- const mkdir = evaluate<PythonFunction>(
137
- "lambda path, recursive: __import__('os').makedirs(path, exist_ok=recursive) if recursive else __import__('os').mkdir(path)",
138
- );
139
- const listDirectory = evaluate<PythonFunction>(
140
- "lambda path: [{'name': entry.name, 'directory': entry.is_dir(), 'file': entry.is_file()} for entry in __import__('pathlib').Path(path).iterdir()]",
141
- );
142
- const readLink = evaluate<PythonFunction>("__import__('os').readlink");
143
- const statPath = evaluate<PythonFunction>(
144
- "lambda path: {'directory': __import__('os').path.isdir(path), 'file': __import__('os').path.isfile(path), 'mode': __import__('os').stat(path).st_mode, 'mtimeMs': __import__('os').stat(path).st_mtime * 1000, 'size': __import__('os').stat(path).st_size}",
145
- );
146
- const popen = evaluate<PythonFunction>(
147
- "lambda command, args, environment, input_text: __import__('subprocess').Popen([command, *list(args)], env=dict(environment) if environment is not None else None, stdin=(__import__('subprocess').PIPE if input_text is not None else None), stdout=__import__('subprocess').PIPE, stderr=__import__('subprocess').PIPE, text=True)",
148
- );
149
- const communicate = evaluate<PythonFunction>(
150
- "lambda proc, input_text: (lambda out: {'returncode': proc.returncode, 'stdout': out[0], 'stderr': out[1]})(proc.communicate(input=input_text))",
151
- );
152
- const killProcess = evaluate<PythonFunction>("lambda proc: proc.kill()");
153
- const requestHttp = evaluate<PythonFunction>(
154
- "lambda url, method, headers, body, timeout: __import__('httpx').request(method or 'GET', url, headers=dict(headers) if headers is not None else None, content=body, timeout=(timeout / 1000) if timeout is not None else 30, follow_redirects=True)",
155
- );
156
- const chmod = evaluate<PythonFunction>(
157
- "lambda path, mode: __import__('os').chmod(path, int(mode))",
158
- );
159
- const isDir = evaluate<PythonFunction>("__import__('os').path.isdir");
160
- const rmtree = evaluate<PythonFunction>("__import__('shutil').rmtree");
161
- const rmdir = evaluate<PythonFunction>("__import__('os').rmdir");
162
- const unlink = evaluate<PythonFunction>("__import__('os').unlink");
163
-
164
- const host: PythonRuntimeHost = {
165
- crypto: {
166
- digest: evaluate<PythonFunction>(
167
- "lambda algorithm, content, encoding: (lambda value: value.hexdigest() if encoding == 'hex' else __import__('base64').b64encode(value.digest()).decode('ascii') if encoding == 'base64' else list(value.digest()))(__import__('hashlib').new(algorithm, bytes(int(item) for item in content)))",
168
- ),
169
- hashes: evaluate<PythonFunction>("lambda: sorted(__import__('hashlib').algorithms_available)"),
170
- randomBytes: evaluate<PythonFunction>(
171
- "lambda length: list(__import__('os').urandom(int(length)))",
172
- ),
173
- },
174
- file: {
175
- async appendBytes(path, content) {
176
- await toThread(appendBytes, path, content);
177
- },
178
- async chmod(path, mode) {
179
- await toThread(chmod, path, mode);
180
- },
181
- async copy(source, destination) {
182
- await toThread(
183
- evaluate<PythonFunction>("__import__('shutil').copyfile"),
184
- source,
185
- destination,
186
- );
187
- },
188
- exists: (path) => Boolean(osPath.exists(path)),
189
- async mkdir(path, recursive) {
190
- if (await toThread(osPath.exists, path)) return false;
191
- await toThread(mkdir, path, recursive);
192
- return true;
193
- },
194
- async mkdtemp(prefix) {
195
- return toThread(
196
- evaluate<PythonFunction>("__import__('tempfile').mkdtemp"),
197
- undefined,
198
- prefix,
199
- );
200
- },
201
- async readBytes(path) {
202
- return toThread(readBytes, path);
203
- },
204
- async readDirectory(path) {
205
- return toThread(listDirectory, path);
206
- },
207
- readDirectorySync: (path) => listDirectory(path),
208
- readLinkSync: (path) => String(readLink(path)),
209
- readTextSync: (path) => String(readText(path)),
210
- async realpath(path) {
211
- return String(await toThread(osPath.realpath, path));
212
- },
213
- realpathSync: (path) => String(osPath.realpath(path)),
214
- async remove(path, recursive, force) {
215
- if (!(await toThread(osPath.exists, path))) {
216
- if (!force) throw Object.assign(new Error(`ENOENT: ${path}`), { code: "ENOENT" });
217
- return;
218
- }
219
- const isDirectory = await toThread(isDir, path);
220
- const operation = isDirectory ? (recursive ? rmtree : rmdir) : unlink;
221
- await toThread(operation, path);
222
- },
223
- async rename(source, destination) {
224
- await toThread(evaluate<PythonFunction>("__import__('os').replace"), source, destination);
225
- },
226
- async stat(path) {
227
- return toThread(statPath, path);
228
- },
229
- statSync: (path) => statPath(path),
230
- async touch(path, atimeMs, mtimeMs) {
231
- await toThread(
232
- evaluate<PythonFunction>(
233
- "lambda path, atime, mtime: __import__('os').utime(path, (atime / 1000, mtime / 1000))",
234
- ),
235
- path,
236
- atimeMs,
237
- mtimeMs,
238
- );
239
- },
240
- async writeBytes(path, content, mode) {
241
- await toThread(writeBytes, path, content);
242
- if (mode !== undefined) await toThread(chmod, path, mode);
243
- },
244
- },
245
- http: {
246
- async fetch(url, method, headers, body, timeoutMs) {
247
- const response = (await toThread(
248
- requestHttp,
249
- url,
250
- method,
251
- headers,
252
- body,
253
- timeoutMs,
254
- )) as PythonHttpResponse;
255
- return {
256
- status: response.status_code,
257
- headers: Object.fromEntries(Object.entries(response.headers)),
258
- body: Array.from(response.content),
259
- };
260
- },
261
- },
262
- os: {
263
- homedir: evaluate<PythonFunction>("lambda: __import__('pathlib').Path.home().as_posix()"),
264
- tmpdir: evaluate<PythonFunction>("__import__('tempfile').gettempdir"),
265
- },
266
- path: {
267
- basename: (path) => String(osPath.basename(path)),
268
- dirname: (path) => String(osPath.dirname(path)),
269
- fileUrlToPath: evaluate<PythonFunction>(
270
- "lambda url: __import__('urllib.parse', fromlist=['urlparse']).unquote(__import__('urllib.parse', fromlist=['urlparse']).urlparse(url).path)",
271
- ),
272
- isAbsolute: (path) => Boolean(osPath.isAbsolute(path)),
273
- join: (parts) => String(osPath.join(parts)),
274
- relative: (from, to) => String(osPath.relative(to, from)),
275
- resolve: (parts) => String(osPath.resolve(parts)),
276
- },
277
- process: {
278
- start(command, args, environment, input) {
279
- // Popen (not subprocess.run) so the child is killable: an aborted caller
280
- // can terminate it instead of leaking a background process. There is no
281
- // imposed timeout - the child runs to completion (an interactive login may
282
- // legitimately take minutes); the caller owns cancellation.
283
- const proc = popen(command, args, environment, input);
284
- let killed = false;
285
- return {
286
- kill() {
287
- if (killed) return;
288
- killed = true;
289
- try {
290
- killProcess(proc);
291
- } catch {
292
- // The child already exited; there is nothing to signal.
293
- }
294
- },
295
- async wait() {
296
- // communicate() blocks until exit, so run it off the main thread.
297
- const result = (await toThread(communicate, proc, input)) as PythonCompletedProcess;
298
- return {
299
- exitCode: result.returncode,
300
- ...(result.stdout?.trim() ? { stdout: result.stdout.trim() } : {}),
301
- ...(result.stderr?.trim() ? { stderr: result.stderr.trim() } : {}),
302
- };
303
- },
304
- };
305
- },
306
- },
307
- };
308
-
309
- export function installPythonGlobals(): void {
310
- const globals = globalThis as typeof globalThis & {
311
- global?: typeof globalThis;
312
- self?: typeof globalThis;
313
- window?: typeof globalThis;
314
- process?: Record<string, unknown>;
315
- };
316
- globals.global = globalThis;
317
- globals.self = globalThis;
318
- globals.window = globalThis;
319
- globals.process ??= {
320
- arch: String(evaluate<PythonFunction>("__import__('platform').machine")())
321
- .replace("aarch64", "arm64")
322
- .replace("x86_64", "x64"),
323
- argv: [],
324
- browser: true,
325
- cwd: evaluate<PythonFunction>("__import__('os').getcwd"),
326
- env: evaluate<PythonFunction>("lambda: dict(__import__('os').environ)")(),
327
- nextTick: (callback: (...args: unknown[]) => void, ...args: unknown[]) =>
328
- Promise.resolve().then(() => callback(...args)),
329
- platform: { Darwin: "darwin", Linux: "linux", Windows: "win32" }[
330
- String(evaluate<PythonFunction>("__import__('platform').system")())
331
- ],
332
- version: "v22.0.0",
333
- versions: {},
334
- };
335
- }
336
-
337
- installPythonGlobals();
338
-
339
- export function pythonHost(): PythonRuntimeHost {
340
- return host;
341
- }
@@ -1,20 +0,0 @@
1
- import { pythonHost } from "./host.ts";
2
-
3
- export const constants = {
4
- errno: {
5
- EEXIST: 17,
6
- ENOTDIR: 20,
7
- EISDIR: 21,
8
- EINVAL: 22,
9
- },
10
- } as const;
11
-
12
- export function homedir(): string {
13
- return pythonHost().os.homedir();
14
- }
15
-
16
- export function tmpdir(): string {
17
- return pythonHost().os.tmpdir();
18
- }
19
-
20
- export default { constants, homedir, tmpdir };
@@ -1,13 +0,0 @@
1
- import { installPythonGlobals } from "./host.ts";
2
-
3
- installPythonGlobals();
4
-
5
- export default process;
6
- export const arch = process.arch;
7
- export const argv = process.argv;
8
- export const cwd = process.cwd;
9
- export const env = process.env;
10
- export const nextTick = process.nextTick;
11
- export const platform = process.platform;
12
- export const version = process.version;
13
- export const versions = process.versions;
@@ -1,37 +0,0 @@
1
- /**
2
- * Async line reader used by subprocess output capture in PythonMonkey bundles.
3
- *
4
- * @module
5
- */
6
-
7
- interface ReadLineOptions {
8
- readonly input: AsyncIterable<unknown>;
9
- }
10
-
11
- class PythonReadLine implements AsyncIterable<string> {
12
- private closed = false;
13
-
14
- constructor(private readonly input: AsyncIterable<unknown>) {}
15
-
16
- async *[Symbol.asyncIterator](): AsyncIterator<string> {
17
- let buffered = "";
18
- for await (const chunk of this.input) {
19
- if (this.closed) break;
20
- buffered += String(chunk);
21
- const lines = buffered.split(/\r?\n/);
22
- buffered = lines.pop() ?? "";
23
- for (const line of lines) yield line;
24
- }
25
- if (!this.closed && buffered) yield buffered.replace(/\r$/, "");
26
- }
27
-
28
- close(): void {
29
- this.closed = true;
30
- }
31
- }
32
-
33
- export function createInterface(options: ReadLineOptions): PythonReadLine {
34
- return new PythonReadLine(options.input);
35
- }
36
-
37
- export default { createInterface };
@@ -1,24 +0,0 @@
1
- // ~~ Generated by projen. To modify, edit .projenrc.js and run "bunx projen".
2
- {
3
- "compilerOptions": {
4
- "target": "ES2022",
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "lib": [
8
- "ES2022",
9
- "DOM"
10
- ],
11
- "types": [
12
- "node"
13
- ],
14
- "noEmit": true,
15
- "skipLibCheck": true,
16
- "strict": false
17
- },
18
- "include": [
19
- "*.ts"
20
- ],
21
- "exclude": [
22
- "node_modules"
23
- ]
24
- }