@projitect/blueprint-tsconfig 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/dist/package.json +48 -0
- package/dist/src/index.d.ts +86 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +99 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +45 -3
- package/src/index.ts +175 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kapil Easwar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@projitect/blueprint-tsconfig",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript tsconfig.json scaffolding blueprint for projitect — strict defaults, owned mode.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/projitect/projitect.git",
|
|
8
|
+
"directory": "packages/blueprint-tsconfig"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/src/index.d.ts",
|
|
15
|
+
"import": "./dist/src/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"!**/*.tsbuildinfo"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc --build",
|
|
25
|
+
"build:clean": "tsc --build --clean",
|
|
26
|
+
"tc": "tsc --build"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@projitect/blueprint": "workspace:*",
|
|
30
|
+
"@projitect/core": "workspace:*",
|
|
31
|
+
"@projitect/test-kit": "workspace:*",
|
|
32
|
+
"effect": "4.0.0-rc.111",
|
|
33
|
+
"typescript": "5.9.3"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@projitect/blueprint": "workspace:*",
|
|
37
|
+
"@projitect/core": "workspace:*",
|
|
38
|
+
"effect": "4.0.0-rc.111"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=22.12.0"
|
|
42
|
+
},
|
|
43
|
+
"projitect": {
|
|
44
|
+
"type": "blueprint",
|
|
45
|
+
"import": "import { tsconfig } from \"@projitect/blueprint-tsconfig\"",
|
|
46
|
+
"call": "tsconfig()"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @projitect/blueprint-tsconfig
|
|
3
|
+
*
|
|
4
|
+
* One owned-mode blueprint that scaffolds `tsconfig.json` with strict defaults. Designed for the
|
|
5
|
+
* common Node-library / Node-app shape; toggle `dom` for browser code and `jsx` for React/JSX.
|
|
6
|
+
*
|
|
7
|
+
* Owned mode means projitect rewrites `tsconfig.json` from scratch on every `pjt remodel` —
|
|
8
|
+
* the user can't accidentally drift it. If a project needs overrides projitect can't model
|
|
9
|
+
* (e.g. `compilerOptions.paths`), the answer is: configure projitect's options here, then
|
|
10
|
+
* compose a second TS config file (`tsconfig.local.json`) that extends this one and adds the
|
|
11
|
+
* overrides. Don't hand-edit the owned file. Project `references` are the exception: TypeScript
|
|
12
|
+
* never inherits them through `extends`, so declare them with the `references` option here.
|
|
13
|
+
*/
|
|
14
|
+
import type { Blueprint } from "@projitect/core";
|
|
15
|
+
export interface TsconfigOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Strict family of compiler flags. Defaults to `true` (`strict`, `noUncheckedIndexedAccess`,
|
|
18
|
+
* `noImplicitOverride`, `noFallthroughCasesInSwitch`, `noPropertyAccessFromIndexSignature`,
|
|
19
|
+
* `exactOptionalPropertyTypes`). Pass `false` to ship the loose defaults TS gives a new
|
|
20
|
+
* project — useful when adopting projitect on a legacy codebase where flipping strict mode
|
|
21
|
+
* at once isn't feasible.
|
|
22
|
+
*/
|
|
23
|
+
readonly strict?: boolean;
|
|
24
|
+
/** ECMAScript target. Defaults to `"ES2023"`. */
|
|
25
|
+
readonly target?: string;
|
|
26
|
+
/** Module system. Defaults to `"NodeNext"` (with matching `moduleResolution`). */
|
|
27
|
+
readonly module?: "NodeNext" | "ESNext" | "Node16" | "CommonJS";
|
|
28
|
+
/**
|
|
29
|
+
* `lib` entries. Defaults to `["ES2023"]` (matches `target`). Use `dom: true` instead of
|
|
30
|
+
* adding `"DOM"` here — the helper handles the right pairing.
|
|
31
|
+
*/
|
|
32
|
+
readonly lib?: readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* Include `"DOM"` + `"DOM.Iterable"` in `lib`. Defaults to `false` (Node-only). Flip to `true`
|
|
35
|
+
* for browser code.
|
|
36
|
+
*/
|
|
37
|
+
readonly dom?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* JSX transform. `null` (default) emits no `jsx` field. `"react-jsx"` is the modern automatic
|
|
40
|
+
* runtime; `"react"` is the classic transform; `"preserve"` keeps JSX as-is for downstream
|
|
41
|
+
* tooling (Vite, etc.).
|
|
42
|
+
*/
|
|
43
|
+
readonly jsx?: "react" | "react-jsx" | "preserve" | null;
|
|
44
|
+
/**
|
|
45
|
+
* Source root. Defaults to `"./src"`. The generated config derives `include` from this
|
|
46
|
+
* (`${rootDir}/...all files...`) and sets `exclude` to `["node_modules", outDir]`.
|
|
47
|
+
*/
|
|
48
|
+
readonly rootDir?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Output directory. Defaults to `"./dist"`.
|
|
51
|
+
*/
|
|
52
|
+
readonly outDir?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Paths to referenced projects (a directory or a tsconfig file), emitted in the given order as
|
|
55
|
+
* top-level `references: [{ path }]` entries. Paths are kept exactly as written. Each referenced
|
|
56
|
+
* project must set `composite: true` in its own tsconfig. Omitted or empty emits no
|
|
57
|
+
* `references` key.
|
|
58
|
+
*/
|
|
59
|
+
readonly references?: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* Type-check only. Defaults to `false`. When `true` the config emits `noEmit: true` and leaves
|
|
62
|
+
* out the emit settings (`rootDir`, `outDir`, `declaration`, `declarationMap`, `sourceMap`),
|
|
63
|
+
* for projects whose bundler or framework does the emitting.
|
|
64
|
+
*/
|
|
65
|
+
readonly noEmit?: boolean;
|
|
66
|
+
/** Emit `allowJs: true`. Defaults to `false` (no `allowJs` field). */
|
|
67
|
+
readonly allowJs?: boolean;
|
|
68
|
+
/** Emit `incremental: true`. Defaults to `false` (no `incremental` field). */
|
|
69
|
+
readonly incremental?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* TypeScript language service plugin names, emitted as `compilerOptions.plugins: [{ name }]` in
|
|
72
|
+
* the given order. Omitted or empty emits no `plugins` key.
|
|
73
|
+
*/
|
|
74
|
+
readonly plugins?: readonly string[];
|
|
75
|
+
/**
|
|
76
|
+
* Extra `include` entries, appended after the glob derived from `rootDir` and kept exactly as
|
|
77
|
+
* written (e.g. generated type directories).
|
|
78
|
+
*/
|
|
79
|
+
readonly include?: readonly string[];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build the tsconfig blueprint. Returns an owned-mode blueprint that emits a single operation
|
|
83
|
+
* writing `tsconfig.json` with the rendered content.
|
|
84
|
+
*/
|
|
85
|
+
export declare const tsconfig: (options?: TsconfigOptions) => Blueprint.Blueprint;
|
|
86
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAQhD,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAA;IAC/D;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI,CAAA;IACxD;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,sEAAsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAC9B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,UAAS,eAAoB,KAAG,SAAS,CAAC,SAO/D,CAAA"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @projitect/blueprint-tsconfig
|
|
3
|
+
*
|
|
4
|
+
* One owned-mode blueprint that scaffolds `tsconfig.json` with strict defaults. Designed for the
|
|
5
|
+
* common Node-library / Node-app shape; toggle `dom` for browser code and `jsx` for React/JSX.
|
|
6
|
+
*
|
|
7
|
+
* Owned mode means projitect rewrites `tsconfig.json` from scratch on every `pjt remodel` —
|
|
8
|
+
* the user can't accidentally drift it. If a project needs overrides projitect can't model
|
|
9
|
+
* (e.g. `compilerOptions.paths`), the answer is: configure projitect's options here, then
|
|
10
|
+
* compose a second TS config file (`tsconfig.local.json`) that extends this one and adds the
|
|
11
|
+
* overrides. Don't hand-edit the owned file. Project `references` are the exception: TypeScript
|
|
12
|
+
* never inherits them through `extends`, so declare them with the `references` option here.
|
|
13
|
+
*/
|
|
14
|
+
import { ownFile } from "@projitect/blueprint";
|
|
15
|
+
import { Array } from "effect";
|
|
16
|
+
import manifest from "../package.json" with { type: "json" };
|
|
17
|
+
// Read the version from the package manifest (emitted next to `dist/src`) so a release bump
|
|
18
|
+
// reaches `.pjt.lock` without a hand-edited constant. JSON import keeps this runtime-pure.
|
|
19
|
+
const PACKAGE_VERSION = manifest.version;
|
|
20
|
+
/**
|
|
21
|
+
* Build the tsconfig blueprint. Returns an owned-mode blueprint that emits a single operation
|
|
22
|
+
* writing `tsconfig.json` with the rendered content.
|
|
23
|
+
*/
|
|
24
|
+
export const tsconfig = (options = {}) => ownFile({
|
|
25
|
+
id: "pjt:tsconfig",
|
|
26
|
+
version: PACKAGE_VERSION,
|
|
27
|
+
description: "TypeScript tsconfig.json with strict defaults",
|
|
28
|
+
path: "tsconfig.json",
|
|
29
|
+
content: renderTsconfig(options),
|
|
30
|
+
});
|
|
31
|
+
const renderTsconfig = (options) => {
|
|
32
|
+
const strict = options.strict ?? true;
|
|
33
|
+
const target = options.target ?? "ES2023";
|
|
34
|
+
const module_ = options.module ?? "NodeNext";
|
|
35
|
+
const baseLib = options.lib ?? [target];
|
|
36
|
+
const lib = options.dom === true ? [...baseLib, "DOM", "DOM.Iterable"] : baseLib;
|
|
37
|
+
const rootDir = options.rootDir ?? "./src";
|
|
38
|
+
const outDir = options.outDir ?? "./dist";
|
|
39
|
+
const jsx = options.jsx ?? null;
|
|
40
|
+
const references = options.references ?? [];
|
|
41
|
+
const noEmit = options.noEmit ?? false;
|
|
42
|
+
const plugins = options.plugins ?? [];
|
|
43
|
+
const config = {
|
|
44
|
+
compilerOptions: {
|
|
45
|
+
target,
|
|
46
|
+
module: module_,
|
|
47
|
+
moduleResolution: moduleResolutionFor(module_),
|
|
48
|
+
lib,
|
|
49
|
+
...(jsx !== null && { jsx }),
|
|
50
|
+
...(noEmit ? { noEmit } : { rootDir, outDir }),
|
|
51
|
+
...(options.allowJs === true && { allowJs: true }),
|
|
52
|
+
...(options.incremental === true && { incremental: true }),
|
|
53
|
+
...(Array.isReadonlyArrayNonEmpty(plugins) && {
|
|
54
|
+
plugins: plugins.map((name) => ({ name })),
|
|
55
|
+
}),
|
|
56
|
+
// Always-on hygiene flags. These don't toggle with `strict` — they're the table stakes
|
|
57
|
+
// every modern TS project should have.
|
|
58
|
+
esModuleInterop: true,
|
|
59
|
+
forceConsistentCasingInFileNames: true,
|
|
60
|
+
skipLibCheck: true,
|
|
61
|
+
isolatedModules: true,
|
|
62
|
+
resolveJsonModule: true,
|
|
63
|
+
...(!noEmit && { declaration: true, declarationMap: true, sourceMap: true }),
|
|
64
|
+
...(strict && {
|
|
65
|
+
strict: true,
|
|
66
|
+
noImplicitOverride: true,
|
|
67
|
+
noFallthroughCasesInSwitch: true,
|
|
68
|
+
noUncheckedIndexedAccess: true,
|
|
69
|
+
noPropertyAccessFromIndexSignature: true,
|
|
70
|
+
exactOptionalPropertyTypes: true,
|
|
71
|
+
}),
|
|
72
|
+
},
|
|
73
|
+
include: [`${stripDot(rootDir)}/**/*`, ...(options.include ?? [])],
|
|
74
|
+
exclude: noEmit ? ["node_modules"] : ["node_modules", stripDot(outDir)],
|
|
75
|
+
...(Array.isReadonlyArrayNonEmpty(references) && {
|
|
76
|
+
references: references.map((path) => ({ path })),
|
|
77
|
+
}),
|
|
78
|
+
};
|
|
79
|
+
return `${JSON.stringify(config, null, 2)}\n`;
|
|
80
|
+
};
|
|
81
|
+
const moduleResolutionFor = (m) => {
|
|
82
|
+
switch (m) {
|
|
83
|
+
case "NodeNext":
|
|
84
|
+
case "Node16": {
|
|
85
|
+
return m;
|
|
86
|
+
}
|
|
87
|
+
case "ESNext": {
|
|
88
|
+
return "Bundler";
|
|
89
|
+
}
|
|
90
|
+
case "CommonJS": {
|
|
91
|
+
return "Node";
|
|
92
|
+
}
|
|
93
|
+
default: {
|
|
94
|
+
return "NodeNext";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const stripDot = (p) => (p.startsWith("./") ? p.slice(2) : p);
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAE9C,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC9B,OAAO,QAAQ,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAE5D,4FAA4F;AAC5F,2FAA2F;AAC3F,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAA;AAqExC;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,UAA2B,EAAE,EAAuB,EAAE,CAC7E,OAAO,CAAC;IACN,EAAE,EAAE,cAAc;IAClB,OAAO,EAAE,eAAe;IACxB,WAAW,EAAE,+CAA+C;IAC5D,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;CACjC,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,CAAC,OAAwB,EAAU,EAAE;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAA;IACrC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAA;IACzC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,UAAU,CAAA;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAChF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAA;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAA;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAA;IAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAA;IAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAA;IACtC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAA;IAErC,MAAM,MAAM,GAA4B;QACtC,eAAe,EAAE;YACf,MAAM;YACN,MAAM,EAAE,OAAO;YACf,gBAAgB,EAAE,mBAAmB,CAAC,OAAO,CAAC;YAC9C,GAAG;YACH,GAAG,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,GAAG,EAAE,CAAC;YAC5B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAC9C,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAClD,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;YAC1D,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAI;gBAC5C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;aAC3C,CAAC;YACF,uFAAuF;YACvF,uCAAuC;YACvC,eAAe,EAAE,IAAI;YACrB,gCAAgC,EAAE,IAAI;YACtC,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,IAAI;YACrB,iBAAiB,EAAE,IAAI;YACvB,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;YAC5E,GAAG,CAAC,MAAM,IAAI;gBACZ,MAAM,EAAE,IAAI;gBACZ,kBAAkB,EAAE,IAAI;gBACxB,0BAA0B,EAAE,IAAI;gBAChC,wBAAwB,EAAE,IAAI;gBAC9B,kCAAkC,EAAE,IAAI;gBACxC,0BAA0B,EAAE,IAAI;aACjC,CAAC;SACH;QACD,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvE,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,UAAU,CAAC,IAAI;YAC/C,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;SACjD,CAAC;KACH,CAAA;IAED,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAA;AAC/C,CAAC,CAAA;AAED,MAAM,mBAAmB,GAAG,CAAC,CAA4B,EAAU,EAAE;IACnE,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,UAAU,CAAC;QAChB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,CAAA;QACV,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,OAAO,MAAM,CAAA;QACf,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,UAAU,CAAA;QACnB,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@projitect/blueprint-tsconfig",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript tsconfig.json scaffolding blueprint for projitect — strict defaults, owned mode.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/projitect/projitect.git",
|
|
8
|
+
"directory": "packages/blueprint-tsconfig"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/src/index.d.ts",
|
|
15
|
+
"import": "./dist/src/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src",
|
|
21
|
+
"!**/*.tsbuildinfo"
|
|
22
|
+
],
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"effect": "4.0.0-rc.111",
|
|
25
|
+
"typescript": "5.9.3",
|
|
26
|
+
"@projitect/blueprint": "1.0.0",
|
|
27
|
+
"@projitect/core": "1.0.0",
|
|
28
|
+
"@projitect/test-kit": "1.0.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"effect": "4.0.0-rc.111",
|
|
32
|
+
"@projitect/blueprint": "1.0.0",
|
|
33
|
+
"@projitect/core": "1.0.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22.12.0"
|
|
37
|
+
},
|
|
38
|
+
"projitect": {
|
|
39
|
+
"type": "blueprint",
|
|
40
|
+
"import": "import { tsconfig } from \"@projitect/blueprint-tsconfig\"",
|
|
41
|
+
"call": "tsconfig()"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc --build",
|
|
45
|
+
"build:clean": "tsc --build --clean",
|
|
46
|
+
"tc": "tsc --build"
|
|
47
|
+
}
|
|
6
48
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @projitect/blueprint-tsconfig
|
|
3
|
+
*
|
|
4
|
+
* One owned-mode blueprint that scaffolds `tsconfig.json` with strict defaults. Designed for the
|
|
5
|
+
* common Node-library / Node-app shape; toggle `dom` for browser code and `jsx` for React/JSX.
|
|
6
|
+
*
|
|
7
|
+
* Owned mode means projitect rewrites `tsconfig.json` from scratch on every `pjt remodel` —
|
|
8
|
+
* the user can't accidentally drift it. If a project needs overrides projitect can't model
|
|
9
|
+
* (e.g. `compilerOptions.paths`), the answer is: configure projitect's options here, then
|
|
10
|
+
* compose a second TS config file (`tsconfig.local.json`) that extends this one and adds the
|
|
11
|
+
* overrides. Don't hand-edit the owned file. Project `references` are the exception: TypeScript
|
|
12
|
+
* never inherits them through `extends`, so declare them with the `references` option here.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { ownFile } from "@projitect/blueprint"
|
|
16
|
+
import type { Blueprint } from "@projitect/core"
|
|
17
|
+
import { Array } from "effect"
|
|
18
|
+
import manifest from "../package.json" with { type: "json" }
|
|
19
|
+
|
|
20
|
+
// Read the version from the package manifest (emitted next to `dist/src`) so a release bump
|
|
21
|
+
// reaches `.pjt.lock` without a hand-edited constant. JSON import keeps this runtime-pure.
|
|
22
|
+
const PACKAGE_VERSION = manifest.version
|
|
23
|
+
|
|
24
|
+
export interface TsconfigOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Strict family of compiler flags. Defaults to `true` (`strict`, `noUncheckedIndexedAccess`,
|
|
27
|
+
* `noImplicitOverride`, `noFallthroughCasesInSwitch`, `noPropertyAccessFromIndexSignature`,
|
|
28
|
+
* `exactOptionalPropertyTypes`). Pass `false` to ship the loose defaults TS gives a new
|
|
29
|
+
* project — useful when adopting projitect on a legacy codebase where flipping strict mode
|
|
30
|
+
* at once isn't feasible.
|
|
31
|
+
*/
|
|
32
|
+
readonly strict?: boolean
|
|
33
|
+
/** ECMAScript target. Defaults to `"ES2023"`. */
|
|
34
|
+
readonly target?: string
|
|
35
|
+
/** Module system. Defaults to `"NodeNext"` (with matching `moduleResolution`). */
|
|
36
|
+
readonly module?: "NodeNext" | "ESNext" | "Node16" | "CommonJS"
|
|
37
|
+
/**
|
|
38
|
+
* `lib` entries. Defaults to `["ES2023"]` (matches `target`). Use `dom: true` instead of
|
|
39
|
+
* adding `"DOM"` here — the helper handles the right pairing.
|
|
40
|
+
*/
|
|
41
|
+
readonly lib?: readonly string[]
|
|
42
|
+
/**
|
|
43
|
+
* Include `"DOM"` + `"DOM.Iterable"` in `lib`. Defaults to `false` (Node-only). Flip to `true`
|
|
44
|
+
* for browser code.
|
|
45
|
+
*/
|
|
46
|
+
readonly dom?: boolean
|
|
47
|
+
/**
|
|
48
|
+
* JSX transform. `null` (default) emits no `jsx` field. `"react-jsx"` is the modern automatic
|
|
49
|
+
* runtime; `"react"` is the classic transform; `"preserve"` keeps JSX as-is for downstream
|
|
50
|
+
* tooling (Vite, etc.).
|
|
51
|
+
*/
|
|
52
|
+
readonly jsx?: "react" | "react-jsx" | "preserve" | null
|
|
53
|
+
/**
|
|
54
|
+
* Source root. Defaults to `"./src"`. The generated config derives `include` from this
|
|
55
|
+
* (`${rootDir}/...all files...`) and sets `exclude` to `["node_modules", outDir]`.
|
|
56
|
+
*/
|
|
57
|
+
readonly rootDir?: string
|
|
58
|
+
/**
|
|
59
|
+
* Output directory. Defaults to `"./dist"`.
|
|
60
|
+
*/
|
|
61
|
+
readonly outDir?: string
|
|
62
|
+
/**
|
|
63
|
+
* Paths to referenced projects (a directory or a tsconfig file), emitted in the given order as
|
|
64
|
+
* top-level `references: [{ path }]` entries. Paths are kept exactly as written. Each referenced
|
|
65
|
+
* project must set `composite: true` in its own tsconfig. Omitted or empty emits no
|
|
66
|
+
* `references` key.
|
|
67
|
+
*/
|
|
68
|
+
readonly references?: readonly string[]
|
|
69
|
+
/**
|
|
70
|
+
* Type-check only. Defaults to `false`. When `true` the config emits `noEmit: true` and leaves
|
|
71
|
+
* out the emit settings (`rootDir`, `outDir`, `declaration`, `declarationMap`, `sourceMap`),
|
|
72
|
+
* for projects whose bundler or framework does the emitting.
|
|
73
|
+
*/
|
|
74
|
+
readonly noEmit?: boolean
|
|
75
|
+
/** Emit `allowJs: true`. Defaults to `false` (no `allowJs` field). */
|
|
76
|
+
readonly allowJs?: boolean
|
|
77
|
+
/** Emit `incremental: true`. Defaults to `false` (no `incremental` field). */
|
|
78
|
+
readonly incremental?: boolean
|
|
79
|
+
/**
|
|
80
|
+
* TypeScript language service plugin names, emitted as `compilerOptions.plugins: [{ name }]` in
|
|
81
|
+
* the given order. Omitted or empty emits no `plugins` key.
|
|
82
|
+
*/
|
|
83
|
+
readonly plugins?: readonly string[]
|
|
84
|
+
/**
|
|
85
|
+
* Extra `include` entries, appended after the glob derived from `rootDir` and kept exactly as
|
|
86
|
+
* written (e.g. generated type directories).
|
|
87
|
+
*/
|
|
88
|
+
readonly include?: readonly string[]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Build the tsconfig blueprint. Returns an owned-mode blueprint that emits a single operation
|
|
93
|
+
* writing `tsconfig.json` with the rendered content.
|
|
94
|
+
*/
|
|
95
|
+
export const tsconfig = (options: TsconfigOptions = {}): Blueprint.Blueprint =>
|
|
96
|
+
ownFile({
|
|
97
|
+
id: "pjt:tsconfig",
|
|
98
|
+
version: PACKAGE_VERSION,
|
|
99
|
+
description: "TypeScript tsconfig.json with strict defaults",
|
|
100
|
+
path: "tsconfig.json",
|
|
101
|
+
content: renderTsconfig(options),
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const renderTsconfig = (options: TsconfigOptions): string => {
|
|
105
|
+
const strict = options.strict ?? true
|
|
106
|
+
const target = options.target ?? "ES2023"
|
|
107
|
+
const module_ = options.module ?? "NodeNext"
|
|
108
|
+
const baseLib = options.lib ?? [target]
|
|
109
|
+
const lib = options.dom === true ? [...baseLib, "DOM", "DOM.Iterable"] : baseLib
|
|
110
|
+
const rootDir = options.rootDir ?? "./src"
|
|
111
|
+
const outDir = options.outDir ?? "./dist"
|
|
112
|
+
const jsx = options.jsx ?? null
|
|
113
|
+
const references = options.references ?? []
|
|
114
|
+
const noEmit = options.noEmit ?? false
|
|
115
|
+
const plugins = options.plugins ?? []
|
|
116
|
+
|
|
117
|
+
const config: Record<string, unknown> = {
|
|
118
|
+
compilerOptions: {
|
|
119
|
+
target,
|
|
120
|
+
module: module_,
|
|
121
|
+
moduleResolution: moduleResolutionFor(module_),
|
|
122
|
+
lib,
|
|
123
|
+
...(jsx !== null && { jsx }),
|
|
124
|
+
...(noEmit ? { noEmit } : { rootDir, outDir }),
|
|
125
|
+
...(options.allowJs === true && { allowJs: true }),
|
|
126
|
+
...(options.incremental === true && { incremental: true }),
|
|
127
|
+
...(Array.isReadonlyArrayNonEmpty(plugins) && {
|
|
128
|
+
plugins: plugins.map((name) => ({ name })),
|
|
129
|
+
}),
|
|
130
|
+
// Always-on hygiene flags. These don't toggle with `strict` — they're the table stakes
|
|
131
|
+
// every modern TS project should have.
|
|
132
|
+
esModuleInterop: true,
|
|
133
|
+
forceConsistentCasingInFileNames: true,
|
|
134
|
+
skipLibCheck: true,
|
|
135
|
+
isolatedModules: true,
|
|
136
|
+
resolveJsonModule: true,
|
|
137
|
+
...(!noEmit && { declaration: true, declarationMap: true, sourceMap: true }),
|
|
138
|
+
...(strict && {
|
|
139
|
+
strict: true,
|
|
140
|
+
noImplicitOverride: true,
|
|
141
|
+
noFallthroughCasesInSwitch: true,
|
|
142
|
+
noUncheckedIndexedAccess: true,
|
|
143
|
+
noPropertyAccessFromIndexSignature: true,
|
|
144
|
+
exactOptionalPropertyTypes: true,
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
include: [`${stripDot(rootDir)}/**/*`, ...(options.include ?? [])],
|
|
148
|
+
exclude: noEmit ? ["node_modules"] : ["node_modules", stripDot(outDir)],
|
|
149
|
+
...(Array.isReadonlyArrayNonEmpty(references) && {
|
|
150
|
+
references: references.map((path) => ({ path })),
|
|
151
|
+
}),
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return `${JSON.stringify(config, null, 2)}\n`
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const moduleResolutionFor = (m: TsconfigOptions["module"]): string => {
|
|
158
|
+
switch (m) {
|
|
159
|
+
case "NodeNext":
|
|
160
|
+
case "Node16": {
|
|
161
|
+
return m
|
|
162
|
+
}
|
|
163
|
+
case "ESNext": {
|
|
164
|
+
return "Bundler"
|
|
165
|
+
}
|
|
166
|
+
case "CommonJS": {
|
|
167
|
+
return "Node"
|
|
168
|
+
}
|
|
169
|
+
default: {
|
|
170
|
+
return "NodeNext"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const stripDot = (p: string): string => (p.startsWith("./") ? p.slice(2) : p)
|
package/README.md
DELETED