@uniswap/ai-toolkit-nx-claude 0.5.30-next.2 → 0.5.30-next.3
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 +28 -27
- package/dist/cli-generator.cjs +4 -10
- package/dist/index.cjs +15 -845
- package/dist/packages/ai-toolkit-nx-claude/src/cli-generator.d.ts +1 -2
- package/dist/packages/ai-toolkit-nx-claude/src/cli-generator.d.ts.map +1 -1
- package/dist/packages/ai-toolkit-nx-claude/src/index.d.ts +0 -1
- package/dist/packages/ai-toolkit-nx-claude/src/index.d.ts.map +1 -1
- package/generators.json +0 -5
- package/package.json +2 -3
- package/dist/generators/hooks/CLAUDE.md +0 -378
- package/dist/generators/hooks/README.md +0 -220
- package/dist/generators/hooks/generator.cjs +0 -1265
- package/dist/generators/hooks/schema.json +0 -41
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/cli-parser.d.ts +0 -2
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/cli-parser.d.ts.map +0 -1
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/dependency-checker.d.ts +0 -46
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/dependency-checker.d.ts.map +0 -1
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/generator.d.ts +0 -9
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/generator.d.ts.map +0 -1
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/install-orchestrator.d.ts +0 -55
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/install-orchestrator.d.ts.map +0 -1
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/repo-manager.d.ts +0 -63
- package/dist/packages/ai-toolkit-nx-claude/src/generators/hooks/repo-manager.d.ts.map +0 -1
|
@@ -1,1265 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// packages/ai-toolkit-nx-claude/src/generators/hooks/generator.ts
|
|
31
|
-
var generator_exports = {};
|
|
32
|
-
__export(generator_exports, {
|
|
33
|
-
default: () => generator_default,
|
|
34
|
-
hooksGenerator: () => hooksGenerator
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(generator_exports);
|
|
37
|
-
var import_devkit4 = require("@nx/devkit");
|
|
38
|
-
var path3 = __toESM(require("path"));
|
|
39
|
-
|
|
40
|
-
// packages/ai-toolkit-nx-claude/src/utils/prompt-utils.ts
|
|
41
|
-
var import_enquirer = require("enquirer");
|
|
42
|
-
var fs = __toESM(require("fs"));
|
|
43
|
-
async function promptForMissingOptions(options, schemaPath, context = {}, explicitlyProvidedOptions) {
|
|
44
|
-
let schema;
|
|
45
|
-
if (typeof schemaPath === "string") {
|
|
46
|
-
const schemaContent = fs.readFileSync(schemaPath, "utf-8");
|
|
47
|
-
schema = JSON.parse(schemaContent);
|
|
48
|
-
} else {
|
|
49
|
-
schema = schemaPath;
|
|
50
|
-
}
|
|
51
|
-
const result = { ...options };
|
|
52
|
-
if (result["no-interactive"] || result.noInteractive || result["non-interactive"] || result.nonInteractive) {
|
|
53
|
-
for (const [key, property] of Object.entries(schema.properties)) {
|
|
54
|
-
if (result[key] === void 0 && property.default !== void 0) {
|
|
55
|
-
result[key] = property.default;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return result;
|
|
59
|
-
}
|
|
60
|
-
for (const [key, property] of Object.entries(schema.properties)) {
|
|
61
|
-
let wasExplicitlyProvided = false;
|
|
62
|
-
if (explicitlyProvidedOptions) {
|
|
63
|
-
if (explicitlyProvidedOptions instanceof Map) {
|
|
64
|
-
wasExplicitlyProvided = explicitlyProvidedOptions.has(key) || explicitlyProvidedOptions.has(key.replace(/-/g, ""));
|
|
65
|
-
} else {
|
|
66
|
-
wasExplicitlyProvided = explicitlyProvidedOptions.has(key) || explicitlyProvidedOptions.has(key.replace(/-/g, ""));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (property["x-skip-prompt"]) {
|
|
70
|
-
if (result[key] === void 0 && property.default !== void 0) {
|
|
71
|
-
result[key] = property.default;
|
|
72
|
-
}
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
const shouldPrompt = property["always-prompt"] ? (
|
|
76
|
-
// For always-prompt fields, only skip if value was explicitly provided
|
|
77
|
-
!wasExplicitlyProvided
|
|
78
|
-
) : (
|
|
79
|
-
// For regular fields (backward compatibility with x-prompt),
|
|
80
|
-
// skip if value exists at all (provided or defaulted)
|
|
81
|
-
(result[key] === void 0 || result[key] === null) && !wasExplicitlyProvided
|
|
82
|
-
);
|
|
83
|
-
if (!shouldPrompt) {
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
if (key === "confirmLocalPath") {
|
|
87
|
-
if (result.installationType !== "local") {
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (key === "nonInteractive" || key === "non-interactive" || key === "no-interactive" || key === "noInteractive") {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
if (key === "force") {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
if (property["prompt-when"]) {
|
|
98
|
-
const shouldShow = evaluatePromptCondition(property["prompt-when"], result);
|
|
99
|
-
if (!shouldShow) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
const promptResult = await promptForProperty(key, property, context, result);
|
|
104
|
-
if (promptResult !== void 0) {
|
|
105
|
-
result[key] = promptResult;
|
|
106
|
-
if (key === "installMode" && promptResult === "default") {
|
|
107
|
-
result.installationType = "global";
|
|
108
|
-
result.installCommands = true;
|
|
109
|
-
result.installAgents = true;
|
|
110
|
-
result.installHooks = true;
|
|
111
|
-
result.hooksMode = "sound";
|
|
112
|
-
result.installAddons = true;
|
|
113
|
-
result.dry = false;
|
|
114
|
-
result.commandSelectionMode = "all";
|
|
115
|
-
result.agentSelectionMode = "all";
|
|
116
|
-
result.addonSelectionMode = "all";
|
|
117
|
-
if (context.defaultCommands) {
|
|
118
|
-
result.commands = context.defaultCommands;
|
|
119
|
-
}
|
|
120
|
-
if (context.defaultAgents) {
|
|
121
|
-
result.agents = context.defaultAgents;
|
|
122
|
-
}
|
|
123
|
-
if (explicitlyProvidedOptions instanceof Map) {
|
|
124
|
-
explicitlyProvidedOptions.set("installMode", "default");
|
|
125
|
-
explicitlyProvidedOptions.set("installationType", "global");
|
|
126
|
-
explicitlyProvidedOptions.set("installCommands", true);
|
|
127
|
-
explicitlyProvidedOptions.set("installAgents", true);
|
|
128
|
-
explicitlyProvidedOptions.set("installHooks", true);
|
|
129
|
-
explicitlyProvidedOptions.set("hooksMode", "sound");
|
|
130
|
-
explicitlyProvidedOptions.set("installAddons", true);
|
|
131
|
-
explicitlyProvidedOptions.set("dry", false);
|
|
132
|
-
explicitlyProvidedOptions.set("commandSelectionMode", "all");
|
|
133
|
-
explicitlyProvidedOptions.set("agentSelectionMode", "all");
|
|
134
|
-
explicitlyProvidedOptions.set("addonSelectionMode", "all");
|
|
135
|
-
if (context.defaultCommands) {
|
|
136
|
-
explicitlyProvidedOptions.set("commands", context.defaultCommands);
|
|
137
|
-
}
|
|
138
|
-
if (context.defaultAgents) {
|
|
139
|
-
explicitlyProvidedOptions.set("agents", context.defaultAgents);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (key === "confirmLocalPath" && result.installationType === "local" && promptResult === false) {
|
|
144
|
-
throw new Error("Installation cancelled - please run from your project root");
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
async function promptForProperty(key, property, context, currentValues) {
|
|
151
|
-
const promptMessage = getPromptMessage(key, property);
|
|
152
|
-
const promptType = property["prompt-type"] || (property.type === "boolean" ? "confirm" : property.enum ? "select" : property.type === "string" ? "input" : null);
|
|
153
|
-
if (promptType === "confirm" || property.type === "boolean") {
|
|
154
|
-
const { value } = await (0, import_enquirer.prompt)({
|
|
155
|
-
type: "confirm",
|
|
156
|
-
name: "value",
|
|
157
|
-
message: promptMessage,
|
|
158
|
-
initial: property.default ?? false
|
|
159
|
-
});
|
|
160
|
-
return value;
|
|
161
|
-
}
|
|
162
|
-
if (promptType === "list" && property["prompt-items"]) {
|
|
163
|
-
const { value } = await (0, import_enquirer.prompt)({
|
|
164
|
-
type: "select",
|
|
165
|
-
name: "value",
|
|
166
|
-
message: promptMessage,
|
|
167
|
-
choices: property["prompt-items"].map((item) => ({
|
|
168
|
-
name: item.value,
|
|
169
|
-
value: item.value,
|
|
170
|
-
message: item.label
|
|
171
|
-
}))
|
|
172
|
-
});
|
|
173
|
-
return value;
|
|
174
|
-
}
|
|
175
|
-
if (property.enum || key === "package" && context.availablePackages) {
|
|
176
|
-
const choices = property.enum || context.availablePackages || [];
|
|
177
|
-
const { value } = await (0, import_enquirer.prompt)({
|
|
178
|
-
type: "select",
|
|
179
|
-
name: "value",
|
|
180
|
-
message: promptMessage,
|
|
181
|
-
choices: choices.map((choice) => {
|
|
182
|
-
if (key === "package" && choice === "__create_new__") {
|
|
183
|
-
return {
|
|
184
|
-
name: "__create_new__",
|
|
185
|
-
value: "__create_new__",
|
|
186
|
-
message: "\u2795 Create new package"
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (key === "package") {
|
|
190
|
-
return { name: choice, value: choice, message: `\u{1F4E6} ${choice}` };
|
|
191
|
-
}
|
|
192
|
-
return { name: choice, value: choice };
|
|
193
|
-
})
|
|
194
|
-
});
|
|
195
|
-
return value;
|
|
196
|
-
}
|
|
197
|
-
if (property.type === "array") {
|
|
198
|
-
if (key === "commands" && context.availableCommands) {
|
|
199
|
-
const installationType = currentValues?.installationType;
|
|
200
|
-
let existingSet;
|
|
201
|
-
let otherLocationSet;
|
|
202
|
-
if (installationType === "global") {
|
|
203
|
-
existingSet = context.globalExistingCommands;
|
|
204
|
-
otherLocationSet = context.localExistingCommands;
|
|
205
|
-
} else if (installationType === "local") {
|
|
206
|
-
existingSet = context.localExistingCommands;
|
|
207
|
-
otherLocationSet = context.globalExistingCommands;
|
|
208
|
-
}
|
|
209
|
-
return await promptMultiSelectWithAll(
|
|
210
|
-
promptMessage,
|
|
211
|
-
context.availableCommands,
|
|
212
|
-
"commands",
|
|
213
|
-
context.commandDescriptions,
|
|
214
|
-
existingSet,
|
|
215
|
-
otherLocationSet,
|
|
216
|
-
installationType
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
if (key === "agents" && context.availableAgents) {
|
|
220
|
-
const installationType = currentValues?.installationType;
|
|
221
|
-
let existingSet;
|
|
222
|
-
let otherLocationSet;
|
|
223
|
-
if (installationType === "global") {
|
|
224
|
-
existingSet = context.globalExistingAgents;
|
|
225
|
-
otherLocationSet = context.localExistingAgents;
|
|
226
|
-
} else if (installationType === "local") {
|
|
227
|
-
existingSet = context.localExistingAgents;
|
|
228
|
-
otherLocationSet = context.globalExistingAgents;
|
|
229
|
-
}
|
|
230
|
-
return await promptMultiSelectWithAll(
|
|
231
|
-
promptMessage,
|
|
232
|
-
context.availableAgents,
|
|
233
|
-
"agents",
|
|
234
|
-
context.agentDescriptions,
|
|
235
|
-
existingSet,
|
|
236
|
-
otherLocationSet,
|
|
237
|
-
installationType
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
if (key === "skills" && context.availableSkills) {
|
|
241
|
-
const installationType = currentValues?.installationType;
|
|
242
|
-
let existingSet;
|
|
243
|
-
let otherLocationSet;
|
|
244
|
-
if (installationType === "global") {
|
|
245
|
-
existingSet = context.globalExistingSkills;
|
|
246
|
-
otherLocationSet = context.localExistingSkills;
|
|
247
|
-
} else if (installationType === "local") {
|
|
248
|
-
existingSet = context.localExistingSkills;
|
|
249
|
-
otherLocationSet = context.globalExistingSkills;
|
|
250
|
-
}
|
|
251
|
-
return await promptMultiSelectWithAll(
|
|
252
|
-
promptMessage,
|
|
253
|
-
context.availableSkills,
|
|
254
|
-
"skills",
|
|
255
|
-
context.skillDescriptions,
|
|
256
|
-
existingSet,
|
|
257
|
-
otherLocationSet,
|
|
258
|
-
installationType
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
if (key === "addons" && context.availableAddons) {
|
|
262
|
-
return await promptMultiSelectWithAll(
|
|
263
|
-
promptMessage,
|
|
264
|
-
context.availableAddons,
|
|
265
|
-
"addons",
|
|
266
|
-
context.addonDescriptions,
|
|
267
|
-
void 0,
|
|
268
|
-
// No existing set for addons
|
|
269
|
-
void 0,
|
|
270
|
-
// No other location set for addons
|
|
271
|
-
void 0
|
|
272
|
-
// No installation type for addons
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
return [];
|
|
276
|
-
}
|
|
277
|
-
if (property.type === "string") {
|
|
278
|
-
if (key === "targetPath") {
|
|
279
|
-
const { value: value2 } = await (0, import_enquirer.prompt)({
|
|
280
|
-
type: "input",
|
|
281
|
-
name: "value",
|
|
282
|
-
message: promptMessage,
|
|
283
|
-
initial: process.cwd()
|
|
284
|
-
});
|
|
285
|
-
return value2;
|
|
286
|
-
}
|
|
287
|
-
const { value } = await (0, import_enquirer.prompt)({
|
|
288
|
-
type: "input",
|
|
289
|
-
name: "value",
|
|
290
|
-
message: promptMessage,
|
|
291
|
-
initial: property.default ?? ""
|
|
292
|
-
});
|
|
293
|
-
return value;
|
|
294
|
-
}
|
|
295
|
-
return void 0;
|
|
296
|
-
}
|
|
297
|
-
async function promptMultiSelectWithAll(message, choices, type, descriptions, existingItems, otherLocationItems, installationType) {
|
|
298
|
-
const displayChoices = choices.map((choice) => {
|
|
299
|
-
let display = descriptions?.[choice] ? `${choice}: ${descriptions[choice]}` : choice;
|
|
300
|
-
const indicators = [];
|
|
301
|
-
if (existingItems?.has(choice)) {
|
|
302
|
-
indicators.push("will overwrite");
|
|
303
|
-
}
|
|
304
|
-
if (otherLocationItems?.has(choice)) {
|
|
305
|
-
const otherLocation = installationType === "global" ? "locally" : "globally";
|
|
306
|
-
indicators.push(`exists ${otherLocation}`);
|
|
307
|
-
}
|
|
308
|
-
if (indicators.length > 0) {
|
|
309
|
-
display += ` (${indicators.join(", ")})`;
|
|
310
|
-
}
|
|
311
|
-
return display;
|
|
312
|
-
});
|
|
313
|
-
const response = await (0, import_enquirer.prompt)({
|
|
314
|
-
type: "multiselect",
|
|
315
|
-
name: "selected",
|
|
316
|
-
message,
|
|
317
|
-
choices: displayChoices,
|
|
318
|
-
initial: displayChoices.map((_, index) => index),
|
|
319
|
-
// Select all by default
|
|
320
|
-
hint: "Use <space> to select, <a> to toggle all, <return> to submit",
|
|
321
|
-
validate: (value) => {
|
|
322
|
-
if (value.length === 0) {
|
|
323
|
-
return `Please select at least one ${type.slice(0, -1)}`;
|
|
324
|
-
}
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
});
|
|
328
|
-
const selected = response.selected || [];
|
|
329
|
-
const actualSelections = [];
|
|
330
|
-
for (const selection of selected) {
|
|
331
|
-
const colonIndex = selection.indexOf(":");
|
|
332
|
-
const parenIndex = selection.indexOf("(");
|
|
333
|
-
let endIndex = selection.length;
|
|
334
|
-
if (colonIndex > -1 && (parenIndex === -1 || colonIndex < parenIndex)) {
|
|
335
|
-
endIndex = colonIndex;
|
|
336
|
-
} else if (parenIndex > -1 && (colonIndex === -1 || parenIndex < colonIndex)) {
|
|
337
|
-
endIndex = parenIndex;
|
|
338
|
-
}
|
|
339
|
-
const name = selection.substring(0, endIndex).trim();
|
|
340
|
-
if (name && !actualSelections.includes(name)) {
|
|
341
|
-
actualSelections.push(name);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return actualSelections;
|
|
345
|
-
}
|
|
346
|
-
function getPromptMessage(key, property) {
|
|
347
|
-
if (property["prompt-message"]) {
|
|
348
|
-
return property["prompt-message"];
|
|
349
|
-
}
|
|
350
|
-
if (property["x-prompt"]) {
|
|
351
|
-
if (typeof property["x-prompt"] === "string") {
|
|
352
|
-
return property["x-prompt"];
|
|
353
|
-
}
|
|
354
|
-
if (property["x-prompt"].message) {
|
|
355
|
-
return property["x-prompt"].message;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
const description = property.description || "";
|
|
359
|
-
switch (key) {
|
|
360
|
-
case "installationType":
|
|
361
|
-
return "Would you like to install agents and commands globally or locally?";
|
|
362
|
-
case "confirmLocalPath":
|
|
363
|
-
return "Are you running this from the root of your project?";
|
|
364
|
-
case "commands":
|
|
365
|
-
return "Select commands to install (use <space> to select, <a> to toggle all):";
|
|
366
|
-
case "agents":
|
|
367
|
-
return "Select agents to install (use <space> to select, <a> to toggle all):";
|
|
368
|
-
case "force":
|
|
369
|
-
return "Overwrite existing installation?";
|
|
370
|
-
default:
|
|
371
|
-
return description || `Enter value for ${key}:`;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
function evaluatePromptCondition(condition, context) {
|
|
375
|
-
if (condition.includes(" && ")) {
|
|
376
|
-
const parts = condition.split(" && ");
|
|
377
|
-
return parts.every((part) => evaluateSingleCondition(part.trim(), context));
|
|
378
|
-
}
|
|
379
|
-
if (condition.includes(" || ")) {
|
|
380
|
-
const parts = condition.split(" || ");
|
|
381
|
-
return parts.some((part) => evaluateSingleCondition(part.trim(), context));
|
|
382
|
-
}
|
|
383
|
-
return evaluateSingleCondition(condition, context);
|
|
384
|
-
}
|
|
385
|
-
function evaluateSingleCondition(condition, context) {
|
|
386
|
-
const parts = condition.split(" ");
|
|
387
|
-
if (parts.length < 3) {
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
const field = parts[0];
|
|
391
|
-
const operator = parts[1];
|
|
392
|
-
const value = parts.slice(2).join(" ").replace(/['"]/g, "");
|
|
393
|
-
const fieldValue = context[field];
|
|
394
|
-
switch (operator) {
|
|
395
|
-
case "===":
|
|
396
|
-
if (value === "true") {
|
|
397
|
-
return fieldValue === true;
|
|
398
|
-
}
|
|
399
|
-
if (value === "false") {
|
|
400
|
-
return fieldValue === false;
|
|
401
|
-
}
|
|
402
|
-
return String(fieldValue) === value;
|
|
403
|
-
case "!==":
|
|
404
|
-
if (value === "true") {
|
|
405
|
-
return fieldValue !== true;
|
|
406
|
-
}
|
|
407
|
-
if (value === "false") {
|
|
408
|
-
return fieldValue !== false;
|
|
409
|
-
}
|
|
410
|
-
return String(fieldValue) !== value;
|
|
411
|
-
default:
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// packages/ai-toolkit-nx-claude/src/generators/hooks/dependency-checker.ts
|
|
417
|
-
var import_child_process = require("child_process");
|
|
418
|
-
var import_devkit = require("@nx/devkit");
|
|
419
|
-
function commandExists(command) {
|
|
420
|
-
try {
|
|
421
|
-
(0, import_child_process.execSync)(`which ${command}`, { stdio: "ignore" });
|
|
422
|
-
return true;
|
|
423
|
-
} catch {
|
|
424
|
-
return false;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
function getCommandVersion(command, versionFlag = "--version") {
|
|
428
|
-
try {
|
|
429
|
-
const output = (0, import_child_process.execSync)(`${command} ${versionFlag}`, {
|
|
430
|
-
encoding: "utf-8",
|
|
431
|
-
stdio: "pipe"
|
|
432
|
-
}).trim();
|
|
433
|
-
const versionMatch = output.match(/(\d+\.\d+\.\d+)/);
|
|
434
|
-
return versionMatch ? versionMatch[1] : output.split("\n")[0];
|
|
435
|
-
} catch {
|
|
436
|
-
return void 0;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
function checkDependencies() {
|
|
440
|
-
const status = {
|
|
441
|
-
hasNode: false,
|
|
442
|
-
hasNpm: false,
|
|
443
|
-
hasGit: false,
|
|
444
|
-
missingDependencies: []
|
|
445
|
-
};
|
|
446
|
-
if (commandExists("node")) {
|
|
447
|
-
status.hasNode = true;
|
|
448
|
-
status.nodeVersion = getCommandVersion("node");
|
|
449
|
-
} else {
|
|
450
|
-
status.missingDependencies.push("Node.js");
|
|
451
|
-
}
|
|
452
|
-
if (commandExists("npm")) {
|
|
453
|
-
status.hasNpm = true;
|
|
454
|
-
status.npmVersion = getCommandVersion("npm");
|
|
455
|
-
} else {
|
|
456
|
-
status.missingDependencies.push("npm");
|
|
457
|
-
}
|
|
458
|
-
if (commandExists("git")) {
|
|
459
|
-
status.hasGit = true;
|
|
460
|
-
status.gitVersion = getCommandVersion("git");
|
|
461
|
-
} else {
|
|
462
|
-
status.missingDependencies.push("Git");
|
|
463
|
-
}
|
|
464
|
-
return status;
|
|
465
|
-
}
|
|
466
|
-
function logDependencyStatus(status) {
|
|
467
|
-
import_devkit.logger.info("\u{1F4CB} Dependency Check Results:");
|
|
468
|
-
if (status.hasNode) {
|
|
469
|
-
import_devkit.logger.info(` \u2705 Node.js: ${status.nodeVersion || "installed"}`);
|
|
470
|
-
} else {
|
|
471
|
-
import_devkit.logger.error(" \u274C Node.js: not found");
|
|
472
|
-
}
|
|
473
|
-
if (status.hasNpm) {
|
|
474
|
-
import_devkit.logger.info(` \u2705 npm: ${status.npmVersion || "installed"}`);
|
|
475
|
-
} else {
|
|
476
|
-
import_devkit.logger.error(" \u274C npm: not found");
|
|
477
|
-
}
|
|
478
|
-
if (status.hasGit) {
|
|
479
|
-
import_devkit.logger.info(` \u2705 Git: ${status.gitVersion || "installed"}`);
|
|
480
|
-
} else {
|
|
481
|
-
import_devkit.logger.error(" \u274C Git: not found");
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
function hasAllDependencies(status) {
|
|
485
|
-
return status.missingDependencies.length === 0;
|
|
486
|
-
}
|
|
487
|
-
function getInstallInstructions(missingDeps) {
|
|
488
|
-
const instructions = [];
|
|
489
|
-
if (missingDeps.includes("Node.js") || missingDeps.includes("npm")) {
|
|
490
|
-
instructions.push(
|
|
491
|
-
"\u{1F4E6} Node.js and npm:",
|
|
492
|
-
" \u2022 macOS: brew install node",
|
|
493
|
-
" \u2022 Linux: sudo apt-get install nodejs npm",
|
|
494
|
-
" \u2022 Windows: Download from https://nodejs.org/",
|
|
495
|
-
""
|
|
496
|
-
);
|
|
497
|
-
}
|
|
498
|
-
if (missingDeps.includes("Git")) {
|
|
499
|
-
instructions.push(
|
|
500
|
-
"\u{1F4E6} Git:",
|
|
501
|
-
" \u2022 macOS: brew install git",
|
|
502
|
-
" \u2022 Linux: sudo apt-get install git",
|
|
503
|
-
" \u2022 Windows: Download from https://git-scm.com/",
|
|
504
|
-
""
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
|
-
return instructions.join("\n");
|
|
508
|
-
}
|
|
509
|
-
function validateVersions(status) {
|
|
510
|
-
const MIN_NODE_VERSION = "16.0.0";
|
|
511
|
-
const MIN_NPM_VERSION = "7.0.0";
|
|
512
|
-
const MIN_GIT_VERSION = "2.0.0";
|
|
513
|
-
const compareVersions = (current, minimum) => {
|
|
514
|
-
if (!current) return false;
|
|
515
|
-
const currentParts = current.split(".").map(Number);
|
|
516
|
-
const minimumParts = minimum.split(".").map(Number);
|
|
517
|
-
for (let i = 0; i < minimumParts.length; i++) {
|
|
518
|
-
if (currentParts[i] > minimumParts[i]) return true;
|
|
519
|
-
if (currentParts[i] < minimumParts[i]) return false;
|
|
520
|
-
}
|
|
521
|
-
return true;
|
|
522
|
-
};
|
|
523
|
-
if (status.hasNode && !compareVersions(status.nodeVersion, MIN_NODE_VERSION)) {
|
|
524
|
-
import_devkit.logger.warn(
|
|
525
|
-
`\u26A0\uFE0F Node.js version ${status.nodeVersion} is below minimum required version ${MIN_NODE_VERSION}`
|
|
526
|
-
);
|
|
527
|
-
return false;
|
|
528
|
-
}
|
|
529
|
-
if (status.hasNpm && !compareVersions(status.npmVersion, MIN_NPM_VERSION)) {
|
|
530
|
-
import_devkit.logger.warn(
|
|
531
|
-
`\u26A0\uFE0F npm version ${status.npmVersion} is below minimum required version ${MIN_NPM_VERSION}`
|
|
532
|
-
);
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
535
|
-
if (status.hasGit && !compareVersions(status.gitVersion, MIN_GIT_VERSION)) {
|
|
536
|
-
import_devkit.logger.warn(
|
|
537
|
-
`\u26A0\uFE0F Git version ${status.gitVersion} is below minimum required version ${MIN_GIT_VERSION}`
|
|
538
|
-
);
|
|
539
|
-
return false;
|
|
540
|
-
}
|
|
541
|
-
return true;
|
|
542
|
-
}
|
|
543
|
-
async function checkAndValidateDependencies() {
|
|
544
|
-
const status = checkDependencies();
|
|
545
|
-
logDependencyStatus(status);
|
|
546
|
-
if (!hasAllDependencies(status)) {
|
|
547
|
-
import_devkit.logger.error("\n\u274C Missing required dependencies:");
|
|
548
|
-
import_devkit.logger.info(getInstallInstructions(status.missingDependencies));
|
|
549
|
-
return false;
|
|
550
|
-
}
|
|
551
|
-
if (!validateVersions(status)) {
|
|
552
|
-
import_devkit.logger.error(
|
|
553
|
-
"\n\u274C Some dependencies do not meet minimum version requirements"
|
|
554
|
-
);
|
|
555
|
-
import_devkit.logger.info("Please update the affected tools to continue.");
|
|
556
|
-
return false;
|
|
557
|
-
}
|
|
558
|
-
import_devkit.logger.info("\n\u2705 All dependencies satisfied!");
|
|
559
|
-
return true;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// packages/ai-toolkit-nx-claude/src/generators/hooks/repo-manager.ts
|
|
563
|
-
var import_child_process2 = require("child_process");
|
|
564
|
-
var import_devkit2 = require("@nx/devkit");
|
|
565
|
-
var fs2 = __toESM(require("fs"));
|
|
566
|
-
var path = __toESM(require("path"));
|
|
567
|
-
var os = __toESM(require("os"));
|
|
568
|
-
var DEFAULT_REPO_URL = "https://github.com/pascalporedda/awesome-claude-code.git";
|
|
569
|
-
function getRepoPath(customPath) {
|
|
570
|
-
if (customPath) {
|
|
571
|
-
return customPath;
|
|
572
|
-
}
|
|
573
|
-
return path.join(os.tmpdir(), "claude-hooks-temp");
|
|
574
|
-
}
|
|
575
|
-
function isGitRepository(repoPath) {
|
|
576
|
-
try {
|
|
577
|
-
if (!fs2.existsSync(repoPath)) {
|
|
578
|
-
return false;
|
|
579
|
-
}
|
|
580
|
-
(0, import_child_process2.execSync)("git rev-parse --git-dir", {
|
|
581
|
-
cwd: repoPath,
|
|
582
|
-
stdio: "ignore"
|
|
583
|
-
});
|
|
584
|
-
return true;
|
|
585
|
-
} catch {
|
|
586
|
-
return false;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
function getCurrentBranch(repoPath) {
|
|
590
|
-
try {
|
|
591
|
-
const branch = (0, import_child_process2.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
592
|
-
cwd: repoPath,
|
|
593
|
-
encoding: "utf-8"
|
|
594
|
-
}).trim();
|
|
595
|
-
return branch;
|
|
596
|
-
} catch {
|
|
597
|
-
return void 0;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
function getLastCommit(repoPath) {
|
|
601
|
-
try {
|
|
602
|
-
const commit = (0, import_child_process2.execSync)("git rev-parse HEAD", {
|
|
603
|
-
cwd: repoPath,
|
|
604
|
-
encoding: "utf-8"
|
|
605
|
-
}).trim();
|
|
606
|
-
return commit.substring(0, 7);
|
|
607
|
-
} catch {
|
|
608
|
-
return void 0;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
function isDirty(repoPath) {
|
|
612
|
-
try {
|
|
613
|
-
const status = (0, import_child_process2.execSync)("git status --porcelain", {
|
|
614
|
-
cwd: repoPath,
|
|
615
|
-
encoding: "utf-8"
|
|
616
|
-
}).trim();
|
|
617
|
-
return status.length > 0;
|
|
618
|
-
} catch {
|
|
619
|
-
return false;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
function getRemoteUrl(repoPath) {
|
|
623
|
-
try {
|
|
624
|
-
const url = (0, import_child_process2.execSync)("git config --get remote.origin.url", {
|
|
625
|
-
cwd: repoPath,
|
|
626
|
-
encoding: "utf-8"
|
|
627
|
-
}).trim();
|
|
628
|
-
return url;
|
|
629
|
-
} catch {
|
|
630
|
-
return void 0;
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
function getRepoStatus(repoPath) {
|
|
634
|
-
const exists = fs2.existsSync(repoPath);
|
|
635
|
-
const isGit = exists && isGitRepository(repoPath);
|
|
636
|
-
const status = {
|
|
637
|
-
exists,
|
|
638
|
-
path: repoPath,
|
|
639
|
-
isGitRepo: isGit
|
|
640
|
-
};
|
|
641
|
-
if (isGit) {
|
|
642
|
-
status.currentBranch = getCurrentBranch(repoPath);
|
|
643
|
-
status.lastCommit = getLastCommit(repoPath);
|
|
644
|
-
status.isDirty = isDirty(repoPath);
|
|
645
|
-
status.remoteUrl = getRemoteUrl(repoPath);
|
|
646
|
-
}
|
|
647
|
-
return status;
|
|
648
|
-
}
|
|
649
|
-
async function cloneRepository(repoUrl = DEFAULT_REPO_URL, targetPath, verbose = false) {
|
|
650
|
-
const repoPath = getRepoPath(targetPath);
|
|
651
|
-
try {
|
|
652
|
-
if (fs2.existsSync(repoPath)) {
|
|
653
|
-
import_devkit2.logger.warn(`Directory already exists: ${repoPath}`);
|
|
654
|
-
if (isGitRepository(repoPath)) {
|
|
655
|
-
import_devkit2.logger.info("Existing git repository found");
|
|
656
|
-
return true;
|
|
657
|
-
} else {
|
|
658
|
-
import_devkit2.logger.info("Removing non-git directory...");
|
|
659
|
-
fs2.rmSync(repoPath, { recursive: true, force: true });
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
import_devkit2.logger.info(`\u{1F4E5} Downloading notification hooks...`);
|
|
663
|
-
try {
|
|
664
|
-
(0, import_child_process2.execSync)(`git clone ${repoUrl} "${repoPath}"`, {
|
|
665
|
-
stdio: verbose ? "inherit" : "ignore"
|
|
666
|
-
});
|
|
667
|
-
import_devkit2.logger.info("\u2705 Download complete");
|
|
668
|
-
return true;
|
|
669
|
-
} catch (httpsError) {
|
|
670
|
-
if (repoUrl === DEFAULT_REPO_URL) {
|
|
671
|
-
import_devkit2.logger.warn("HTTPS clone failed, trying SSH...");
|
|
672
|
-
const sshUrl = "git@github.com:pascalporedda/awesome-claude-code.git";
|
|
673
|
-
try {
|
|
674
|
-
(0, import_child_process2.execSync)(`git clone ${sshUrl} "${repoPath}"`, {
|
|
675
|
-
stdio: verbose ? "inherit" : "ignore"
|
|
676
|
-
});
|
|
677
|
-
import_devkit2.logger.info("\u2705 Download complete via SSH");
|
|
678
|
-
return true;
|
|
679
|
-
} catch (sshError) {
|
|
680
|
-
import_devkit2.logger.error("\u274C Both HTTPS and SSH clone attempts failed");
|
|
681
|
-
throw sshError;
|
|
682
|
-
}
|
|
683
|
-
} else {
|
|
684
|
-
throw httpsError;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
} catch (error) {
|
|
688
|
-
import_devkit2.logger.error(`\u274C Failed to download hooks: ${error}`);
|
|
689
|
-
return false;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
async function updateRepository(repoPath, verbose = false) {
|
|
693
|
-
try {
|
|
694
|
-
if (!isGitRepository(repoPath)) {
|
|
695
|
-
import_devkit2.logger.error("Not a git repository");
|
|
696
|
-
return false;
|
|
697
|
-
}
|
|
698
|
-
if (isDirty(repoPath)) {
|
|
699
|
-
import_devkit2.logger.warn("\u26A0\uFE0F Repository has uncommitted changes");
|
|
700
|
-
import_devkit2.logger.info("Stashing changes...");
|
|
701
|
-
(0, import_child_process2.execSync)("git stash", {
|
|
702
|
-
cwd: repoPath,
|
|
703
|
-
stdio: verbose ? "inherit" : "ignore"
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
import_devkit2.logger.info("\u{1F4E5} Updating to latest version...");
|
|
707
|
-
(0, import_child_process2.execSync)("git fetch origin", {
|
|
708
|
-
cwd: repoPath,
|
|
709
|
-
stdio: verbose ? "inherit" : "ignore"
|
|
710
|
-
});
|
|
711
|
-
(0, import_child_process2.execSync)("git pull origin main", {
|
|
712
|
-
cwd: repoPath,
|
|
713
|
-
stdio: verbose ? "inherit" : "ignore"
|
|
714
|
-
});
|
|
715
|
-
import_devkit2.logger.info("\u2705 Update complete");
|
|
716
|
-
return true;
|
|
717
|
-
} catch (error) {
|
|
718
|
-
import_devkit2.logger.error(`\u274C Failed to update: ${error}`);
|
|
719
|
-
return false;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
function cleanupRepository(repoPath) {
|
|
723
|
-
try {
|
|
724
|
-
if (fs2.existsSync(repoPath)) {
|
|
725
|
-
fs2.rmSync(repoPath, { recursive: true, force: true });
|
|
726
|
-
import_devkit2.logger.info("\u{1F9F9} Temporary files cleaned up");
|
|
727
|
-
return true;
|
|
728
|
-
}
|
|
729
|
-
return true;
|
|
730
|
-
} catch (error) {
|
|
731
|
-
import_devkit2.logger.error(`\u274C Failed to cleanup: ${error}`);
|
|
732
|
-
return false;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
async function ensureRepository(options) {
|
|
736
|
-
const repoUrl = options.repoUrl || DEFAULT_REPO_URL;
|
|
737
|
-
const repoPath = getRepoPath(options.targetPath);
|
|
738
|
-
const status = getRepoStatus(repoPath);
|
|
739
|
-
if (options.verbose) {
|
|
740
|
-
import_devkit2.logger.info("Repository status:");
|
|
741
|
-
import_devkit2.logger.info(` Path: ${status.path}`);
|
|
742
|
-
import_devkit2.logger.info(` Exists: ${status.exists}`);
|
|
743
|
-
import_devkit2.logger.info(` Is Git Repo: ${status.isGitRepo}`);
|
|
744
|
-
if (status.isGitRepo) {
|
|
745
|
-
import_devkit2.logger.info(` Branch: ${status.currentBranch}`);
|
|
746
|
-
import_devkit2.logger.info(` Last Commit: ${status.lastCommit}`);
|
|
747
|
-
import_devkit2.logger.info(` Has Changes: ${status.isDirty}`);
|
|
748
|
-
import_devkit2.logger.info(` Remote URL: ${status.remoteUrl}`);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
if (status.exists && status.isGitRepo) {
|
|
752
|
-
if (status.remoteUrl && !status.remoteUrl.includes("awesome-claude-code")) {
|
|
753
|
-
cleanupRepository(repoPath);
|
|
754
|
-
const cloned2 = await cloneRepository(
|
|
755
|
-
DEFAULT_REPO_URL,
|
|
756
|
-
options.targetPath,
|
|
757
|
-
options.verbose
|
|
758
|
-
);
|
|
759
|
-
if (!cloned2) {
|
|
760
|
-
return null;
|
|
761
|
-
}
|
|
762
|
-
return repoPath;
|
|
763
|
-
}
|
|
764
|
-
const updated = await updateRepository(repoPath, options.verbose);
|
|
765
|
-
if (!updated) {
|
|
766
|
-
import_devkit2.logger.warn("\u26A0\uFE0F Failed to update, using existing version");
|
|
767
|
-
}
|
|
768
|
-
return repoPath;
|
|
769
|
-
}
|
|
770
|
-
const cloned = await cloneRepository(
|
|
771
|
-
repoUrl,
|
|
772
|
-
options.targetPath,
|
|
773
|
-
options.verbose
|
|
774
|
-
);
|
|
775
|
-
if (!cloned) {
|
|
776
|
-
return null;
|
|
777
|
-
}
|
|
778
|
-
return repoPath;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
// packages/ai-toolkit-nx-claude/src/generators/hooks/install-orchestrator.ts
|
|
782
|
-
var import_child_process3 = require("child_process");
|
|
783
|
-
var import_devkit3 = require("@nx/devkit");
|
|
784
|
-
var path2 = __toESM(require("path"));
|
|
785
|
-
var fs3 = __toESM(require("fs"));
|
|
786
|
-
var os2 = __toESM(require("os"));
|
|
787
|
-
var ROOT_CLAUDE_DIR = path2.join(os2.homedir(), ".claude");
|
|
788
|
-
var HOOKS_DIR = path2.join(ROOT_CLAUDE_DIR, "hooks");
|
|
789
|
-
function backupExistingHooks(verbose = false) {
|
|
790
|
-
if (!fs3.existsSync(HOOKS_DIR)) {
|
|
791
|
-
if (verbose) {
|
|
792
|
-
import_devkit3.logger.info("No existing hooks to backup");
|
|
793
|
-
}
|
|
794
|
-
return null;
|
|
795
|
-
}
|
|
796
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
797
|
-
const backupDir = path2.join(ROOT_CLAUDE_DIR, `hooks-backup-${timestamp}`);
|
|
798
|
-
try {
|
|
799
|
-
if (verbose) {
|
|
800
|
-
import_devkit3.logger.info(`\u{1F4E6} Creating backup at: ${backupDir}`);
|
|
801
|
-
}
|
|
802
|
-
fs3.mkdirSync(backupDir, { recursive: true });
|
|
803
|
-
(0, import_child_process3.execSync)(`cp -r "${HOOKS_DIR}"/* "${backupDir}"/`, {
|
|
804
|
-
stdio: verbose ? "inherit" : "ignore"
|
|
805
|
-
});
|
|
806
|
-
const settingsPath = path2.join(ROOT_CLAUDE_DIR, "settings.json");
|
|
807
|
-
if (fs3.existsSync(settingsPath)) {
|
|
808
|
-
const backupSettingsPath = path2.join(backupDir, "settings.json.backup");
|
|
809
|
-
fs3.copyFileSync(settingsPath, backupSettingsPath);
|
|
810
|
-
}
|
|
811
|
-
import_devkit3.logger.info(`\u2705 Backup created at: ${backupDir}`);
|
|
812
|
-
return backupDir;
|
|
813
|
-
} catch (error) {
|
|
814
|
-
import_devkit3.logger.error(`\u274C Failed to create backup: ${error}`);
|
|
815
|
-
return null;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
async function executeInstallScript(scriptPath, options) {
|
|
819
|
-
return new Promise((resolve) => {
|
|
820
|
-
try {
|
|
821
|
-
if (options.dryRun) {
|
|
822
|
-
import_devkit3.logger.info("\u{1F50D} DRY RUN: Would execute install script with defaults");
|
|
823
|
-
resolve(true);
|
|
824
|
-
return;
|
|
825
|
-
}
|
|
826
|
-
import_devkit3.logger.info("\u{1F680} Running hook installation...");
|
|
827
|
-
const repoDir = path2.dirname(scriptPath);
|
|
828
|
-
const child = (0, import_child_process3.spawn)("bash", [scriptPath], {
|
|
829
|
-
stdio: ["pipe", options.verbose ? "inherit" : "pipe", "inherit"],
|
|
830
|
-
shell: true,
|
|
831
|
-
cwd: repoDir
|
|
832
|
-
// Set working directory to the repo directory
|
|
833
|
-
});
|
|
834
|
-
if (child.stdin) {
|
|
835
|
-
child.stdin.write("1\n");
|
|
836
|
-
child.stdin.end();
|
|
837
|
-
}
|
|
838
|
-
child.on("close", (code) => {
|
|
839
|
-
if (code === 0) {
|
|
840
|
-
import_devkit3.logger.info("\u2705 Installation script completed successfully");
|
|
841
|
-
resolve(true);
|
|
842
|
-
} else {
|
|
843
|
-
import_devkit3.logger.error(`\u274C Installation script exited with code ${code}`);
|
|
844
|
-
resolve(false);
|
|
845
|
-
}
|
|
846
|
-
});
|
|
847
|
-
child.on("error", (error) => {
|
|
848
|
-
import_devkit3.logger.error(`\u274C Failed to execute install script: ${error}`);
|
|
849
|
-
resolve(false);
|
|
850
|
-
});
|
|
851
|
-
} catch (error) {
|
|
852
|
-
import_devkit3.logger.error(`\u274C Error executing install script: ${error}`);
|
|
853
|
-
resolve(false);
|
|
854
|
-
}
|
|
855
|
-
});
|
|
856
|
-
}
|
|
857
|
-
function fixHookPaths(verbose = false) {
|
|
858
|
-
const settingsPath = path2.join(ROOT_CLAUDE_DIR, "settings.json");
|
|
859
|
-
if (!fs3.existsSync(settingsPath)) {
|
|
860
|
-
if (verbose) {
|
|
861
|
-
import_devkit3.logger.warn("\u26A0\uFE0F settings.json not found - cannot fix paths");
|
|
862
|
-
}
|
|
863
|
-
return false;
|
|
864
|
-
}
|
|
865
|
-
try {
|
|
866
|
-
const settings = JSON.parse(fs3.readFileSync(settingsPath, "utf-8"));
|
|
867
|
-
if (!settings.hooks) {
|
|
868
|
-
if (verbose) {
|
|
869
|
-
import_devkit3.logger.warn("\u26A0\uFE0F No hooks configuration found in settings.json");
|
|
870
|
-
}
|
|
871
|
-
return false;
|
|
872
|
-
}
|
|
873
|
-
const homeDir = os2.homedir();
|
|
874
|
-
let modified = false;
|
|
875
|
-
const fixPathInHooks = (hookArray) => {
|
|
876
|
-
for (const hookConfig of hookArray) {
|
|
877
|
-
if (hookConfig.hooks && Array.isArray(hookConfig.hooks)) {
|
|
878
|
-
for (const hook of hookConfig.hooks) {
|
|
879
|
-
if (hook.command && typeof hook.command === "string") {
|
|
880
|
-
if (hook.command.includes(homeDir)) {
|
|
881
|
-
hook.command = hook.command.replace(homeDir, "~");
|
|
882
|
-
modified = true;
|
|
883
|
-
}
|
|
884
|
-
const pathMatch = hook.command.match(/\/(Users|home)\/[^/]+\/\.claude\/hooks\//);
|
|
885
|
-
if (pathMatch) {
|
|
886
|
-
hook.command = hook.command.replace(pathMatch[0], "~/.claude/hooks/");
|
|
887
|
-
modified = true;
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
};
|
|
894
|
-
const hookTypes = ["Notification", "Stop", "SubagentStop", "PreToolUse", "PostToolUse"];
|
|
895
|
-
for (const hookType of hookTypes) {
|
|
896
|
-
if (settings.hooks[hookType] && Array.isArray(settings.hooks[hookType])) {
|
|
897
|
-
fixPathInHooks(settings.hooks[hookType]);
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
if (modified) {
|
|
901
|
-
fs3.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
902
|
-
if (verbose) {
|
|
903
|
-
import_devkit3.logger.info("\u2705 Fixed hook paths to use ~ expansion for Docker compatibility");
|
|
904
|
-
}
|
|
905
|
-
return true;
|
|
906
|
-
}
|
|
907
|
-
return true;
|
|
908
|
-
} catch (error) {
|
|
909
|
-
import_devkit3.logger.error(`\u274C Failed to fix hook paths: ${error}`);
|
|
910
|
-
return false;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
function verifyInstallation() {
|
|
914
|
-
const expectedFiles = ["notification.ts", "stop.ts", "subagent_stop.ts"];
|
|
915
|
-
const installedFiles = [];
|
|
916
|
-
const missingFiles = [];
|
|
917
|
-
for (const file of expectedFiles) {
|
|
918
|
-
const filePath = path2.join(HOOKS_DIR, file);
|
|
919
|
-
if (fs3.existsSync(filePath)) {
|
|
920
|
-
installedFiles.push(filePath);
|
|
921
|
-
} else {
|
|
922
|
-
missingFiles.push(file);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
if (missingFiles.length > 0) {
|
|
926
|
-
import_devkit3.logger.warn(`\u26A0\uFE0F Missing expected files: ${missingFiles.join(", ")}`);
|
|
927
|
-
return null;
|
|
928
|
-
}
|
|
929
|
-
const settingsPath = path2.join(ROOT_CLAUDE_DIR, "settings.json");
|
|
930
|
-
if (!fs3.existsSync(settingsPath)) {
|
|
931
|
-
import_devkit3.logger.warn("\u26A0\uFE0F settings.json not found");
|
|
932
|
-
return null;
|
|
933
|
-
}
|
|
934
|
-
try {
|
|
935
|
-
const settings = JSON.parse(fs3.readFileSync(settingsPath, "utf-8"));
|
|
936
|
-
if (!settings.hooks) {
|
|
937
|
-
import_devkit3.logger.warn("\u26A0\uFE0F No hooks configuration found in settings.json");
|
|
938
|
-
return null;
|
|
939
|
-
}
|
|
940
|
-
import_devkit3.logger.info("\u2705 Installation verified successfully");
|
|
941
|
-
return installedFiles;
|
|
942
|
-
} catch (error) {
|
|
943
|
-
import_devkit3.logger.error(`\u274C Failed to verify settings.json: ${error}`);
|
|
944
|
-
return null;
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
async function runInstallation(repoPath, options) {
|
|
948
|
-
const result = {
|
|
949
|
-
success: false,
|
|
950
|
-
installedPath: HOOKS_DIR
|
|
951
|
-
};
|
|
952
|
-
try {
|
|
953
|
-
const installScriptPath = path2.join(repoPath, "install-global.sh");
|
|
954
|
-
if (!fs3.existsSync(installScriptPath)) {
|
|
955
|
-
throw new Error(`Install script not found at: ${installScriptPath}`);
|
|
956
|
-
}
|
|
957
|
-
(0, import_child_process3.execSync)(`chmod +x "${installScriptPath}"`, { stdio: "ignore" });
|
|
958
|
-
if (options.backupExisting) {
|
|
959
|
-
const backupPath = backupExistingHooks(options.verbose);
|
|
960
|
-
if (backupPath) {
|
|
961
|
-
result.backupPath = backupPath;
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
const installSuccess = await executeInstallScript(
|
|
965
|
-
installScriptPath,
|
|
966
|
-
options
|
|
967
|
-
);
|
|
968
|
-
if (!installSuccess) {
|
|
969
|
-
throw new Error("Installation script failed");
|
|
970
|
-
}
|
|
971
|
-
const installedFiles = verifyInstallation();
|
|
972
|
-
if (!installedFiles) {
|
|
973
|
-
throw new Error("Installation verification failed");
|
|
974
|
-
}
|
|
975
|
-
fixHookPaths(options.verbose);
|
|
976
|
-
result.success = true;
|
|
977
|
-
result.installedFiles = installedFiles;
|
|
978
|
-
import_devkit3.logger.info("\n\u{1F4CB} Installation Summary:");
|
|
979
|
-
import_devkit3.logger.info(` \u2705 Hooks installed to: ${result.installedPath}`);
|
|
980
|
-
if (result.backupPath) {
|
|
981
|
-
import_devkit3.logger.info(` \u2705 Backup created at: ${result.backupPath}`);
|
|
982
|
-
}
|
|
983
|
-
import_devkit3.logger.info(` \u2705 Files installed: ${installedFiles.length}`);
|
|
984
|
-
return result;
|
|
985
|
-
} catch (error) {
|
|
986
|
-
result.error = error instanceof Error ? error.message : String(error);
|
|
987
|
-
import_devkit3.logger.error(`\u274C Installation failed: ${result.error}`);
|
|
988
|
-
if (result.backupPath && !options.dryRun) {
|
|
989
|
-
import_devkit3.logger.info("\u{1F504} Attempting to restore backup...");
|
|
990
|
-
await restoreBackup(result.backupPath);
|
|
991
|
-
}
|
|
992
|
-
return result;
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
async function restoreBackup(backupPath) {
|
|
996
|
-
try {
|
|
997
|
-
if (fs3.existsSync(HOOKS_DIR)) {
|
|
998
|
-
fs3.rmSync(HOOKS_DIR, { recursive: true, force: true });
|
|
999
|
-
}
|
|
1000
|
-
fs3.mkdirSync(HOOKS_DIR, { recursive: true });
|
|
1001
|
-
(0, import_child_process3.execSync)(`cp -r "${backupPath}"/* "${HOOKS_DIR}"/`, {
|
|
1002
|
-
stdio: "ignore"
|
|
1003
|
-
});
|
|
1004
|
-
const backupSettingsPath = path2.join(backupPath, "settings.json.backup");
|
|
1005
|
-
if (fs3.existsSync(backupSettingsPath)) {
|
|
1006
|
-
const settingsPath = path2.join(ROOT_CLAUDE_DIR, "settings.json");
|
|
1007
|
-
fs3.copyFileSync(backupSettingsPath, settingsPath);
|
|
1008
|
-
}
|
|
1009
|
-
import_devkit3.logger.info("\u2705 Backup restored successfully");
|
|
1010
|
-
return true;
|
|
1011
|
-
} catch (error) {
|
|
1012
|
-
import_devkit3.logger.error(`\u274C Failed to restore backup: ${error}`);
|
|
1013
|
-
return false;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
async function testHooks() {
|
|
1017
|
-
try {
|
|
1018
|
-
import_devkit3.logger.info("\u{1F9EA} Testing installed hooks...");
|
|
1019
|
-
const testPayload = {
|
|
1020
|
-
hook_event_name: "Notification",
|
|
1021
|
-
session_id: "test-session",
|
|
1022
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1023
|
-
cwd: process.cwd()
|
|
1024
|
-
};
|
|
1025
|
-
const notificationHook = path2.join(HOOKS_DIR, "notification.ts");
|
|
1026
|
-
if (!fs3.existsSync(notificationHook)) {
|
|
1027
|
-
import_devkit3.logger.error("\u274C Notification hook not found");
|
|
1028
|
-
return false;
|
|
1029
|
-
}
|
|
1030
|
-
const command = `echo '${JSON.stringify(
|
|
1031
|
-
testPayload
|
|
1032
|
-
)}' | npx tsx "${notificationHook}" --notify`;
|
|
1033
|
-
import_devkit3.logger.info("\u{1F514} Triggering test notification...");
|
|
1034
|
-
(0, import_child_process3.execSync)(command, { stdio: "inherit" });
|
|
1035
|
-
import_devkit3.logger.info("\u2705 Hook test completed successfully");
|
|
1036
|
-
import_devkit3.logger.info("You should have heard a notification sound/speech");
|
|
1037
|
-
return true;
|
|
1038
|
-
} catch (error) {
|
|
1039
|
-
import_devkit3.logger.error(`\u274C Hook test failed: ${error}`);
|
|
1040
|
-
return false;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
// packages/ai-toolkit-nx-claude/src/utils/cli-parser.ts
|
|
1045
|
-
function getExplicitlyProvidedOptions(options) {
|
|
1046
|
-
const providedOptions = /* @__PURE__ */ new Map();
|
|
1047
|
-
const args = process.argv;
|
|
1048
|
-
for (let i = 0; i < args.length; i++) {
|
|
1049
|
-
const arg = args[i];
|
|
1050
|
-
if (arg.startsWith("--")) {
|
|
1051
|
-
if (arg.includes("=")) {
|
|
1052
|
-
const [flagPart, ...valueParts] = arg.split("=");
|
|
1053
|
-
const flagName = flagPart.slice(2);
|
|
1054
|
-
const value = valueParts.join("=");
|
|
1055
|
-
const camelCaseName = flagName.replace(
|
|
1056
|
-
/-([a-z])/g,
|
|
1057
|
-
(_, letter) => letter.toUpperCase()
|
|
1058
|
-
);
|
|
1059
|
-
const parsedValue = parseValue(value);
|
|
1060
|
-
providedOptions.set(flagName, parsedValue);
|
|
1061
|
-
providedOptions.set(camelCaseName, parsedValue);
|
|
1062
|
-
} else {
|
|
1063
|
-
const flagName = arg.slice(2);
|
|
1064
|
-
const camelCaseName = flagName.replace(
|
|
1065
|
-
/-([a-z])/g,
|
|
1066
|
-
(_, letter) => letter.toUpperCase()
|
|
1067
|
-
);
|
|
1068
|
-
if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
|
|
1069
|
-
const value = args[i + 1];
|
|
1070
|
-
const parsedValue = parseValue(value);
|
|
1071
|
-
providedOptions.set(flagName, parsedValue);
|
|
1072
|
-
providedOptions.set(camelCaseName, parsedValue);
|
|
1073
|
-
i++;
|
|
1074
|
-
} else {
|
|
1075
|
-
providedOptions.set(flagName, true);
|
|
1076
|
-
providedOptions.set(camelCaseName, true);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
} else if (arg.startsWith("-") && !arg.startsWith("--") && arg.length === 2) {
|
|
1080
|
-
const shortFlagMap = {
|
|
1081
|
-
d: "dry-run",
|
|
1082
|
-
v: "verbose",
|
|
1083
|
-
f: "force",
|
|
1084
|
-
h: "help"
|
|
1085
|
-
};
|
|
1086
|
-
const shortFlag = arg.slice(1);
|
|
1087
|
-
if (shortFlagMap[shortFlag]) {
|
|
1088
|
-
const longFlag = shortFlagMap[shortFlag];
|
|
1089
|
-
const camelCaseName = longFlag.replace(
|
|
1090
|
-
/-([a-z])/g,
|
|
1091
|
-
(_, letter) => letter.toUpperCase()
|
|
1092
|
-
);
|
|
1093
|
-
providedOptions.set(longFlag, true);
|
|
1094
|
-
providedOptions.set(camelCaseName, true);
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
if (options) {
|
|
1099
|
-
for (const [key, value] of Object.entries(options)) {
|
|
1100
|
-
providedOptions.set(key, value);
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
return providedOptions;
|
|
1104
|
-
}
|
|
1105
|
-
function parseValue(value) {
|
|
1106
|
-
if (value === "true") return true;
|
|
1107
|
-
if (value === "false") return false;
|
|
1108
|
-
if (/^-?\d+$/.test(value)) {
|
|
1109
|
-
return parseInt(value, 10);
|
|
1110
|
-
}
|
|
1111
|
-
if (/^-?\d*\.\d+$/.test(value)) {
|
|
1112
|
-
return parseFloat(value);
|
|
1113
|
-
}
|
|
1114
|
-
if (value === "null") return null;
|
|
1115
|
-
if (value === "undefined") return void 0;
|
|
1116
|
-
return value;
|
|
1117
|
-
}
|
|
1118
|
-
function isNxDryRunProvided() {
|
|
1119
|
-
const args = process.argv;
|
|
1120
|
-
return (
|
|
1121
|
-
// Check for --dry-run
|
|
1122
|
-
args.some((a) => a === "--dry-run") || args.some((a) => a.startsWith("--dry-run=") && !a.endsWith("=false")) || // Check for --dryRun
|
|
1123
|
-
args.some((a) => a === "--dryRun") || args.some((a) => a.startsWith("--dryRun=") && !a.endsWith("=false")) || // Check for short form -d
|
|
1124
|
-
args.some((a) => a === "-d")
|
|
1125
|
-
);
|
|
1126
|
-
}
|
|
1127
|
-
function isNxNoInteractiveProvided() {
|
|
1128
|
-
const args = process.argv;
|
|
1129
|
-
return (
|
|
1130
|
-
// Check for --no-interactive
|
|
1131
|
-
args.some((a) => a === "--no-interactive") || args.some(
|
|
1132
|
-
(a) => a.startsWith("--no-interactive=") && !a.endsWith("=false")
|
|
1133
|
-
) || // Check for --noInteractive
|
|
1134
|
-
args.some((a) => a === "--noInteractive") || args.some((a) => a.startsWith("--noInteractive=") && !a.endsWith("=false"))
|
|
1135
|
-
);
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
|
-
// packages/ai-toolkit-nx-claude/src/generators/hooks/generator.ts
|
|
1139
|
-
async function hooksGenerator(tree, options) {
|
|
1140
|
-
import_devkit4.logger.info("\u{1F3AF} Claude Code Hooks Generator");
|
|
1141
|
-
import_devkit4.logger.info("Installing notification hooks for Claude Code...\n");
|
|
1142
|
-
import_devkit4.logger.info("\u{1F4CB} Step 1: Checking dependencies...");
|
|
1143
|
-
const depsOk = await checkAndValidateDependencies();
|
|
1144
|
-
if (!depsOk && !options.force) {
|
|
1145
|
-
import_devkit4.logger.error(
|
|
1146
|
-
"\u274C Missing required dependencies. Install them and try again."
|
|
1147
|
-
);
|
|
1148
|
-
import_devkit4.logger.info("Use --force to skip dependency checks (not recommended)");
|
|
1149
|
-
return;
|
|
1150
|
-
}
|
|
1151
|
-
const schemaPath = path3.join(__dirname, "schema.json");
|
|
1152
|
-
let normalizedOptions;
|
|
1153
|
-
if (options.installMode === "default") {
|
|
1154
|
-
normalizedOptions = {
|
|
1155
|
-
backup: options.backup !== false,
|
|
1156
|
-
// Default to true unless explicitly false
|
|
1157
|
-
dry: options.dry || false,
|
|
1158
|
-
force: options.force || false,
|
|
1159
|
-
verbose: options.verbose || false,
|
|
1160
|
-
installMode: "default"
|
|
1161
|
-
};
|
|
1162
|
-
} else {
|
|
1163
|
-
const explicitlyProvided = getExplicitlyProvidedOptions(options);
|
|
1164
|
-
const nxDryRunProvided = isNxDryRunProvided();
|
|
1165
|
-
if (nxDryRunProvided) {
|
|
1166
|
-
options.dry = true;
|
|
1167
|
-
explicitlyProvided.set("dry", true);
|
|
1168
|
-
}
|
|
1169
|
-
const nxNoInteractiveProvided = isNxNoInteractiveProvided();
|
|
1170
|
-
const optionsWithNoInteractive = {
|
|
1171
|
-
...options,
|
|
1172
|
-
"no-interactive": nxNoInteractiveProvided
|
|
1173
|
-
};
|
|
1174
|
-
try {
|
|
1175
|
-
normalizedOptions = await promptForMissingOptions(
|
|
1176
|
-
optionsWithNoInteractive,
|
|
1177
|
-
schemaPath,
|
|
1178
|
-
{},
|
|
1179
|
-
// context for multi-select (not used here)
|
|
1180
|
-
explicitlyProvided
|
|
1181
|
-
// pass the explicitly provided options
|
|
1182
|
-
);
|
|
1183
|
-
} catch (error) {
|
|
1184
|
-
if (error.message?.includes("Installation cancelled")) {
|
|
1185
|
-
import_devkit4.logger.warn(`\u274C ${error.message}`);
|
|
1186
|
-
return;
|
|
1187
|
-
}
|
|
1188
|
-
throw error;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
const isDryRun = normalizedOptions.dry;
|
|
1192
|
-
if (isDryRun) {
|
|
1193
|
-
import_devkit4.logger.info("\n\u{1F50D} DRY RUN MODE - No changes will be made");
|
|
1194
|
-
import_devkit4.logger.info("The following would be performed:");
|
|
1195
|
-
import_devkit4.logger.info(` 1. Download latest notification hooks`);
|
|
1196
|
-
import_devkit4.logger.info(` 2. Configure notification hooks`);
|
|
1197
|
-
import_devkit4.logger.info(` 3. Install hooks to ~/.claude/hooks/`);
|
|
1198
|
-
import_devkit4.logger.info(` 4. Update ~/.claude/settings.json`);
|
|
1199
|
-
if (normalizedOptions.backup) {
|
|
1200
|
-
import_devkit4.logger.info(` 5. Create backup of existing configuration`);
|
|
1201
|
-
}
|
|
1202
|
-
return;
|
|
1203
|
-
}
|
|
1204
|
-
import_devkit4.logger.info("\n\u{1F4E6} Step 2: Downloading notification hooks...");
|
|
1205
|
-
const repoPath = await ensureRepository({
|
|
1206
|
-
update: true,
|
|
1207
|
-
// Always update to latest
|
|
1208
|
-
verbose: normalizedOptions.verbose
|
|
1209
|
-
});
|
|
1210
|
-
if (!repoPath) {
|
|
1211
|
-
import_devkit4.logger.error("\u274C Failed to prepare repository");
|
|
1212
|
-
return;
|
|
1213
|
-
}
|
|
1214
|
-
import_devkit4.logger.info(`\u2705 Repository ready at: ${repoPath}`);
|
|
1215
|
-
import_devkit4.logger.info("\n\u{1F680} Step 3: Installing hooks...");
|
|
1216
|
-
const installResult = await runInstallation(repoPath, {
|
|
1217
|
-
backupExisting: normalizedOptions.backup !== false,
|
|
1218
|
-
verbose: normalizedOptions.verbose || false,
|
|
1219
|
-
dryRun: isDryRun
|
|
1220
|
-
});
|
|
1221
|
-
if (!installResult.success) {
|
|
1222
|
-
import_devkit4.logger.error("\u274C Installation failed");
|
|
1223
|
-
if (installResult.error) {
|
|
1224
|
-
import_devkit4.logger.error(`Error: ${installResult.error}`);
|
|
1225
|
-
}
|
|
1226
|
-
if (!normalizedOptions.verbose) {
|
|
1227
|
-
cleanupRepository(repoPath);
|
|
1228
|
-
}
|
|
1229
|
-
return;
|
|
1230
|
-
}
|
|
1231
|
-
const shouldTest = !isDryRun && normalizedOptions.verbose;
|
|
1232
|
-
if (shouldTest) {
|
|
1233
|
-
import_devkit4.logger.info("\n\u{1F9EA} Step 4: Testing installation...");
|
|
1234
|
-
const { prompt: prompt2 } = await import("enquirer");
|
|
1235
|
-
const { runTest } = await prompt2({
|
|
1236
|
-
type: "confirm",
|
|
1237
|
-
name: "runTest",
|
|
1238
|
-
message: "Would you like to test the hooks now?",
|
|
1239
|
-
initial: true
|
|
1240
|
-
});
|
|
1241
|
-
if (runTest) {
|
|
1242
|
-
await testHooks();
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
if (!normalizedOptions.verbose) {
|
|
1246
|
-
import_devkit4.logger.info("\n\u{1F9F9} Cleaning up temporary files...");
|
|
1247
|
-
cleanupRepository(repoPath);
|
|
1248
|
-
}
|
|
1249
|
-
await (0, import_devkit4.formatFiles)(tree);
|
|
1250
|
-
import_devkit4.logger.info("\n\u2728 SUCCESS! Claude Code hooks installed successfully!");
|
|
1251
|
-
import_devkit4.logger.info("\n\u{1F4DA} Next Steps:");
|
|
1252
|
-
import_devkit4.logger.info(" 1. Start a Claude Code session");
|
|
1253
|
-
import_devkit4.logger.info(" 2. When Claude needs your input, you'll hear a notification");
|
|
1254
|
-
import_devkit4.logger.info(" 3. Check ~/.claude/logs/ for event logs (if enabled)");
|
|
1255
|
-
if (installResult.backupPath) {
|
|
1256
|
-
import_devkit4.logger.info(`
|
|
1257
|
-
\u{1F4BE} Backup saved at: ${installResult.backupPath}`);
|
|
1258
|
-
}
|
|
1259
|
-
import_devkit4.logger.info("\n\u{1F389} Happy coding with Claude!");
|
|
1260
|
-
}
|
|
1261
|
-
var generator_default = hooksGenerator;
|
|
1262
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1263
|
-
0 && (module.exports = {
|
|
1264
|
-
hooksGenerator
|
|
1265
|
-
});
|