@ttsc/banner 0.12.4 → 0.13.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/README.md +21 -10
- package/driver/banner.go +101 -57
- package/lib/index.js +24 -5
- package/lib/index.js.map +1 -1
- package/lib/structures/{TtscBannerConfig.d.ts → ITtscBannerConfig.d.ts} +2 -2
- package/lib/structures/{TtscBannerConfig.js → ITtscBannerConfig.js} +1 -1
- package/lib/structures/ITtscBannerConfig.js.map +1 -0
- package/lib/structures/ITtscBannerPluginConfig.d.ts +7 -6
- package/lib/structures/index.d.ts +1 -1
- package/lib/structures/index.js +1 -1
- package/lib/structures/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +28 -5
- package/src/structures/ITtscBannerConfig.ts +5 -0
- package/src/structures/ITtscBannerPluginConfig.ts +7 -8
- package/src/structures/index.ts +1 -1
- package/lib/structures/TtscBannerConfig.js.map +0 -1
- package/src/structures/TtscBannerConfig.ts +0 -7
package/README.md
CHANGED
|
@@ -20,45 +20,56 @@ npm install -D ttsc @typescript/native-preview
|
|
|
20
20
|
npm install -D @ttsc/banner
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Register the plugin in your `tsconfig.json`:
|
|
24
24
|
|
|
25
25
|
```jsonc
|
|
26
26
|
// tsconfig.json
|
|
27
27
|
{
|
|
28
28
|
"compilerOptions": {
|
|
29
29
|
"plugins": [
|
|
30
|
-
{ "transform": "@ttsc/banner"
|
|
30
|
+
{ "transform": "@ttsc/banner" }
|
|
31
31
|
]
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Drop a `banner.config.ts` next to your `tsconfig.json`:
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
// banner.config.ts
|
|
40
|
-
import type {
|
|
40
|
+
import type { ITtscBannerConfig } from "@ttsc/banner";
|
|
41
41
|
|
|
42
42
|
export default {
|
|
43
43
|
text: "License MIT (c) 2026 Acme",
|
|
44
|
-
} satisfies
|
|
44
|
+
} satisfies ITtscBannerConfig;
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
A `banner.config.*` file always exports an object with a `text` string.
|
|
48
|
+
|
|
47
49
|
Run your normal `ttsc` command:
|
|
48
50
|
|
|
49
51
|
```bash
|
|
50
52
|
npx ttsc
|
|
51
53
|
```
|
|
52
54
|
|
|
53
|
-
If `@ttsc/banner` is installed and
|
|
55
|
+
If `@ttsc/banner` is installed and no `banner.config.*` file is found, the compile fails.
|
|
54
56
|
|
|
55
57
|
## Configuration
|
|
56
58
|
|
|
57
|
-
`@ttsc/banner`
|
|
59
|
+
`@ttsc/banner` discovers its config by walking upward from the tsconfig directory, looking for `banner.config.{ts,cts,mts,js,cjs,mjs,json}`.
|
|
60
|
+
|
|
61
|
+
To point at a specific file instead of using auto-discovery, set `configFile` on the tsconfig entry:
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
```jsonc
|
|
64
|
+
// tsconfig.json
|
|
65
|
+
{
|
|
66
|
+
"compilerOptions": {
|
|
67
|
+
"plugins": [
|
|
68
|
+
{ "transform": "@ttsc/banner", "configFile": "./config/banner.config.ts" }
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
62
73
|
|
|
63
74
|
The plugin formats every line of the resolved text inside a JSDoc block and appends `@packageDocumentation`.
|
|
64
75
|
|
package/driver/banner.go
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package banner
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"bytes"
|
|
4
5
|
"encoding/json"
|
|
5
6
|
"fmt"
|
|
6
7
|
"os"
|
|
@@ -25,6 +26,35 @@ var (
|
|
|
25
26
|
writeConfigLoaderFile = os.WriteFile
|
|
26
27
|
)
|
|
27
28
|
|
|
29
|
+
// frameworkKeys lists the tsconfig plugin-entry keys that the ttsc host
|
|
30
|
+
// framework owns. They are accepted without error; all other keys are rejected.
|
|
31
|
+
var frameworkKeys = map[string]struct{}{
|
|
32
|
+
"enabled": {},
|
|
33
|
+
"name": {},
|
|
34
|
+
"stage": {},
|
|
35
|
+
"transform": {},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// validateBannerConfig rejects any tsconfig plugin entry key that is not a
|
|
39
|
+
// known framework key and is not the single banner-specific "configFile" key.
|
|
40
|
+
func validateBannerConfig(config map[string]any) error {
|
|
41
|
+
for key := range config {
|
|
42
|
+
if _, ok := frameworkKeys[key]; ok {
|
|
43
|
+
continue
|
|
44
|
+
}
|
|
45
|
+
if key == "configFile" {
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
return fmt.Errorf(
|
|
49
|
+
"@ttsc/banner: tsconfig plugin entry contains unsupported key %q. "+
|
|
50
|
+
"Banner options must be placed in a banner.config.{ts,cts,mts,js,cjs,mjs,json} file. "+
|
|
51
|
+
"The only accepted key in the tsconfig entry is \"configFile\" (optional path to the config file).",
|
|
52
|
+
key,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
return nil
|
|
56
|
+
}
|
|
57
|
+
|
|
28
58
|
// SourcePreamble resolves the banner text from the plugin config and returns it
|
|
29
59
|
// formatted as a JSDoc block comment suitable for prepending to each emitted file.
|
|
30
60
|
func (plugin) SourcePreamble(ctx driver.PluginContext) (string, error) {
|
|
@@ -60,18 +90,22 @@ func parseBanner(config map[string]any, cwd, tsconfigPath string) (string, error
|
|
|
60
90
|
}
|
|
61
91
|
|
|
62
92
|
// resolveBannerText extracts the banner text from the plugin config.
|
|
63
|
-
//
|
|
64
|
-
//
|
|
93
|
+
// The config entry is validated first: only the "configFile" key (plus
|
|
94
|
+
// framework keys) is accepted. When "configFile" is present its value is
|
|
95
|
+
// resolved to an absolute path and loaded. When absent the upward-walk
|
|
96
|
+
// discovery is used. Returns an error when the config is invalid or when
|
|
97
|
+
// no banner text can be found.
|
|
65
98
|
func resolveBannerText(config map[string]any, cwd, tsconfigPath string) (string, error) {
|
|
66
|
-
if
|
|
67
|
-
return
|
|
99
|
+
if err := validateBannerConfig(config); err != nil {
|
|
100
|
+
return "", err
|
|
68
101
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
102
|
+
|
|
103
|
+
if rawConfigFile, ok := config["configFile"]; ok {
|
|
104
|
+
configFile, ok := rawConfigFile.(string)
|
|
105
|
+
if !ok || strings.TrimSpace(configFile) == "" {
|
|
106
|
+
return "", fmt.Errorf("@ttsc/banner: \"configFile\" must be a non-empty string path")
|
|
73
107
|
}
|
|
74
|
-
location := resolveBannerConfigPath(
|
|
108
|
+
location := resolveBannerConfigPath(configFile, cwd, tsconfigPath)
|
|
75
109
|
raw, err := loadBannerConfigFile(location)
|
|
76
110
|
if err != nil {
|
|
77
111
|
return "", err
|
|
@@ -81,16 +115,17 @@ func resolveBannerText(config map[string]any, cwd, tsconfigPath string) (string,
|
|
|
81
115
|
return "", err
|
|
82
116
|
}
|
|
83
117
|
if !ok {
|
|
84
|
-
return "", fmt.Errorf("@ttsc/banner: %s must export
|
|
118
|
+
return "", fmt.Errorf("@ttsc/banner: %s must export an object with a non-empty \"text\" string", location)
|
|
85
119
|
}
|
|
86
120
|
return text, nil
|
|
87
121
|
}
|
|
122
|
+
|
|
88
123
|
location, err := findBannerConfigFile(cwd, tsconfigPath)
|
|
89
124
|
if err != nil {
|
|
90
125
|
return "", err
|
|
91
126
|
}
|
|
92
127
|
if location == "" {
|
|
93
|
-
return "", fmt.Errorf("@ttsc/banner:
|
|
128
|
+
return "", fmt.Errorf("@ttsc/banner: no banner.config.{ts,cts,mts,js,cjs,mjs,json} file found; create one or set \"configFile\" in the tsconfig plugin entry")
|
|
94
129
|
}
|
|
95
130
|
raw, err := loadBannerConfigFile(location)
|
|
96
131
|
if err != nil {
|
|
@@ -101,36 +136,30 @@ func resolveBannerText(config map[string]any, cwd, tsconfigPath string) (string,
|
|
|
101
136
|
return "", err
|
|
102
137
|
}
|
|
103
138
|
if !ok {
|
|
104
|
-
return "", fmt.Errorf("@ttsc/banner: %s must export
|
|
139
|
+
return "", fmt.Errorf("@ttsc/banner: %s must export an object with a non-empty \"text\" string", location)
|
|
105
140
|
}
|
|
106
141
|
return text, nil
|
|
107
142
|
}
|
|
108
143
|
|
|
109
144
|
// bannerTextFromConfigValue extracts a banner text string from a config value.
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
// ("",
|
|
113
|
-
// error messages and
|
|
145
|
+
// A banner config value must be an object with a non-empty "text" string; raw
|
|
146
|
+
// may also be nil (not present). Returns (text, true, nil) on success,
|
|
147
|
+
// ("", false, nil) when absent, or ("", true, err) on a type mismatch. label is
|
|
148
|
+
// used in error messages and is the config file's base name (e.g.
|
|
149
|
+
// "banner.config.json").
|
|
114
150
|
func bannerTextFromConfigValue(raw any, label string) (string, bool, error) {
|
|
115
151
|
if raw == nil {
|
|
116
152
|
return "", false, nil
|
|
117
153
|
}
|
|
118
|
-
text, ok := raw.(string)
|
|
119
|
-
if ok {
|
|
120
|
-
if strings.TrimSpace(text) == "" {
|
|
121
|
-
return "", true, fmt.Errorf("@ttsc/banner: %s must be a non-empty string", label)
|
|
122
|
-
}
|
|
123
|
-
return text, true, nil
|
|
124
|
-
}
|
|
125
154
|
object, ok := raw.(map[string]any)
|
|
126
155
|
if !ok {
|
|
127
|
-
return "", true, fmt.Errorf("@ttsc/banner: %s must be
|
|
156
|
+
return "", true, fmt.Errorf("@ttsc/banner: %s must be an object with a non-empty \"text\" string", label)
|
|
128
157
|
}
|
|
129
158
|
rawText, ok := object["text"]
|
|
130
159
|
if !ok {
|
|
131
160
|
return "", false, nil
|
|
132
161
|
}
|
|
133
|
-
text, ok
|
|
162
|
+
text, ok := rawText.(string)
|
|
134
163
|
if !ok || strings.TrimSpace(text) == "" {
|
|
135
164
|
return "", true, fmt.Errorf("@ttsc/banner: %s.text must be a non-empty string", label)
|
|
136
165
|
}
|
|
@@ -138,14 +167,15 @@ func bannerTextFromConfigValue(raw any, label string) (string, bool, error) {
|
|
|
138
167
|
}
|
|
139
168
|
|
|
140
169
|
// findBannerConfigFile walks up from the tsconfig (or cwd) directory looking for
|
|
141
|
-
// a banner.config.{js,cjs,mjs,
|
|
170
|
+
// a banner.config.{ts,cts,mts,js,cjs,mjs,json} file. Returns the path when exactly
|
|
142
171
|
// one match is found per directory, "" when none exists at any level, or an
|
|
143
172
|
// error when multiple candidates exist in the same directory.
|
|
144
173
|
func findBannerConfigFile(cwd, tsconfigPath string) (string, error) {
|
|
145
|
-
dir :=
|
|
174
|
+
dir := tsconfigBaseDir(cwd, tsconfigPath)
|
|
146
175
|
for {
|
|
147
176
|
matches := make([]string, 0, 1)
|
|
148
177
|
for _, name := range []string{
|
|
178
|
+
"banner.config.json",
|
|
149
179
|
"banner.config.js",
|
|
150
180
|
"banner.config.cjs",
|
|
151
181
|
"banner.config.mjs",
|
|
@@ -159,7 +189,14 @@ func findBannerConfigFile(cwd, tsconfigPath string) (string, error) {
|
|
|
159
189
|
}
|
|
160
190
|
}
|
|
161
191
|
if len(matches) > 1 {
|
|
162
|
-
|
|
192
|
+
names := make([]string, len(matches))
|
|
193
|
+
for i, match := range matches {
|
|
194
|
+
names[i] = filepath.Base(match)
|
|
195
|
+
}
|
|
196
|
+
return "", fmt.Errorf(
|
|
197
|
+
"@ttsc/banner: multiple banner config files found in %s (%s); set \"configFile\" explicitly in the tsconfig plugin entry",
|
|
198
|
+
dir, strings.Join(names, ", "),
|
|
199
|
+
)
|
|
163
200
|
}
|
|
164
201
|
if len(matches) == 1 {
|
|
165
202
|
return matches[0], nil
|
|
@@ -183,7 +220,8 @@ func resolveBannerConfigPath(configPath, cwd, tsconfigPath string) string {
|
|
|
183
220
|
}
|
|
184
221
|
|
|
185
222
|
// tsconfigBaseDir returns the directory that contains the tsconfig file, or cwd
|
|
186
|
-
// when tsconfigPath is empty.
|
|
223
|
+
// when tsconfigPath is empty. It is the base both for resolving an explicit
|
|
224
|
+
// `configFile` path and for starting the upward banner-config-file search.
|
|
187
225
|
func tsconfigBaseDir(cwd, tsconfigPath string) string {
|
|
188
226
|
if tsconfigPath == "" {
|
|
189
227
|
return cwd
|
|
@@ -195,30 +233,20 @@ func tsconfigBaseDir(cwd, tsconfigPath string) string {
|
|
|
195
233
|
return filepath.Dir(resolvedTsconfig)
|
|
196
234
|
}
|
|
197
235
|
|
|
198
|
-
// discoveryConfigBaseDir returns the starting directory for the upward banner
|
|
199
|
-
// config file search. Semantically identical to tsconfigBaseDir; kept separate
|
|
200
|
-
// to make the call sites self-documenting.
|
|
201
|
-
func discoveryConfigBaseDir(cwd, tsconfigPath string) string {
|
|
202
|
-
if tsconfigPath != "" {
|
|
203
|
-
resolvedTsconfig := tsconfigPath
|
|
204
|
-
if !filepath.IsAbs(resolvedTsconfig) {
|
|
205
|
-
resolvedTsconfig = filepath.Join(cwd, resolvedTsconfig)
|
|
206
|
-
}
|
|
207
|
-
return filepath.Dir(resolvedTsconfig)
|
|
208
|
-
}
|
|
209
|
-
return cwd
|
|
210
|
-
}
|
|
211
|
-
|
|
212
236
|
// loadBannerConfigFile loads and evaluates a banner config file, returning its
|
|
213
|
-
// exported value as a Go any
|
|
214
|
-
//
|
|
215
|
-
//
|
|
237
|
+
// exported value as a Go any. A valid banner config exports an object with a
|
|
238
|
+
// "text" string; the value is validated by bannerTextFromConfigValue. The file
|
|
239
|
+
// must be named banner.config.{ts,cts,mts,js,cjs,mjs,json}; JS/CJS/MJS variants
|
|
240
|
+
// run under Node, TypeScript variants compile and run via ttsx in a temp
|
|
241
|
+
// directory, and JSON files are parsed natively.
|
|
216
242
|
func loadBannerConfigFile(location string) (any, error) {
|
|
217
243
|
if !isBannerConfigFileName(filepath.Base(location)) {
|
|
218
|
-
return nil, fmt.Errorf("@ttsc/banner: config file must be named banner.config.{js,cjs,mjs,
|
|
244
|
+
return nil, fmt.Errorf("@ttsc/banner: config file must be named banner.config.{ts,cts,mts,js,cjs,mjs,json}: %s", location)
|
|
219
245
|
}
|
|
220
246
|
ext := strings.ToLower(filepath.Ext(location))
|
|
221
247
|
switch ext {
|
|
248
|
+
case ".json":
|
|
249
|
+
return loadBannerJSONConfigFile(location)
|
|
222
250
|
case ".js", ".cjs", ".mjs":
|
|
223
251
|
return loadBannerScriptConfigFile(location)
|
|
224
252
|
}
|
|
@@ -228,7 +256,8 @@ func loadBannerConfigFile(location string) (any, error) {
|
|
|
228
256
|
// isBannerConfigFileName reports whether name is an allowed banner config file name.
|
|
229
257
|
func isBannerConfigFileName(name string) bool {
|
|
230
258
|
switch name {
|
|
231
|
-
case "banner.config.
|
|
259
|
+
case "banner.config.json",
|
|
260
|
+
"banner.config.js",
|
|
232
261
|
"banner.config.cjs",
|
|
233
262
|
"banner.config.mjs",
|
|
234
263
|
"banner.config.ts",
|
|
@@ -240,6 +269,24 @@ func isBannerConfigFileName(name string) bool {
|
|
|
240
269
|
}
|
|
241
270
|
}
|
|
242
271
|
|
|
272
|
+
// loadBannerJSONConfigFile reads and JSON-parses a banner config file. A leading
|
|
273
|
+
// UTF-8 BOM is stripped before parsing so files saved by Windows editors are
|
|
274
|
+
// accepted. The parsed value must be an object with a non-empty "text" string.
|
|
275
|
+
func loadBannerJSONConfigFile(location string) (any, error) {
|
|
276
|
+
body, err := os.ReadFile(location)
|
|
277
|
+
if err != nil {
|
|
278
|
+
return nil, fmt.Errorf("@ttsc/banner: read config file %s: %w", location, err)
|
|
279
|
+
}
|
|
280
|
+
// Strip a leading UTF-8 BOM so files saved by Windows editors round
|
|
281
|
+
// trip through json.Unmarshal without an opaque "invalid character" failure.
|
|
282
|
+
body = bytes.TrimPrefix(body, []byte{0xEF, 0xBB, 0xBF})
|
|
283
|
+
var out any
|
|
284
|
+
if err := json.Unmarshal(body, &out); err != nil {
|
|
285
|
+
return nil, fmt.Errorf("@ttsc/banner: parse config file %s: %w", location, err)
|
|
286
|
+
}
|
|
287
|
+
return out, nil
|
|
288
|
+
}
|
|
289
|
+
|
|
243
290
|
// loadBannerScriptConfigFile evaluates a JS/CJS/MJS banner config file by
|
|
244
291
|
// running a small Node.js loader script that dynamic-imports the file and
|
|
245
292
|
// serializes its exported value to stdout as JSON.
|
|
@@ -258,13 +305,10 @@ const { pathToFileURL } = require("node:url");
|
|
|
258
305
|
});
|
|
259
306
|
|
|
260
307
|
function toSerializableBanner(value) {
|
|
261
|
-
if (typeof value === "string") {
|
|
262
|
-
return value;
|
|
263
|
-
}
|
|
264
308
|
if (value !== null && typeof value === "object" && typeof value.text === "string") {
|
|
265
309
|
return { text: value.text };
|
|
266
310
|
}
|
|
267
|
-
throw new Error("config file must export
|
|
311
|
+
throw new Error("config file must export an object with a non-empty \"text\" string");
|
|
268
312
|
}
|
|
269
313
|
`
|
|
270
314
|
node := os.Getenv("TTSC_NODE_BINARY")
|
|
@@ -293,7 +337,9 @@ function toSerializableBanner(value) {
|
|
|
293
337
|
|
|
294
338
|
// loadBannerTypeScriptConfigFile compiles and runs a TypeScript banner config
|
|
295
339
|
// file using ttsx in a temp directory. A symlink to the nearest node_modules
|
|
296
|
-
// is created so the config file can import its own dependencies.
|
|
340
|
+
// is created so the config file can import its own dependencies. The ttsx
|
|
341
|
+
// build runs with `--no-plugins` so evaluating the config never triggers the
|
|
342
|
+
// host project's transform/check plugins against the loader tsconfig.
|
|
297
343
|
func loadBannerTypeScriptConfigFile(location string) (any, error) {
|
|
298
344
|
tempDir, err := os.MkdirTemp("", "ttsc-banner-config-")
|
|
299
345
|
if err != nil {
|
|
@@ -323,6 +369,7 @@ func loadBannerTypeScriptConfigFile(location string) (any, error) {
|
|
|
323
369
|
"--project", tsconfig,
|
|
324
370
|
"--cwd", tempDir,
|
|
325
371
|
"--cache-dir", filepath.Join(tempDir, "cache"),
|
|
372
|
+
"--no-plugins",
|
|
326
373
|
}
|
|
327
374
|
if tsgo := os.Getenv("TTSC_TSGO_BINARY"); tsgo != "" {
|
|
328
375
|
args = append(args, "--binary", tsgo)
|
|
@@ -407,13 +454,10 @@ function hasOwn(value: Record<string, unknown>, key: string): boolean {
|
|
|
407
454
|
}
|
|
408
455
|
|
|
409
456
|
function toSerializableBanner(value: unknown): unknown {
|
|
410
|
-
if (typeof value === "string") {
|
|
411
|
-
return value;
|
|
412
|
-
}
|
|
413
457
|
if (isObject(value) && typeof value.text === "string") {
|
|
414
458
|
return { text: value.text };
|
|
415
459
|
}
|
|
416
|
-
throw new Error("config file must export
|
|
460
|
+
throw new Error("config file must export an object with a non-empty \"text\" string");
|
|
417
461
|
}
|
|
418
462
|
`, importLiteral)
|
|
419
463
|
}
|
package/lib/index.js
CHANGED
|
@@ -20,18 +20,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
20
20
|
exports.default = createTtscBanner;
|
|
21
21
|
const node_path_1 = __importDefault(require("node:path"));
|
|
22
22
|
__exportStar(require("./structures/index"), exports);
|
|
23
|
+
/**
|
|
24
|
+
* Keys that the ttsc plugin host injects into every plugin entry and are not
|
|
25
|
+
* owned by `@ttsc/banner`. These pass through the factory without validation so
|
|
26
|
+
* the host can freely add new framework keys in the future.
|
|
27
|
+
*/
|
|
28
|
+
const FRAMEWORK_KEYS = new Set([
|
|
29
|
+
"enabled",
|
|
30
|
+
"name",
|
|
31
|
+
"stage",
|
|
32
|
+
"transform",
|
|
33
|
+
]);
|
|
23
34
|
/**
|
|
24
35
|
* Plugin factory for `@ttsc/banner` — called by the ttsc host to obtain the
|
|
25
36
|
* plugin descriptor.
|
|
26
37
|
*
|
|
27
|
-
* The
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
38
|
+
* The only banner-specific key accepted in the tsconfig plugin entry is
|
|
39
|
+
* `configFile`. Any other key that is not a known framework key is rejected
|
|
40
|
+
* with a specific error so users discover the correct configuration surface
|
|
41
|
+
* (the dedicated config file) rather than silently receiving no banner.
|
|
31
42
|
*
|
|
32
43
|
* @internal
|
|
33
44
|
*/
|
|
34
|
-
function createTtscBanner(
|
|
45
|
+
function createTtscBanner(context) {
|
|
46
|
+
const entry = context.plugin;
|
|
47
|
+
for (const key of Object.keys(entry)) {
|
|
48
|
+
if (!FRAMEWORK_KEYS.has(key) && key !== "configFile") {
|
|
49
|
+
throw new Error(`@ttsc/banner: tsconfig plugin entry contains unsupported key ${JSON.stringify(key)}. ` +
|
|
50
|
+
`Banner options must be placed in a banner.config.{ts,cts,mts,js,cjs,mjs,json} file. ` +
|
|
51
|
+
`The only accepted key in the tsconfig entry is "configFile" (optional path to the config file).`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
35
54
|
return {
|
|
36
55
|
name: "@ttsc/banner",
|
|
37
56
|
// Point at the `driver/` directory one level above `lib/` in the
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,0DAA6B;AAI7B,qDAAmC;AA4CnC;;;;;;;;;;GAUG;AACH,0BACE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,0DAA6B;AAI7B,qDAAmC;AA4CnC;;;;GAIG;AACH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAS;IACrC,SAAS;IACT,MAAM;IACN,OAAO;IACP,WAAW;CACZ,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,0BACE,OAA0D;IAE1D,MAAM,KAAK,GAAG,OAAO,CAAC,MAAiC,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CACb,gEAAgE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI;gBACrF,sFAAsF;gBACtF,iGAAiG,CACpG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,iEAAiE;QACjE,sDAAsD;QACtD,MAAM,EAAE,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC;QAC/C,KAAK,EAAE,WAAW;KACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITtscBannerConfig.js","sourceRoot":"","sources":["../../src/structures/ITtscBannerConfig.ts"],"names":[],"mappings":""}
|
|
@@ -4,10 +4,11 @@ export interface ITtscBannerPluginConfig {
|
|
|
4
4
|
enabled?: boolean;
|
|
5
5
|
/** Plugin module specifier. */
|
|
6
6
|
transform?: string;
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Path to a `banner.config.*` file, resolved from the directory that contains
|
|
9
|
+
* the tsconfig. When omitted, `@ttsc/banner` walks up from that directory and
|
|
10
|
+
* uses the first `banner.config.{ts,cts,mts,js,cjs,mjs,json}` file it finds.
|
|
11
|
+
* Any other key in this entry is rejected with an error.
|
|
12
|
+
*/
|
|
13
|
+
configFile?: string;
|
|
13
14
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./ITtscBannerPluginConfig";
|
|
2
|
-
export * from "./
|
|
2
|
+
export * from "./ITtscBannerConfig";
|
package/lib/structures/index.js
CHANGED
|
@@ -15,5 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./ITtscBannerPluginConfig"), exports);
|
|
18
|
-
__exportStar(require("./
|
|
18
|
+
__exportStar(require("./ITtscBannerConfig"), exports);
|
|
19
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/structures/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C;AAC1C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/structures/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4DAA0C;AAC1C,sDAAoC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/banner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "First-party ttsc plugin that adds package-documentation JSDoc banners during emit.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
],
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^25.3.0",
|
|
36
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
36
|
+
"@typescript/native-preview": "7.0.0-dev.20260522.1",
|
|
37
37
|
"rimraf": "^6.1.2",
|
|
38
|
-
"ttsc": "0.
|
|
38
|
+
"ttsc": "0.13.0"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
package/src/index.ts
CHANGED
|
@@ -46,20 +46,43 @@ type TtscPluginFactoryContext<TConfig> = {
|
|
|
46
46
|
tsconfig: string;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Keys that the ttsc plugin host injects into every plugin entry and are not
|
|
51
|
+
* owned by `@ttsc/banner`. These pass through the factory without validation so
|
|
52
|
+
* the host can freely add new framework keys in the future.
|
|
53
|
+
*/
|
|
54
|
+
const FRAMEWORK_KEYS = new Set<string>([
|
|
55
|
+
"enabled",
|
|
56
|
+
"name",
|
|
57
|
+
"stage",
|
|
58
|
+
"transform",
|
|
59
|
+
]);
|
|
60
|
+
|
|
49
61
|
/**
|
|
50
62
|
* Plugin factory for `@ttsc/banner` — called by the ttsc host to obtain the
|
|
51
63
|
* plugin descriptor.
|
|
52
64
|
*
|
|
53
|
-
* The
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
65
|
+
* The only banner-specific key accepted in the tsconfig plugin entry is
|
|
66
|
+
* `configFile`. Any other key that is not a known framework key is rejected
|
|
67
|
+
* with a specific error so users discover the correct configuration surface
|
|
68
|
+
* (the dedicated config file) rather than silently receiving no banner.
|
|
57
69
|
*
|
|
58
70
|
* @internal
|
|
59
71
|
*/
|
|
60
72
|
export default function createTtscBanner(
|
|
61
|
-
|
|
73
|
+
context: TtscPluginFactoryContext<ITtscBannerPluginConfig>,
|
|
62
74
|
): TtscPluginDescriptor {
|
|
75
|
+
const entry = context.plugin as Record<string, unknown>;
|
|
76
|
+
for (const key of Object.keys(entry)) {
|
|
77
|
+
if (!FRAMEWORK_KEYS.has(key) && key !== "configFile") {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`@ttsc/banner: tsconfig plugin entry contains unsupported key ${JSON.stringify(key)}. ` +
|
|
80
|
+
`Banner options must be placed in a banner.config.{ts,cts,mts,js,cjs,mjs,json} file. ` +
|
|
81
|
+
`The only accepted key in the tsconfig entry is "configFile" (optional path to the config file).`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
63
86
|
return {
|
|
64
87
|
name: "@ttsc/banner",
|
|
65
88
|
// Point at the `driver/` directory one level above `lib/` in the
|
|
@@ -6,12 +6,11 @@ export interface ITtscBannerPluginConfig {
|
|
|
6
6
|
/** Plugin module specifier. */
|
|
7
7
|
transform?: string;
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[key: string]: unknown;
|
|
9
|
+
/**
|
|
10
|
+
* Path to a `banner.config.*` file, resolved from the directory that contains
|
|
11
|
+
* the tsconfig. When omitted, `@ttsc/banner` walks up from that directory and
|
|
12
|
+
* uses the first `banner.config.{ts,cts,mts,js,cjs,mjs,json}` file it finds.
|
|
13
|
+
* Any other key in this entry is rejected with an error.
|
|
14
|
+
*/
|
|
15
|
+
configFile?: string;
|
|
17
16
|
}
|
package/src/structures/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./ITtscBannerPluginConfig";
|
|
2
|
-
export * from "./
|
|
2
|
+
export * from "./ITtscBannerConfig";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TtscBannerConfig.js","sourceRoot":"","sources":["../../src/structures/TtscBannerConfig.ts"],"names":[],"mappings":""}
|