@typespec/spec-coverage-sdk 0.1.0-alpha.16-dev.0 → 0.1.0-alpha.16-dev.2
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/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +70 -9
- package/dist/client.js.map +1 -1
- package/package.json +7 -6
- package/src/client.ts +77 -9
- package/temp/.tsbuildinfo +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -14,8 +14,10 @@ export declare class SpecCoverageClient {
|
|
|
14
14
|
export declare class SpecManifestOperations {
|
|
15
15
|
#private;
|
|
16
16
|
constructor(container: ContainerClient);
|
|
17
|
-
upload(
|
|
18
|
-
|
|
17
|
+
upload(name: string, manifest: ScenarioManifest): Promise<void>;
|
|
18
|
+
uploadIfVersionNew(name: string, manifest: ScenarioManifest): Promise<"uploaded" | "skipped">;
|
|
19
|
+
get(name: string, version?: string): Promise<ScenarioManifest>;
|
|
20
|
+
tryGet(name: string, version?: string): Promise<ScenarioManifest | undefined>;
|
|
19
21
|
}
|
|
20
22
|
export declare class SpecCoverageOperations {
|
|
21
23
|
#private;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,mBAAmB,EAGnB,eAAe,EACf,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,mBAAmB,EAGnB,eAAe,EACf,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,qBAAa,kBAAkB;;IAE7B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,QAAQ,EAAE,sBAAsB,CAAC;gBAG/B,kBAAkB,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,0BAA0B,GAAG,mBAAmB,GAAG,eAAe,CAAC;QAChF,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;IAWU,iBAAiB;CAK/B;AAED,qBAAa,sBAAsB;;gBAGrB,SAAS,EAAE,eAAe;IAIzB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAe/D,kBAAkB,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAcrB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAK9D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;CAe3F;AAoBD,qBAAa,sBAAsB;;gBAGrB,SAAS,EAAE,eAAe;IAIzB,MAAM,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBnF,oBAAoB,CAC/B,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;YA4ChC,WAAW;CAY1B"}
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BlobServiceClient, } from "@azure/storage-blob";
|
|
2
|
+
import { eq as semverEq, gt as semverGt, valid as semverValid } from "semver";
|
|
2
3
|
export class SpecCoverageClient {
|
|
3
4
|
#container;
|
|
4
5
|
manifest;
|
|
@@ -15,23 +16,70 @@ export class SpecCoverageClient {
|
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
export class SpecManifestOperations {
|
|
18
|
-
#blob;
|
|
19
19
|
#container;
|
|
20
20
|
constructor(container) {
|
|
21
21
|
this.#container = container;
|
|
22
|
-
this.#blob = this.#container.getBlockBlobClient("manifest.json");
|
|
23
22
|
}
|
|
24
|
-
async upload(manifest) {
|
|
23
|
+
async upload(name, manifest) {
|
|
24
|
+
await this.#upload(name, "latest", manifest);
|
|
25
|
+
await this.#upload(name, manifest.version, manifest);
|
|
26
|
+
}
|
|
27
|
+
async #upload(name, version, manifest) {
|
|
28
|
+
const blob = this.#container.getBlockBlobClient(this.#blobName(name, version));
|
|
25
29
|
const content = JSON.stringify(manifest, null, 2);
|
|
26
|
-
await
|
|
30
|
+
await blob.upload(content, content.length, {
|
|
27
31
|
blobHTTPHeaders: {
|
|
28
32
|
blobContentType: "application/json; charset=utf-8",
|
|
29
33
|
},
|
|
30
34
|
});
|
|
31
35
|
}
|
|
32
|
-
async
|
|
33
|
-
|
|
36
|
+
async uploadIfVersionNew(name, manifest) {
|
|
37
|
+
const existingVersion = await this.tryGet(name, manifest.version);
|
|
38
|
+
if (existingVersion) {
|
|
39
|
+
return "skipped";
|
|
40
|
+
}
|
|
41
|
+
const existingLatest = await this.tryGet(name);
|
|
42
|
+
if (existingLatest && !isVersionNewer(manifest.version, existingLatest.version)) {
|
|
43
|
+
return "skipped";
|
|
44
|
+
}
|
|
45
|
+
await this.upload(name, manifest);
|
|
46
|
+
return "uploaded";
|
|
47
|
+
}
|
|
48
|
+
async get(name, version) {
|
|
49
|
+
const blob = this.#container.getBlockBlobClient(this.#blobName(name, version));
|
|
50
|
+
return readJsonBlob(blob);
|
|
51
|
+
}
|
|
52
|
+
async tryGet(name, version) {
|
|
53
|
+
const blob = this.#container.getBlockBlobClient(this.#blobName(name, version));
|
|
54
|
+
try {
|
|
55
|
+
return await readJsonBlob(blob);
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
if ("code" in e && e.code === "BlobNotFound") {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
throw e;
|
|
62
|
+
}
|
|
34
63
|
}
|
|
64
|
+
#blobName(name, version) {
|
|
65
|
+
return `manifests/${name}/${version ?? "latest"}.json`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function areVersionsEquivalent(left, right) {
|
|
69
|
+
const leftValid = semverValid(left);
|
|
70
|
+
const rightValid = semverValid(right);
|
|
71
|
+
if (leftValid && rightValid) {
|
|
72
|
+
return semverEq(leftValid, rightValid);
|
|
73
|
+
}
|
|
74
|
+
return left === right;
|
|
75
|
+
}
|
|
76
|
+
function isVersionNewer(candidate, existing) {
|
|
77
|
+
const candidateValid = semverValid(candidate);
|
|
78
|
+
const existingValid = semverValid(existing);
|
|
79
|
+
if (candidateValid && existingValid) {
|
|
80
|
+
return semverGt(candidateValid, existingValid);
|
|
81
|
+
}
|
|
82
|
+
return !areVersionsEquivalent(candidate, existing);
|
|
35
83
|
}
|
|
36
84
|
export class SpecCoverageOperations {
|
|
37
85
|
#container;
|
|
@@ -113,8 +161,21 @@ function getCoverageContainer(storageAccountName, credential, containerName) {
|
|
|
113
161
|
}
|
|
114
162
|
async function readJsonBlob(blobClient) {
|
|
115
163
|
const blob = await blobClient.download();
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
164
|
+
if (blob.blobBody) {
|
|
165
|
+
const body = await blob.blobBody;
|
|
166
|
+
const content = await body.text();
|
|
167
|
+
return JSON.parse(content);
|
|
168
|
+
}
|
|
169
|
+
else if (blob.readableStreamBody) {
|
|
170
|
+
const stream = blob.readableStreamBody;
|
|
171
|
+
let content = "";
|
|
172
|
+
for await (const chunk of stream) {
|
|
173
|
+
content += chunk;
|
|
174
|
+
}
|
|
175
|
+
return JSON.parse(content);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
throw new Error("Blob has no body");
|
|
179
|
+
}
|
|
119
180
|
}
|
|
120
181
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,iBAAiB,GAIlB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/spec-coverage-sdk",
|
|
3
|
-
"version": "0.1.0-alpha.16-dev.
|
|
3
|
+
"version": "0.1.0-alpha.16-dev.2",
|
|
4
4
|
"description": "Spec utility to manage the reported coverage",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,14 +19,15 @@
|
|
|
19
19
|
"homepage": "https://github.com/microsoft/typespec#readme",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@azure/identity": "~4.13.0",
|
|
22
|
-
"@azure/storage-blob": "~12.
|
|
23
|
-
"@types/node": "~25.0
|
|
22
|
+
"@azure/storage-blob": "~12.31.0",
|
|
23
|
+
"@types/node": "~25.3.0",
|
|
24
|
+
"@types/semver": "^7.5.8",
|
|
25
|
+
"semver": "^7.7.1"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
26
|
-
"rimraf": "~6.1.
|
|
27
|
-
"typescript": "~5.9.
|
|
28
|
+
"rimraf": "~6.1.3",
|
|
29
|
+
"typescript": "~5.9.3"
|
|
28
30
|
},
|
|
29
|
-
"peerDependencies": {},
|
|
30
31
|
"scripts": {
|
|
31
32
|
"watch": "tsc -p ./tsconfig.build.json --watch",
|
|
32
33
|
"build": "tsc -p ./tsconfig.build.json",
|
package/src/client.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ContainerClient,
|
|
7
7
|
StorageSharedKeyCredential,
|
|
8
8
|
} from "@azure/storage-blob";
|
|
9
|
+
import { eq as semverEq, gt as semverGt, valid as semverValid } from "semver";
|
|
9
10
|
import {
|
|
10
11
|
CoverageReport,
|
|
11
12
|
GeneratorMetadata,
|
|
@@ -42,26 +43,82 @@ export class SpecCoverageClient {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
export class SpecManifestOperations {
|
|
45
|
-
#blob: BlockBlobClient;
|
|
46
46
|
#container: ContainerClient;
|
|
47
47
|
|
|
48
48
|
constructor(container: ContainerClient) {
|
|
49
49
|
this.#container = container;
|
|
50
|
-
this.#blob = this.#container.getBlockBlobClient("manifest.json");
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
public async upload(
|
|
52
|
+
public async upload(name: string, manifest: ScenarioManifest): Promise<void> {
|
|
53
|
+
await this.#upload(name, "latest", manifest);
|
|
54
|
+
await this.#upload(name, manifest.version, manifest);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async #upload(name: string, version: string, manifest: ScenarioManifest): Promise<void> {
|
|
58
|
+
const blob = this.#container.getBlockBlobClient(this.#blobName(name, version));
|
|
54
59
|
const content = JSON.stringify(manifest, null, 2);
|
|
55
|
-
await
|
|
60
|
+
await blob.upload(content, content.length, {
|
|
56
61
|
blobHTTPHeaders: {
|
|
57
62
|
blobContentType: "application/json; charset=utf-8",
|
|
58
63
|
},
|
|
59
64
|
});
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
public async
|
|
63
|
-
|
|
67
|
+
public async uploadIfVersionNew(
|
|
68
|
+
name: string,
|
|
69
|
+
manifest: ScenarioManifest,
|
|
70
|
+
): Promise<"uploaded" | "skipped"> {
|
|
71
|
+
const existingVersion = await this.tryGet(name, manifest.version);
|
|
72
|
+
if (existingVersion) {
|
|
73
|
+
return "skipped";
|
|
74
|
+
}
|
|
75
|
+
const existingLatest = await this.tryGet(name);
|
|
76
|
+
if (existingLatest && !isVersionNewer(manifest.version, existingLatest.version)) {
|
|
77
|
+
return "skipped";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await this.upload(name, manifest);
|
|
81
|
+
return "uploaded";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async get(name: string, version?: string): Promise<ScenarioManifest> {
|
|
85
|
+
const blob = this.#container.getBlockBlobClient(this.#blobName(name, version));
|
|
86
|
+
return readJsonBlob<ScenarioManifest>(blob);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public async tryGet(name: string, version?: string): Promise<ScenarioManifest | undefined> {
|
|
90
|
+
const blob = this.#container.getBlockBlobClient(this.#blobName(name, version));
|
|
91
|
+
try {
|
|
92
|
+
return await readJsonBlob<ScenarioManifest>(blob);
|
|
93
|
+
} catch (e: any) {
|
|
94
|
+
if ("code" in e && e.code === "BlobNotFound") {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
throw e;
|
|
98
|
+
}
|
|
64
99
|
}
|
|
100
|
+
|
|
101
|
+
#blobName(name: string, version?: string) {
|
|
102
|
+
return `manifests/${name}/${version ?? "latest"}.json`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function areVersionsEquivalent(left: string, right: string): boolean {
|
|
107
|
+
const leftValid = semverValid(left);
|
|
108
|
+
const rightValid = semverValid(right);
|
|
109
|
+
if (leftValid && rightValid) {
|
|
110
|
+
return semverEq(leftValid, rightValid);
|
|
111
|
+
}
|
|
112
|
+
return left === right;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isVersionNewer(candidate: string, existing: string): boolean {
|
|
116
|
+
const candidateValid = semverValid(candidate);
|
|
117
|
+
const existingValid = semverValid(existing);
|
|
118
|
+
if (candidateValid && existingValid) {
|
|
119
|
+
return semverGt(candidateValid, existingValid);
|
|
120
|
+
}
|
|
121
|
+
return !areVersionsEquivalent(candidate, existing);
|
|
65
122
|
}
|
|
66
123
|
|
|
67
124
|
export class SpecCoverageOperations {
|
|
@@ -168,7 +225,18 @@ function getCoverageContainer(
|
|
|
168
225
|
|
|
169
226
|
async function readJsonBlob<T>(blobClient: BlockBlobClient): Promise<T> {
|
|
170
227
|
const blob = await blobClient.download();
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
228
|
+
if (blob.blobBody) {
|
|
229
|
+
const body = await blob.blobBody;
|
|
230
|
+
const content = await body!.text();
|
|
231
|
+
return JSON.parse(content);
|
|
232
|
+
} else if (blob.readableStreamBody) {
|
|
233
|
+
const stream = blob.readableStreamBody;
|
|
234
|
+
let content = "";
|
|
235
|
+
for await (const chunk of stream) {
|
|
236
|
+
content += chunk;
|
|
237
|
+
}
|
|
238
|
+
return JSON.parse(content);
|
|
239
|
+
} else {
|
|
240
|
+
throw new Error("Blob has no body");
|
|
241
|
+
}
|
|
174
242
|
}
|