@typespec/protobuf 0.43.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/.c8rc.json +3 -0
- package/.eslintrc.cjs +7 -0
- package/.mocharc.yaml +4 -0
- package/.rush/temp/operation/build/state.json +3 -0
- package/.rush/temp/operation/test-official/state.json +3 -0
- package/.rush/temp/package-deps_build.json +81 -0
- package/.rush/temp/package-deps_test-official.json +81 -0
- package/.rush/temp/shrinkwrap-deps.json +177 -0
- package/CHANGELOG.json +4 -0
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/coverage/cobertura-coverage.xml +2291 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/tmp/coverage-6408-1683144315012-0.json +1 -0
- package/dist/src/ast.d.ts +199 -0
- package/dist/src/ast.d.ts.map +1 -0
- package/dist/src/ast.js +60 -0
- package/dist/src/ast.js.map +1 -0
- package/dist/src/index.d.ts +62 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib.d.ts +197 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +134 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/proto.d.ts +62 -0
- package/dist/src/proto.d.ts.map +1 -0
- package/dist/src/proto.js +162 -0
- package/dist/src/proto.js.map +1 -0
- package/dist/src/transform/index.d.ts +7 -0
- package/dist/src/transform/index.d.ts.map +1 -0
- package/dist/src/transform/index.js +744 -0
- package/dist/src/transform/index.js.map +1 -0
- package/dist/src/write.d.ts +12 -0
- package/dist/src/write.d.ts.map +1 -0
- package/dist/src/write.js +204 -0
- package/dist/src/write.js.map +1 -0
- package/dist/test/scenarios.test.d.ts +2 -0
- package/dist/test/scenarios.test.d.ts.map +1 -0
- package/dist/test/scenarios.test.js +165 -0
- package/dist/test/scenarios.test.js.map +1 -0
- package/lib/proto.tsp +303 -0
- package/package.json +49 -0
- package/protobuf.build.log +48 -0
- package/src/ast.ts +279 -0
- package/src/index.ts +7 -0
- package/src/lib.ts +161 -0
- package/src/proto.ts +217 -0
- package/src/transform/index.ts +980 -0
- package/src/write.ts +244 -0
- package/temp/tsconfig.tsbuildinfo +1 -0
- package/test/include/foo/bar.proto +7 -0
- package/test/scenarios/addressbook/input/addressbook.tsp +27 -0
- package/test/scenarios/addressbook/input/main.tsp +13 -0
- package/test/scenarios/addressbook/output/@typespec/protobuf/addressbook.proto +26 -0
- package/test/scenarios/addressbook/output/@typespec/protobuf/main.proto +14 -0
- package/test/scenarios/anonymous-model/diagnostics.txt +1 -0
- package/test/scenarios/anonymous-model/input/main.tsp +24 -0
- package/test/scenarios/anonymous-package/input/main.tsp +19 -0
- package/test/scenarios/anonymous-package/output/@typespec/protobuf/main.proto +15 -0
- package/test/scenarios/array/input/main.tsp +22 -0
- package/test/scenarios/array/output/@typespec/protobuf/com/azure/test.proto +18 -0
- package/test/scenarios/array-nested/diagnostics.txt +1 -0
- package/test/scenarios/array-nested/input/main.tsp +20 -0
- package/test/scenarios/cross package references/input/main.tsp +27 -0
- package/test/scenarios/cross package references/output/@typespec/protobuf/A.proto +10 -0
- package/test/scenarios/cross package references/output/@typespec/protobuf/B.proto +15 -0
- package/test/scenarios/derived-scalar/input/main.tsp +24 -0
- package/test/scenarios/derived-scalar/output/@typespec/protobuf/com/azure/Test.proto +18 -0
- package/test/scenarios/enum/input/main.tsp +33 -0
- package/test/scenarios/enum/output/@typespec/protobuf/main.proto +31 -0
- package/test/scenarios/enum-nonintegral/diagnostics.txt +4 -0
- package/test/scenarios/enum-nonintegral/input/main.tsp +31 -0
- package/test/scenarios/enum-nozero/diagnostics.txt +1 -0
- package/test/scenarios/enum-nozero/input/main.tsp +25 -0
- package/test/scenarios/extern/input/main.tsp +17 -0
- package/test/scenarios/extern/output/@typespec/protobuf/main.proto +19 -0
- package/test/scenarios/illegal field reservations/diagnostics.txt +2 -0
- package/test/scenarios/illegal field reservations/input/main.tsp +16 -0
- package/test/scenarios/inferred-message-names/input/main.tsp +16 -0
- package/test/scenarios/inferred-message-names/output/@typespec/protobuf/com/azure/test.proto +18 -0
- package/test/scenarios/intrinsics/input/main.tsp +17 -0
- package/test/scenarios/intrinsics/output/@typespec/protobuf/com/azure/Test.proto +16 -0
- package/test/scenarios/map/input/main.tsp +15 -0
- package/test/scenarios/map/output/@typespec/protobuf/main.proto +13 -0
- package/test/scenarios/model-no-package/diagnostics.txt +2 -0
- package/test/scenarios/model-no-package/input/main.tsp +19 -0
- package/test/scenarios/name-collision/input/main.tsp +24 -0
- package/test/scenarios/name-collision/output/@typespec/protobuf/main.proto +24 -0
- package/test/scenarios/options/input/main.tsp +25 -0
- package/test/scenarios/options/output/@typespec/protobuf/com/azure/Test.proto +20 -0
- package/test/scenarios/options-invalid/diagnostics.txt +1 -0
- package/test/scenarios/options-invalid/input/main.tsp +25 -0
- package/test/scenarios/reserved field collisions/diagnostics.txt +5 -0
- package/test/scenarios/reserved field collisions/input/main.tsp +19 -0
- package/test/scenarios/reserved fields/input/main.tsp +16 -0
- package/test/scenarios/reserved fields/output/@typespec/protobuf/main.proto +16 -0
- package/test/scenarios/simple/input/main.tsp +22 -0
- package/test/scenarios/simple/output/@typespec/protobuf/com/azure/Test.proto +18 -0
- package/test/scenarios/simple-error/diagnostics.txt +6 -0
- package/test/scenarios/simple-error/input/main.tsp +22 -0
- package/test/scenarios/simple-no-service/input/main.tsp +22 -0
- package/test/scenarios/simple-no-service/output/@typespec/protobuf/com/azure/Test.proto +18 -0
- package/test/scenarios/streams/input/main.tsp +30 -0
- package/test/scenarios/streams/output/@typespec/protobuf/main.proto +19 -0
- package/test/scenarios/type-validation/diagnostics.txt +1 -0
- package/test/scenarios/type-validation/input/main.tsp +11 -0
- package/test/scenarios/union/diagnostics.txt +1 -0
- package/test/scenarios/union/input/main.tsp +33 -0
- package/test/scenarios.test.ts +226 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/test/main.tsp:12:5 - error @typespec/protobuf/field-index: field index 0 is invalid (must be an integer greater than zero)
|
|
2
|
+
/test/main.tsp:13:5 - error @typespec/protobuf/field-index: field index 536870912 is out of bounds (must be less than 536870912)
|
|
3
|
+
/test/main.tsp:14:5 - error @typespec/protobuf/field-index: field index 19000 falls within the implementation-reserved range of 19000-19999 inclusive
|
|
4
|
+
/test/main.tsp:15:5 - error @typespec/protobuf/field-index: field index 19123 falls within the implementation-reserved range of 19000-19999 inclusive
|
|
5
|
+
/test/main.tsp:16:5 - error @typespec/protobuf/field-index: field index 19999 falls within the implementation-reserved range of 19000-19999 inclusive
|
|
6
|
+
/test/main.tsp:21:1 - error decorator-wrong-target: Cannot apply @message decorator to Test.Test since it is not assignable to object
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "@typespec/protobuf";
|
|
2
|
+
|
|
3
|
+
using TypeSpec.Protobuf;
|
|
4
|
+
|
|
5
|
+
@package
|
|
6
|
+
namespace Test;
|
|
7
|
+
|
|
8
|
+
@Protobuf.service
|
|
9
|
+
interface Service {
|
|
10
|
+
// invalid field index
|
|
11
|
+
invalidIndices(
|
|
12
|
+
@field(0) testInputField: string,
|
|
13
|
+
@field(536870912) testInputField2: string,
|
|
14
|
+
@field(19000) testInputField3: string,
|
|
15
|
+
@field(19123) testInputField4: string,
|
|
16
|
+
@field(19999) testInputField5: string
|
|
17
|
+
): {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Cannot apply @message to interface
|
|
21
|
+
@message
|
|
22
|
+
interface Test {}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "@typespec/protobuf";
|
|
2
|
+
|
|
3
|
+
using TypeSpec.Protobuf;
|
|
4
|
+
|
|
5
|
+
@package({
|
|
6
|
+
name: "com.azure.Test",
|
|
7
|
+
})
|
|
8
|
+
namespace Test;
|
|
9
|
+
|
|
10
|
+
model Input {
|
|
11
|
+
@field(1) testInputField: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
model Output {
|
|
15
|
+
@field(1) testOutputField: int32;
|
|
16
|
+
@field(2) secondField: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@message
|
|
20
|
+
model ExplicitlyDeclared {
|
|
21
|
+
@field(2) testField: string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* Generated by Microsoft TypeSpec */
|
|
2
|
+
|
|
3
|
+
syntax = "proto3";
|
|
4
|
+
|
|
5
|
+
package com.azure.Test;
|
|
6
|
+
|
|
7
|
+
message Input {
|
|
8
|
+
string testInputField = 1;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
message Output {
|
|
12
|
+
int32 testOutputField = 1;
|
|
13
|
+
string secondField = 2;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
message ExplicitlyDeclared {
|
|
17
|
+
string testField = 2;
|
|
18
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import "@typespec/protobuf";
|
|
2
|
+
|
|
3
|
+
using TypeSpec.Protobuf;
|
|
4
|
+
|
|
5
|
+
@package
|
|
6
|
+
namespace Test;
|
|
7
|
+
|
|
8
|
+
@Protobuf.service
|
|
9
|
+
interface Service {
|
|
10
|
+
@stream(StreamMode.Duplex)
|
|
11
|
+
duplex(...Input): Output;
|
|
12
|
+
|
|
13
|
+
@stream(StreamMode.In)
|
|
14
|
+
in(...Input): Output;
|
|
15
|
+
|
|
16
|
+
@stream(StreamMode.Out)
|
|
17
|
+
out(...Input): Output;
|
|
18
|
+
|
|
19
|
+
@stream(StreamMode.None)
|
|
20
|
+
none(...Input): Output;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
model Input {
|
|
24
|
+
@field(1) testInputField: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
model Output {
|
|
28
|
+
@field(1) testOutputField: int32;
|
|
29
|
+
@field(2) secondField: string;
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/* Generated by Microsoft TypeSpec */
|
|
2
|
+
|
|
3
|
+
syntax = "proto3";
|
|
4
|
+
|
|
5
|
+
message Input {
|
|
6
|
+
string testInputField = 1;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
message Output {
|
|
10
|
+
int32 testOutputField = 1;
|
|
11
|
+
string secondField = 2;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
service Service {
|
|
15
|
+
rpc Duplex(stream Input) returns (stream Output);
|
|
16
|
+
rpc In(stream Input) returns (Output);
|
|
17
|
+
rpc Out(Input) returns (stream Output);
|
|
18
|
+
rpc None(Input) returns (Output);
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/test/main.tsp:10:20 - error @typespec/protobuf/unsupported-return-type: Protobuf methods must return a named Model
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/test/main.tsp:14:3 - error @typespec/protobuf/unsupported-field-type: a message field's type may not be a union
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import "@typespec/protobuf";
|
|
2
|
+
|
|
3
|
+
using TypeSpec.Protobuf;
|
|
4
|
+
|
|
5
|
+
@package
|
|
6
|
+
namespace Test;
|
|
7
|
+
|
|
8
|
+
@Protobuf.service
|
|
9
|
+
interface Service {
|
|
10
|
+
foo(...Input): Output;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
model Input {
|
|
14
|
+
@field(1) value: U;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
model InputA {
|
|
18
|
+
@field(1) testInputField: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
union U {
|
|
22
|
+
a: InputA,
|
|
23
|
+
b: InputB,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
model InputB {
|
|
27
|
+
@field(1) testInputField: uint32;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
model Output {
|
|
31
|
+
@field(1) testOutputField: int32;
|
|
32
|
+
@field(2) secondField: string;
|
|
33
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import url from "url";
|
|
4
|
+
|
|
5
|
+
import micromatch from "micromatch";
|
|
6
|
+
|
|
7
|
+
import { formatDiagnostic } from "@typespec/compiler";
|
|
8
|
+
import {
|
|
9
|
+
createTestHost,
|
|
10
|
+
resolveVirtualPath,
|
|
11
|
+
TypeSpecTestLibrary,
|
|
12
|
+
} from "@typespec/compiler/testing";
|
|
13
|
+
import { readdirSync, statSync } from "fs";
|
|
14
|
+
import { mkdir, readdir, readFile, rm, stat, writeFile } from "fs/promises";
|
|
15
|
+
|
|
16
|
+
const SCENARIOS_DIRECTORY = url.fileURLToPath(new url.URL("../../test/scenarios", import.meta.url));
|
|
17
|
+
|
|
18
|
+
const shouldRecord = process.env.RECORD === "true";
|
|
19
|
+
const patternsToRun = process.env.RUN_SCENARIOS?.split(",") ?? ["*"];
|
|
20
|
+
|
|
21
|
+
const TypeSpecProtobufTestLibrary: TypeSpecTestLibrary = {
|
|
22
|
+
name: "@typespec/protobuf",
|
|
23
|
+
packageRoot: path.resolve(url.fileURLToPath(import.meta.url), "../../../"),
|
|
24
|
+
files: [
|
|
25
|
+
{ realDir: "", pattern: "package.json", virtualPath: "./node_modules/@typespec/protobuf" },
|
|
26
|
+
{
|
|
27
|
+
realDir: "dist/src",
|
|
28
|
+
pattern: "*.js",
|
|
29
|
+
virtualPath: "./node_modules/@typespec/protobuf/dist/src",
|
|
30
|
+
},
|
|
31
|
+
{ realDir: "lib/", pattern: "*.tsp", virtualPath: "./node_modules/@typespec/protobuf/lib" },
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
describe("protobuf scenarios", function () {
|
|
36
|
+
const scenarios = readdirSync(SCENARIOS_DIRECTORY)
|
|
37
|
+
.map((dn) => path.join(SCENARIOS_DIRECTORY, dn))
|
|
38
|
+
.filter((dn) => statSync(dn).isDirectory());
|
|
39
|
+
|
|
40
|
+
for (const scenario of scenarios) {
|
|
41
|
+
const scenarioName = path.basename(scenario);
|
|
42
|
+
|
|
43
|
+
const shouldRun = micromatch.isMatch(scenarioName, patternsToRun);
|
|
44
|
+
|
|
45
|
+
shouldRun &&
|
|
46
|
+
it(scenarioName, async function () {
|
|
47
|
+
const inputFiles = await readdirRecursive(path.join(scenario, "input"));
|
|
48
|
+
const emitResult = await doEmit(inputFiles);
|
|
49
|
+
|
|
50
|
+
const expectationDirectory = path.resolve(scenario, "output");
|
|
51
|
+
const diagnosticsExpectationPath = path.resolve(scenario, "diagnostics.txt");
|
|
52
|
+
|
|
53
|
+
if (shouldRecord) {
|
|
54
|
+
// Write new output to the scenario's output folder.
|
|
55
|
+
|
|
56
|
+
await writeExpectationDirectory(expectationDirectory, emitResult.files);
|
|
57
|
+
|
|
58
|
+
await rm(diagnosticsExpectationPath, { force: true });
|
|
59
|
+
|
|
60
|
+
if (emitResult.diagnostics.length > 0) {
|
|
61
|
+
const diagnostics = emitResult.diagnostics.join("\n");
|
|
62
|
+
|
|
63
|
+
await writeFile(diagnosticsExpectationPath, diagnostics);
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
// It's an error if any file in the expected files is missing, if any file in the output files doesn't have a
|
|
67
|
+
// corresponding expectation, or if any file in the output files doesn't match its corresponding output file
|
|
68
|
+
// character for character.
|
|
69
|
+
|
|
70
|
+
let err: Error | undefined = undefined;
|
|
71
|
+
|
|
72
|
+
// `throwIfNoEntry` is not supported with promisified fs.promises.stat.
|
|
73
|
+
if (!statSync(expectationDirectory, { throwIfNoEntry: false })) {
|
|
74
|
+
assert.strictEqual(
|
|
75
|
+
Object.entries(emitResult.files).length,
|
|
76
|
+
0,
|
|
77
|
+
"no expectations exist, but output files were generated"
|
|
78
|
+
);
|
|
79
|
+
} else {
|
|
80
|
+
const expectedFiles = await readdirRecursive(expectationDirectory);
|
|
81
|
+
|
|
82
|
+
// Need to defer this error until we've checked for diagnostics below. If diagnostics were unexpectedly
|
|
83
|
+
// raised and inhibited emit, that should be the primary error, not this one.
|
|
84
|
+
try {
|
|
85
|
+
assertFilesAsExpected(emitResult.files, expectedFiles);
|
|
86
|
+
} catch (e: unknown) {
|
|
87
|
+
err = e as Error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let expectedDiagnostics: string;
|
|
92
|
+
try {
|
|
93
|
+
expectedDiagnostics = (await readFile(diagnosticsExpectationPath)).toString("utf-8");
|
|
94
|
+
} catch {
|
|
95
|
+
expectedDiagnostics = "";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Fix the start of lines on Windows
|
|
99
|
+
const processedDiagnostics =
|
|
100
|
+
process.platform === "win32"
|
|
101
|
+
? emitResult.diagnostics.map((d) => d.replace(/^Z:/, ""))
|
|
102
|
+
: emitResult.diagnostics;
|
|
103
|
+
|
|
104
|
+
const diagnostics = processedDiagnostics.join("\n");
|
|
105
|
+
|
|
106
|
+
assert.strictEqual(diagnostics, expectedDiagnostics, "expected equivalent diagnostics");
|
|
107
|
+
|
|
108
|
+
if (err) throw err;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
interface EmitResult {
|
|
115
|
+
files: Record<string, string>;
|
|
116
|
+
diagnostics: string[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function doEmit(files: Record<string, string>): Promise<EmitResult> {
|
|
120
|
+
const baseOutputPath = resolveVirtualPath("test-output/");
|
|
121
|
+
|
|
122
|
+
const host = await createTestHost({
|
|
123
|
+
libraries: [TypeSpecProtobufTestLibrary],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
for (const [fileName, content] of Object.entries(files)) {
|
|
127
|
+
host.addTypeSpecFile(fileName, content);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const [, diagnostics] = await host.compileAndDiagnose("main.tsp", {
|
|
131
|
+
outputDir: baseOutputPath,
|
|
132
|
+
noEmit: false,
|
|
133
|
+
emitters: {
|
|
134
|
+
"@typespec/protobuf": {},
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
files: Object.fromEntries(
|
|
140
|
+
[...host.fs.entries()]
|
|
141
|
+
.filter(([name]) => name.startsWith(baseOutputPath))
|
|
142
|
+
.map(([name, value]) => [name.replace(baseOutputPath, ""), value])
|
|
143
|
+
),
|
|
144
|
+
diagnostics: diagnostics.map(formatDiagnostic),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function assertFilesAsExpected(
|
|
149
|
+
outputFiles: Record<string, string>,
|
|
150
|
+
expectedFiles: Record<string, string>
|
|
151
|
+
) {
|
|
152
|
+
for (const fn of Object.keys(expectedFiles)) {
|
|
153
|
+
assert.ok(
|
|
154
|
+
Object.prototype.hasOwnProperty.call(outputFiles, fn),
|
|
155
|
+
`expected file ${fn} was not produced`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const [fn, content] of Object.entries(outputFiles)) {
|
|
160
|
+
const expectedContent = expectedFiles[fn];
|
|
161
|
+
|
|
162
|
+
assert.ok(expectedContent, `output file ${fn} has no corresponding expectation`);
|
|
163
|
+
|
|
164
|
+
assert.strictEqual(content, expectedContent);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Writes an expectation map to disk.
|
|
170
|
+
*
|
|
171
|
+
* @param expectationDirectory - The directory to write to.
|
|
172
|
+
* @param outputFiles - A map of relative paths to file contents.
|
|
173
|
+
*/
|
|
174
|
+
async function writeExpectationDirectory(
|
|
175
|
+
expectationDirectory: string,
|
|
176
|
+
outputFiles: Record<string, string>
|
|
177
|
+
) {
|
|
178
|
+
const fileEntries = Object.entries(outputFiles);
|
|
179
|
+
|
|
180
|
+
// It'll be annoying to fiddle with .gitkeep files, so let's omit the `output` directory if it's empty.
|
|
181
|
+
if (fileEntries.length === 0) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
await rm(expectationDirectory, { recursive: true, force: true });
|
|
186
|
+
|
|
187
|
+
await mkdir(expectationDirectory);
|
|
188
|
+
|
|
189
|
+
for (const [fn, content] of fileEntries) {
|
|
190
|
+
const fullPath = path.join(expectationDirectory, fn);
|
|
191
|
+
await mkdir(path.dirname(fullPath), { recursive: true });
|
|
192
|
+
await writeFile(fullPath, content);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param dir - The directory to read recursively.
|
|
198
|
+
* @param base - The base directory to use for relative paths.
|
|
199
|
+
* @returns A map of relative paths to file contents.
|
|
200
|
+
*/
|
|
201
|
+
async function readdirRecursive(dir: string, base: string = dir): Promise<Record<string, string>> {
|
|
202
|
+
const res: Record<string, string> = {};
|
|
203
|
+
|
|
204
|
+
for (const entry of (await readdir(dir)).map((e) => path.join(dir, e))) {
|
|
205
|
+
const stats = await stat(entry);
|
|
206
|
+
|
|
207
|
+
if (stats.isDirectory()) {
|
|
208
|
+
for (const [name, content] of Object.entries(await readdirRecursive(entry, base))) {
|
|
209
|
+
res[name] = content;
|
|
210
|
+
}
|
|
211
|
+
} else if (stats.isFile()) {
|
|
212
|
+
const content = (await readFile(entry)).toString("utf-8");
|
|
213
|
+
|
|
214
|
+
const relativePath = path.relative(base, entry);
|
|
215
|
+
|
|
216
|
+
const correctedPath =
|
|
217
|
+
process.platform === "win32" ? relativePath.replace(/\\/g, "/") : relativePath;
|
|
218
|
+
|
|
219
|
+
res[correctedPath] = content;
|
|
220
|
+
} else {
|
|
221
|
+
throw new Error("Unsupported file type.");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return res;
|
|
226
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../tsconfig.json",
|
|
3
|
+
"references": [
|
|
4
|
+
{ "path": "../compiler/tsconfig.json" },
|
|
5
|
+
{ "path": "../rest/tsconfig.json" },
|
|
6
|
+
{ "path": "../openapi/tsconfig.json" }
|
|
7
|
+
],
|
|
8
|
+
"compilerOptions": {
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
"rootDir": ".",
|
|
11
|
+
"tsBuildInfoFile": "temp/tsconfig.tsbuildinfo",
|
|
12
|
+
"types": ["node", "mocha"]
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*.ts", "test/**/*.ts"]
|
|
15
|
+
}
|