@m100/core 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +5 -0
- package/dist/commentUtils.d.ts +8 -0
- package/dist/commentUtils.js +64 -0
- package/dist/commentUtils.js.map +1 -0
- package/dist/detokenize/detokenize.d.ts +18 -0
- package/dist/detokenize/detokenize.js +57 -0
- package/dist/detokenize/detokenize.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/pack/pack.d.ts +29 -0
- package/dist/pack/pack.js +229 -0
- package/dist/pack/pack.js.map +1 -0
- package/dist/removeComments/removeComments.d.ts +15 -0
- package/dist/removeComments/removeComments.js +98 -0
- package/dist/removeComments/removeComments.js.map +1 -0
- package/dist/renumber/renumber.d.ts +29 -0
- package/dist/renumber/renumber.js +87 -0
- package/dist/renumber/renumber.js.map +1 -0
- package/dist/squash/squash.d.ts +31 -0
- package/dist/squash/squash.js +247 -0
- package/dist/squash/squash.js.map +1 -0
- package/dist/tokenize/errors.d.ts +28 -0
- package/dist/tokenize/errors.js +41 -0
- package/dist/tokenize/errors.js.map +1 -0
- package/dist/tokenize/tokenizeProgram.d.ts +9 -0
- package/dist/tokenize/tokenizeProgram.js +165 -0
- package/dist/tokenize/tokenizeProgram.js.map +1 -0
- package/dist/tokenize/types.d.ts +24 -0
- package/dist/tokenize/types.js +2 -0
- package/dist/tokenize/types.js.map +1 -0
- package/dist/tokens.d.ts +13 -0
- package/dist/tokens.js +151 -0
- package/dist/tokens.js.map +1 -0
- package/dist/utils/programAnalysis.d.ts +41 -0
- package/dist/utils/programAnalysis.js +152 -0
- package/dist/utils/programAnalysis.js.map +1 -0
- package/package.json +26 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tokenize/types.ts"],"names":[],"mappings":""}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared token table for TRS-80 Model 100 BASIC tokenization/detokenization
|
|
3
|
+
* Based on: http://fileformats.archiveteam.org/wiki/Tandy_200_BASIC_tokenized_file
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Token table: maps BASIC keywords to token bytes (0x80-0xFF)
|
|
7
|
+
*/
|
|
8
|
+
export declare const TOKENS: Record<string, number>;
|
|
9
|
+
/**
|
|
10
|
+
* Reverse token table: maps token bytes to BASIC keywords
|
|
11
|
+
* Automatically generated from TOKENS
|
|
12
|
+
*/
|
|
13
|
+
export declare const REVERSE_TOKENS: Record<number, string>;
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared token table for TRS-80 Model 100 BASIC tokenization/detokenization
|
|
3
|
+
* Based on: http://fileformats.archiveteam.org/wiki/Tandy_200_BASIC_tokenized_file
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Token table: maps BASIC keywords to token bytes (0x80-0xFF)
|
|
7
|
+
*/
|
|
8
|
+
export const TOKENS = {
|
|
9
|
+
// 0x80-0x8F
|
|
10
|
+
'END': 0x80,
|
|
11
|
+
'FOR': 0x81,
|
|
12
|
+
'NEXT': 0x82,
|
|
13
|
+
'DATA': 0x83,
|
|
14
|
+
'INPUT': 0x84,
|
|
15
|
+
'DIM': 0x85,
|
|
16
|
+
'READ': 0x86,
|
|
17
|
+
'LET': 0x87,
|
|
18
|
+
'GOTO': 0x88,
|
|
19
|
+
'RUN': 0x89,
|
|
20
|
+
'IF': 0x8A,
|
|
21
|
+
'RESTORE': 0x8B,
|
|
22
|
+
'GOSUB': 0x8C,
|
|
23
|
+
'RETURN': 0x8D,
|
|
24
|
+
'REM': 0x8E,
|
|
25
|
+
'STOP': 0x8F,
|
|
26
|
+
// 0x90-0x9F
|
|
27
|
+
'WIDTH': 0x90,
|
|
28
|
+
'ELSE': 0x91,
|
|
29
|
+
'LINE': 0x92,
|
|
30
|
+
'EDIT': 0x93,
|
|
31
|
+
'ERROR': 0x94,
|
|
32
|
+
'RESUME': 0x95,
|
|
33
|
+
'OUT': 0x96,
|
|
34
|
+
'ON': 0x97,
|
|
35
|
+
'DSKO$': 0x98,
|
|
36
|
+
'OPEN': 0x99,
|
|
37
|
+
'CLOSE': 0x9A,
|
|
38
|
+
'LOAD': 0x9B,
|
|
39
|
+
'MERGE': 0x9C,
|
|
40
|
+
'FILES': 0x9D,
|
|
41
|
+
'SAVE': 0x9E,
|
|
42
|
+
'LFILES': 0x9F,
|
|
43
|
+
// 0xA0-0xAF
|
|
44
|
+
'LPRINT': 0xA0,
|
|
45
|
+
'DEF': 0xA1,
|
|
46
|
+
'POKE': 0xA2,
|
|
47
|
+
'PRINT': 0xA3,
|
|
48
|
+
'CONT': 0xA4,
|
|
49
|
+
'LIST': 0xA5,
|
|
50
|
+
'LLIST': 0xA6,
|
|
51
|
+
'CLEAR': 0xA7,
|
|
52
|
+
'CLOAD': 0xA8,
|
|
53
|
+
'CSAVE': 0xA9,
|
|
54
|
+
'TIME$': 0xAA,
|
|
55
|
+
'DATE$': 0xAB,
|
|
56
|
+
'DAY$': 0xAC,
|
|
57
|
+
'COM': 0xAD,
|
|
58
|
+
'MDM': 0xAE,
|
|
59
|
+
'KEY': 0xAF,
|
|
60
|
+
// 0xB0-0xBF
|
|
61
|
+
'CLS': 0xB0,
|
|
62
|
+
'BEEP': 0xB1,
|
|
63
|
+
'SOUND': 0xB2,
|
|
64
|
+
'LCOPY': 0xB3,
|
|
65
|
+
'PSET': 0xB4,
|
|
66
|
+
'PRESET': 0xB5,
|
|
67
|
+
'MOTOR': 0xB6,
|
|
68
|
+
'MAX': 0xB7,
|
|
69
|
+
'POWER': 0xB8,
|
|
70
|
+
'CALL': 0xB9,
|
|
71
|
+
'MENU': 0xBA,
|
|
72
|
+
'IPL': 0xBB,
|
|
73
|
+
'NAME': 0xBC,
|
|
74
|
+
'KILL': 0xBD,
|
|
75
|
+
'SCREEN': 0xBE,
|
|
76
|
+
'NEW': 0xBF,
|
|
77
|
+
// 0xC0-0xCF
|
|
78
|
+
'TAB(': 0xC0,
|
|
79
|
+
'TO': 0xC1,
|
|
80
|
+
'USING': 0xC2,
|
|
81
|
+
'VARPTR': 0xC3,
|
|
82
|
+
'ERL': 0xC4,
|
|
83
|
+
'ERR': 0xC5,
|
|
84
|
+
'STRING$': 0xC6,
|
|
85
|
+
'INSTR': 0xC7,
|
|
86
|
+
'DSKI$': 0xC8,
|
|
87
|
+
'INKEY$': 0xC9,
|
|
88
|
+
'CSRLIN': 0xCA,
|
|
89
|
+
'OFF': 0xCB,
|
|
90
|
+
'HIMEM': 0xCC,
|
|
91
|
+
'THEN': 0xCD,
|
|
92
|
+
'NOT': 0xCE,
|
|
93
|
+
'STEP': 0xCF,
|
|
94
|
+
// 0xD0-0xDF (Operators)
|
|
95
|
+
'+': 0xD0,
|
|
96
|
+
'-': 0xD1,
|
|
97
|
+
'*': 0xD2,
|
|
98
|
+
'/': 0xD3,
|
|
99
|
+
'^': 0xD4,
|
|
100
|
+
'AND': 0xD5,
|
|
101
|
+
'OR': 0xD6,
|
|
102
|
+
'XOR': 0xD7,
|
|
103
|
+
'EQV': 0xD8,
|
|
104
|
+
'IMP': 0xD9,
|
|
105
|
+
'MOD': 0xDA,
|
|
106
|
+
'\\': 0xDB,
|
|
107
|
+
'>': 0xDC,
|
|
108
|
+
'=': 0xDD,
|
|
109
|
+
'<': 0xDE,
|
|
110
|
+
// 0xDF-0xEF (Functions)
|
|
111
|
+
'SGN': 0xDF,
|
|
112
|
+
'INT': 0xE0,
|
|
113
|
+
'ABS': 0xE1,
|
|
114
|
+
'FRE': 0xE2,
|
|
115
|
+
'INP': 0xE3,
|
|
116
|
+
'LPOS': 0xE4,
|
|
117
|
+
'POS': 0xE5,
|
|
118
|
+
'SQR': 0xE6,
|
|
119
|
+
'RND': 0xE7,
|
|
120
|
+
'LOG': 0xE8,
|
|
121
|
+
'EXP': 0xE9,
|
|
122
|
+
'COS': 0xEA,
|
|
123
|
+
'SIN': 0xEB,
|
|
124
|
+
'TAN': 0xEC,
|
|
125
|
+
'ATN': 0xED,
|
|
126
|
+
'PEEK': 0xEE,
|
|
127
|
+
'EOF': 0xEF,
|
|
128
|
+
// 0xF0-0xFF
|
|
129
|
+
'LOC': 0xF0,
|
|
130
|
+
'LOF': 0xF1,
|
|
131
|
+
'CINT': 0xF2,
|
|
132
|
+
'CSNG': 0xF3,
|
|
133
|
+
'CDBL': 0xF4,
|
|
134
|
+
'FIX': 0xF5,
|
|
135
|
+
'LEN': 0xF6,
|
|
136
|
+
'STR$': 0xF7,
|
|
137
|
+
'VAL': 0xF8,
|
|
138
|
+
'ASC': 0xF9,
|
|
139
|
+
'CHR$': 0xFA,
|
|
140
|
+
'SPACE$': 0xFB,
|
|
141
|
+
'LEFT$': 0xFC,
|
|
142
|
+
'RIGHT$': 0xFD,
|
|
143
|
+
'MID$': 0xFE,
|
|
144
|
+
"'": 0xFF, // Single quote
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Reverse token table: maps token bytes to BASIC keywords
|
|
148
|
+
* Automatically generated from TOKENS
|
|
149
|
+
*/
|
|
150
|
+
export const REVERSE_TOKENS = Object.fromEntries(Object.entries(TOKENS).map(([keyword, byte]) => [byte, keyword]));
|
|
151
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String-based program analysis utilities (VS Code-free)
|
|
3
|
+
*
|
|
4
|
+
* This module provides the same analysis as src/programAnalysis.ts
|
|
5
|
+
* but works with plain strings instead of VS Code TextDocument.
|
|
6
|
+
*/
|
|
7
|
+
export type NumberedLineInfo = {
|
|
8
|
+
line: number;
|
|
9
|
+
number: number;
|
|
10
|
+
numberStart: number;
|
|
11
|
+
numberEnd: number;
|
|
12
|
+
bodyOffset: number;
|
|
13
|
+
textBeforeComment: string;
|
|
14
|
+
};
|
|
15
|
+
export type LineReference = {
|
|
16
|
+
lineIndex: number;
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
target: number;
|
|
20
|
+
fromNumber: number;
|
|
21
|
+
keyword: ReferenceKeyword;
|
|
22
|
+
};
|
|
23
|
+
export type ProgramStructure = {
|
|
24
|
+
numberedLines: NumberedLineInfo[];
|
|
25
|
+
references: LineReference[];
|
|
26
|
+
};
|
|
27
|
+
export type ReferenceSpan = {
|
|
28
|
+
start: number;
|
|
29
|
+
end: number;
|
|
30
|
+
digits: string;
|
|
31
|
+
keyword: ReferenceKeyword;
|
|
32
|
+
};
|
|
33
|
+
export type ReferenceKeyword = 'GOTO' | 'GOSUB' | 'THEN' | 'ELSE' | 'RUN' | 'RESUME' | 'RESTORE' | 'ON_GOTO' | 'ON_GOSUB' | 'ON_KEY_GOSUB';
|
|
34
|
+
/**
|
|
35
|
+
* Analyze BASIC program structure from plain text.
|
|
36
|
+
*
|
|
37
|
+
* @param basicCode - BASIC source code as a string
|
|
38
|
+
* @returns Program structure with numbered lines and references
|
|
39
|
+
*/
|
|
40
|
+
export declare function collectProgramStructure(basicCode: string): ProgramStructure;
|
|
41
|
+
export declare function findLineReferenceSpans(body: string): ReferenceSpan[];
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { findCommentStart } from '../commentUtils.js';
|
|
2
|
+
/**
|
|
3
|
+
* Analyze BASIC program structure from plain text.
|
|
4
|
+
*
|
|
5
|
+
* @param basicCode - BASIC source code as a string
|
|
6
|
+
* @returns Program structure with numbered lines and references
|
|
7
|
+
*/
|
|
8
|
+
export function collectProgramStructure(basicCode) {
|
|
9
|
+
const lines = basicCode.split(/\r?\n/);
|
|
10
|
+
const numberedLines = [];
|
|
11
|
+
const references = [];
|
|
12
|
+
const referenceSpans = new Set();
|
|
13
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
14
|
+
const sourceText = lines[lineIndex];
|
|
15
|
+
const commentStart = findCommentStart(sourceText);
|
|
16
|
+
const scanLimit = commentStart ?? sourceText.length;
|
|
17
|
+
const textBeforeComment = sourceText.slice(0, scanLimit);
|
|
18
|
+
const numberMatch = /^\s*(\d+)\b/.exec(textBeforeComment);
|
|
19
|
+
if (!numberMatch) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const rawNumber = numberMatch[1];
|
|
23
|
+
const number = parseInt(rawNumber, 10);
|
|
24
|
+
if (Number.isNaN(number)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const numberIndex = textBeforeComment.indexOf(rawNumber);
|
|
28
|
+
const numberStart = numberIndex === -1
|
|
29
|
+
? numberMatch[0].length - rawNumber.length
|
|
30
|
+
: numberIndex;
|
|
31
|
+
const numberEnd = numberStart + rawNumber.length;
|
|
32
|
+
let bodyOffset = numberStart + rawNumber.length;
|
|
33
|
+
while (bodyOffset < scanLimit && /\s/.test(sourceText[bodyOffset])) {
|
|
34
|
+
bodyOffset += 1;
|
|
35
|
+
}
|
|
36
|
+
const body = sourceText.slice(bodyOffset, scanLimit);
|
|
37
|
+
const spans = findLineReferenceSpans(body);
|
|
38
|
+
for (const span of spans) {
|
|
39
|
+
addReferenceIfValid(references, referenceSpans, lineIndex, number, bodyOffset + span.start, span.digits, span.keyword);
|
|
40
|
+
}
|
|
41
|
+
numberedLines.push({
|
|
42
|
+
line: lineIndex,
|
|
43
|
+
number,
|
|
44
|
+
numberStart,
|
|
45
|
+
numberEnd,
|
|
46
|
+
bodyOffset,
|
|
47
|
+
textBeforeComment,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return { numberedLines, references };
|
|
51
|
+
}
|
|
52
|
+
export function findLineReferenceSpans(body) {
|
|
53
|
+
const spans = [];
|
|
54
|
+
const seen = new Set();
|
|
55
|
+
const simplePatterns = [
|
|
56
|
+
{
|
|
57
|
+
pattern: buildKeywordReferencePattern('GOTO', ['ON', 'ONKEY', 'THEN', 'ELSE']),
|
|
58
|
+
keyword: 'GOTO',
|
|
59
|
+
digitsGroup: 1,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
pattern: buildKeywordReferencePattern('GOSUB', ['ON', 'ONKEY', 'THEN', 'ELSE']),
|
|
63
|
+
keyword: 'GOSUB',
|
|
64
|
+
digitsGroup: 1,
|
|
65
|
+
},
|
|
66
|
+
{ pattern: buildKeywordReferencePattern('THEN'), keyword: 'THEN', digitsGroup: 1 },
|
|
67
|
+
{ pattern: buildKeywordReferencePattern('ELSE'), keyword: 'ELSE', digitsGroup: 1 },
|
|
68
|
+
{ pattern: buildKeywordReferencePattern('RUN'), keyword: 'RUN', digitsGroup: 1 },
|
|
69
|
+
{ pattern: buildKeywordReferencePattern('RESUME'), keyword: 'RESUME', digitsGroup: 1 },
|
|
70
|
+
{ pattern: buildKeywordReferencePattern('RESTORE'), keyword: 'RESTORE', digitsGroup: 1 },
|
|
71
|
+
];
|
|
72
|
+
for (const { pattern, keyword, digitsGroup } of simplePatterns) {
|
|
73
|
+
pattern.lastIndex = 0;
|
|
74
|
+
let match;
|
|
75
|
+
while ((match = pattern.exec(body)) !== null) {
|
|
76
|
+
const digits = match[digitsGroup];
|
|
77
|
+
const offset = (match.index ?? 0) + match[0].lastIndexOf(digits);
|
|
78
|
+
addSpan(spans, seen, offset, digits, keyword);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const onKeyPattern = /\bON\s*KEY\s*GOSUB\s*([0-9,\s]+)/gi;
|
|
82
|
+
onKeyPattern.lastIndex = 0;
|
|
83
|
+
let onKeyMatch;
|
|
84
|
+
while ((onKeyMatch = onKeyPattern.exec(body)) !== null) {
|
|
85
|
+
const list = onKeyMatch[1];
|
|
86
|
+
addListSpans(spans, seen, onKeyMatch, list, 'ON_KEY_GOSUB');
|
|
87
|
+
}
|
|
88
|
+
const onGenericPattern = /\bON(?!\s*KEY)[^:]*?(GOTO|GOSUB)\s*([0-9][0-9,\s]*)/gi;
|
|
89
|
+
onGenericPattern.lastIndex = 0;
|
|
90
|
+
let onGenericMatch;
|
|
91
|
+
while ((onGenericMatch = onGenericPattern.exec(body)) !== null) {
|
|
92
|
+
const list = onGenericMatch[2];
|
|
93
|
+
if (!list) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const keyword = onGenericMatch[1]?.toUpperCase() === 'GOSUB'
|
|
97
|
+
? 'ON_GOSUB'
|
|
98
|
+
: 'ON_GOTO';
|
|
99
|
+
addListSpans(spans, seen, onGenericMatch, list, keyword);
|
|
100
|
+
}
|
|
101
|
+
return spans;
|
|
102
|
+
}
|
|
103
|
+
function buildKeywordReferencePattern(keyword, allowAfter) {
|
|
104
|
+
const upper = allowAfter?.map(value => value.toUpperCase());
|
|
105
|
+
const boundary = '(?:^|[^A-Za-z])';
|
|
106
|
+
const allowedSegment = upper && upper.length ? `(?:${upper.join('|')})\\s*` : '';
|
|
107
|
+
const optionalAllowed = allowedSegment ? `(?:${allowedSegment})?` : '';
|
|
108
|
+
const prefix = `${boundary}${optionalAllowed}`;
|
|
109
|
+
return new RegExp(`${prefix}${keyword}\\s*(\\d+)`, 'gi');
|
|
110
|
+
}
|
|
111
|
+
function addListSpans(spans, seen, match, list, keyword) {
|
|
112
|
+
const numbersTextIndex = (match.index ?? 0) + match[0].lastIndexOf(list);
|
|
113
|
+
const digitPattern = /\d+/g;
|
|
114
|
+
let digitMatch;
|
|
115
|
+
while ((digitMatch = digitPattern.exec(list)) !== null) {
|
|
116
|
+
const digits = digitMatch[0];
|
|
117
|
+
const digitsIndex = digitMatch.index ?? 0;
|
|
118
|
+
addSpan(spans, seen, numbersTextIndex + digitsIndex, digits, keyword);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function addSpan(spans, seen, offset, digits, keyword) {
|
|
122
|
+
if (seen.has(offset)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
seen.add(offset);
|
|
126
|
+
spans.push({
|
|
127
|
+
start: offset,
|
|
128
|
+
end: offset + digits.length,
|
|
129
|
+
digits,
|
|
130
|
+
keyword,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function addReferenceIfValid(references, seen, lineIndex, fromNumber, position, digits, keyword) {
|
|
134
|
+
const target = parseInt(digits, 10);
|
|
135
|
+
if (Number.isNaN(target)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const key = `${lineIndex}:${position}`;
|
|
139
|
+
if (seen.has(key)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
seen.add(key);
|
|
143
|
+
references.push({
|
|
144
|
+
lineIndex,
|
|
145
|
+
start: position,
|
|
146
|
+
end: position + digits.length,
|
|
147
|
+
target,
|
|
148
|
+
fromNumber,
|
|
149
|
+
keyword,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=programAnalysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"programAnalysis.js","sourceRoot":"","sources":["../../src/utils/programAnalysis.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@m100/core",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"test": "node --test"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^20.19.27"
|
|
25
|
+
}
|
|
26
|
+
}
|