@ttsc/banner 0.26.1 → 0.27.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/driver/banner.go +900 -69
- package/lib/index.js +85 -0
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +109 -0
package/lib/index.js
CHANGED
|
@@ -18,6 +18,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
exports.default = createTtscBanner;
|
|
21
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
22
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
21
23
|
const node_path_1 = __importDefault(require("node:path"));
|
|
22
24
|
__exportStar(require("./structures/index"), exports);
|
|
23
25
|
/**
|
|
@@ -51,7 +53,11 @@ function createTtscBanner(context) {
|
|
|
51
53
|
`The only accepted key in the tsconfig entry is "configFile" (optional path to the config file).`);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
56
|
+
const configInputs = bannerConfigInputs(context);
|
|
54
57
|
return {
|
|
58
|
+
hostInputHashes: configInputs.hashes,
|
|
59
|
+
hostInputRealpaths: configInputs.realpaths,
|
|
60
|
+
hostInputs: configInputs.inputs,
|
|
55
61
|
name: "@ttsc/banner",
|
|
56
62
|
// Point at the `driver/` directory one level above `lib/` in the
|
|
57
63
|
// installed package tree (where the Go sources live). `context.dirname`
|
|
@@ -61,4 +67,83 @@ function createTtscBanner(context) {
|
|
|
61
67
|
stage: "transform",
|
|
62
68
|
};
|
|
63
69
|
}
|
|
70
|
+
const BANNER_CONFIG_FILENAMES = [
|
|
71
|
+
"banner.config.json",
|
|
72
|
+
"banner.config.js",
|
|
73
|
+
"banner.config.cjs",
|
|
74
|
+
"banner.config.mjs",
|
|
75
|
+
"banner.config.ts",
|
|
76
|
+
"banner.config.cts",
|
|
77
|
+
"banner.config.mts",
|
|
78
|
+
];
|
|
79
|
+
/** Mirror native config resolution while retaining missing priority probes. */
|
|
80
|
+
function bannerConfigInputs(context) {
|
|
81
|
+
const configFile = context.plugin.configFile;
|
|
82
|
+
const base = node_path_1.default.resolve(context.pluginConfigDir ?? node_path_1.default.dirname(context.tsconfig));
|
|
83
|
+
if (typeof configFile === "string" && configFile.trim() !== "") {
|
|
84
|
+
const file = node_path_1.default.isAbsolute(configFile)
|
|
85
|
+
? node_path_1.default.resolve(configFile)
|
|
86
|
+
: node_path_1.default.resolve(base, configFile);
|
|
87
|
+
return {
|
|
88
|
+
hashes: { [file]: hostInputHash(file) },
|
|
89
|
+
inputs: [file],
|
|
90
|
+
realpaths: { [file]: hostInputRealpath(file) },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return configDiscoveryInputs(base, BANNER_CONFIG_FILENAMES);
|
|
94
|
+
}
|
|
95
|
+
function configDiscoveryInputs(base, names) {
|
|
96
|
+
const inputs = [];
|
|
97
|
+
const hashes = {};
|
|
98
|
+
const realpaths = {};
|
|
99
|
+
for (let directory = base;; directory = node_path_1.default.dirname(directory)) {
|
|
100
|
+
const candidates = names.map((name) => node_path_1.default.join(directory, name));
|
|
101
|
+
inputs.push(...candidates);
|
|
102
|
+
for (const candidate of candidates) {
|
|
103
|
+
hashes[candidate] = hostInputHash(candidate);
|
|
104
|
+
realpaths[candidate] = hostInputRealpath(candidate);
|
|
105
|
+
}
|
|
106
|
+
if (candidates.some(configCandidateExists))
|
|
107
|
+
break;
|
|
108
|
+
const parent = node_path_1.default.dirname(directory);
|
|
109
|
+
if (parent === directory)
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
return { hashes, inputs, realpaths };
|
|
113
|
+
}
|
|
114
|
+
function hostInputRealpath(file) {
|
|
115
|
+
try {
|
|
116
|
+
return node_fs_1.default.realpathSync.native(file);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Hash the exact candidate state observed before discovery selects a file. */
|
|
123
|
+
function hostInputHash(file) {
|
|
124
|
+
try {
|
|
125
|
+
if (node_fs_1.default.statSync(file).isDirectory()) {
|
|
126
|
+
return node_crypto_1.default
|
|
127
|
+
.createHash("sha256")
|
|
128
|
+
.update("ttsc:host-input:directory\0")
|
|
129
|
+
.digest("hex");
|
|
130
|
+
}
|
|
131
|
+
return node_crypto_1.default
|
|
132
|
+
.createHash("sha256")
|
|
133
|
+
.update(node_fs_1.default.readFileSync(file))
|
|
134
|
+
.digest("hex");
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Match the native discovery rule: a directory is never a config file. */
|
|
141
|
+
function configCandidateExists(file) {
|
|
142
|
+
try {
|
|
143
|
+
return !node_fs_1.default.statSync(file).isDirectory();
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
64
149
|
//# sourceMappingURL=index.js.map
|
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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/banner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.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",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@types/node": "^25.3.0",
|
|
36
36
|
"rimraf": "^6.1.2",
|
|
37
37
|
"typescript": "^7.0.2",
|
|
38
|
-
"ttsc": "0.
|
|
38
|
+
"ttsc": "0.27.0"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
|
|
3
5
|
import type { ITtscBannerPluginConfig } from "./structures";
|
|
@@ -12,6 +14,12 @@ export * from "./structures/index";
|
|
|
12
14
|
* executable sidecar or linked native source.
|
|
13
15
|
*/
|
|
14
16
|
type TtscPluginDescriptor = {
|
|
17
|
+
/** Universal config-discovery inputs consumed by the native transform. */
|
|
18
|
+
hostInputs?: string[];
|
|
19
|
+
/** Evaluation-time fingerprints paired with {@link hostInputs}. */
|
|
20
|
+
hostInputHashes?: Record<string, string | null>;
|
|
21
|
+
/** Evaluation-time physical targets paired with {@link hostInputs}. */
|
|
22
|
+
hostInputRealpaths?: Record<string, string | null>;
|
|
15
23
|
/** Human-readable plugin name used in logs and error messages. */
|
|
16
24
|
name: string;
|
|
17
25
|
/** Absolute path to the Go source directory for this plugin. */
|
|
@@ -45,6 +53,8 @@ type TtscPluginFactoryContext<TConfig> = {
|
|
|
45
53
|
* replacement for `__filename`.
|
|
46
54
|
*/
|
|
47
55
|
filename: string;
|
|
56
|
+
/** Host-declared anchor for implicit plugin config discovery. */
|
|
57
|
+
pluginConfigDir?: string;
|
|
48
58
|
/** The raw plugin entry from `compilerOptions.plugins[]`. */
|
|
49
59
|
plugin: TConfig;
|
|
50
60
|
/** Absolute path to the project root (directory containing tsconfig). */
|
|
@@ -90,7 +100,11 @@ export default function createTtscBanner(
|
|
|
90
100
|
}
|
|
91
101
|
}
|
|
92
102
|
|
|
103
|
+
const configInputs = bannerConfigInputs(context);
|
|
93
104
|
return {
|
|
105
|
+
hostInputHashes: configInputs.hashes,
|
|
106
|
+
hostInputRealpaths: configInputs.realpaths,
|
|
107
|
+
hostInputs: configInputs.inputs,
|
|
94
108
|
name: "@ttsc/banner",
|
|
95
109
|
// Point at the `driver/` directory one level above `lib/` in the
|
|
96
110
|
// installed package tree (where the Go sources live). `context.dirname`
|
|
@@ -100,3 +114,98 @@ export default function createTtscBanner(
|
|
|
100
114
|
stage: "transform",
|
|
101
115
|
};
|
|
102
116
|
}
|
|
117
|
+
|
|
118
|
+
const BANNER_CONFIG_FILENAMES = [
|
|
119
|
+
"banner.config.json",
|
|
120
|
+
"banner.config.js",
|
|
121
|
+
"banner.config.cjs",
|
|
122
|
+
"banner.config.mjs",
|
|
123
|
+
"banner.config.ts",
|
|
124
|
+
"banner.config.cts",
|
|
125
|
+
"banner.config.mts",
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
/** Mirror native config resolution while retaining missing priority probes. */
|
|
129
|
+
function bannerConfigInputs(
|
|
130
|
+
context: TtscPluginFactoryContext<ITtscBannerPluginConfig>,
|
|
131
|
+
): {
|
|
132
|
+
hashes: Record<string, string | null>;
|
|
133
|
+
inputs: string[];
|
|
134
|
+
realpaths: Record<string, string | null>;
|
|
135
|
+
} {
|
|
136
|
+
const configFile = (context.plugin as { configFile?: unknown }).configFile;
|
|
137
|
+
const base = path.resolve(
|
|
138
|
+
context.pluginConfigDir ?? path.dirname(context.tsconfig),
|
|
139
|
+
);
|
|
140
|
+
if (typeof configFile === "string" && configFile.trim() !== "") {
|
|
141
|
+
const file = path.isAbsolute(configFile)
|
|
142
|
+
? path.resolve(configFile)
|
|
143
|
+
: path.resolve(base, configFile);
|
|
144
|
+
return {
|
|
145
|
+
hashes: { [file]: hostInputHash(file) },
|
|
146
|
+
inputs: [file],
|
|
147
|
+
realpaths: { [file]: hostInputRealpath(file) },
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return configDiscoveryInputs(base, BANNER_CONFIG_FILENAMES);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function configDiscoveryInputs(
|
|
154
|
+
base: string,
|
|
155
|
+
names: readonly string[],
|
|
156
|
+
): {
|
|
157
|
+
hashes: Record<string, string | null>;
|
|
158
|
+
inputs: string[];
|
|
159
|
+
realpaths: Record<string, string | null>;
|
|
160
|
+
} {
|
|
161
|
+
const inputs: string[] = [];
|
|
162
|
+
const hashes: Record<string, string | null> = {};
|
|
163
|
+
const realpaths: Record<string, string | null> = {};
|
|
164
|
+
for (let directory = base; ; directory = path.dirname(directory)) {
|
|
165
|
+
const candidates = names.map((name) => path.join(directory, name));
|
|
166
|
+
inputs.push(...candidates);
|
|
167
|
+
for (const candidate of candidates) {
|
|
168
|
+
hashes[candidate] = hostInputHash(candidate);
|
|
169
|
+
realpaths[candidate] = hostInputRealpath(candidate);
|
|
170
|
+
}
|
|
171
|
+
if (candidates.some(configCandidateExists)) break;
|
|
172
|
+
const parent = path.dirname(directory);
|
|
173
|
+
if (parent === directory) break;
|
|
174
|
+
}
|
|
175
|
+
return { hashes, inputs, realpaths };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function hostInputRealpath(file: string): string | null {
|
|
179
|
+
try {
|
|
180
|
+
return fs.realpathSync.native(file);
|
|
181
|
+
} catch {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Hash the exact candidate state observed before discovery selects a file. */
|
|
187
|
+
function hostInputHash(file: string): string | null {
|
|
188
|
+
try {
|
|
189
|
+
if (fs.statSync(file).isDirectory()) {
|
|
190
|
+
return crypto
|
|
191
|
+
.createHash("sha256")
|
|
192
|
+
.update("ttsc:host-input:directory\0")
|
|
193
|
+
.digest("hex");
|
|
194
|
+
}
|
|
195
|
+
return crypto
|
|
196
|
+
.createHash("sha256")
|
|
197
|
+
.update(fs.readFileSync(file))
|
|
198
|
+
.digest("hex");
|
|
199
|
+
} catch {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Match the native discovery rule: a directory is never a config file. */
|
|
205
|
+
function configCandidateExists(file: string): boolean {
|
|
206
|
+
try {
|
|
207
|
+
return !fs.statSync(file).isDirectory();
|
|
208
|
+
} catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|