@hanzo/runtime 0.0.0-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +147 -0
- package/hanzo-runtime-0.0.0-dev.tgz +0 -0
- package/hooks/typedoc-custom.mjs +640 -0
- package/jest.config.js +15 -0
- package/package.json +24 -0
- package/project.json +57 -0
- package/src/ComputerUse.ts +618 -0
- package/src/Daytona.ts +644 -0
- package/src/FileSystem.ts +414 -0
- package/src/Git.ts +303 -0
- package/src/Image.ts +643 -0
- package/src/LspServer.ts +245 -0
- package/src/ObjectStorage.ts +232 -0
- package/src/Process.ts +357 -0
- package/src/Sandbox.ts +478 -0
- package/src/Snapshot.ts +260 -0
- package/src/Volume.ts +110 -0
- package/src/code-toolbox/SandboxPythonCodeToolbox.ts +366 -0
- package/src/code-toolbox/SandboxTsCodeToolbox.ts +17 -0
- package/src/errors/DaytonaError.ts +15 -0
- package/src/index.ts +50 -0
- package/src/types/Charts.ts +193 -0
- package/src/types/ExecuteResponse.ts +33 -0
- package/src/utils/ArtifactParser.ts +58 -0
- package/src/utils/Path.ts +25 -0
- package/src/utils/Stream.ts +89 -0
- package/tsconfig.json +16 -0
- package/tsconfig.lib.json +16 -0
- package/tsconfig.spec.json +12 -0
- package/typedoc.json +33 -0
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
// Copyright 2025 Daytona Platforms Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
// @ts-check
|
|
5
|
+
/* eslint-disable no-useless-escape */
|
|
6
|
+
|
|
7
|
+
import { MarkdownPageEvent } from 'typedoc-plugin-markdown'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {import('typedoc-plugin-markdown').MarkdownApplication} app
|
|
11
|
+
*/
|
|
12
|
+
export function load(app) {
|
|
13
|
+
// --- TITLE HACK ---
|
|
14
|
+
app.renderer.markdownHooks.on('page.begin', () => {
|
|
15
|
+
// We'll add the title later in the END event
|
|
16
|
+
return '---\ntitle: ""\nhideTitleOnPage: true\n---\n'
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// --- CONTENT HACKS ---
|
|
20
|
+
app.renderer.on(MarkdownPageEvent.END, (page) => {
|
|
21
|
+
if (!page.contents) return
|
|
22
|
+
|
|
23
|
+
// Extract title from filename and capitalize first letter of each word
|
|
24
|
+
let title = ''
|
|
25
|
+
if (page.filename) {
|
|
26
|
+
const filename = page.filename
|
|
27
|
+
// Get the last part of the filename (after the last dot)
|
|
28
|
+
const baseFilename = filename.split('/').pop()?.replace(/\.md$/, '').split('.').pop() || ''
|
|
29
|
+
// Split into words and capitalize each word
|
|
30
|
+
const words = baseFilename.split(/[-_]/)
|
|
31
|
+
title = words
|
|
32
|
+
.map((word) => {
|
|
33
|
+
if (word.length === 0) return ''
|
|
34
|
+
return word.charAt(0).toUpperCase() + word.slice(1)
|
|
35
|
+
})
|
|
36
|
+
.join('')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Replace the empty title with the actual title
|
|
40
|
+
page.contents = page.contents.replace(/title: ""/, `title: "${title}"`)
|
|
41
|
+
|
|
42
|
+
page.contents = transformContent(page.contents)
|
|
43
|
+
page.filename = transformFilename(page.filename)
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function transformContent(contents) {
|
|
48
|
+
return [
|
|
49
|
+
removeInternalLinks,
|
|
50
|
+
escapePromiseSpecialCharacters,
|
|
51
|
+
transformExtendsSection,
|
|
52
|
+
transformInheritedSections,
|
|
53
|
+
transformParametersSection,
|
|
54
|
+
transformReturnsSection,
|
|
55
|
+
transformPropertiesSection,
|
|
56
|
+
transformExamplesSection,
|
|
57
|
+
transformEnumSection,
|
|
58
|
+
transformThrowsSection,
|
|
59
|
+
transformTypeDeclarationSection,
|
|
60
|
+
fixFormattingArtifacts,
|
|
61
|
+
].reduce((acc, fn) => fn(acc), contents)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function transformFilename(filename) {
|
|
65
|
+
return filename.replace(/\/([^/]+)\.md$/, (_, name) => {
|
|
66
|
+
const formatted = name
|
|
67
|
+
.split('.')
|
|
68
|
+
.pop()
|
|
69
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2') // Add hyphen between lowercase & uppercase
|
|
70
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2') // Add hyphen between uppercase followed by lowercase
|
|
71
|
+
.replace(/([0-9])([A-Za-z])/g, '$1-$2') // Add hyphen between number & letter
|
|
72
|
+
.toLowerCase() // Convert to lowercase
|
|
73
|
+
return `/${formatted}.mdx`
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function removeInternalLinks(contents) {
|
|
78
|
+
return contents.replace(/\[([^\]]+)]\([^)]+\)/g, '$1')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function escapePromiseSpecialCharacters(contents) {
|
|
82
|
+
return contents.replace(/`Promise`\s*\\<((?:`?[^`<>]+`?|<[^<>]+>)*?)>/g, (_match, typeContent) => {
|
|
83
|
+
return '`Promise<' + typeContent.replace(/[`\\]/g, '') + '>`'
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function transformParametersSection(contents) {
|
|
88
|
+
for (let i = 6; i > 1; i--) {
|
|
89
|
+
let paramsRegex = new RegExp(`\#{${i}} Parameters\\s*\\n\\n([\\s\\S]*?)(?=\\n\#{1,${i}} |$)`, 'g')
|
|
90
|
+
if (i == 6) {
|
|
91
|
+
paramsRegex = new RegExp(
|
|
92
|
+
`\#{${i}} Parameters\\s*\\n\\n([\\s\\S]*?)(?=\\n\#{1,${
|
|
93
|
+
i - 1
|
|
94
|
+
}} |\#{1,${i}} Returns|\#{1,${i}} Example|\#{1,${i}} Examples|$)`,
|
|
95
|
+
'g',
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
contents = contents.replace(paramsRegex, (match, paramsContent) => {
|
|
99
|
+
const paramHeadingLevel = i == 6 ? 6 : i + 1
|
|
100
|
+
const headingHashes = '#'.repeat(paramHeadingLevel)
|
|
101
|
+
const headingHashesShorter = Array.from({ length: paramHeadingLevel }, (_, k) => '#'.repeat(k + 1)).join('|')
|
|
102
|
+
|
|
103
|
+
const paramBlockRegex = new RegExp(
|
|
104
|
+
`${headingHashes} ([^\\n]+)\\n\\n` + // parameter name
|
|
105
|
+
'([^\\n]+)' + // type line
|
|
106
|
+
`(?:\\n\\n((?:(?!${headingHashes} |${headingHashesShorter} |\\*\\*\\*|#{1,6} ).+[\\r\\n]*)*))?`, // safe multiline description
|
|
107
|
+
'g',
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
const parameters = []
|
|
111
|
+
let paramMatch
|
|
112
|
+
|
|
113
|
+
while ((paramMatch = paramBlockRegex.exec(paramsContent)) !== null) {
|
|
114
|
+
const [, name, typeLine, rawDescription = ''] = paramMatch
|
|
115
|
+
|
|
116
|
+
const lines = rawDescription
|
|
117
|
+
.split('\n')
|
|
118
|
+
.map((line) => line.trim())
|
|
119
|
+
.filter((line) => line.length > 0)
|
|
120
|
+
|
|
121
|
+
parameters.push({
|
|
122
|
+
name,
|
|
123
|
+
typeLine,
|
|
124
|
+
mainDescription: lines[0] || '',
|
|
125
|
+
otherLines: lines.slice(1),
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (parameters.length === 0) return match
|
|
130
|
+
|
|
131
|
+
let result = '**Parameters**:\n\n'
|
|
132
|
+
|
|
133
|
+
for (const { name, typeLine, mainDescription, otherLines } of parameters) {
|
|
134
|
+
let type = typeLine.replace(/`/g, '').trim()
|
|
135
|
+
type = type.replace(/readonly\s+/, '').trim()
|
|
136
|
+
type = type.replace(/(?<!\\)([*_`[\]()<>|])/g, '\\$1')
|
|
137
|
+
|
|
138
|
+
result += `- \`${name}\` _${type}_`
|
|
139
|
+
if (mainDescription) result += ` - ${mainDescription}`
|
|
140
|
+
result += '\n'
|
|
141
|
+
|
|
142
|
+
for (const line of otherLines) {
|
|
143
|
+
result += ` ${line}\n`
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return result + '\n'
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return contents
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function transformReturnsSection(contents) {
|
|
155
|
+
return contents.replace(
|
|
156
|
+
/^#{1,6} Returns\s*\n+`([^`]+)`\n+((?:(?!^#{1,6} |\*\*\*).*\n?)*)/gm,
|
|
157
|
+
(_, type, rawDescription) => {
|
|
158
|
+
const lines = rawDescription
|
|
159
|
+
.split('\n')
|
|
160
|
+
.map((l) => l.trim())
|
|
161
|
+
.filter((l) => l && !/^#{1,6} /.test(l) && l !== '***') // ignore headings and separators
|
|
162
|
+
|
|
163
|
+
let result = '**Returns**:\n\n- `' + type + '`'
|
|
164
|
+
if (lines.length > 0) {
|
|
165
|
+
result += ' - ' + lines[0] + '\n'
|
|
166
|
+
for (const line of lines.slice(1)) {
|
|
167
|
+
result += ` ${line}\n`
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
result += '\n'
|
|
171
|
+
}
|
|
172
|
+
result += '\n'
|
|
173
|
+
return result
|
|
174
|
+
},
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function transformPropertiesSection(contents) {
|
|
179
|
+
contents = transformPropsOrTypeDeclaration(contents, 'Properties')
|
|
180
|
+
|
|
181
|
+
// Move Properties section right after each class/interface description
|
|
182
|
+
const sections = contents.split(/^## /gm)
|
|
183
|
+
const updatedSections = sections.map((section, i) => {
|
|
184
|
+
if (i === 0) return section // Skip content before first ##
|
|
185
|
+
|
|
186
|
+
const sectionLines = section.split('\n')
|
|
187
|
+
const classHeader = sectionLines[0].trim()
|
|
188
|
+
const body = sectionLines.slice(1).join('\n')
|
|
189
|
+
|
|
190
|
+
const propsMatch = body.match(/\*\*Properties\*\*:\s*\n\n([\s\S]*?)(?=\n###|\n\*\*|\n## |\n# |$)/)
|
|
191
|
+
if (!propsMatch) return '## ' + section
|
|
192
|
+
|
|
193
|
+
const fullPropsBlock = propsMatch[0]
|
|
194
|
+
const bodyWithoutProps = body.replace(fullPropsBlock, '').trim()
|
|
195
|
+
|
|
196
|
+
let descEnd = bodyWithoutProps.search(/\n{2,}(?=###|\*\*|$)|(?=^\s*$)/m)
|
|
197
|
+
if (descEnd === -1) {
|
|
198
|
+
const trimmed = bodyWithoutProps.trim()
|
|
199
|
+
|
|
200
|
+
if (!trimmed.includes('\n') && !trimmed.startsWith('#') && !trimmed.startsWith('**')) {
|
|
201
|
+
descEnd = bodyWithoutProps.length
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
let newBody
|
|
205
|
+
|
|
206
|
+
if (descEnd !== -1) {
|
|
207
|
+
const desc = bodyWithoutProps.slice(0, descEnd).trim()
|
|
208
|
+
const rest = bodyWithoutProps.slice(descEnd).trim()
|
|
209
|
+
newBody = `${desc}\n\n${fullPropsBlock}\n\n${rest}`
|
|
210
|
+
} else {
|
|
211
|
+
newBody = `${fullPropsBlock}\n\n${bodyWithoutProps}`
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return `## ${classHeader}\n\n${newBody.trim()}`
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
return updatedSections.join('\n')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function transformExamplesSection(contents) {
|
|
221
|
+
return contents.replace(/^#{1,10}\s*(Example|Examples)$/gm, '**$1:**')
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function transformExtendsSection(contents) {
|
|
225
|
+
return contents.replace(/^#{1,10}\s*(Extends)$/gm, '**$1:**')
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function transformInheritedSections(contents) {
|
|
229
|
+
// Transform "##### Inherited from" sections into inline inheritance notes
|
|
230
|
+
// Handle both simple and complex patterns (with Memberof sections and code blocks)
|
|
231
|
+
|
|
232
|
+
const hasInheritedFrom = contents.includes('##### Inherited from')
|
|
233
|
+
|
|
234
|
+
if (!hasInheritedFrom) {
|
|
235
|
+
return contents
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Use line-by-line processing for maximum reliability
|
|
239
|
+
const lines = contents.split('\n')
|
|
240
|
+
let modified = false
|
|
241
|
+
|
|
242
|
+
for (let i = 0; i < lines.length; i++) {
|
|
243
|
+
// Look for "##### Inherited from" lines
|
|
244
|
+
if (lines[i].trim() === '##### Inherited from') {
|
|
245
|
+
// Look backwards for property definition (list item or heading)
|
|
246
|
+
let propertyLineIndex = -1
|
|
247
|
+
let propertyLine = ''
|
|
248
|
+
|
|
249
|
+
// Search backwards up to 20 lines
|
|
250
|
+
for (let j = i - 1; j >= Math.max(0, i - 20); j--) {
|
|
251
|
+
const line = lines[j].trim()
|
|
252
|
+
// Property heading format: #### propertyName
|
|
253
|
+
if (line.match(/^#### [^#]+$/)) {
|
|
254
|
+
propertyLineIndex = j
|
|
255
|
+
propertyLine = lines[j]
|
|
256
|
+
break
|
|
257
|
+
}
|
|
258
|
+
// Property list item format: - `property` _type_ - description
|
|
259
|
+
if (line.match(/^- `[^`]+` _[^_]+_/)) {
|
|
260
|
+
propertyLineIndex = j
|
|
261
|
+
propertyLine = lines[j]
|
|
262
|
+
break
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Look forwards for inheritance info
|
|
267
|
+
let inheritanceInfo = ''
|
|
268
|
+
let memberofInfo = ''
|
|
269
|
+
let endIndex = i
|
|
270
|
+
|
|
271
|
+
// Check for code block format
|
|
272
|
+
for (let k = i + 1; k < Math.min(lines.length, i + 5); k++) {
|
|
273
|
+
if (lines[k].trim() === '```ts' && k + 2 < lines.length) {
|
|
274
|
+
const nextLine = lines[k + 1].trim()
|
|
275
|
+
if (nextLine && lines[k + 2].trim() === '```') {
|
|
276
|
+
inheritanceInfo = nextLine
|
|
277
|
+
endIndex = k + 2
|
|
278
|
+
break
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// Check for simple format: `Class`.`property`
|
|
282
|
+
if (lines[k].trim().match(/^`[^`]+`\.`[^`]+`$/)) {
|
|
283
|
+
inheritanceInfo = lines[k].trim().replace(/`/g, '')
|
|
284
|
+
endIndex = k
|
|
285
|
+
break
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Look backwards for Memberof info
|
|
290
|
+
for (let m = i - 1; m >= Math.max(0, i - 5); m--) {
|
|
291
|
+
if (lines[m].trim() === '##### Memberof') {
|
|
292
|
+
// Look for the memberof value in the next few lines
|
|
293
|
+
for (let n = m + 1; n < Math.min(lines.length, m + 5); n++) {
|
|
294
|
+
if (lines[n].trim() === '```ts' && n + 2 < lines.length) {
|
|
295
|
+
const memberofLine = lines[n + 1].trim()
|
|
296
|
+
if (memberofLine && lines[n + 2].trim() === '```') {
|
|
297
|
+
memberofInfo = memberofLine
|
|
298
|
+
break
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Check for simple format: `ClassName`
|
|
302
|
+
if (lines[n].trim().match(/^`[^`]+`$/)) {
|
|
303
|
+
memberofInfo = lines[n].trim().replace(/`/g, '')
|
|
304
|
+
break
|
|
305
|
+
}
|
|
306
|
+
// Check for plain text format: ClassName
|
|
307
|
+
if (lines[n].trim().length > 0 && !lines[n].trim().startsWith('#') && !lines[n].trim().startsWith('```')) {
|
|
308
|
+
memberofInfo = lines[n].trim()
|
|
309
|
+
break
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
break
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// If we found both property and inheritance info, transform it
|
|
317
|
+
if (propertyLineIndex >= 0 && inheritanceInfo) {
|
|
318
|
+
// Use memberof info if available, otherwise use inheritance info
|
|
319
|
+
let finalInheritanceInfo
|
|
320
|
+
if (memberofInfo && inheritanceInfo.includes('.')) {
|
|
321
|
+
// Extract property name from inheritance info and combine with memberof class
|
|
322
|
+
const propertyName = inheritanceInfo.split('.').pop()
|
|
323
|
+
finalInheritanceInfo = `${memberofInfo}.${propertyName}`
|
|
324
|
+
} else {
|
|
325
|
+
finalInheritanceInfo = inheritanceInfo
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Add inheritance info to property line
|
|
329
|
+
if (propertyLine.startsWith('#### ')) {
|
|
330
|
+
// For headings, add after the heading
|
|
331
|
+
lines[propertyLineIndex] = propertyLine + `\n\n_Inherited from_: \`${finalInheritanceInfo}\``
|
|
332
|
+
} else if (propertyLine.startsWith('- `')) {
|
|
333
|
+
// For list items, add as a sub-item
|
|
334
|
+
lines[propertyLineIndex] = propertyLine + `\n - _Inherited from_: \`${finalInheritanceInfo}\``
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Remove the inheritance section
|
|
338
|
+
// Find the start of the section (might include Memberof)
|
|
339
|
+
let startIndex = i
|
|
340
|
+
for (let m = i - 1; m >= Math.max(0, i - 5); m--) {
|
|
341
|
+
if (lines[m].trim() === '##### Memberof') {
|
|
342
|
+
startIndex = m
|
|
343
|
+
break
|
|
344
|
+
}
|
|
345
|
+
// Also check for empty lines to find the start of the inheritance block
|
|
346
|
+
if (lines[m].trim() === '' && m > 0 && lines[m - 1].trim() !== '') {
|
|
347
|
+
startIndex = m
|
|
348
|
+
break
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Remove all lines from startIndex to endIndex (inclusive)
|
|
353
|
+
for (let r = endIndex; r >= startIndex; r--) {
|
|
354
|
+
lines.splice(r, 1)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Adjust our loop index since we removed lines
|
|
358
|
+
i = propertyLineIndex
|
|
359
|
+
modified = true
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Remove any remaining standalone "##### Memberof" sections
|
|
365
|
+
if (modified) {
|
|
366
|
+
const finalLines = lines.join('\n').split('\n')
|
|
367
|
+
for (let i = finalLines.length - 1; i >= 0; i--) {
|
|
368
|
+
if (finalLines[i].trim() === '##### Memberof') {
|
|
369
|
+
// Remove the Memberof line and any following content until next heading or empty line
|
|
370
|
+
let endMemberof = i
|
|
371
|
+
for (let j = i + 1; j < finalLines.length; j++) {
|
|
372
|
+
if (finalLines[j].trim() === '' || finalLines[j].match(/^#{1,6} /)) {
|
|
373
|
+
break
|
|
374
|
+
}
|
|
375
|
+
endMemberof = j
|
|
376
|
+
}
|
|
377
|
+
finalLines.splice(i, endMemberof - i + 1)
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Also remove any standalone class name lines that might be leftover
|
|
382
|
+
const cleanedContent = finalLines
|
|
383
|
+
.join('\n')
|
|
384
|
+
.replace(/\n\s*\n\s*([A-Z][a-zA-Z]*)\s*\n\s*\n/g, '\n\n') // Remove standalone class names between empty lines
|
|
385
|
+
.replace(/\n\s*([A-Z][a-zA-Z]*)\s*\n(?=\s*-|\s*\*\*)/g, '\n') // Remove class names before property lists or sections
|
|
386
|
+
|
|
387
|
+
return cleanedContent
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return modified ? lines.join('\n') : contents
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function transformEnumSection(contents) {
|
|
394
|
+
// First, find all sections with "Enumeration Members" headings
|
|
395
|
+
const sections = contents.split(/^## /gm)
|
|
396
|
+
let newContent = ''
|
|
397
|
+
|
|
398
|
+
for (let i = 0; i < sections.length; i++) {
|
|
399
|
+
const section = sections[i]
|
|
400
|
+
|
|
401
|
+
if (i === 0) {
|
|
402
|
+
// This is content before the first ## heading
|
|
403
|
+
newContent += section
|
|
404
|
+
continue
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Add back the ## that was removed in the split
|
|
408
|
+
const sectionWithHeader = '## ' + section
|
|
409
|
+
|
|
410
|
+
// Check if this section contains an enum
|
|
411
|
+
if (sectionWithHeader.includes('### Enumeration Members')) {
|
|
412
|
+
// Split at the enum members heading
|
|
413
|
+
const [headerPart, membersPart] = sectionWithHeader.split('### Enumeration Members')
|
|
414
|
+
|
|
415
|
+
// Parse and extract all enum values
|
|
416
|
+
const enumValues = []
|
|
417
|
+
const regex = /#### ([A-Z0-9_]+)[\s\S]*?```ts[\s\S]*?\1:\s*"([^"]+)"/g
|
|
418
|
+
let match
|
|
419
|
+
|
|
420
|
+
const memberPartCopy = membersPart
|
|
421
|
+
while ((match = regex.exec(memberPartCopy)) !== null) {
|
|
422
|
+
enumValues.push({
|
|
423
|
+
name: match[1],
|
|
424
|
+
value: match[2],
|
|
425
|
+
})
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Create the transformed section
|
|
429
|
+
let transformedSection = headerPart + '**Enum Members**:\n\n'
|
|
430
|
+
|
|
431
|
+
if (enumValues.length > 0) {
|
|
432
|
+
enumValues.forEach((entry) => {
|
|
433
|
+
transformedSection += `- \`${entry.name}\` ("${entry.value}")\n`
|
|
434
|
+
})
|
|
435
|
+
transformedSection += '\n'
|
|
436
|
+
} else {
|
|
437
|
+
// If we couldn't parse any values, just keep the original content
|
|
438
|
+
transformedSection = sectionWithHeader
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
newContent += transformedSection
|
|
442
|
+
} else {
|
|
443
|
+
// Non-enum section, just add it back unchanged
|
|
444
|
+
newContent += sectionWithHeader
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return newContent
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function transformThrowsSection(contents) {
|
|
452
|
+
// Process "Throws" headers from level 2 to level 7
|
|
453
|
+
for (let level = 2; level <= 7; level++) {
|
|
454
|
+
const throwsHeader = '#'.repeat(level) + ' Throws' // Generate header (e.g., ## Throws, ### Throws)
|
|
455
|
+
const sectionHeaderRegex = new RegExp(`(?=^#{${level - 1}} .+)`, 'gm') // Regex for section start (parent level)
|
|
456
|
+
const throwsRegex = new RegExp(`(\n${throwsHeader}\n)`, 'g') // Matches only the "Throws" header itself
|
|
457
|
+
|
|
458
|
+
if (!contents) continue
|
|
459
|
+
|
|
460
|
+
// Split document into sections at parent level
|
|
461
|
+
const sections = contents.split(sectionHeaderRegex)
|
|
462
|
+
|
|
463
|
+
contents = sections
|
|
464
|
+
.map((section) => {
|
|
465
|
+
if (!section.includes(`\n${throwsHeader}`)) return section // Skip if no "Throws" found at this level
|
|
466
|
+
|
|
467
|
+
// Capture all occurrences of "Throws" headers at this specific level
|
|
468
|
+
const throwsMatches = [...section.matchAll(throwsRegex)]
|
|
469
|
+
|
|
470
|
+
if (throwsMatches.length <= 1) {
|
|
471
|
+
// Transform single occurrence
|
|
472
|
+
return section.replace(throwsRegex, '\n**Throws**:\n')
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Keep the first "Throws" header and remove only subsequent ones
|
|
476
|
+
let headerRemovedCount = 0
|
|
477
|
+
const cleanedSection = section.replace(throwsRegex, () => {
|
|
478
|
+
return headerRemovedCount++ === 0 ? '\n**Throws**:\n' : '' // Transform first one to bold, remove others
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
return cleanedSection
|
|
482
|
+
})
|
|
483
|
+
.join('')
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return contents
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function fixFormattingArtifacts(content) {
|
|
490
|
+
return content.replace(/`~~([^`]+?)\?~~`/g, '~~`$1?`~~')
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function transformTypeDeclarationSection(contents) {
|
|
494
|
+
return transformPropsOrTypeDeclaration(contents, 'Type declaration')
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function transformPropsOrTypeDeclaration(contents, headerTitle) {
|
|
498
|
+
for (let i = 5; i > 1; i--) {
|
|
499
|
+
contents = contents.replace(
|
|
500
|
+
new RegExp(`\#{${i}} ${headerTitle}\\s*\\n\\n([\\s\\S]*?)(?=\\n\#{1,${i}} |$)`, 'g'),
|
|
501
|
+
(match, sectionContent) => {
|
|
502
|
+
const itemHeadingLevel = i + 1
|
|
503
|
+
const headingHashes = '#'.repeat(itemHeadingLevel)
|
|
504
|
+
const headingHashesShorter = Array.from({ length: itemHeadingLevel }, (_, k) => '#'.repeat(k + 1)).join('|')
|
|
505
|
+
const itemBlockRegex = new RegExp(
|
|
506
|
+
`${headingHashes} ([^\\n]+)\\n\\n` + // #### propName
|
|
507
|
+
'(?:_Inherited from_: `([^`]+)`\\n\\n)?' + // optional inheritance info
|
|
508
|
+
'(?:([A-Za-z]+)\\n)?' + // optional leftover memberof text (like "Workspace")
|
|
509
|
+
'(?:\\n)?' + // optional empty line after leftover text
|
|
510
|
+
'```ts\\n([^\\n]+);\\n```\\n' + // code block
|
|
511
|
+
'([\\s\\S]*?)' + // description block (may include Index Signature)
|
|
512
|
+
`(?=(?:\\n\\*\\*\\*\\n)?(?=\\n${headingHashes} )|\\n(?:${headingHashesShorter}) |$)`,
|
|
513
|
+
'g',
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
const items = []
|
|
517
|
+
let itemMatch
|
|
518
|
+
|
|
519
|
+
while ((itemMatch = itemBlockRegex.exec(sectionContent)) !== null) {
|
|
520
|
+
const [, name, inheritanceInfo, leftoverText, typeLine, rawDescription] = itemMatch
|
|
521
|
+
|
|
522
|
+
const lines = rawDescription
|
|
523
|
+
.trim()
|
|
524
|
+
.split('\n')
|
|
525
|
+
.map((line) => line.trim())
|
|
526
|
+
.filter((line) => !line.includes('***'))
|
|
527
|
+
|
|
528
|
+
let deprecation = ''
|
|
529
|
+
const contentLines = []
|
|
530
|
+
const indexSignatureLines = []
|
|
531
|
+
let inIndexSignature = false
|
|
532
|
+
|
|
533
|
+
for (let i = 0; i < lines.length; i++) {
|
|
534
|
+
if (new RegExp(`^\#{${itemHeadingLevel + 1}}? Index Signature`, 'i').test(lines[i])) {
|
|
535
|
+
inIndexSignature = true
|
|
536
|
+
indexSignatureLines.push(lines[i])
|
|
537
|
+
continue
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (inIndexSignature) {
|
|
541
|
+
indexSignatureLines.push(lines[i])
|
|
542
|
+
continue
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (new RegExp(`^\#{${itemHeadingLevel + 1}}? Overrides`, 'i').test(lines[i])) {
|
|
546
|
+
let j = i + 1
|
|
547
|
+
while (j < lines.length && !lines[j].trim().startsWith('#')) j++
|
|
548
|
+
i = j - 1
|
|
549
|
+
} else if (new RegExp(`^\#{${itemHeadingLevel + 1}}? Deprecated`, 'i').test(lines[i])) {
|
|
550
|
+
let j = i + 1
|
|
551
|
+
while (j < lines.length && lines[j].trim() === '') j++
|
|
552
|
+
if (j < lines.length) {
|
|
553
|
+
deprecation = lines[j].trim()
|
|
554
|
+
i = j
|
|
555
|
+
}
|
|
556
|
+
} else {
|
|
557
|
+
contentLines.push(lines[i])
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const mainDescription = contentLines[0] || ''
|
|
562
|
+
const otherLines = contentLines.slice(1)
|
|
563
|
+
|
|
564
|
+
// Extract index signature type if present
|
|
565
|
+
let indexSignatureType = null
|
|
566
|
+
for (const line of indexSignatureLines) {
|
|
567
|
+
if (line.includes('[') && line.includes(']:')) {
|
|
568
|
+
indexSignatureType = line.trim()
|
|
569
|
+
break
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
items.push({
|
|
574
|
+
name,
|
|
575
|
+
typeLine,
|
|
576
|
+
mainDescription,
|
|
577
|
+
otherLines,
|
|
578
|
+
deprecation,
|
|
579
|
+
inheritanceInfo,
|
|
580
|
+
indexSignatureType,
|
|
581
|
+
})
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (items.length === 0) return match
|
|
585
|
+
|
|
586
|
+
let result = `**${headerTitle}**:\n\n`
|
|
587
|
+
|
|
588
|
+
for (const {
|
|
589
|
+
name,
|
|
590
|
+
typeLine,
|
|
591
|
+
mainDescription,
|
|
592
|
+
otherLines,
|
|
593
|
+
deprecation,
|
|
594
|
+
inheritanceInfo,
|
|
595
|
+
indexSignatureType,
|
|
596
|
+
} of items) {
|
|
597
|
+
const typeMatch = typeLine.match(/:\s*([^;]+)/)
|
|
598
|
+
if (!typeMatch) continue
|
|
599
|
+
|
|
600
|
+
let type = typeMatch[1].trim()
|
|
601
|
+
type = type.replace(/readonly\s+/, '').trim()
|
|
602
|
+
|
|
603
|
+
// Use index signature type if available, otherwise use the original type
|
|
604
|
+
if (indexSignatureType) {
|
|
605
|
+
type = indexSignatureType
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
type = type.replace(/([*_`\[\]()<>|])/g, '\\$1')
|
|
609
|
+
|
|
610
|
+
if (!mainDescription && deprecation) {
|
|
611
|
+
result += `- \`${name}\` _${type}_ - **_Deprecated_** - ${deprecation}\n`
|
|
612
|
+
continue
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
result += `- \`${name}\` _${type}_`
|
|
616
|
+
if (mainDescription) result += ` - ${mainDescription}`
|
|
617
|
+
result += '\n'
|
|
618
|
+
|
|
619
|
+
for (const line of otherLines) {
|
|
620
|
+
result += ` ${line}\n`
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if (deprecation) {
|
|
624
|
+
result += ` - **_Deprecated_** - ${deprecation}\n`
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (inheritanceInfo) {
|
|
628
|
+
result += ` - _Inherited from_: \`${inheritanceInfo}\`\n`
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
result = result.replace(/^\s{4}\*\*\*/gm, '***')
|
|
633
|
+
|
|
634
|
+
return result + '\n'
|
|
635
|
+
},
|
|
636
|
+
)
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return contents
|
|
640
|
+
}
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
7
|
+
module.exports = {
|
|
8
|
+
preset: 'ts-jest',
|
|
9
|
+
testEnvironment: 'node',
|
|
10
|
+
transform: {
|
|
11
|
+
'^.+\\.tsx?$': 'ts-jest',
|
|
12
|
+
},
|
|
13
|
+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
14
|
+
testMatch: ['**/__tests__/**/*.test.ts'],
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hanzo/runtime",
|
|
3
|
+
"version": "0.0.0-dev",
|
|
4
|
+
"description": "TypeScript SDK for Hanzo Runtime",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/hanzoai/runtime.git"
|
|
10
|
+
},
|
|
11
|
+
"author": "Hanzo Industries Inc",
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/hanzoai/runtime/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/hanzoai/runtime",
|
|
17
|
+
"config": {
|
|
18
|
+
"docsDir": "../../apps/docs/src/content/docs/typescript-sdk"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"docs": "bash -O extglob -c 'rm -rf $npm_package_config_docsDir/!(index.mdx)' && typedoc && rm -f $npm_package_config_docsDir/readme.mdx"
|
|
22
|
+
},
|
|
23
|
+
"keywords": []
|
|
24
|
+
}
|