@flexiberry/berrycore 0.1.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 +21 -0
- package/dist/adapter/cli-adapter.d.ts +37 -0
- package/dist/adapter/cli-adapter.js +119 -0
- package/dist/berry-core.d.ts +108 -0
- package/dist/berry-core.js +258 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +18 -0
- package/dist/interpreter/environment.d.ts +45 -0
- package/dist/interpreter/environment.js +96 -0
- package/dist/interpreter/errors.d.ts +16 -0
- package/dist/interpreter/errors.js +27 -0
- package/dist/interpreter/interpreter.d.ts +111 -0
- package/dist/interpreter/interpreter.js +682 -0
- package/dist/interpreter/interpreter.types.d.ts +182 -0
- package/dist/interpreter/interpreter.types.js +73 -0
- package/dist/parser/ast/ast.engine.d.ts +103 -0
- package/dist/parser/ast/ast.engine.js +526 -0
- package/dist/parser/ast/ast.types.d.ts +242 -0
- package/dist/parser/ast/ast.types.js +37 -0
- package/dist/parser/formatter/formatter.d.ts +44 -0
- package/dist/parser/formatter/formatter.js +214 -0
- package/dist/parser/tokenizer/reader/grammer/api.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/api.grammer.js +102 -0
- package/dist/parser/tokenizer/reader/grammer/capture.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/capture.grammer.js +21 -0
- package/dist/parser/tokenizer/reader/grammer/check.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/check.grammer.js +21 -0
- package/dist/parser/tokenizer/reader/grammer/comment.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/comment.grammer.js +13 -0
- package/dist/parser/tokenizer/reader/grammer/conditions.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/conditions.grammer.js +68 -0
- package/dist/parser/tokenizer/reader/grammer/input.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/input.grammer.js +17 -0
- package/dist/parser/tokenizer/reader/grammer/keyvalue.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/keyvalue.grammer.js +240 -0
- package/dist/parser/tokenizer/reader/grammer/link.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/link.grammer.js +17 -0
- package/dist/parser/tokenizer/reader/grammer/params.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/params.grammer.js +21 -0
- package/dist/parser/tokenizer/reader/grammer/step.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/step.grammer.js +25 -0
- package/dist/parser/tokenizer/reader/grammer/task.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/task.grammer.js +17 -0
- package/dist/parser/tokenizer/reader/grammer/var.grammer.d.ts +2 -0
- package/dist/parser/tokenizer/reader/grammer/var.grammer.js +47 -0
- package/dist/parser/tokenizer/reader/lexer.engine.d.ts +43 -0
- package/dist/parser/tokenizer/reader/lexer.engine.js +178 -0
- package/dist/parser/tokenizer/reader/lexer.types.d.ts +18 -0
- package/dist/parser/tokenizer/reader/lexer.types.js +1 -0
- package/dist/parser/tokenizer/token.d.ts +13 -0
- package/dist/parser/tokenizer/token.js +13 -0
- package/dist/parser/tokenizer/tokenType.d.ts +58 -0
- package/dist/parser/tokenizer/tokenType.js +64 -0
- package/dist/script/format-util.d.ts +33 -0
- package/dist/script/format-util.js +94 -0
- package/dist/script/postman.util.d.ts +88 -0
- package/dist/script/postman.util.js +176 -0
- package/dist/script/swagger.util.d.ts +80 -0
- package/dist/script/swagger.util.js +202 -0
- package/dist/util/store-util.d.ts +5 -0
- package/dist/util/store-util.js +22 -0
- package/package.json +25 -0
- package/readme.md +107 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { Token } from "../token.js";
|
|
2
|
+
import { comment } from "./grammer/comment.grammer.js";
|
|
3
|
+
import { varLexerGrammer } from "./grammer/var.grammer.js";
|
|
4
|
+
import { TokenType } from "../tokenType.js";
|
|
5
|
+
import { apiGrammer } from "./grammer/api.grammer.js";
|
|
6
|
+
import { taskGrammer } from "./grammer/task.grammer.js";
|
|
7
|
+
import { stepGrammer } from "./grammer/step.grammer.js";
|
|
8
|
+
import { paramsGrammer } from "./grammer/params.grammer.js";
|
|
9
|
+
import { captureGrammer } from "./grammer/capture.grammer.js";
|
|
10
|
+
import { checkGrammer } from "./grammer/check.grammer.js";
|
|
11
|
+
import { linkGrammer } from "./grammer/link.grammer.js";
|
|
12
|
+
import { inputGrammer } from "./grammer/input.grammer.js";
|
|
13
|
+
const grammer = [
|
|
14
|
+
linkGrammer,
|
|
15
|
+
inputGrammer,
|
|
16
|
+
...varLexerGrammer,
|
|
17
|
+
comment,
|
|
18
|
+
...apiGrammer,
|
|
19
|
+
taskGrammer,
|
|
20
|
+
stepGrammer,
|
|
21
|
+
paramsGrammer,
|
|
22
|
+
captureGrammer,
|
|
23
|
+
checkGrammer,
|
|
24
|
+
];
|
|
25
|
+
export class LexerError extends Error {
|
|
26
|
+
line;
|
|
27
|
+
column;
|
|
28
|
+
constructor(message, line, column) {
|
|
29
|
+
super(`[LexerError at ${line}:${column}] ${message}`);
|
|
30
|
+
this.line = line;
|
|
31
|
+
this.column = column;
|
|
32
|
+
this.name = "LexerError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class LexerEngine {
|
|
36
|
+
input;
|
|
37
|
+
tokens = [];
|
|
38
|
+
lines = [];
|
|
39
|
+
lineIndex = 0;
|
|
40
|
+
columnIndex = 0;
|
|
41
|
+
currentLine = "";
|
|
42
|
+
at() {
|
|
43
|
+
return this.lines[this.lineIndex];
|
|
44
|
+
}
|
|
45
|
+
next() {
|
|
46
|
+
do {
|
|
47
|
+
this.lineIndex++;
|
|
48
|
+
} while (comment.regex.test(this.at()) &&
|
|
49
|
+
this.lineIndex < this.lines.length);
|
|
50
|
+
this.columnIndex = 0;
|
|
51
|
+
return this.at();
|
|
52
|
+
}
|
|
53
|
+
prev() {
|
|
54
|
+
this.lineIndex--;
|
|
55
|
+
return this.at();
|
|
56
|
+
}
|
|
57
|
+
constructor(input) {
|
|
58
|
+
this.input = input;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Processes a grammar rule against the given line and updates tokens.
|
|
62
|
+
* Optimized for readability and performance.
|
|
63
|
+
*/
|
|
64
|
+
processGrammer(grammar) {
|
|
65
|
+
// Handle multi-line grammar start/end
|
|
66
|
+
if (grammar.start && grammar.end && grammar.start.test(this.currentLine)) {
|
|
67
|
+
this.currentLine = this.mergeLinesUntilEnd(grammar, this.currentLine);
|
|
68
|
+
}
|
|
69
|
+
// Check if the line matches the grammar regex
|
|
70
|
+
if (grammar.regex.test(this.currentLine)) {
|
|
71
|
+
const match = this.currentLine.match(grammar.regex);
|
|
72
|
+
if (match) {
|
|
73
|
+
this.processGroups(grammar, match);
|
|
74
|
+
// Handle next grammar rules if present
|
|
75
|
+
if (grammar.next) {
|
|
76
|
+
this.processNextGrammars(grammar.next);
|
|
77
|
+
}
|
|
78
|
+
if (grammar.loopUntil) {
|
|
79
|
+
this.processLoopUntil(grammar);
|
|
80
|
+
if (grammar.moveNextLine ||
|
|
81
|
+
grammar.loopUntil.test(this.currentLine)) {
|
|
82
|
+
this.currentLine = this.prev();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
if (grammar.isOptional === false) {
|
|
90
|
+
throw new LexerError("Invalid syntax or grammar at current line", this.lineIndex, this.columnIndex);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Merges lines until the grammar's end pattern is matched or lines run out.
|
|
97
|
+
*/
|
|
98
|
+
mergeLinesUntilEnd(grammar, line) {
|
|
99
|
+
while (grammar.end &&
|
|
100
|
+
!grammar.end.test(line) &&
|
|
101
|
+
grammar.mergeLines &&
|
|
102
|
+
this.lineIndex < this.lines.length) {
|
|
103
|
+
line += this.next();
|
|
104
|
+
}
|
|
105
|
+
return line;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Processes the groups in the grammar and generates tokens.
|
|
109
|
+
*/
|
|
110
|
+
processGroups(grammar, match) {
|
|
111
|
+
for (const group of grammar.groups) {
|
|
112
|
+
const groupIdx = group.index ?? 0;
|
|
113
|
+
const matchedValue = match[groupIdx];
|
|
114
|
+
if (group.index !== undefined && matchedValue) {
|
|
115
|
+
this.tokens.push(Token.from(matchedValue, group.tokenType, this.columnIndex, this.columnIndex + matchedValue.length, this.lineIndex));
|
|
116
|
+
const indexofmatch = this.currentLine.indexOf(matchedValue);
|
|
117
|
+
this.columnIndex += indexofmatch >= 0 ? indexofmatch : 0;
|
|
118
|
+
this.currentLine = this.currentLine.substring(indexofmatch + matchedValue.length);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Processes any next grammar rules chained to the current grammar.
|
|
124
|
+
*/
|
|
125
|
+
processNextGrammars(nextGrammars) {
|
|
126
|
+
let isProcessed = false;
|
|
127
|
+
for (const nextGrammar of nextGrammars) {
|
|
128
|
+
if (isProcessed && nextGrammar.isOptional)
|
|
129
|
+
continue;
|
|
130
|
+
if (nextGrammar.moveNextLine) {
|
|
131
|
+
this.currentLine = this.next();
|
|
132
|
+
}
|
|
133
|
+
isProcessed = this.processGrammer(nextGrammar);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Handles looping a grammar until a condition is met.
|
|
138
|
+
*/
|
|
139
|
+
processLoopUntil(grammar) {
|
|
140
|
+
if (!grammar.loopUntil)
|
|
141
|
+
return true;
|
|
142
|
+
do {
|
|
143
|
+
this.currentLine = grammar.mergeLines
|
|
144
|
+
? this.currentLine + this.next()
|
|
145
|
+
: grammar.moveNextLine
|
|
146
|
+
? this.next()
|
|
147
|
+
: this.currentLine;
|
|
148
|
+
const isProcessed = this.processGrammer(grammar);
|
|
149
|
+
if (!isProcessed)
|
|
150
|
+
return false;
|
|
151
|
+
} while (grammar.loopUntil &&
|
|
152
|
+
grammar.loopUntil.test(this.currentLine) &&
|
|
153
|
+
this.lineIndex < this.lines.length);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Tokenizes the input string into tokens using the defined grammar list.
|
|
158
|
+
*/
|
|
159
|
+
tokenize() {
|
|
160
|
+
this.lines = this.input.split("\n");
|
|
161
|
+
const totalLines = this.lines.length;
|
|
162
|
+
// Process each line
|
|
163
|
+
while (this.lineIndex < totalLines) {
|
|
164
|
+
this.columnIndex = 0;
|
|
165
|
+
this.currentLine = this.at();
|
|
166
|
+
// Try each grammar rule; break if processed
|
|
167
|
+
for (const grammarRule of grammer) {
|
|
168
|
+
if (this.processGrammer(grammarRule)) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
this.next();
|
|
173
|
+
}
|
|
174
|
+
// Add EOF token at the end
|
|
175
|
+
this.tokens.push(Token.from("EOF", TokenType.Eof, this.columnIndex, this.columnIndex, this.lineIndex));
|
|
176
|
+
return this.tokens;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TokenType } from "../tokenType.js";
|
|
2
|
+
export type CaptureGroup = {
|
|
3
|
+
tokenType: TokenType;
|
|
4
|
+
index?: number;
|
|
5
|
+
};
|
|
6
|
+
export type LexerGrammer = {
|
|
7
|
+
name: string;
|
|
8
|
+
regex: RegExp;
|
|
9
|
+
groups: CaptureGroup[];
|
|
10
|
+
isOptional?: boolean;
|
|
11
|
+
moveNextLine?: boolean;
|
|
12
|
+
isMultiline?: boolean;
|
|
13
|
+
next?: LexerGrammer[];
|
|
14
|
+
loopUntil?: RegExp;
|
|
15
|
+
mergeLines?: boolean;
|
|
16
|
+
start?: RegExp;
|
|
17
|
+
end?: RegExp;
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TokenType } from "./tokenType.js";
|
|
2
|
+
export type Position = {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
line?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare class Token {
|
|
8
|
+
value: any;
|
|
9
|
+
type: TokenType;
|
|
10
|
+
position: Position;
|
|
11
|
+
constructor(value: any, type: TokenType, position: Position);
|
|
12
|
+
static from(value: any, type: TokenType, start: number, end: number, line?: number): Token;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class Token {
|
|
2
|
+
value;
|
|
3
|
+
type;
|
|
4
|
+
position;
|
|
5
|
+
constructor(value, type, position) {
|
|
6
|
+
this.value = value;
|
|
7
|
+
this.type = type;
|
|
8
|
+
this.position = position;
|
|
9
|
+
}
|
|
10
|
+
static from(value, type, start, end, line) {
|
|
11
|
+
return new Token(value, type, { start: start, end: end, line: line });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export declare function TokenTypeValueOf(value: TokenType): string;
|
|
2
|
+
export declare enum TokenType {
|
|
3
|
+
Number = 0,
|
|
4
|
+
Scalar = 1,
|
|
5
|
+
Value = 2,
|
|
6
|
+
Identifier = 3,
|
|
7
|
+
Env = 4,
|
|
8
|
+
Var = 5,
|
|
9
|
+
Link = 6,
|
|
10
|
+
LinkPath = 7,
|
|
11
|
+
Input = 8,
|
|
12
|
+
InputPath = 9,
|
|
13
|
+
Decrypt = 10,
|
|
14
|
+
Pointer = 11,
|
|
15
|
+
Pointed = 12,
|
|
16
|
+
Api = 13,
|
|
17
|
+
ApiMethod = 14,
|
|
18
|
+
Url = 15,
|
|
19
|
+
Body = 16,
|
|
20
|
+
BodyType = 17,
|
|
21
|
+
Header = 18,
|
|
22
|
+
HeaderValue = 19,
|
|
23
|
+
ApiEnd = 20,
|
|
24
|
+
Task = 21,
|
|
25
|
+
Step = 22,
|
|
26
|
+
StepName = 23,
|
|
27
|
+
Call = 24,
|
|
28
|
+
Title = 25,
|
|
29
|
+
And = 26,
|
|
30
|
+
Or = 27,
|
|
31
|
+
Gte = 28,
|
|
32
|
+
Gt = 29,
|
|
33
|
+
Lte = 30,
|
|
34
|
+
Lt = 31,
|
|
35
|
+
Equal = 32,
|
|
36
|
+
Lhs = 33,
|
|
37
|
+
Rhs = 34,
|
|
38
|
+
Operands = 35,
|
|
39
|
+
Operator = 36,
|
|
40
|
+
OperandsScalar = 37,
|
|
41
|
+
Comment = 38,
|
|
42
|
+
DocumentStart = 39,
|
|
43
|
+
DocumentEnd = 40,
|
|
44
|
+
Whitespace = 41,
|
|
45
|
+
Eof = 42,
|
|
46
|
+
EmptyLine = 43,
|
|
47
|
+
Comma = 44,
|
|
48
|
+
Colon = 45,
|
|
49
|
+
Backtick = 46,
|
|
50
|
+
Hyphen = 47,
|
|
51
|
+
Hash = 48,
|
|
52
|
+
Quote = 49,
|
|
53
|
+
Capture = 50,
|
|
54
|
+
Params = 51,
|
|
55
|
+
Check = 52,
|
|
56
|
+
NotEqual = 53,
|
|
57
|
+
Unknown = 54
|
|
58
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function TokenTypeValueOf(value) {
|
|
2
|
+
return TokenType[value]; // Return the name of the TokenType
|
|
3
|
+
}
|
|
4
|
+
export var TokenType;
|
|
5
|
+
(function (TokenType) {
|
|
6
|
+
// Literal Types
|
|
7
|
+
TokenType[TokenType["Number"] = 0] = "Number";
|
|
8
|
+
TokenType[TokenType["Scalar"] = 1] = "Scalar";
|
|
9
|
+
TokenType[TokenType["Value"] = 2] = "Value";
|
|
10
|
+
TokenType[TokenType["Identifier"] = 3] = "Identifier";
|
|
11
|
+
// Keywords
|
|
12
|
+
TokenType[TokenType["Env"] = 4] = "Env";
|
|
13
|
+
TokenType[TokenType["Var"] = 5] = "Var";
|
|
14
|
+
TokenType[TokenType["Link"] = 6] = "Link";
|
|
15
|
+
TokenType[TokenType["LinkPath"] = 7] = "LinkPath";
|
|
16
|
+
TokenType[TokenType["Input"] = 8] = "Input";
|
|
17
|
+
TokenType[TokenType["InputPath"] = 9] = "InputPath";
|
|
18
|
+
TokenType[TokenType["Decrypt"] = 10] = "Decrypt";
|
|
19
|
+
TokenType[TokenType["Pointer"] = 11] = "Pointer";
|
|
20
|
+
TokenType[TokenType["Pointed"] = 12] = "Pointed";
|
|
21
|
+
TokenType[TokenType["Api"] = 13] = "Api";
|
|
22
|
+
TokenType[TokenType["ApiMethod"] = 14] = "ApiMethod";
|
|
23
|
+
TokenType[TokenType["Url"] = 15] = "Url";
|
|
24
|
+
TokenType[TokenType["Body"] = 16] = "Body";
|
|
25
|
+
TokenType[TokenType["BodyType"] = 17] = "BodyType";
|
|
26
|
+
TokenType[TokenType["Header"] = 18] = "Header";
|
|
27
|
+
TokenType[TokenType["HeaderValue"] = 19] = "HeaderValue";
|
|
28
|
+
TokenType[TokenType["ApiEnd"] = 20] = "ApiEnd";
|
|
29
|
+
TokenType[TokenType["Task"] = 21] = "Task";
|
|
30
|
+
TokenType[TokenType["Step"] = 22] = "Step";
|
|
31
|
+
TokenType[TokenType["StepName"] = 23] = "StepName";
|
|
32
|
+
TokenType[TokenType["Call"] = 24] = "Call";
|
|
33
|
+
TokenType[TokenType["Title"] = 25] = "Title";
|
|
34
|
+
// logic types
|
|
35
|
+
TokenType[TokenType["And"] = 26] = "And";
|
|
36
|
+
TokenType[TokenType["Or"] = 27] = "Or";
|
|
37
|
+
TokenType[TokenType["Gte"] = 28] = "Gte";
|
|
38
|
+
TokenType[TokenType["Gt"] = 29] = "Gt";
|
|
39
|
+
TokenType[TokenType["Lte"] = 30] = "Lte";
|
|
40
|
+
TokenType[TokenType["Lt"] = 31] = "Lt";
|
|
41
|
+
TokenType[TokenType["Equal"] = 32] = "Equal";
|
|
42
|
+
TokenType[TokenType["Lhs"] = 33] = "Lhs";
|
|
43
|
+
TokenType[TokenType["Rhs"] = 34] = "Rhs";
|
|
44
|
+
TokenType[TokenType["Operands"] = 35] = "Operands";
|
|
45
|
+
TokenType[TokenType["Operator"] = 36] = "Operator";
|
|
46
|
+
TokenType[TokenType["OperandsScalar"] = 37] = "OperandsScalar";
|
|
47
|
+
TokenType[TokenType["Comment"] = 38] = "Comment";
|
|
48
|
+
TokenType[TokenType["DocumentStart"] = 39] = "DocumentStart";
|
|
49
|
+
TokenType[TokenType["DocumentEnd"] = 40] = "DocumentEnd";
|
|
50
|
+
TokenType[TokenType["Whitespace"] = 41] = "Whitespace";
|
|
51
|
+
TokenType[TokenType["Eof"] = 42] = "Eof";
|
|
52
|
+
TokenType[TokenType["EmptyLine"] = 43] = "EmptyLine";
|
|
53
|
+
TokenType[TokenType["Comma"] = 44] = "Comma";
|
|
54
|
+
TokenType[TokenType["Colon"] = 45] = "Colon";
|
|
55
|
+
TokenType[TokenType["Backtick"] = 46] = "Backtick";
|
|
56
|
+
TokenType[TokenType["Hyphen"] = 47] = "Hyphen";
|
|
57
|
+
TokenType[TokenType["Hash"] = 48] = "Hash";
|
|
58
|
+
TokenType[TokenType["Quote"] = 49] = "Quote";
|
|
59
|
+
TokenType[TokenType["Capture"] = 50] = "Capture";
|
|
60
|
+
TokenType[TokenType["Params"] = 51] = "Params";
|
|
61
|
+
TokenType[TokenType["Check"] = 52] = "Check";
|
|
62
|
+
TokenType[TokenType["NotEqual"] = 53] = "NotEqual";
|
|
63
|
+
TokenType[TokenType["Unknown"] = 54] = "Unknown";
|
|
64
|
+
})(TokenType || (TokenType = {}));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format Utility
|
|
3
|
+
*
|
|
4
|
+
* Utilities for converting external API formats (CURL, etc.) to Berry code.
|
|
5
|
+
*/
|
|
6
|
+
export interface ApiCommand {
|
|
7
|
+
method: string;
|
|
8
|
+
url: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
body?: string;
|
|
11
|
+
bodyType?: string;
|
|
12
|
+
headers?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class FormatUtil {
|
|
15
|
+
/**
|
|
16
|
+
* Convert a CURL command to Berry Api string
|
|
17
|
+
* @param curl The CURL command string
|
|
18
|
+
* @param id The name/identifier for the Api
|
|
19
|
+
*/
|
|
20
|
+
static convertCurlToBerry(curl: string, id: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Build a Berry Api block from a command object
|
|
23
|
+
*/
|
|
24
|
+
static buildApi(name: string, cmd: ApiCommand): string;
|
|
25
|
+
/**
|
|
26
|
+
* Build a Berry Var block
|
|
27
|
+
*/
|
|
28
|
+
static buildVar(title: string, variables: string[], env?: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Build a Berry Env block
|
|
31
|
+
*/
|
|
32
|
+
static buildEnv(envs: (string | null | undefined)[]): string;
|
|
33
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format Utility
|
|
3
|
+
*
|
|
4
|
+
* Utilities for converting external API formats (CURL, etc.) to Berry code.
|
|
5
|
+
*/
|
|
6
|
+
export class FormatUtil {
|
|
7
|
+
/**
|
|
8
|
+
* Convert a CURL command to Berry Api string
|
|
9
|
+
* @param curl The CURL command string
|
|
10
|
+
* @param id The name/identifier for the Api
|
|
11
|
+
*/
|
|
12
|
+
static convertCurlToBerry(curl, id) {
|
|
13
|
+
// 1. Extract Method
|
|
14
|
+
const methodMatch = curl.match(/(?:--location|-X)\s+(\w+)/);
|
|
15
|
+
const method = (methodMatch ? methodMatch[1] : "GET").toUpperCase();
|
|
16
|
+
// 2. Extract URL
|
|
17
|
+
const urlMatch = curl.match(/(?:['"]?)(https?:\/\/[^\s'"]+)(?:['"]?)/);
|
|
18
|
+
const url = urlMatch ? urlMatch[1] : "";
|
|
19
|
+
// 3. Extract Headers
|
|
20
|
+
const headers = {};
|
|
21
|
+
const headerPattern = /(?:--header|-[Hh])\s+(['"])(.*?):\s*(.*?)\1/gm;
|
|
22
|
+
let match;
|
|
23
|
+
while ((match = headerPattern.exec(curl)) !== null) {
|
|
24
|
+
if (match[2] && match[3]) {
|
|
25
|
+
headers[match[2].trim()] = match[3].trim();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// 4. Extract Body
|
|
29
|
+
const bodyMatch = curl.match(/(?:--data-raw|--data-binary|--data|-[dD])\s+(?:'|")?(\{.*\}|.*)(?:'|")?/s);
|
|
30
|
+
// Cleanup body: remove leading/trailing quotes if the regex captured them lazily
|
|
31
|
+
let body = bodyMatch ? bodyMatch[1].trim() : null;
|
|
32
|
+
if (body && (body.startsWith("'") || body.startsWith('"'))) {
|
|
33
|
+
body = body.slice(1, -1);
|
|
34
|
+
}
|
|
35
|
+
// 5. Construct Berry String
|
|
36
|
+
const lines = [`Api ${method} #${id}`];
|
|
37
|
+
lines.push(`Url ${url}`);
|
|
38
|
+
if (body) {
|
|
39
|
+
// Inline the body for simplicity in CURL conversion
|
|
40
|
+
const cleanBody = body.replace(/\n/g, " ").trim();
|
|
41
|
+
lines.push(`Body JSON \`${cleanBody}\``);
|
|
42
|
+
}
|
|
43
|
+
if (Object.entries(headers).length > 0) {
|
|
44
|
+
lines.push("Header");
|
|
45
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
46
|
+
lines.push(`- ${key}: '${value}'`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return lines.join("\n") + "\n";
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a Berry Api block from a command object
|
|
53
|
+
*/
|
|
54
|
+
static buildApi(name, cmd) {
|
|
55
|
+
const lines = [`Api ${cmd.method.toUpperCase()} #${name} ${cmd.title || ""}`];
|
|
56
|
+
lines.push(`Url ${cmd.url}`);
|
|
57
|
+
if (cmd.body) {
|
|
58
|
+
const type = (cmd.bodyType || "JSON").toUpperCase();
|
|
59
|
+
lines.push(`Body ${type}`);
|
|
60
|
+
lines.push("`", cmd.body, "`");
|
|
61
|
+
}
|
|
62
|
+
if (cmd.headers) {
|
|
63
|
+
lines.push("Header");
|
|
64
|
+
const headerList = cmd.headers.split(",").map((h) => h.trim());
|
|
65
|
+
for (const h of headerList) {
|
|
66
|
+
if (h)
|
|
67
|
+
lines.push(`- ${h}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return lines.join("\n") + "\n";
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a Berry Var block
|
|
74
|
+
*/
|
|
75
|
+
static buildVar(title, variables, env) {
|
|
76
|
+
const header = `Var ${env ? "@" + env : ""} ${title}`;
|
|
77
|
+
const lines = [header];
|
|
78
|
+
for (const v of variables) {
|
|
79
|
+
lines.push(`- ${v}`);
|
|
80
|
+
}
|
|
81
|
+
return lines.join("\n") + "\n";
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build a Berry Env block
|
|
85
|
+
*/
|
|
86
|
+
static buildEnv(envs) {
|
|
87
|
+
const validEnvs = envs
|
|
88
|
+
.filter((e) => !!e)
|
|
89
|
+
.map((e) => e.trim().toUpperCase());
|
|
90
|
+
if (validEnvs.length === 0)
|
|
91
|
+
return "";
|
|
92
|
+
return `Env ${validEnvs.join(",")}\n`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postman Collection Interfaces (Minimal for conversion)
|
|
3
|
+
*/
|
|
4
|
+
export interface PostmanHeader {
|
|
5
|
+
key: string;
|
|
6
|
+
value: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PostmanUrl {
|
|
10
|
+
raw: string;
|
|
11
|
+
protocol?: string;
|
|
12
|
+
host?: string[];
|
|
13
|
+
path?: string[];
|
|
14
|
+
query?: Array<{
|
|
15
|
+
key: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}>;
|
|
18
|
+
variable?: Array<{
|
|
19
|
+
key: string;
|
|
20
|
+
value: string;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface PostmanBody {
|
|
24
|
+
mode: "raw" | "urlencoded" | "formdata" | "file" | "graphql";
|
|
25
|
+
raw?: string;
|
|
26
|
+
urlencoded?: Array<{
|
|
27
|
+
key: string;
|
|
28
|
+
value: string;
|
|
29
|
+
}>;
|
|
30
|
+
formdata?: Array<{
|
|
31
|
+
key: string;
|
|
32
|
+
value: string;
|
|
33
|
+
}>;
|
|
34
|
+
options?: {
|
|
35
|
+
raw?: {
|
|
36
|
+
language: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export interface PostmanRequest {
|
|
41
|
+
method: string;
|
|
42
|
+
header: PostmanHeader[];
|
|
43
|
+
url: PostmanUrl | string;
|
|
44
|
+
body?: PostmanBody;
|
|
45
|
+
}
|
|
46
|
+
export interface PostmanItem {
|
|
47
|
+
name: string;
|
|
48
|
+
request?: PostmanRequest;
|
|
49
|
+
item?: PostmanItem[];
|
|
50
|
+
}
|
|
51
|
+
export interface PostmanCollection {
|
|
52
|
+
info: {
|
|
53
|
+
name: string;
|
|
54
|
+
schema: string;
|
|
55
|
+
};
|
|
56
|
+
item: PostmanItem[];
|
|
57
|
+
}
|
|
58
|
+
export declare class PostmanUtil {
|
|
59
|
+
/**
|
|
60
|
+
* Convert a Postman collection file (JSON) to Berry API code
|
|
61
|
+
* @param filePath Path to the Postman collection JSON file
|
|
62
|
+
*/
|
|
63
|
+
static convertFromPostmanFile(filePath: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Internal recursive processor for Postman items
|
|
66
|
+
*/
|
|
67
|
+
private static processItems;
|
|
68
|
+
/**
|
|
69
|
+
* Build URL string from Postman URL object
|
|
70
|
+
*/
|
|
71
|
+
private static buildUrl;
|
|
72
|
+
/**
|
|
73
|
+
* Abbreviate title to camelCase ID
|
|
74
|
+
*/
|
|
75
|
+
private static abbreviate;
|
|
76
|
+
/**
|
|
77
|
+
* Extract headers to Berry format
|
|
78
|
+
*/
|
|
79
|
+
private static extractHeaders;
|
|
80
|
+
/**
|
|
81
|
+
* Extract body content from Postman request
|
|
82
|
+
*/
|
|
83
|
+
private static extractBody;
|
|
84
|
+
/**
|
|
85
|
+
* Detect Berry body type from content-type or Postman options
|
|
86
|
+
*/
|
|
87
|
+
private static detectBodyType;
|
|
88
|
+
}
|