norn-cli 2.3.0 → 2.4.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/.claude/skills/norn-social-campaign/SKILL.md +70 -0
- package/CHANGELOG.md +6 -0
- package/demos/nornenv-region-refactor/README.md +64 -0
- package/dist/cli.js +360 -1
- package/out/apiResponseIntellisenseCache.js +394 -0
- package/out/assertionRunner.js +567 -0
- package/out/cacheDir.js +136 -0
- package/out/chatParticipant.js +763 -0
- package/out/cli/colors.js +127 -0
- package/out/cli/formatters/assertion.js +102 -0
- package/out/cli/formatters/index.js +23 -0
- package/out/cli/formatters/response.js +106 -0
- package/out/cli/formatters/summary.js +246 -0
- package/out/cli/redaction.js +237 -0
- package/out/cli/reporters/html.js +689 -0
- package/out/cli/reporters/index.js +22 -0
- package/out/cli/reporters/junit.js +226 -0
- package/out/codeLensProvider.js +351 -0
- package/out/compareContentProvider.js +85 -0
- package/out/completionProvider.js +3739 -0
- package/out/contractAssertionSummary.js +225 -0
- package/out/contractDecorationProvider.js +243 -0
- package/out/coverageCalculator.js +879 -0
- package/out/coveragePanel.js +597 -0
- package/out/debug/breakpointResolver.js +84 -0
- package/out/debug/breakpoints.js +52 -0
- package/out/debug/nornDebugAdapter.js +166 -0
- package/out/debug/nornDebugSession.js +613 -0
- package/out/debug/sequenceLocationIndex.js +77 -0
- package/out/debug/types.js +3 -0
- package/out/deepClone.js +21 -0
- package/out/diagnosticProvider.js +2554 -0
- package/out/environmentParser.js +736 -0
- package/out/environmentProvider.js +544 -0
- package/out/environmentTemplates.js +146 -0
- package/out/errors/formatError.js +113 -0
- package/out/errors/nornError.js +29 -0
- package/out/formUrlEncoded.js +89 -0
- package/out/httpClient.js +348 -0
- package/out/httpRuntimeOptions.js +16 -0
- package/out/importErrors.js +31 -0
- package/out/inlayHintResolver.js +70 -0
- package/out/jsonFileReader.js +323 -0
- package/out/mcpClient.js +193 -0
- package/out/mcpConfig.js +184 -0
- package/out/mcpToolIntellisenseCache.js +96 -0
- package/out/mcpToolSchema.js +50 -0
- package/out/nornConfig.js +132 -0
- package/out/nornHoverProvider.js +124 -0
- package/out/nornInlayHintsProvider.js +191 -0
- package/out/nornPrompt.js +755 -0
- package/out/nornSqlParser.js +286 -0
- package/out/nornapiHoverProvider.js +135 -0
- package/out/nornapiInlayHintsProvider.js +94 -0
- package/out/nornapiParser.js +324 -0
- package/out/nornenvCodeActionProvider.js +101 -0
- package/out/nornenvDecorationProvider.js +239 -0
- package/out/nornenvFoldingProvider.js +63 -0
- package/out/nornenvHoverProvider.js +114 -0
- package/out/nornenvInlayHintsProvider.js +99 -0
- package/out/nornenvLanguageModel.js +187 -0
- package/out/nornenvRegionRefactor.js +267 -0
- package/out/nornsqlHoverProvider.js +95 -0
- package/out/nornsqlInlayHintsProvider.js +114 -0
- package/out/parser.js +839 -0
- package/out/pathAccess.js +28 -0
- package/out/postmanImportPanel.js +732 -0
- package/out/postmanImportPlanner.js +1155 -0
- package/out/postmanImportSidebarView.js +532 -0
- package/out/quotedString.js +35 -0
- package/out/requestPreparation.js +179 -0
- package/out/requestValidation.js +146 -0
- package/out/responsePanel.js +7754 -0
- package/out/schemaGenerator.js +562 -0
- package/out/scriptRunner.js +419 -0
- package/out/secrets/cliSecrets.js +415 -0
- package/out/secrets/crypto.js +105 -0
- package/out/secrets/envFileSecrets.js +177 -0
- package/out/secrets/keyStore.js +259 -0
- package/out/sequenceDeclaration.js +15 -0
- package/out/sequenceRunner.js +3590 -0
- package/out/sqlAdapterRunner.js +122 -0
- package/out/sqlBuiltInAdapters.js +604 -0
- package/out/sqlConfig.js +184 -0
- package/out/starterCatalog.js +554 -0
- package/out/stringUtils.js +25 -0
- package/out/swaggerBodyIntellisenseCache.js +114 -0
- package/out/swaggerParser.js +464 -0
- package/out/testProvider.js +767 -0
- package/out/theoryCaseLoader.js +113 -0
- package/out/validationCache.js +211 -0
- package/package.json +6 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveBareVariableRequestBody = resolveBareVariableRequestBody;
|
|
4
|
+
exports.applyHeaderGroupsToRequest = applyHeaderGroupsToRequest;
|
|
5
|
+
exports.prepareRequestFromContent = prepareRequestFromContent;
|
|
6
|
+
const parser_1 = require("./parser");
|
|
7
|
+
const nornapiParser_1 = require("./nornapiParser");
|
|
8
|
+
const pathAccess_1 = require("./pathAccess");
|
|
9
|
+
function escapeRegExp(value) {
|
|
10
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
11
|
+
}
|
|
12
|
+
function stringifyRequestValue(value) {
|
|
13
|
+
if (typeof value === 'string') {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === 'object' && value !== null) {
|
|
17
|
+
return JSON.stringify(value);
|
|
18
|
+
}
|
|
19
|
+
return String(value);
|
|
20
|
+
}
|
|
21
|
+
function shouldResolveBareRequestValue(value, variables) {
|
|
22
|
+
if (!Object.prototype.hasOwnProperty.call(variables, value)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const envScope = variables['$env'];
|
|
26
|
+
const isEnvOnlyValue = envScope
|
|
27
|
+
&& typeof envScope === 'object'
|
|
28
|
+
&& Object.prototype.hasOwnProperty.call(envScope, value)
|
|
29
|
+
&& variables[value] === envScope[value];
|
|
30
|
+
return !isEnvOnlyValue;
|
|
31
|
+
}
|
|
32
|
+
function resolveRequestValueExpression(value, variables) {
|
|
33
|
+
if (shouldResolveBareRequestValue(value, variables)) {
|
|
34
|
+
return stringifyRequestValue(variables[value]);
|
|
35
|
+
}
|
|
36
|
+
const pathMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)(\.\w[\w-]*(?:\.\w[\w-]*|\[\d+\])*|\[\d+\](?:\.\w[\w-]*|\[\d+\])*)$/);
|
|
37
|
+
if (pathMatch && shouldResolveBareRequestValue(pathMatch[1], variables)) {
|
|
38
|
+
const nestedValue = (0, pathAccess_1.getNestedPathValue)(variables[pathMatch[1]], pathMatch[2].replace(/^\./, ''));
|
|
39
|
+
if (nestedValue !== undefined) {
|
|
40
|
+
return stringifyRequestValue(nestedValue);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return (0, parser_1.substituteVariables)(value, variables);
|
|
44
|
+
}
|
|
45
|
+
function resolveBareVariableRequestBody(request, variables) {
|
|
46
|
+
if (!request.body) {
|
|
47
|
+
return request;
|
|
48
|
+
}
|
|
49
|
+
const bareVariableMatch = request.body.trim().match(/^([a-zA-Z_][a-zA-Z0-9_]*)$/);
|
|
50
|
+
if (!bareVariableMatch || !(bareVariableMatch[1] in variables)) {
|
|
51
|
+
return request;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
...request,
|
|
55
|
+
body: stringifyRequestValue(variables[bareVariableMatch[1]])
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function applyHeaderGroupsToRequest(parsed, requestText, headerGroups, variables) {
|
|
59
|
+
const lines = requestText.split('\n');
|
|
60
|
+
const headerGroupNames = headerGroups.map(hg => hg.name);
|
|
61
|
+
const headerGroupHeaders = {};
|
|
62
|
+
const foundGroups = [];
|
|
63
|
+
const cleanedBodyLines = [];
|
|
64
|
+
let sawRequestLine = false;
|
|
65
|
+
let inBodySection = false;
|
|
66
|
+
let sawBlankLineAfterRequest = false;
|
|
67
|
+
for (const line of lines) {
|
|
68
|
+
const trimmed = line.trim();
|
|
69
|
+
if (trimmed.startsWith('#') || trimmed.startsWith('var ')) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!trimmed) {
|
|
73
|
+
if (sawRequestLine && !inBodySection) {
|
|
74
|
+
sawBlankLineAfterRequest = true;
|
|
75
|
+
}
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const methodMatch = trimmed.match(/^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(.+)$/i);
|
|
79
|
+
if (!sawRequestLine && methodMatch) {
|
|
80
|
+
sawRequestLine = true;
|
|
81
|
+
const afterMethod = methodMatch[2];
|
|
82
|
+
const tokens = afterMethod.split(/\s+/);
|
|
83
|
+
for (let index = tokens.length - 1; index >= 0; index--) {
|
|
84
|
+
if (headerGroupNames.includes(tokens[index])) {
|
|
85
|
+
foundGroups.push(tokens[index]);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (!sawRequestLine) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (sawBlankLineAfterRequest) {
|
|
97
|
+
inBodySection = true;
|
|
98
|
+
}
|
|
99
|
+
if (!inBodySection) {
|
|
100
|
+
if (/^[A-Za-z0-9\-_]+\s*:\s*.+$/.test(trimmed)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const potentialGroups = trimmed.split(/\s+/).filter(Boolean);
|
|
104
|
+
const matchingGroups = potentialGroups.filter(groupName => headerGroupNames.includes(groupName));
|
|
105
|
+
if (matchingGroups.length > 0 && matchingGroups.length === potentialGroups.length) {
|
|
106
|
+
foundGroups.push(...matchingGroups);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
inBodySection = true;
|
|
110
|
+
}
|
|
111
|
+
cleanedBodyLines.push(trimmed);
|
|
112
|
+
}
|
|
113
|
+
for (const groupName of foundGroups) {
|
|
114
|
+
const group = headerGroups.find(hg => hg.name === groupName);
|
|
115
|
+
if (group) {
|
|
116
|
+
Object.assign(headerGroupHeaders, (0, nornapiParser_1.resolveHeaderValues)(group, variables));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
let modifiedUrl = parsed.url;
|
|
120
|
+
for (const groupName of foundGroups) {
|
|
121
|
+
const endPattern = new RegExp(`\\s+${escapeRegExp(groupName)}$`);
|
|
122
|
+
modifiedUrl = modifiedUrl.replace(endPattern, '');
|
|
123
|
+
}
|
|
124
|
+
modifiedUrl = modifiedUrl.trim();
|
|
125
|
+
const result = {
|
|
126
|
+
...parsed,
|
|
127
|
+
url: modifiedUrl,
|
|
128
|
+
body: cleanedBodyLines.length > 0 ? (0, parser_1.substituteVariables)(cleanedBodyLines.join('\n'), variables) : undefined
|
|
129
|
+
};
|
|
130
|
+
if (Object.keys(headerGroupHeaders).length > 0) {
|
|
131
|
+
result.headers = { ...headerGroupHeaders, ...parsed.headers };
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
function prepareRequestFromContent(requestContent, variables, apiDefinitions) {
|
|
136
|
+
if (apiDefinitions && apiDefinitions.endpoints.length > 0 && (0, nornapiParser_1.isApiRequestLine)(requestContent, apiDefinitions.endpoints)) {
|
|
137
|
+
const apiRequest = (0, nornapiParser_1.parseApiRequest)(requestContent, apiDefinitions.endpoints, apiDefinitions.headerGroups);
|
|
138
|
+
if (apiRequest) {
|
|
139
|
+
const endpoint = (0, nornapiParser_1.getEndpoint)(apiDefinitions, apiRequest.endpointName);
|
|
140
|
+
if (!endpoint) {
|
|
141
|
+
throw new Error(`Unknown endpoint: ${apiRequest.endpointName}`);
|
|
142
|
+
}
|
|
143
|
+
const resolvedParams = {};
|
|
144
|
+
for (const [paramName, paramValue] of Object.entries(apiRequest.params)) {
|
|
145
|
+
resolvedParams[paramName] = resolveRequestValueExpression(paramValue, variables);
|
|
146
|
+
}
|
|
147
|
+
const resolvedPath = (0, parser_1.substituteVariables)((0, nornapiParser_1.resolveEndpointPath)(endpoint, resolvedParams), variables);
|
|
148
|
+
const combinedHeaders = {};
|
|
149
|
+
for (const groupName of apiRequest.headerGroupNames) {
|
|
150
|
+
const group = (0, nornapiParser_1.getHeaderGroup)(apiDefinitions, groupName);
|
|
151
|
+
if (group) {
|
|
152
|
+
Object.assign(combinedHeaders, (0, nornapiParser_1.resolveHeaderValues)(group, variables));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const [headerName, headerValue] of Object.entries(apiRequest.inlineHeaders)) {
|
|
156
|
+
combinedHeaders[headerName] = (0, parser_1.substituteVariables)(headerValue, variables);
|
|
157
|
+
}
|
|
158
|
+
const request = {
|
|
159
|
+
method: apiRequest.method,
|
|
160
|
+
url: resolvedPath,
|
|
161
|
+
headers: combinedHeaders,
|
|
162
|
+
body: apiRequest.body ? (0, parser_1.substituteVariables)(apiRequest.body, variables) : undefined
|
|
163
|
+
};
|
|
164
|
+
return {
|
|
165
|
+
request,
|
|
166
|
+
description: `${apiRequest.endpointName}(${Object.values(resolvedParams).join(', ')}) -> ${request.method} ${request.url}`
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
let request = (0, parser_1.parserHttpRequest)(requestContent, variables);
|
|
171
|
+
if (apiDefinitions && apiDefinitions.headerGroups.length > 0) {
|
|
172
|
+
request = applyHeaderGroupsToRequest(request, requestContent, apiDefinitions.headerGroups, variables);
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
request,
|
|
176
|
+
description: `${request.method} ${request.url}`
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=requestPreparation.js.map
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findPlaceholderReferences = findPlaceholderReferences;
|
|
4
|
+
exports.validatePreparedRequest = validatePreparedRequest;
|
|
5
|
+
const nornError_1 = require("./errors/nornError");
|
|
6
|
+
const formUrlEncoded_1 = require("./formUrlEncoded");
|
|
7
|
+
const PLACEHOLDER_REGEX = /\{\{(\$env|\$[0-9]+|[a-zA-Z_][a-zA-Z0-9_]*)((?:\.[a-zA-Z_][a-zA-Z0-9_-]*|\[\d+\])*)\}\}/g;
|
|
8
|
+
function findPlaceholderReferences(text) {
|
|
9
|
+
if (!text) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const references = [];
|
|
13
|
+
let match;
|
|
14
|
+
PLACEHOLDER_REGEX.lastIndex = 0;
|
|
15
|
+
while ((match = PLACEHOLDER_REGEX.exec(text)) !== null) {
|
|
16
|
+
references.push({
|
|
17
|
+
text: match[0],
|
|
18
|
+
name: match[1],
|
|
19
|
+
pathPart: match[2] || '',
|
|
20
|
+
index: match.index
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return references;
|
|
24
|
+
}
|
|
25
|
+
function collectUnresolvedPlaceholders(text) {
|
|
26
|
+
if (!text) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const names = new Set();
|
|
30
|
+
for (const reference of findPlaceholderReferences(text)) {
|
|
31
|
+
names.add(reference.text);
|
|
32
|
+
}
|
|
33
|
+
return [...names];
|
|
34
|
+
}
|
|
35
|
+
function extractEnvScopedNames(placeholders) {
|
|
36
|
+
return placeholders
|
|
37
|
+
.filter(value => value.startsWith('{{$env.'))
|
|
38
|
+
.map(value => value.slice('{{$env.'.length, -2).split(/[.[\]]/)[0])
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
}
|
|
41
|
+
function buildMissingVariableHint(missingVars, context) {
|
|
42
|
+
const env = context?.environment;
|
|
43
|
+
const envScopedNames = extractEnvScopedNames(missingVars);
|
|
44
|
+
const unscopedVars = missingVars.filter(value => !value.startsWith('{{$env.'));
|
|
45
|
+
if (env?.hasEnvFile && env.availableEnvironments && env.availableEnvironments.length > 0 && !env.activeEnvironment) {
|
|
46
|
+
return `A .nornenv file was found but no environment is selected. Select one of: ${env.availableEnvironments.join(', ')}.`;
|
|
47
|
+
}
|
|
48
|
+
if (env?.hasEnvFile && env.activeEnvironment && envScopedNames.length > 0 && unscopedVars.length === 0) {
|
|
49
|
+
return `Check that ${envScopedNames.map(v => `'${v}'`).join(', ')} exist in the active environment '${env.activeEnvironment}'.`;
|
|
50
|
+
}
|
|
51
|
+
if (env?.hasEnvFile && env.activeEnvironment) {
|
|
52
|
+
return `Check that ${missingVars.map(v => `'${v}'`).join(', ')} exist in the active environment '${env.activeEnvironment}' or as file-level variables.`;
|
|
53
|
+
}
|
|
54
|
+
return `Define ${missingVars.length === 1 ? 'the variable' : 'the variables'} ${missingVars.map(v => `'${v}'`).join(', ')} before sending the request.`;
|
|
55
|
+
}
|
|
56
|
+
function buildRequestContext(parsed, context) {
|
|
57
|
+
return {
|
|
58
|
+
...context,
|
|
59
|
+
method: context?.method || parsed.method,
|
|
60
|
+
url: context?.url || parsed.url,
|
|
61
|
+
environment: context?.environment
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function getHeaderValueCaseInsensitive(headers, headerName) {
|
|
65
|
+
const targetName = headerName.toLowerCase();
|
|
66
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
67
|
+
if (name.toLowerCase() === targetName) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
function describeUnresolvedLocation(label, vars) {
|
|
74
|
+
if (vars.length === 0) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return `${label}: unresolved ${vars.length === 1 ? 'variable' : 'variables'} ${vars.join(', ')}`;
|
|
78
|
+
}
|
|
79
|
+
function shouldValidateBodyPlaceholders(parsed) {
|
|
80
|
+
const method = String(parsed.method || '').toUpperCase();
|
|
81
|
+
// Be conservative: GET/HEAD commonly ignore bodies and legacy Norn tests may contain
|
|
82
|
+
// body-like trailing text that should not block execution for these methods.
|
|
83
|
+
return method !== 'GET' && method !== 'HEAD';
|
|
84
|
+
}
|
|
85
|
+
function validatePreparedRequest(parsed, context) {
|
|
86
|
+
const urlVars = collectUnresolvedPlaceholders(parsed.url);
|
|
87
|
+
const headerVars = [...new Set(Object.values(parsed.headers).flatMap(value => collectUnresolvedPlaceholders(value)))];
|
|
88
|
+
const bodyVars = shouldValidateBodyPlaceholders(parsed) ? collectUnresolvedPlaceholders(parsed.body) : [];
|
|
89
|
+
const missingVars = [...new Set([...urlVars, ...headerVars, ...bodyVars])];
|
|
90
|
+
if (missingVars.length > 0) {
|
|
91
|
+
const details = [
|
|
92
|
+
describeUnresolvedLocation('URL', urlVars),
|
|
93
|
+
describeUnresolvedLocation('Headers', headerVars),
|
|
94
|
+
describeUnresolvedLocation('Body', bodyVars)
|
|
95
|
+
].filter((d) => Boolean(d));
|
|
96
|
+
throw new nornError_1.NornError({
|
|
97
|
+
category: 'variable-resolution',
|
|
98
|
+
code: 'unresolved-request-variables',
|
|
99
|
+
message: `Request could not be prepared: unresolved ${missingVars.length === 1 ? 'variable' : 'variables'} ${missingVars.join(', ')}.`,
|
|
100
|
+
details,
|
|
101
|
+
hint: buildMissingVariableHint(missingVars, context),
|
|
102
|
+
context: {
|
|
103
|
+
...buildRequestContext(parsed, context),
|
|
104
|
+
unresolvedVariables: missingVars
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (!parsed.url || !parsed.url.trim()) {
|
|
109
|
+
throw new nornError_1.NornError({
|
|
110
|
+
category: 'url',
|
|
111
|
+
code: 'missing-request-url',
|
|
112
|
+
message: 'Request URL is missing.',
|
|
113
|
+
hint: 'Add a URL after the HTTP method (for example: GET https://api.example.com/path).',
|
|
114
|
+
context: buildRequestContext(parsed, context)
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
new URL(parsed.url);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
throw new nornError_1.NornError({
|
|
122
|
+
category: 'url',
|
|
123
|
+
code: 'invalid-request-url',
|
|
124
|
+
message: `Invalid request URL: ${parsed.url}`,
|
|
125
|
+
details: error instanceof Error ? error.message : String(error),
|
|
126
|
+
hint: 'Check the URL format and any variables used to build it.',
|
|
127
|
+
context: buildRequestContext(parsed, context),
|
|
128
|
+
cause: error
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
const contentType = getHeaderValueCaseInsensitive(parsed.headers, 'Content-Type');
|
|
132
|
+
if ((0, formUrlEncoded_1.isFormUrlEncodedContentType)(contentType)) {
|
|
133
|
+
const { errors } = (0, formUrlEncoded_1.parseFormUrlEncodedBody)(parsed.body);
|
|
134
|
+
if (errors.length > 0) {
|
|
135
|
+
throw new nornError_1.NornError({
|
|
136
|
+
category: 'syntax',
|
|
137
|
+
code: 'invalid-form-urlencoded-body',
|
|
138
|
+
message: 'Request could not be prepared: invalid application/x-www-form-urlencoded body syntax.',
|
|
139
|
+
details: errors.map(error => `Body line ${error.lineIndex + 1}: ${error.message} (${error.line})`),
|
|
140
|
+
hint: 'Use key=value, key: value, or a single line like key1=value1&key2=value2.',
|
|
141
|
+
context: buildRequestContext(parsed, context)
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=requestValidation.js.map
|