@gaosh3n/pi-package-manager 0.1.0 → 0.1.2
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 +11 -0
- package/index.ts +76 -655
- package/internal/controller.ts +298 -0
- package/internal/model.ts +45 -0
- package/internal/records.ts +81 -0
- package/internal/reports.ts +396 -0
- package/internal/runtime.ts +69 -0
- package/package.json +2 -1
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import {
|
|
2
|
+
keyText,
|
|
3
|
+
type ExtensionContext,
|
|
4
|
+
type ExecResult,
|
|
5
|
+
} from "@earendil-works/pi-coding-agent"
|
|
6
|
+
import { Box, Text } from "@earendil-works/pi-tui"
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
OUTPUT_PREVIEW_LINE_COUNT,
|
|
10
|
+
PACKAGE_MANAGER_TITLE,
|
|
11
|
+
PACKAGE_MANAGER_WIDGET_KEY,
|
|
12
|
+
type AutoUpdateOutcome,
|
|
13
|
+
type AutoUpdateRecord,
|
|
14
|
+
type InstallOutcome,
|
|
15
|
+
type PackageManagerReport,
|
|
16
|
+
type PackageStatusSnapshot,
|
|
17
|
+
type WidgetState,
|
|
18
|
+
} from "./model.ts"
|
|
19
|
+
|
|
20
|
+
interface ThemeLike {
|
|
21
|
+
fg(token: string, text: string): string
|
|
22
|
+
bg(token: string, text: string): string
|
|
23
|
+
bold(text: string): string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createReportEntryRenderer() {
|
|
27
|
+
return (
|
|
28
|
+
entry: { data?: PackageManagerReport },
|
|
29
|
+
{ expanded }: { expanded: boolean },
|
|
30
|
+
theme: ThemeLike,
|
|
31
|
+
) => {
|
|
32
|
+
const report = entry.data
|
|
33
|
+
|
|
34
|
+
if (!report) {
|
|
35
|
+
return undefined
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const toneColor =
|
|
39
|
+
report.tone === "error"
|
|
40
|
+
? "error"
|
|
41
|
+
: report.tone === "warning"
|
|
42
|
+
? "warning"
|
|
43
|
+
: report.tone === "success"
|
|
44
|
+
? "success"
|
|
45
|
+
: "accent"
|
|
46
|
+
const lineTextTone = report.lineTone === "dim" ? "dim" : "customMessageText"
|
|
47
|
+
const outputTextTone = report.outputTone === "dim" ? "dim" : lineTextTone
|
|
48
|
+
|
|
49
|
+
const box = new Box(1, 1, (text: string) => theme.bg("customMessageBg", text))
|
|
50
|
+
|
|
51
|
+
box.addChild(
|
|
52
|
+
new Text(
|
|
53
|
+
`${theme.fg(toneColor, "●")} ${theme.bold(theme.fg("customMessageLabel", report.title))}`,
|
|
54
|
+
0,
|
|
55
|
+
0,
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if (report.headline) {
|
|
60
|
+
box.addChild(new Text(theme.fg("text", report.headline), 0, 0))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (report.lines.length > 0) {
|
|
64
|
+
box.addChild(
|
|
65
|
+
new Text(
|
|
66
|
+
report.lines.map((line) => theme.fg(lineTextTone, line)).join("\n"),
|
|
67
|
+
0,
|
|
68
|
+
0,
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (report.output?.trim()) {
|
|
74
|
+
if (!expanded && report.hideOutputWhenCollapsed) {
|
|
75
|
+
box.addChild(
|
|
76
|
+
new Text(
|
|
77
|
+
formatExpandHint(
|
|
78
|
+
theme,
|
|
79
|
+
`to expand to see ${report.outputDescription ?? "output"}.`,
|
|
80
|
+
),
|
|
81
|
+
0,
|
|
82
|
+
0,
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
} else {
|
|
86
|
+
const { text, truncated } = formatReportOutput(report.output, expanded)
|
|
87
|
+
|
|
88
|
+
box.addChild(
|
|
89
|
+
new Text(
|
|
90
|
+
theme.fg(outputTextTone, report.outputLabel ?? "Output:"),
|
|
91
|
+
0,
|
|
92
|
+
0,
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
box.addChild(new Text(theme.fg(outputTextTone, text), 0, 0))
|
|
96
|
+
|
|
97
|
+
if (truncated) {
|
|
98
|
+
box.addChild(
|
|
99
|
+
new Text(
|
|
100
|
+
formatExpandHint(
|
|
101
|
+
theme,
|
|
102
|
+
`to expand to view the full ${report.outputDescription ?? "output"}.`,
|
|
103
|
+
),
|
|
104
|
+
0,
|
|
105
|
+
0,
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return box
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function formatUtcTimestamp(isoUtc: string): string {
|
|
117
|
+
return isoUtc.replace("T", " ").replace(/\.\d{3}Z$/, " UTC+00")
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function formatStatusLines(snapshot: PackageStatusSnapshot): string[] {
|
|
121
|
+
if (!snapshot.lastAutoUpdate) {
|
|
122
|
+
return ["Latest package update: none recorded."]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const lines = [
|
|
126
|
+
`Latest update start: ${formatUtcTimestamp(snapshot.lastAutoUpdate.startedAtUtc)}`,
|
|
127
|
+
`Latest update end: ${formatUtcTimestamp(snapshot.lastAutoUpdate.endedAtUtc)}`,
|
|
128
|
+
`Latest update result: ${snapshot.lastAutoUpdate.outcome}`,
|
|
129
|
+
`Latest update packages updated: ${snapshot.lastAutoUpdate.packagesUpdated}`,
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
if (snapshot.lastAutoUpdate.reason) {
|
|
133
|
+
lines.push(`Latest update detail: ${snapshot.lastAutoUpdate.reason}`)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return lines
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function createStatusReport(
|
|
140
|
+
snapshot: PackageStatusSnapshot,
|
|
141
|
+
): PackageManagerReport {
|
|
142
|
+
return {
|
|
143
|
+
title: PACKAGE_MANAGER_TITLE,
|
|
144
|
+
headline:
|
|
145
|
+
snapshot.availableUpdates.length === 0
|
|
146
|
+
? "No package updates are available."
|
|
147
|
+
: `${snapshot.availableUpdates.length} package update${snapshot.availableUpdates.length === 1 ? " is" : "s are"} available.`,
|
|
148
|
+
tone: snapshot.availableUpdates.length > 0 ? "warning" : "info",
|
|
149
|
+
lines: formatStatusLines(snapshot),
|
|
150
|
+
lineTone: "dim",
|
|
151
|
+
output:
|
|
152
|
+
snapshot.availableUpdates.length > 0
|
|
153
|
+
? snapshot.availableUpdates.map((name) => `- ${name}`).join("\n")
|
|
154
|
+
: undefined,
|
|
155
|
+
outputLabel:
|
|
156
|
+
snapshot.availableUpdates.length > 0 ? "Available updates:" : undefined,
|
|
157
|
+
outputTone: "dim",
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function createStatusErrorReport(
|
|
162
|
+
snapshot: PackageStatusSnapshot,
|
|
163
|
+
errorMessage: string,
|
|
164
|
+
): PackageManagerReport {
|
|
165
|
+
return {
|
|
166
|
+
title: PACKAGE_MANAGER_TITLE,
|
|
167
|
+
headline: "Package status check failed.",
|
|
168
|
+
tone: "error",
|
|
169
|
+
lines: formatStatusLines(snapshot),
|
|
170
|
+
lineTone: "dim",
|
|
171
|
+
output: `Failed to check package updates: ${errorMessage}`,
|
|
172
|
+
outputLabel: "Error detail:",
|
|
173
|
+
outputTone: "dim",
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function createAutoUpdateResultReport(input: {
|
|
178
|
+
record: AutoUpdateRecord
|
|
179
|
+
output?: string
|
|
180
|
+
reloadAfterSeconds?: number
|
|
181
|
+
}): PackageManagerReport {
|
|
182
|
+
const lines = [
|
|
183
|
+
`Start: ${formatUtcTimestamp(input.record.startedAtUtc)}`,
|
|
184
|
+
`End: ${formatUtcTimestamp(input.record.endedAtUtc)}`,
|
|
185
|
+
`Result: ${input.record.outcome}`,
|
|
186
|
+
`Packages updated: ${input.record.packagesUpdated}`,
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
if (input.reloadAfterSeconds) {
|
|
190
|
+
lines.push(
|
|
191
|
+
`Reloading in ${input.reloadAfterSeconds} seconds to activate updated package resources.`,
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
title: PACKAGE_MANAGER_TITLE,
|
|
197
|
+
headline: formatAutomaticUpdateHeadline(input.record.outcome),
|
|
198
|
+
tone:
|
|
199
|
+
input.record.outcome === "failed"
|
|
200
|
+
? "error"
|
|
201
|
+
: input.record.outcome === "succeeded"
|
|
202
|
+
? "success"
|
|
203
|
+
: "info",
|
|
204
|
+
lines,
|
|
205
|
+
lineTone: "dim",
|
|
206
|
+
output: input.output ?? input.record.reason,
|
|
207
|
+
outputLabel: "Update output:",
|
|
208
|
+
outputDescription: "update output",
|
|
209
|
+
outputTone: "dim",
|
|
210
|
+
hideOutputWhenCollapsed: true,
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function createInstallResultReport(input: {
|
|
215
|
+
startedAtUtc: string
|
|
216
|
+
endedAtUtc: string
|
|
217
|
+
source: string
|
|
218
|
+
outcome: InstallOutcome
|
|
219
|
+
output?: string
|
|
220
|
+
reason?: string
|
|
221
|
+
}): PackageManagerReport {
|
|
222
|
+
return {
|
|
223
|
+
title: PACKAGE_MANAGER_TITLE,
|
|
224
|
+
headline:
|
|
225
|
+
input.outcome === "succeeded"
|
|
226
|
+
? "Pi package install completed."
|
|
227
|
+
: "Pi package install failed.",
|
|
228
|
+
tone: input.outcome === "succeeded" ? "success" : "error",
|
|
229
|
+
lines: [
|
|
230
|
+
`Start: ${formatUtcTimestamp(input.startedAtUtc)}`,
|
|
231
|
+
`End: ${formatUtcTimestamp(input.endedAtUtc)}`,
|
|
232
|
+
`Result: ${input.outcome}`,
|
|
233
|
+
`Package source: ${input.source}`,
|
|
234
|
+
...(input.outcome === "succeeded"
|
|
235
|
+
? ["Run /reload to activate installed package resources."]
|
|
236
|
+
: []),
|
|
237
|
+
],
|
|
238
|
+
lineTone: "dim",
|
|
239
|
+
output: input.output ?? input.reason,
|
|
240
|
+
outputLabel:
|
|
241
|
+
input.outcome === "succeeded" ? "Install output:" : "Error detail:",
|
|
242
|
+
outputDescription:
|
|
243
|
+
input.outcome === "succeeded" ? "install output" : "error detail",
|
|
244
|
+
outputTone: "dim",
|
|
245
|
+
hideOutputWhenCollapsed: true,
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function createAutomaticUpdateWidgetLines(state: WidgetState): string[] {
|
|
250
|
+
if (state.mode === "status-checking") {
|
|
251
|
+
return ["Pi package status in progress.", "Checking for package updates..."]
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (state.mode === "checking") {
|
|
255
|
+
return [
|
|
256
|
+
formatAutomaticUpdateHeadline("in-progress"),
|
|
257
|
+
"Checking for package updates...",
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (state.mode === "installing") {
|
|
262
|
+
return [
|
|
263
|
+
formatAutomaticUpdateHeadline("in-progress"),
|
|
264
|
+
`Installing ${state.packages} package update${state.packages === 1 ? "" : "s"}...`,
|
|
265
|
+
]
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (state.mode === "package-installing") {
|
|
269
|
+
return [
|
|
270
|
+
"Pi package install in progress.",
|
|
271
|
+
`Installing package from ${state.source}...`,
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return [
|
|
276
|
+
formatAutomaticUpdateHeadline("succeeded"),
|
|
277
|
+
`Reloading in ${state.secondsRemaining} second${state.secondsRemaining === 1 ? "" : "s"} to activate updated package resources.`,
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function setPackageManagerWidget(
|
|
282
|
+
ctx: ExtensionContext,
|
|
283
|
+
state: WidgetState,
|
|
284
|
+
): void {
|
|
285
|
+
if (ctx.mode !== "tui") {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
ctx.ui.setWidget(
|
|
290
|
+
PACKAGE_MANAGER_WIDGET_KEY,
|
|
291
|
+
(_tui, theme) => {
|
|
292
|
+
const background =
|
|
293
|
+
state.mode === "countdown"
|
|
294
|
+
? (text: string) => theme.bg("toolSuccessBg", text)
|
|
295
|
+
: (text: string) => theme.bg("toolPendingBg", text)
|
|
296
|
+
const box = new Box(1, 1, background)
|
|
297
|
+
const titleColor = state.mode === "countdown" ? "success" : "accent"
|
|
298
|
+
const bodyLines = createAutomaticUpdateWidgetLines(state)
|
|
299
|
+
|
|
300
|
+
box.addChild(
|
|
301
|
+
new Text(
|
|
302
|
+
`${theme.fg(titleColor, "●")} ${theme.bold(theme.fg("customMessageLabel", PACKAGE_MANAGER_TITLE))}`,
|
|
303
|
+
0,
|
|
304
|
+
0,
|
|
305
|
+
),
|
|
306
|
+
)
|
|
307
|
+
box.addChild(
|
|
308
|
+
new Text(
|
|
309
|
+
bodyLines
|
|
310
|
+
.map((line, index) =>
|
|
311
|
+
theme.fg(
|
|
312
|
+
index === bodyLines.length - 1 ? "dim" : "text",
|
|
313
|
+
line,
|
|
314
|
+
),
|
|
315
|
+
)
|
|
316
|
+
.join("\n"),
|
|
317
|
+
0,
|
|
318
|
+
0,
|
|
319
|
+
),
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
return box
|
|
323
|
+
},
|
|
324
|
+
{ placement: "aboveEditor" },
|
|
325
|
+
)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function clearPackageManagerWidget(ctx: ExtensionContext): void {
|
|
329
|
+
if (ctx.mode !== "tui") {
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
ctx.ui.setWidget(PACKAGE_MANAGER_WIDGET_KEY, undefined)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export function getExecDisplayOutput(result: ExecResult): string | undefined {
|
|
337
|
+
const stdout = result.stdout.trim()
|
|
338
|
+
const stderr = result.stderr.trim()
|
|
339
|
+
const sections: string[] = []
|
|
340
|
+
|
|
341
|
+
if (stdout) {
|
|
342
|
+
sections.push(stdout)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (stderr) {
|
|
346
|
+
sections.push(`[stderr]\n${stderr}`)
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return sections.length > 0 ? sections.join("\n\n") : undefined
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function getExecFailureDetail(result: ExecResult): string {
|
|
353
|
+
const stderr = result.stderr.trim()
|
|
354
|
+
const stdout = result.stdout.trim()
|
|
355
|
+
const detail = stderr || stdout || "Package update command failed."
|
|
356
|
+
|
|
357
|
+
return detail.length > 400 ? `${detail.slice(0, 397)}...` : detail
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function formatAutomaticUpdateHeadline(
|
|
361
|
+
state: AutoUpdateOutcome | "in-progress",
|
|
362
|
+
): string {
|
|
363
|
+
const suffix =
|
|
364
|
+
state === "in-progress"
|
|
365
|
+
? "in progress"
|
|
366
|
+
: state === "succeeded"
|
|
367
|
+
? "completed"
|
|
368
|
+
: state
|
|
369
|
+
|
|
370
|
+
return `Pi package(s) update ${suffix}.`
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function formatExpandHint(theme: ThemeLike, description: string): string {
|
|
374
|
+
const expandKey = keyText("app.tools.expand") || "Ctrl+O"
|
|
375
|
+
|
|
376
|
+
return `${theme.fg("dim", expandKey)}${theme.fg("muted", ` ${description}`)}`
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function formatReportOutput(
|
|
380
|
+
output: string,
|
|
381
|
+
expanded: boolean,
|
|
382
|
+
): { text: string; truncated: boolean } {
|
|
383
|
+
const normalizedLines = output.trim().split(/\r?\n/)
|
|
384
|
+
|
|
385
|
+
if (expanded || normalizedLines.length <= OUTPUT_PREVIEW_LINE_COUNT) {
|
|
386
|
+
return {
|
|
387
|
+
text: normalizedLines.join("\n"),
|
|
388
|
+
truncated: false,
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
text: normalizedLines.slice(0, OUTPUT_PREVIEW_LINE_COUNT).join("\n"),
|
|
394
|
+
truncated: true,
|
|
395
|
+
}
|
|
396
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DefaultPackageManager,
|
|
3
|
+
SettingsManager,
|
|
4
|
+
getAgentDir,
|
|
5
|
+
type ExecResult,
|
|
6
|
+
type ExtensionAPI,
|
|
7
|
+
type ExtensionCommandContext,
|
|
8
|
+
type ExtensionContext,
|
|
9
|
+
} from "@earendil-works/pi-coding-agent"
|
|
10
|
+
|
|
11
|
+
import { INSTALL_COMMAND, UPDATE_COMMAND } from "./model.ts"
|
|
12
|
+
|
|
13
|
+
export interface PackageManagerDeps {
|
|
14
|
+
nowIso(): string
|
|
15
|
+
sleep(milliseconds: number): Promise<void>
|
|
16
|
+
isOffline(): boolean
|
|
17
|
+
checkForAvailableUpdates(ctx: ExtensionContext): Promise<string[]>
|
|
18
|
+
runNativeUpdate(
|
|
19
|
+
pi: Pick<ExtensionAPI, "exec">,
|
|
20
|
+
ctx: ExtensionCommandContext,
|
|
21
|
+
): Promise<ExecResult>
|
|
22
|
+
runNativeInstall(
|
|
23
|
+
pi: Pick<ExtensionAPI, "exec">,
|
|
24
|
+
ctx: ExtensionCommandContext,
|
|
25
|
+
source: string,
|
|
26
|
+
): Promise<ExecResult>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const defaultPackageManagerDeps: PackageManagerDeps = {
|
|
30
|
+
nowIso: () => new Date().toISOString(),
|
|
31
|
+
sleep(milliseconds: number) {
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
setTimeout(resolve, milliseconds)
|
|
34
|
+
})
|
|
35
|
+
},
|
|
36
|
+
isOffline: () => Boolean(process.env.PI_OFFLINE),
|
|
37
|
+
async checkForAvailableUpdates(ctx: ExtensionContext): Promise<string[]> {
|
|
38
|
+
const agentDir = getAgentDir()
|
|
39
|
+
const settingsManager = SettingsManager.create(ctx.cwd, agentDir, {
|
|
40
|
+
projectTrusted: ctx.isProjectTrusted(),
|
|
41
|
+
})
|
|
42
|
+
const packageManager = new DefaultPackageManager({
|
|
43
|
+
cwd: ctx.cwd,
|
|
44
|
+
agentDir,
|
|
45
|
+
settingsManager,
|
|
46
|
+
})
|
|
47
|
+
const updates = await packageManager.checkForAvailableUpdates()
|
|
48
|
+
|
|
49
|
+
return updates
|
|
50
|
+
.map((update) => update.displayName)
|
|
51
|
+
.sort((left, right) => left.localeCompare(right))
|
|
52
|
+
},
|
|
53
|
+
runNativeUpdate(pi: Pick<ExtensionAPI, "exec">, ctx: ExtensionCommandContext) {
|
|
54
|
+
return pi.exec("pi", [...UPDATE_COMMAND], {
|
|
55
|
+
cwd: ctx.cwd,
|
|
56
|
+
signal: ctx.signal,
|
|
57
|
+
})
|
|
58
|
+
},
|
|
59
|
+
runNativeInstall(
|
|
60
|
+
pi: Pick<ExtensionAPI, "exec">,
|
|
61
|
+
ctx: ExtensionCommandContext,
|
|
62
|
+
source: string,
|
|
63
|
+
) {
|
|
64
|
+
return pi.exec("pi", [...INSTALL_COMMAND, source], {
|
|
65
|
+
cwd: ctx.cwd,
|
|
66
|
+
signal: ctx.signal,
|
|
67
|
+
})
|
|
68
|
+
},
|
|
69
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaosh3n/pi-package-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Package Manager for Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@11.23.0",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"index.ts",
|
|
30
|
+
"internal/**/*.ts",
|
|
30
31
|
"README.md",
|
|
31
32
|
"LICENSE"
|
|
32
33
|
],
|