• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Orckestra / orc-scripts / 103025

03 Apr 2025 02:53PM UTC coverage: 33.968% (-0.7%) from 34.628%
103025

push

Azure Pipelines

web-flow
Merge pull request #1268 from Orckestra/features/82082-generateApi

Add new requestsFile args to generateApi

153 of 441 branches covered (34.69%)

Branch coverage included in aggregate %.

0 of 40 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

275 of 819 relevant lines covered (33.58%)

4.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/scripts/generateApi.js
1
const fs = require("fs");
×
2
const https = require("https");
×
3
const lodash = require("lodash");
×
4

5
const occUrl = process.env.OccUrl;
×
6
const occToken = process.env.OccToken;
×
7
let outputFile = "";
×
NEW
8
let requestsFile = "";
×
9

10
if (process.argv.includes("--outputFile")) {
×
11
        outputFile = process.argv[process.argv.indexOf("--outputFile") + 1];
×
12
}
13

14
if (!outputFile) {
×
15
        throw new Error("Missing --outputFile 'file' argument.");
×
16
}
17

NEW
18
if (process.argv.includes("--requestsFile")) {
×
NEW
19
        requestsFile = process.argv[process.argv.indexOf("--requestsFile") + 1];
×
20
}
21

22
if (!occToken) {
×
23
        throw new Error(
×
24
                "Missing OccToken environment variable. This environment variable needs to contains the authentication token used to access the OCC platform specified in OccUrl.",
25
        );
26
}
27

28
if (!occUrl) {
×
29
        throw new Error(
×
30
                "Missing OccUrl environment variable. This environment variable needs to contains the URL of the OCC platform which contains the OpenAPI metadata.",
31
        );
32
}
33

34
function uncapitalizeFirstLetter(s) {
35
        return s.charAt(0).toLowerCase() + s.slice(1);
×
36
}
37

38
function extractRequestNameFromOperation(operation) {
39
        const rx = /.*{(?<name>[^{}]*)}$/;
×
40
        return uncapitalizeFirstLetter(operation.summary.match(rx).groups["name"]);
×
41
}
42

43
function isVerbAllowed(verb) {
44
        const lowerCaseVerb = verb.toLowerCase();
×
45
        return lowerCaseVerb === "get" || lowerCaseVerb === "post" || lowerCaseVerb === "put" || lowerCaseVerb === "delete";
×
46
}
47

48
function generateOperationsFromPath(url, pathData, desiredRequests) {
49
        const operations = [];
×
50

51
        for (const verb of Object.getOwnPropertyNames(pathData)) {
×
52
                if (!isVerbAllowed(verb)) {
×
53
                        continue;
×
54
                }
55

56
                const operation = pathData[verb];
×
57

NEW
58
                const operationName = extractRequestNameFromOperation(operation);
×
59

NEW
60
                const shouldAddOperation = desiredRequests == null || desiredRequests.includes(operationName.toLowerCase());
×
NEW
61
                if( !shouldAddOperation ){
×
NEW
62
                        continue;
×
63
                }
64

UNCOV
65
                operations.push({
×
66
                        name: operationName,
67
                        url: url,
68
                        verb: verb.toUpperCase(),
69
                        hasQueryString: operation.parameters.filter(p => p.in === "query").length > 0,
×
70
                });
71
        }
72

73
        return operations;
×
74
}
75

76
function generateOperation(operation) {
77
        // trim '/' from start/end and split on the '/' character. We do this to avoid having an empty element in the array
78
        const urlSegments = lodash.trim(operation.url, "/").split("/");
×
79
        const parameters = [];
×
80
        const buildUrlParams = [];
×
81

82
        // An OCC URL has the following format: /customers/{ScopeId}/{CustomerId}/orders
83
        // The code below extract the tokens between curly braces and generates the parameters for the buildUrl method
84

85
        for (const segment of urlSegments) {
×
86
                if (segment.startsWith("{")) {
×
87
                        const cleanName = uncapitalizeFirstLetter(segment.match(/{(?<name>[^{}]*)}/).groups["name"]);
×
88
                        parameters.push(cleanName);
×
89
                        buildUrlParams.push(cleanName);
×
90
                } else {
91
                        buildUrlParams.push(`"${segment}"`);
×
92
                }
93
        }
94

95
        let buildUrlParamsStr = `[${buildUrlParams.join(", ")}]`;
×
96

97
        if (operation.hasQueryString) {
×
98
                parameters.push("queryParams");
×
99
                buildUrlParamsStr += ", queryParams";
×
100
        }
101

102
        return `export const ${operation.name} = {
×
103
\tname: '${operation.name}',
104
\tbuildUrl: (${parameters.join(", ")}) => buildUrl(${buildUrlParamsStr}),
105
\tverb: '${operation.verb}'
106
}\n\n`;
107
}
108

109
function generateImports() {
110
        if (fs.existsSync("node_modules/orc-shared")) {
×
111
                return 'import { buildUrl } from "orc-shared/src/utils/buildUrl";\n\n';
×
112
        }
113

114
        return 'import { buildUrl } from "../utils/buildUrl";\n\n';
×
115
}
116

NEW
117
if (requestsFile) {
×
NEW
118
        fs.readFile(requestsFile, 'utf-8', (err, data) => {
×
NEW
119
                if (err) {
×
NEW
120
                        return console.error(err);
×
121
                }
NEW
122
                const desiredRequests = data.split("\n").map(d => d.trim().toLowerCase());
×
NEW
123
                generate(desiredRequests);
×
124
        })
125
}else {
NEW
126
        generate(null);
×
127
}
128

129

130
function generate(desiredRequests) {
NEW
131
        https
×
132
                .get(occUrl, { headers: { "X-AUTH": occToken } }, resp => {
NEW
133
                        let data = "";
×
NEW
134
                        let error = "";
×
135

NEW
136
                        if (resp.statusCode !== 200) {
×
NEW
137
                                error = new Error(`Request Failed. Status Code: ${resp.statusCode}`);
×
138
                        }
NEW
139
                        if (error) {
×
NEW
140
                                console.error(error.message);
×
141
                                // Consume response data to free up memory
NEW
142
                                resp.resume();
×
NEW
143
                                return;
×
144
                        }
145

146
                        // A chunk of data has been received.
NEW
147
                        resp.on("data", chunk => {
×
NEW
148
                                data += chunk;
×
149
                        });
150

151
                        // The whole response has been received. Print out the result.
NEW
152
                        resp.on("end", () => {
×
NEW
153
                                const swaggerMetaData = JSON.parse(data);
×
NEW
154
                                const paths = swaggerMetaData.paths;
×
NEW
155
                                let operations = [];
×
156

NEW
157
                                for (const url of Object.getOwnPropertyNames(paths)) {
×
NEW
158
                                        operations = operations.concat(generateOperationsFromPath(url, paths[url], desiredRequests));
×
159
                                }
160

NEW
161
                                let helperData = "/* istanbul ignore file */\n\n";
×
NEW
162
                                helperData += generateImports();
×
163

NEW
164
                                for (const op of lodash.sortBy(operations, [o => o.name])) {
×
NEW
165
                                        helperData += generateOperation(op);
×
166
                                }
167

NEW
168
                                fs.writeFile(outputFile, helperData, function (err) {
×
NEW
169
                                        if (err) {
×
NEW
170
                                                return console.error(err);
×
171
                                        }
NEW
172
                                        console.log(`File '${outputFile}' has been created`);
×
173
                                });
174
                        });
175
                })
176
                .on("error", err => {
NEW
177
                        console.log("Error: " + err.message);
×
178
                });
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc