@vercel/cervel 0.0.6 → 0.0.7
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/cli.mjs +97 -110
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +97 -110
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -2,11 +2,107 @@ import { parseArgs } from "node:util";
|
|
|
2
2
|
import { createRequire } from "module";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
4
|
import { readFile, rm, writeFile } from "fs/promises";
|
|
5
|
-
import { extname, join
|
|
5
|
+
import { extname, join } from "path";
|
|
6
6
|
import { build } from "rolldown";
|
|
7
7
|
import { spawn } from "child_process";
|
|
8
8
|
import execa from "execa";
|
|
9
9
|
|
|
10
|
+
//#region src/rolldown.ts
|
|
11
|
+
/**
|
|
12
|
+
* Escapes special regex characters in a string to treat it as a literal pattern.
|
|
13
|
+
*/
|
|
14
|
+
function escapeRegExp(string) {
|
|
15
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16
|
+
}
|
|
17
|
+
const rolldown = async (args) => {
|
|
18
|
+
const baseDir = args.repoRootPath || args.workPath;
|
|
19
|
+
const entrypointPath = join(args.workPath, args.entrypoint);
|
|
20
|
+
const shouldAddSourcemapSupport = false;
|
|
21
|
+
const extension = extname(args.entrypoint);
|
|
22
|
+
const extensionMap = {
|
|
23
|
+
".ts": {
|
|
24
|
+
format: "auto",
|
|
25
|
+
extension: "js"
|
|
26
|
+
},
|
|
27
|
+
".mts": {
|
|
28
|
+
format: "esm",
|
|
29
|
+
extension: "mjs"
|
|
30
|
+
},
|
|
31
|
+
".cts": {
|
|
32
|
+
format: "cjs",
|
|
33
|
+
extension: "cjs"
|
|
34
|
+
},
|
|
35
|
+
".cjs": {
|
|
36
|
+
format: "cjs",
|
|
37
|
+
extension: "cjs"
|
|
38
|
+
},
|
|
39
|
+
".js": {
|
|
40
|
+
format: "auto",
|
|
41
|
+
extension: "js"
|
|
42
|
+
},
|
|
43
|
+
".mjs": {
|
|
44
|
+
format: "esm",
|
|
45
|
+
extension: "mjs"
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const extensionInfo = extensionMap[extension] || extensionMap[".js"];
|
|
49
|
+
let resolvedFormat = extensionInfo.format === "auto" ? void 0 : extensionInfo.format;
|
|
50
|
+
const packageJsonPath = join(args.workPath, "package.json");
|
|
51
|
+
const external = [];
|
|
52
|
+
let pkg = {};
|
|
53
|
+
if (existsSync(packageJsonPath)) {
|
|
54
|
+
const source = await readFile(packageJsonPath, "utf8");
|
|
55
|
+
try {
|
|
56
|
+
pkg = JSON.parse(source.toString());
|
|
57
|
+
} catch (_e) {
|
|
58
|
+
pkg = {};
|
|
59
|
+
}
|
|
60
|
+
if (extensionInfo.format === "auto") if (pkg.type === "module") resolvedFormat = "esm";
|
|
61
|
+
else resolvedFormat = "cjs";
|
|
62
|
+
for (const dependency of Object.keys(pkg.dependencies || {})) external.push(dependency);
|
|
63
|
+
for (const dependency of Object.keys(pkg.devDependencies || {})) external.push(dependency);
|
|
64
|
+
for (const dependency of Object.keys(pkg.peerDependencies || {})) external.push(dependency);
|
|
65
|
+
for (const dependency of Object.keys(pkg.optionalDependencies || {})) external.push(dependency);
|
|
66
|
+
}
|
|
67
|
+
const relativeOutputDir = args.out;
|
|
68
|
+
const outputDir = join(baseDir, relativeOutputDir);
|
|
69
|
+
const out = await build({
|
|
70
|
+
input: entrypointPath,
|
|
71
|
+
cwd: baseDir,
|
|
72
|
+
platform: "node",
|
|
73
|
+
tsconfig: true,
|
|
74
|
+
external: external.map((pkg$1) => /* @__PURE__ */ new RegExp(`^${escapeRegExp(pkg$1)}`)),
|
|
75
|
+
output: {
|
|
76
|
+
cleanDir: true,
|
|
77
|
+
dir: outputDir,
|
|
78
|
+
format: resolvedFormat,
|
|
79
|
+
preserveModules: true,
|
|
80
|
+
sourcemap: false
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
let handler = null;
|
|
84
|
+
for (const entry of out.output) if (entry.type === "chunk") {
|
|
85
|
+
if (entry.isEntry) handler = entry.fileName;
|
|
86
|
+
}
|
|
87
|
+
if (typeof handler !== "string") throw new Error(`Unable to resolve module for ${args.entrypoint}`);
|
|
88
|
+
const cleanup = async () => {
|
|
89
|
+
await rm(outputDir, {
|
|
90
|
+
recursive: true,
|
|
91
|
+
force: true
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
result: {
|
|
96
|
+
pkg,
|
|
97
|
+
shouldAddSourcemapSupport,
|
|
98
|
+
handler,
|
|
99
|
+
outputDir
|
|
100
|
+
},
|
|
101
|
+
cleanup
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
10
106
|
//#region src/utils.ts
|
|
11
107
|
const noColor = globalThis.process?.env?.NO_COLOR === "1" || globalThis.process?.env?.TERM === "dumb";
|
|
12
108
|
const resets = {
|
|
@@ -119,115 +215,6 @@ const findNearestTsconfig = async (workPath) => {
|
|
|
119
215
|
return findNearestTsconfig(join(workPath, ".."));
|
|
120
216
|
};
|
|
121
217
|
|
|
122
|
-
//#endregion
|
|
123
|
-
//#region src/rolldown.ts
|
|
124
|
-
const rolldown = async (args) => {
|
|
125
|
-
const baseDir = args.repoRootPath || args.workPath;
|
|
126
|
-
const entrypointPath = join(args.workPath, args.entrypoint);
|
|
127
|
-
const shouldAddSourcemapSupport = false;
|
|
128
|
-
const extension = extname(args.entrypoint);
|
|
129
|
-
const extensionMap = {
|
|
130
|
-
".ts": {
|
|
131
|
-
format: "auto",
|
|
132
|
-
extension: "js"
|
|
133
|
-
},
|
|
134
|
-
".mts": {
|
|
135
|
-
format: "esm",
|
|
136
|
-
extension: "mjs"
|
|
137
|
-
},
|
|
138
|
-
".cts": {
|
|
139
|
-
format: "cjs",
|
|
140
|
-
extension: "cjs"
|
|
141
|
-
},
|
|
142
|
-
".cjs": {
|
|
143
|
-
format: "cjs",
|
|
144
|
-
extension: "cjs"
|
|
145
|
-
},
|
|
146
|
-
".js": {
|
|
147
|
-
format: "auto",
|
|
148
|
-
extension: "js"
|
|
149
|
-
},
|
|
150
|
-
".mjs": {
|
|
151
|
-
format: "esm",
|
|
152
|
-
extension: "mjs"
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
let format = (extensionMap[extension] || extensionMap[".js"]).format;
|
|
156
|
-
const packageJsonPath = join(args.workPath, "package.json");
|
|
157
|
-
const external = [];
|
|
158
|
-
let pkg = {};
|
|
159
|
-
if (existsSync(packageJsonPath)) {
|
|
160
|
-
const source = await readFile(packageJsonPath, "utf8");
|
|
161
|
-
try {
|
|
162
|
-
pkg = JSON.parse(source.toString());
|
|
163
|
-
} catch (_e) {
|
|
164
|
-
pkg = {};
|
|
165
|
-
}
|
|
166
|
-
if (format === "auto") if (pkg.type === "module") format = "esm";
|
|
167
|
-
else format = "cjs";
|
|
168
|
-
for (const dependency of Object.keys(pkg.dependencies || {})) external.push(dependency);
|
|
169
|
-
for (const dependency of Object.keys(pkg.devDependencies || {})) external.push(dependency);
|
|
170
|
-
for (const dependency of Object.keys(pkg.peerDependencies || {})) external.push(dependency);
|
|
171
|
-
for (const dependency of Object.keys(pkg.optionalDependencies || {})) external.push(dependency);
|
|
172
|
-
}
|
|
173
|
-
const tsconfig = await findNearestTsconfig(baseDir);
|
|
174
|
-
const relativeOutputDir = args.out;
|
|
175
|
-
const outputDir = join(baseDir, relativeOutputDir);
|
|
176
|
-
let handler = null;
|
|
177
|
-
await build({
|
|
178
|
-
input: entrypointPath,
|
|
179
|
-
cwd: baseDir,
|
|
180
|
-
platform: "node",
|
|
181
|
-
external: (source) => {
|
|
182
|
-
if (source.startsWith(".") || source.startsWith("/")) return false;
|
|
183
|
-
return external.some((pkg$1) => {
|
|
184
|
-
return source === pkg$1 || source.startsWith(pkg$1 + "/");
|
|
185
|
-
});
|
|
186
|
-
},
|
|
187
|
-
tsconfig,
|
|
188
|
-
output: {
|
|
189
|
-
dir: outputDir,
|
|
190
|
-
entryFileNames: (info) => {
|
|
191
|
-
if (info.name === "rolldown_runtime") return "rolldown_runtime.js";
|
|
192
|
-
const facadeModuleId = info.facadeModuleId;
|
|
193
|
-
if (!facadeModuleId) throw new Error(`Unable to resolve module for ${info.name}`);
|
|
194
|
-
const relPath = relative(baseDir, facadeModuleId);
|
|
195
|
-
const extension$1 = extname(relPath);
|
|
196
|
-
const ext = {
|
|
197
|
-
".ts": ".js",
|
|
198
|
-
".mts": ".mjs",
|
|
199
|
-
".mjs": ".mjs",
|
|
200
|
-
".cts": ".cjs",
|
|
201
|
-
".cjs": ".cjs",
|
|
202
|
-
".js": ".js"
|
|
203
|
-
}[extension$1] || ".js";
|
|
204
|
-
const nameWithJS = relPath.slice(0, -extension$1.length) + ext;
|
|
205
|
-
if (info.isEntry) handler = nameWithJS;
|
|
206
|
-
return nameWithJS;
|
|
207
|
-
},
|
|
208
|
-
format,
|
|
209
|
-
preserveModules: true,
|
|
210
|
-
sourcemap: false
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
if (typeof handler !== "string") throw new Error(`Unable to resolve module for ${args.entrypoint}`);
|
|
214
|
-
const cleanup = async () => {
|
|
215
|
-
await rm(outputDir, {
|
|
216
|
-
recursive: true,
|
|
217
|
-
force: true
|
|
218
|
-
});
|
|
219
|
-
};
|
|
220
|
-
return {
|
|
221
|
-
result: {
|
|
222
|
-
pkg,
|
|
223
|
-
shouldAddSourcemapSupport,
|
|
224
|
-
handler,
|
|
225
|
-
outputDir
|
|
226
|
-
},
|
|
227
|
-
cleanup
|
|
228
|
-
};
|
|
229
|
-
};
|
|
230
|
-
|
|
231
218
|
//#endregion
|
|
232
219
|
//#region src/find-entrypoint.ts
|
|
233
220
|
const frameworks = [
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,107 @@
|
|
|
1
1
|
import { createRequire } from "module";
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { readFile, rm, writeFile } from "fs/promises";
|
|
4
|
-
import { extname, join
|
|
4
|
+
import { extname, join } from "path";
|
|
5
5
|
import { build as build$1 } from "rolldown";
|
|
6
6
|
import { spawn } from "child_process";
|
|
7
7
|
import execa from "execa";
|
|
8
8
|
|
|
9
|
+
//#region src/rolldown.ts
|
|
10
|
+
/**
|
|
11
|
+
* Escapes special regex characters in a string to treat it as a literal pattern.
|
|
12
|
+
*/
|
|
13
|
+
function escapeRegExp(string) {
|
|
14
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15
|
+
}
|
|
16
|
+
const rolldown = async (args) => {
|
|
17
|
+
const baseDir = args.repoRootPath || args.workPath;
|
|
18
|
+
const entrypointPath = join(args.workPath, args.entrypoint);
|
|
19
|
+
const shouldAddSourcemapSupport = false;
|
|
20
|
+
const extension = extname(args.entrypoint);
|
|
21
|
+
const extensionMap = {
|
|
22
|
+
".ts": {
|
|
23
|
+
format: "auto",
|
|
24
|
+
extension: "js"
|
|
25
|
+
},
|
|
26
|
+
".mts": {
|
|
27
|
+
format: "esm",
|
|
28
|
+
extension: "mjs"
|
|
29
|
+
},
|
|
30
|
+
".cts": {
|
|
31
|
+
format: "cjs",
|
|
32
|
+
extension: "cjs"
|
|
33
|
+
},
|
|
34
|
+
".cjs": {
|
|
35
|
+
format: "cjs",
|
|
36
|
+
extension: "cjs"
|
|
37
|
+
},
|
|
38
|
+
".js": {
|
|
39
|
+
format: "auto",
|
|
40
|
+
extension: "js"
|
|
41
|
+
},
|
|
42
|
+
".mjs": {
|
|
43
|
+
format: "esm",
|
|
44
|
+
extension: "mjs"
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const extensionInfo = extensionMap[extension] || extensionMap[".js"];
|
|
48
|
+
let resolvedFormat = extensionInfo.format === "auto" ? void 0 : extensionInfo.format;
|
|
49
|
+
const packageJsonPath = join(args.workPath, "package.json");
|
|
50
|
+
const external = [];
|
|
51
|
+
let pkg = {};
|
|
52
|
+
if (existsSync(packageJsonPath)) {
|
|
53
|
+
const source = await readFile(packageJsonPath, "utf8");
|
|
54
|
+
try {
|
|
55
|
+
pkg = JSON.parse(source.toString());
|
|
56
|
+
} catch (_e) {
|
|
57
|
+
pkg = {};
|
|
58
|
+
}
|
|
59
|
+
if (extensionInfo.format === "auto") if (pkg.type === "module") resolvedFormat = "esm";
|
|
60
|
+
else resolvedFormat = "cjs";
|
|
61
|
+
for (const dependency of Object.keys(pkg.dependencies || {})) external.push(dependency);
|
|
62
|
+
for (const dependency of Object.keys(pkg.devDependencies || {})) external.push(dependency);
|
|
63
|
+
for (const dependency of Object.keys(pkg.peerDependencies || {})) external.push(dependency);
|
|
64
|
+
for (const dependency of Object.keys(pkg.optionalDependencies || {})) external.push(dependency);
|
|
65
|
+
}
|
|
66
|
+
const relativeOutputDir = args.out;
|
|
67
|
+
const outputDir = join(baseDir, relativeOutputDir);
|
|
68
|
+
const out = await build$1({
|
|
69
|
+
input: entrypointPath,
|
|
70
|
+
cwd: baseDir,
|
|
71
|
+
platform: "node",
|
|
72
|
+
tsconfig: true,
|
|
73
|
+
external: external.map((pkg$1) => /* @__PURE__ */ new RegExp(`^${escapeRegExp(pkg$1)}`)),
|
|
74
|
+
output: {
|
|
75
|
+
cleanDir: true,
|
|
76
|
+
dir: outputDir,
|
|
77
|
+
format: resolvedFormat,
|
|
78
|
+
preserveModules: true,
|
|
79
|
+
sourcemap: false
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
let handler = null;
|
|
83
|
+
for (const entry of out.output) if (entry.type === "chunk") {
|
|
84
|
+
if (entry.isEntry) handler = entry.fileName;
|
|
85
|
+
}
|
|
86
|
+
if (typeof handler !== "string") throw new Error(`Unable to resolve module for ${args.entrypoint}`);
|
|
87
|
+
const cleanup = async () => {
|
|
88
|
+
await rm(outputDir, {
|
|
89
|
+
recursive: true,
|
|
90
|
+
force: true
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
result: {
|
|
95
|
+
pkg,
|
|
96
|
+
shouldAddSourcemapSupport,
|
|
97
|
+
handler,
|
|
98
|
+
outputDir
|
|
99
|
+
},
|
|
100
|
+
cleanup
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
9
105
|
//#region src/utils.ts
|
|
10
106
|
const noColor = globalThis.process?.env?.NO_COLOR === "1" || globalThis.process?.env?.TERM === "dumb";
|
|
11
107
|
const resets = {
|
|
@@ -118,115 +214,6 @@ const findNearestTsconfig = async (workPath) => {
|
|
|
118
214
|
return findNearestTsconfig(join(workPath, ".."));
|
|
119
215
|
};
|
|
120
216
|
|
|
121
|
-
//#endregion
|
|
122
|
-
//#region src/rolldown.ts
|
|
123
|
-
const rolldown = async (args) => {
|
|
124
|
-
const baseDir = args.repoRootPath || args.workPath;
|
|
125
|
-
const entrypointPath = join(args.workPath, args.entrypoint);
|
|
126
|
-
const shouldAddSourcemapSupport = false;
|
|
127
|
-
const extension = extname(args.entrypoint);
|
|
128
|
-
const extensionMap = {
|
|
129
|
-
".ts": {
|
|
130
|
-
format: "auto",
|
|
131
|
-
extension: "js"
|
|
132
|
-
},
|
|
133
|
-
".mts": {
|
|
134
|
-
format: "esm",
|
|
135
|
-
extension: "mjs"
|
|
136
|
-
},
|
|
137
|
-
".cts": {
|
|
138
|
-
format: "cjs",
|
|
139
|
-
extension: "cjs"
|
|
140
|
-
},
|
|
141
|
-
".cjs": {
|
|
142
|
-
format: "cjs",
|
|
143
|
-
extension: "cjs"
|
|
144
|
-
},
|
|
145
|
-
".js": {
|
|
146
|
-
format: "auto",
|
|
147
|
-
extension: "js"
|
|
148
|
-
},
|
|
149
|
-
".mjs": {
|
|
150
|
-
format: "esm",
|
|
151
|
-
extension: "mjs"
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
let format = (extensionMap[extension] || extensionMap[".js"]).format;
|
|
155
|
-
const packageJsonPath = join(args.workPath, "package.json");
|
|
156
|
-
const external = [];
|
|
157
|
-
let pkg = {};
|
|
158
|
-
if (existsSync(packageJsonPath)) {
|
|
159
|
-
const source = await readFile(packageJsonPath, "utf8");
|
|
160
|
-
try {
|
|
161
|
-
pkg = JSON.parse(source.toString());
|
|
162
|
-
} catch (_e) {
|
|
163
|
-
pkg = {};
|
|
164
|
-
}
|
|
165
|
-
if (format === "auto") if (pkg.type === "module") format = "esm";
|
|
166
|
-
else format = "cjs";
|
|
167
|
-
for (const dependency of Object.keys(pkg.dependencies || {})) external.push(dependency);
|
|
168
|
-
for (const dependency of Object.keys(pkg.devDependencies || {})) external.push(dependency);
|
|
169
|
-
for (const dependency of Object.keys(pkg.peerDependencies || {})) external.push(dependency);
|
|
170
|
-
for (const dependency of Object.keys(pkg.optionalDependencies || {})) external.push(dependency);
|
|
171
|
-
}
|
|
172
|
-
const tsconfig = await findNearestTsconfig(baseDir);
|
|
173
|
-
const relativeOutputDir = args.out;
|
|
174
|
-
const outputDir = join(baseDir, relativeOutputDir);
|
|
175
|
-
let handler = null;
|
|
176
|
-
await build$1({
|
|
177
|
-
input: entrypointPath,
|
|
178
|
-
cwd: baseDir,
|
|
179
|
-
platform: "node",
|
|
180
|
-
external: (source) => {
|
|
181
|
-
if (source.startsWith(".") || source.startsWith("/")) return false;
|
|
182
|
-
return external.some((pkg$1) => {
|
|
183
|
-
return source === pkg$1 || source.startsWith(pkg$1 + "/");
|
|
184
|
-
});
|
|
185
|
-
},
|
|
186
|
-
tsconfig,
|
|
187
|
-
output: {
|
|
188
|
-
dir: outputDir,
|
|
189
|
-
entryFileNames: (info) => {
|
|
190
|
-
if (info.name === "rolldown_runtime") return "rolldown_runtime.js";
|
|
191
|
-
const facadeModuleId = info.facadeModuleId;
|
|
192
|
-
if (!facadeModuleId) throw new Error(`Unable to resolve module for ${info.name}`);
|
|
193
|
-
const relPath = relative(baseDir, facadeModuleId);
|
|
194
|
-
const extension$1 = extname(relPath);
|
|
195
|
-
const ext = {
|
|
196
|
-
".ts": ".js",
|
|
197
|
-
".mts": ".mjs",
|
|
198
|
-
".mjs": ".mjs",
|
|
199
|
-
".cts": ".cjs",
|
|
200
|
-
".cjs": ".cjs",
|
|
201
|
-
".js": ".js"
|
|
202
|
-
}[extension$1] || ".js";
|
|
203
|
-
const nameWithJS = relPath.slice(0, -extension$1.length) + ext;
|
|
204
|
-
if (info.isEntry) handler = nameWithJS;
|
|
205
|
-
return nameWithJS;
|
|
206
|
-
},
|
|
207
|
-
format,
|
|
208
|
-
preserveModules: true,
|
|
209
|
-
sourcemap: false
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
if (typeof handler !== "string") throw new Error(`Unable to resolve module for ${args.entrypoint}`);
|
|
213
|
-
const cleanup = async () => {
|
|
214
|
-
await rm(outputDir, {
|
|
215
|
-
recursive: true,
|
|
216
|
-
force: true
|
|
217
|
-
});
|
|
218
|
-
};
|
|
219
|
-
return {
|
|
220
|
-
result: {
|
|
221
|
-
pkg,
|
|
222
|
-
shouldAddSourcemapSupport,
|
|
223
|
-
handler,
|
|
224
|
-
outputDir
|
|
225
|
-
},
|
|
226
|
-
cleanup
|
|
227
|
-
};
|
|
228
|
-
};
|
|
229
|
-
|
|
230
217
|
//#endregion
|
|
231
218
|
//#region src/find-entrypoint.ts
|
|
232
219
|
const frameworks = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/cervel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://vercel.com/docs",
|
|
6
6
|
"publishConfig": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"execa": "3.2.0",
|
|
32
|
-
"rolldown": "1.0.0-beta.
|
|
32
|
+
"rolldown": "1.0.0-beta.52",
|
|
33
33
|
"srvx": "0.8.9",
|
|
34
34
|
"tsx": "4.19.2"
|
|
35
35
|
},
|