@clarigen/cli 4.0.0 → 4.0.2-alpha.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/dist/esm-CO92uOgU.mjs +917 -0
- package/dist/esm-CO92uOgU.mjs.map +1 -0
- package/dist/esm-CRbGFHSR.cjs +1226 -0
- package/dist/esm-CRbGFHSR.cjs.map +1 -0
- package/dist/index.cjs +47 -1365
- package/dist/index.d.cts +173 -243
- package/dist/index.d.mts +252 -0
- package/dist/index.mjs +3 -0
- package/dist/run-cli.cjs +259 -1528
- package/dist/run-cli.cjs.map +1 -1
- package/dist/run-cli.d.cts +1 -1
- package/dist/run-cli.d.mts +1 -0
- package/dist/run-cli.mjs +321 -0
- package/dist/run-cli.mjs.map +1 -0
- package/package.json +18 -7
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -322
- package/dist/index.js +0 -1291
- package/dist/index.js.map +0 -1
- package/dist/run-cli.d.ts +0 -1
- package/dist/run-cli.js +0 -1585
- package/dist/run-cli.js.map +0 -1
|
@@ -0,0 +1,917 @@
|
|
|
1
|
+
import { cvToValue, getContractName, getTypeString, isClarityAbiBuffer, isClarityAbiList, isClarityAbiOptional, isClarityAbiPrimitive, isClarityAbiResponse, isClarityAbiStringAscii, isClarityAbiStringUtf8, isClarityAbiTraitReference, isClarityAbiTuple, toCamelCase } from "@clarigen/core";
|
|
2
|
+
import { pino } from "pino";
|
|
3
|
+
import pinoPretty from "pino-pretty";
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
import { basename, dirname, extname, join, relative, resolve } from "path";
|
|
6
|
+
import { mkdir, readFile, stat, writeFile } from "fs/promises";
|
|
7
|
+
import { type } from "arktype";
|
|
8
|
+
import { parse, stringify } from "@iarna/toml";
|
|
9
|
+
import { inspect } from "util";
|
|
10
|
+
import { parse as parse$1 } from "yaml";
|
|
11
|
+
import { getContractTxs, getDeploymentContract, getDeploymentTxPath, getIdentifierForDeploymentTx } from "@clarigen/core/deployment";
|
|
12
|
+
|
|
13
|
+
//#region src/logger.ts
|
|
14
|
+
const colorizedClarigen = `\x1b[33m[Clarigen]\x1b[0m`;
|
|
15
|
+
const logger = pino(pinoPretty({
|
|
16
|
+
colorize: true,
|
|
17
|
+
ignore: "pid,hostname,time",
|
|
18
|
+
messageFormat: `${colorizedClarigen} {msg}`,
|
|
19
|
+
minimumLevel: "debug"
|
|
20
|
+
}));
|
|
21
|
+
logger.level = "info";
|
|
22
|
+
const log = logger;
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/docs/index.ts
|
|
26
|
+
const FN_TYPES = [
|
|
27
|
+
"read-only",
|
|
28
|
+
"public",
|
|
29
|
+
"private"
|
|
30
|
+
];
|
|
31
|
+
const VAR_TYPES = [
|
|
32
|
+
"map",
|
|
33
|
+
"data-var",
|
|
34
|
+
"constant"
|
|
35
|
+
];
|
|
36
|
+
function createContractDocInfo({ contractSrc, abi }) {
|
|
37
|
+
const lines = contractSrc.split("\n");
|
|
38
|
+
let comments = [];
|
|
39
|
+
let parensCount = 0;
|
|
40
|
+
let currentFn;
|
|
41
|
+
const contract = {
|
|
42
|
+
comments: [],
|
|
43
|
+
functions: [],
|
|
44
|
+
variables: [],
|
|
45
|
+
maps: []
|
|
46
|
+
};
|
|
47
|
+
lines.forEach((line, lineNumber) => {
|
|
48
|
+
if (currentFn) {
|
|
49
|
+
currentFn.source.push(line);
|
|
50
|
+
parensCount = traceParens(line, parensCount);
|
|
51
|
+
if (parensCount === 0) {
|
|
52
|
+
pushItem(contract, currentFn);
|
|
53
|
+
currentFn = void 0;
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (isComment(line)) {
|
|
58
|
+
const comment = line.replace(/^\s*;;\s*/g, "");
|
|
59
|
+
if (contract.comments.length === lineNumber) contract.comments.push(comment);
|
|
60
|
+
else comments.push(comment);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const name = findItemNameFromLine(line);
|
|
64
|
+
if (typeof name === "undefined") comments = [];
|
|
65
|
+
else {
|
|
66
|
+
const abiFn = findAbiItemByName(abi, name);
|
|
67
|
+
if (!abiFn) {
|
|
68
|
+
console.debug(`[claridoc]: Unable to find ABI for function \`${name}\`. Probably a bug.`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
parensCount = traceParens(line, 0);
|
|
72
|
+
currentFn = {
|
|
73
|
+
abi: abiFn,
|
|
74
|
+
comments: parseComments(comments, abiFn),
|
|
75
|
+
startLine: lineNumber,
|
|
76
|
+
source: [line]
|
|
77
|
+
};
|
|
78
|
+
if (parensCount === 0) {
|
|
79
|
+
pushItem(contract, currentFn);
|
|
80
|
+
currentFn = void 0;
|
|
81
|
+
}
|
|
82
|
+
comments = [];
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return contract;
|
|
86
|
+
}
|
|
87
|
+
function pushItem(contract, item) {
|
|
88
|
+
if ("args" in item.abi) contract.functions.push(item);
|
|
89
|
+
else if ("key" in item.abi) contract.maps.push(item);
|
|
90
|
+
else if ("access" in item.abi) contract.variables.push(item);
|
|
91
|
+
}
|
|
92
|
+
function clarityNameMatcher(line) {
|
|
93
|
+
return /[\w|\-|\?|\!]+/.exec(line);
|
|
94
|
+
}
|
|
95
|
+
function findItemNameFromLine(line) {
|
|
96
|
+
const fnType = FN_TYPES.find((type$1) => {
|
|
97
|
+
return line.startsWith(`(define-${type$1}`);
|
|
98
|
+
});
|
|
99
|
+
if (fnType) {
|
|
100
|
+
const prefix = `(define-${fnType} (`;
|
|
101
|
+
const match = clarityNameMatcher(line.slice(prefix.length));
|
|
102
|
+
if (!match) {
|
|
103
|
+
console.debug(`[claridocs]: Unable to determine function name from line:\n \`${line}\``);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
return match[0];
|
|
107
|
+
}
|
|
108
|
+
for (const type$1 of VAR_TYPES) {
|
|
109
|
+
const prefix = `(define-${type$1} `;
|
|
110
|
+
if (!line.startsWith(prefix)) continue;
|
|
111
|
+
const match = clarityNameMatcher(line.slice(prefix.length));
|
|
112
|
+
if (!match) {
|
|
113
|
+
console.debug(`[claridocs]: Unable to determine ${type$1} name from line:\n \`${line}\``);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
return match[0];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function findAbiItemByName(abi, name) {
|
|
120
|
+
const fn = abi.functions.find((fn$1) => {
|
|
121
|
+
return fn$1.name === name;
|
|
122
|
+
});
|
|
123
|
+
if (fn) return fn;
|
|
124
|
+
const map = abi.maps.find((m) => m.name === name);
|
|
125
|
+
if (map) return map;
|
|
126
|
+
return abi.variables.find((v) => v.name === name);
|
|
127
|
+
}
|
|
128
|
+
function isComment(line) {
|
|
129
|
+
return line.startsWith(";;");
|
|
130
|
+
}
|
|
131
|
+
function getFnName(line) {
|
|
132
|
+
const fnType = FN_TYPES.find((type$1) => {
|
|
133
|
+
return line.startsWith(`(define-${type$1}`);
|
|
134
|
+
});
|
|
135
|
+
if (typeof fnType === "undefined") return;
|
|
136
|
+
const prefix = `(define-${fnType} (`;
|
|
137
|
+
const match = clarityNameMatcher(line.slice(prefix.length));
|
|
138
|
+
if (!match) {
|
|
139
|
+
console.debug(`[claridocs]: Unable to determine function name from line:\n \`${line}\``);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
return match[0];
|
|
143
|
+
}
|
|
144
|
+
function traceParens(line, count) {
|
|
145
|
+
let newCount = count;
|
|
146
|
+
line.split("").forEach((char) => {
|
|
147
|
+
if (char === "(") newCount++;
|
|
148
|
+
if (char === ")") newCount--;
|
|
149
|
+
});
|
|
150
|
+
return newCount;
|
|
151
|
+
}
|
|
152
|
+
function parseComments(comments, abi) {
|
|
153
|
+
let curParam;
|
|
154
|
+
const parsed = {
|
|
155
|
+
text: [],
|
|
156
|
+
params: {}
|
|
157
|
+
};
|
|
158
|
+
comments.forEach((line) => {
|
|
159
|
+
const paramMatches = /\s*@param\s([\w|\-]+)([;|-|\s]*)(.*)/.exec(line);
|
|
160
|
+
if (paramMatches === null) {
|
|
161
|
+
if (!curParam || line.trim() === "") {
|
|
162
|
+
curParam = void 0;
|
|
163
|
+
parsed.text.push(line);
|
|
164
|
+
} else parsed.params[curParam].comments.push(line);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!("args" in abi)) return;
|
|
168
|
+
const [_full, name, _separator, rest] = paramMatches;
|
|
169
|
+
const arg = abi.args.find((arg$1) => arg$1.name === name);
|
|
170
|
+
if (!arg) {
|
|
171
|
+
console.debug(`[claridocs]: Unable to find ABI for @param ${name}`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
curParam = name;
|
|
175
|
+
parsed.params[curParam] = {
|
|
176
|
+
abi: arg,
|
|
177
|
+
comments: [rest]
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
if ("args" in abi) abi.args.forEach((arg) => {
|
|
181
|
+
if (!parsed.params[arg.name]) parsed.params[arg.name] = {
|
|
182
|
+
abi: arg,
|
|
183
|
+
comments: []
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
return parsed;
|
|
187
|
+
}
|
|
188
|
+
async function afterDocs(config) {
|
|
189
|
+
var _config$docs;
|
|
190
|
+
const command = (_config$docs = config.docs) === null || _config$docs === void 0 ? void 0 : _config$docs.after;
|
|
191
|
+
if (!command) return;
|
|
192
|
+
logger.debug(`Running after docs command: ${command}`);
|
|
193
|
+
const [cmd, ...args] = command.split(" ");
|
|
194
|
+
return new Promise((resolve$1, reject) => {
|
|
195
|
+
const child = spawn(cmd, args, {
|
|
196
|
+
cwd: config.cwd,
|
|
197
|
+
stdio: "inherit"
|
|
198
|
+
});
|
|
199
|
+
child.on("error", reject);
|
|
200
|
+
child.on("exit", (code) => {
|
|
201
|
+
if (code === 0) resolve$1();
|
|
202
|
+
else reject(/* @__PURE__ */ new Error(`Command failed with code ${code ?? "unknown"}`));
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/utils.ts
|
|
209
|
+
function encodeVariableName(name) {
|
|
210
|
+
if (/^[A-Z\-_]*$/.test(name)) return name.replaceAll("-", "_");
|
|
211
|
+
return toCamelCase(name);
|
|
212
|
+
}
|
|
213
|
+
async function fileExists(filename) {
|
|
214
|
+
try {
|
|
215
|
+
await stat(filename);
|
|
216
|
+
return true;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function writeFile$1(path, contents) {
|
|
222
|
+
await mkdir(dirname(path), { recursive: true });
|
|
223
|
+
await writeFile(path, contents, "utf-8");
|
|
224
|
+
return path;
|
|
225
|
+
}
|
|
226
|
+
function cwdRelative(path) {
|
|
227
|
+
return relative(process.cwd(), path);
|
|
228
|
+
}
|
|
229
|
+
function sortContracts(contracts) {
|
|
230
|
+
return [...contracts].sort((a, b) => {
|
|
231
|
+
if (getContractName(a.contract_id, false) < getContractName(b.contract_id, false)) return -1;
|
|
232
|
+
return 1;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/docs/markdown.ts
|
|
238
|
+
function generateMarkdown({ contract, contractFile, withToc = true }) {
|
|
239
|
+
const contractName = getContractName(contract.contract_id, false);
|
|
240
|
+
const doc = createContractDocInfo({
|
|
241
|
+
contractSrc: contract.source,
|
|
242
|
+
abi: contract.contract_interface
|
|
243
|
+
});
|
|
244
|
+
const functions = doc.functions.map((fn) => markdownFunction(fn, contractFile));
|
|
245
|
+
const maps = doc.maps.map((map) => markdownMap(map, contractFile));
|
|
246
|
+
const vars = doc.variables.filter((v) => v.abi.access === "variable").map((v) => markdownVar(v, contractFile));
|
|
247
|
+
const constants = doc.variables.filter((v) => v.abi.access === "constant").map((v) => markdownVar(v, contractFile));
|
|
248
|
+
let fileLine = "";
|
|
249
|
+
if (contractFile) fileLine = `\n[\`${basename(contractFile)}\`](${contractFile})`;
|
|
250
|
+
return `
|
|
251
|
+
# ${contractName}
|
|
252
|
+
${fileLine}
|
|
253
|
+
|
|
254
|
+
${doc.comments.join("\n\n")}
|
|
255
|
+
|
|
256
|
+
${withToc ? markdownTOC(doc) : ""}
|
|
257
|
+
|
|
258
|
+
## Functions
|
|
259
|
+
|
|
260
|
+
${functions.join("\n\n")}
|
|
261
|
+
|
|
262
|
+
## Maps
|
|
263
|
+
|
|
264
|
+
${maps.join("\n\n")}
|
|
265
|
+
|
|
266
|
+
## Variables
|
|
267
|
+
|
|
268
|
+
${vars.join("\n\n")}
|
|
269
|
+
|
|
270
|
+
## Constants
|
|
271
|
+
|
|
272
|
+
${constants.join("\n\n")}
|
|
273
|
+
`;
|
|
274
|
+
}
|
|
275
|
+
function markdownFunction(fn, contractFile) {
|
|
276
|
+
const params = mdParams(fn);
|
|
277
|
+
const returnType = getTypeString(fn.abi.outputs.type);
|
|
278
|
+
const paramSigs = fn.abi.args.map((arg) => {
|
|
279
|
+
return `(${arg.name} ${getTypeString(arg.type)})`;
|
|
280
|
+
});
|
|
281
|
+
const startLine = fn.startLine + 1;
|
|
282
|
+
let link = "";
|
|
283
|
+
if (contractFile) link = `[View in file](${contractFile}#L${startLine})`;
|
|
284
|
+
const source = `<details>
|
|
285
|
+
<summary>Source code:</summary>
|
|
286
|
+
|
|
287
|
+
\`\`\`clarity
|
|
288
|
+
${fn.source.join("\n")}
|
|
289
|
+
\`\`\`
|
|
290
|
+
</details>
|
|
291
|
+
`;
|
|
292
|
+
const sig = `(define-${fn.abi.access.replace("_", "-")} (${fn.abi.name} (${paramSigs.join(" ")}) ${returnType})`;
|
|
293
|
+
return `### ${fn.abi.name}
|
|
294
|
+
|
|
295
|
+
${link}
|
|
296
|
+
|
|
297
|
+
\`${sig}\`
|
|
298
|
+
|
|
299
|
+
${fn.comments.text.join("\n")}
|
|
300
|
+
|
|
301
|
+
${source}
|
|
302
|
+
|
|
303
|
+
${params}`;
|
|
304
|
+
}
|
|
305
|
+
function mdParams(fn) {
|
|
306
|
+
if (fn.abi.args.length === 0) return "";
|
|
307
|
+
const hasDescription = Object.values(fn.comments.params).some((p) => p.comments.length > 0);
|
|
308
|
+
const params = Object.values(fn.comments.params).map((p) => markdownParam(p, hasDescription));
|
|
309
|
+
return `**Parameters:**
|
|
310
|
+
|
|
311
|
+
| Name | Type | ${hasDescription ? "Description |" : ""}
|
|
312
|
+
| --- | --- | ${hasDescription ? "--- |" : ""}
|
|
313
|
+
${params.join("\n")}`;
|
|
314
|
+
}
|
|
315
|
+
function markdownParam(param, withDescription) {
|
|
316
|
+
const typeString = getTypeString(param.abi.type);
|
|
317
|
+
const base = `| ${param.abi.name} | ${typeString} |`;
|
|
318
|
+
if (!withDescription) return base;
|
|
319
|
+
return `${base} ${param.comments.join(" ")} |`;
|
|
320
|
+
}
|
|
321
|
+
function markdownMap(map, contractFile) {
|
|
322
|
+
const startLine = map.startLine + 1;
|
|
323
|
+
let link = "";
|
|
324
|
+
if (contractFile) link = `[View in file](${contractFile}#L${startLine})`;
|
|
325
|
+
return `### ${map.abi.name}
|
|
326
|
+
|
|
327
|
+
${map.comments.text.join("\n")}
|
|
328
|
+
|
|
329
|
+
\`\`\`clarity
|
|
330
|
+
${map.source.join("\n")}
|
|
331
|
+
\`\`\`
|
|
332
|
+
|
|
333
|
+
${link}`;
|
|
334
|
+
}
|
|
335
|
+
function markdownVar(variable, contractFile) {
|
|
336
|
+
const startLine = variable.startLine + 1;
|
|
337
|
+
let link = "";
|
|
338
|
+
if (contractFile) link = `[View in file](${contractFile}#L${startLine})`;
|
|
339
|
+
const sig = variable.abi.access === "variable" ? getTypeString(variable.abi.type) : "";
|
|
340
|
+
return `### ${variable.abi.name}
|
|
341
|
+
|
|
342
|
+
${sig}
|
|
343
|
+
|
|
344
|
+
${variable.comments.text.join("\n")}
|
|
345
|
+
|
|
346
|
+
\`\`\`clarity
|
|
347
|
+
${variable.source.join("\n")}
|
|
348
|
+
\`\`\`
|
|
349
|
+
|
|
350
|
+
${link}`;
|
|
351
|
+
}
|
|
352
|
+
function markdownTOC(contract) {
|
|
353
|
+
const publics = contract.functions.filter((fn) => fn.abi.access === "public");
|
|
354
|
+
const readOnly = contract.functions.filter((fn) => fn.abi.access === "read_only");
|
|
355
|
+
const privates = contract.functions.filter((fn) => fn.abi.access === "private");
|
|
356
|
+
const maps = contract.maps;
|
|
357
|
+
const constants = contract.variables.filter((v) => v.abi.access === "constant");
|
|
358
|
+
const vars = contract.variables.filter((v) => v.abi.access === "variable");
|
|
359
|
+
function tocLine(fn) {
|
|
360
|
+
const name = fn.abi.name;
|
|
361
|
+
return `- [\`${name}\`](#${name.toLowerCase().replaceAll("?", "")})`;
|
|
362
|
+
}
|
|
363
|
+
return `**Public functions:**
|
|
364
|
+
|
|
365
|
+
${publics.map(tocLine).join("\n")}
|
|
366
|
+
|
|
367
|
+
**Read-only functions:**
|
|
368
|
+
|
|
369
|
+
${readOnly.map(tocLine).join("\n")}
|
|
370
|
+
|
|
371
|
+
**Private functions:**
|
|
372
|
+
|
|
373
|
+
${privates.map(tocLine).join("\n")}
|
|
374
|
+
|
|
375
|
+
**Maps**
|
|
376
|
+
|
|
377
|
+
${maps.map(tocLine).join("\n")}
|
|
378
|
+
|
|
379
|
+
**Variables**
|
|
380
|
+
|
|
381
|
+
${vars.map(tocLine).join("\n")}
|
|
382
|
+
|
|
383
|
+
**Constants**
|
|
384
|
+
|
|
385
|
+
${constants.map(tocLine).join("\n")}
|
|
386
|
+
`;
|
|
387
|
+
}
|
|
388
|
+
function generateReadme(session, excluded) {
|
|
389
|
+
const contractLines = [];
|
|
390
|
+
sortContracts(session.contracts).forEach((contract) => {
|
|
391
|
+
const name = getContractName(contract.contract_id, false);
|
|
392
|
+
if (excluded[name]) return;
|
|
393
|
+
const line = `- [\`${name}\`](${`${name}.md`})`;
|
|
394
|
+
contractLines.push(line);
|
|
395
|
+
});
|
|
396
|
+
return `# Contracts
|
|
397
|
+
|
|
398
|
+
${contractLines.join("\n")}
|
|
399
|
+
`;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/clarinet-config.ts
|
|
404
|
+
const ClarinetConfig = type({
|
|
405
|
+
project: type({
|
|
406
|
+
requirements: type({ contract_id: type("string").describe("Contract ID") }).array().describe("Project requirements").optional(),
|
|
407
|
+
cache_location: type({ path: type("string").describe("Cache location path") }).optional()
|
|
408
|
+
}),
|
|
409
|
+
contracts: type({ "[string]": type({ path: type("string").describe("Contract path") }) }).optional()
|
|
410
|
+
});
|
|
411
|
+
async function getClarinetConfig(path) {
|
|
412
|
+
const file = await readFile(path, "utf-8");
|
|
413
|
+
return ClarinetConfig.assert(parse(file));
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
//#endregion
|
|
417
|
+
//#region src/config.ts
|
|
418
|
+
const CONFIG_FILE = "Clarigen.toml";
|
|
419
|
+
let OutputType = /* @__PURE__ */ function(OutputType$1) {
|
|
420
|
+
OutputType$1["ESM"] = "types";
|
|
421
|
+
OutputType$1["ESM_OLD"] = "esm";
|
|
422
|
+
OutputType$1["Docs"] = "docs";
|
|
423
|
+
return OutputType$1;
|
|
424
|
+
}({});
|
|
425
|
+
const typesSchema = type({
|
|
426
|
+
"output?": type("string").describe("Path to the output file"),
|
|
427
|
+
"outputs?": type("string[]").describe("Paths to the output files"),
|
|
428
|
+
"include_accounts?": type("boolean").describe("Include accounts in the output"),
|
|
429
|
+
"after?": type("string").describe("Script to run after the output is generated"),
|
|
430
|
+
"include_boot_contracts?": type("boolean").describe("Include boot contracts in the output"),
|
|
431
|
+
"watch_folders?": type("string[]").describe("Folders to watch for changes")
|
|
432
|
+
}).optional();
|
|
433
|
+
const ConfigFile = type({
|
|
434
|
+
clarinet: type("string").describe("Path to the Clarinet config file"),
|
|
435
|
+
[OutputType.ESM]: typesSchema,
|
|
436
|
+
[OutputType.ESM_OLD]: typesSchema,
|
|
437
|
+
[OutputType.Docs]: type({
|
|
438
|
+
"output?": type("string").describe("Path to docs output folder. Defaults to ./docs"),
|
|
439
|
+
"outputs?": type("string[]").describe("Paths to docs output folders"),
|
|
440
|
+
"exclude?": type("string[]").describe("Contracts to exclude from docs generation"),
|
|
441
|
+
"after?": type("string").describe("Script to run after docs are generated")
|
|
442
|
+
}).optional()
|
|
443
|
+
});
|
|
444
|
+
const defaultConfigFile = { clarinet: "./Clarinet.toml" };
|
|
445
|
+
var Config = class {
|
|
446
|
+
configFile;
|
|
447
|
+
clarinet;
|
|
448
|
+
cwd;
|
|
449
|
+
constructor(config, clarinet, cwd) {
|
|
450
|
+
this.configFile = config;
|
|
451
|
+
this.clarinet = clarinet;
|
|
452
|
+
this.cwd = cwd ?? process.cwd();
|
|
453
|
+
}
|
|
454
|
+
static async load(cwd) {
|
|
455
|
+
const config = await getConfig(cwd);
|
|
456
|
+
if (config[OutputType.ESM_OLD]) {
|
|
457
|
+
config[OutputType.ESM] = config[OutputType.ESM_OLD];
|
|
458
|
+
delete config[OutputType.ESM_OLD];
|
|
459
|
+
}
|
|
460
|
+
const clarinet = await getClarinetConfig(resolve(cwd ?? "", config.clarinet));
|
|
461
|
+
return new this(config, clarinet, cwd);
|
|
462
|
+
}
|
|
463
|
+
getOutputs(type$1) {
|
|
464
|
+
var _this$configFile$type, _this$configFile$type2;
|
|
465
|
+
const singlePath = (_this$configFile$type = this.configFile[type$1]) === null || _this$configFile$type === void 0 ? void 0 : _this$configFile$type.output;
|
|
466
|
+
const multiPath = ((_this$configFile$type2 = this.configFile[type$1]) === null || _this$configFile$type2 === void 0 ? void 0 : _this$configFile$type2.outputs) || [];
|
|
467
|
+
if (singlePath !== void 0) return [singlePath];
|
|
468
|
+
return multiPath;
|
|
469
|
+
}
|
|
470
|
+
outputResolve(type$1, filePath) {
|
|
471
|
+
const outputs = this.getOutputs(type$1);
|
|
472
|
+
if (!this.supports(type$1)) return null;
|
|
473
|
+
return outputs.map((path) => {
|
|
474
|
+
return resolve(this.cwd, path, filePath || "");
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
async writeOutput(type$1, contents, filePath) {
|
|
478
|
+
const paths = this.outputResolve(type$1, filePath);
|
|
479
|
+
if (paths === null) return null;
|
|
480
|
+
await Promise.all(paths.map(async (path) => {
|
|
481
|
+
await writeFile$1(path, contents);
|
|
482
|
+
log.debug(`Generated ${type$1} file at ${relative(this.cwd, path)}`);
|
|
483
|
+
}));
|
|
484
|
+
return paths;
|
|
485
|
+
}
|
|
486
|
+
supports(type$1) {
|
|
487
|
+
return this.getOutputs(type$1).length > 0;
|
|
488
|
+
}
|
|
489
|
+
type(type$1) {
|
|
490
|
+
return this.configFile[type$1];
|
|
491
|
+
}
|
|
492
|
+
get esm() {
|
|
493
|
+
return this.configFile[OutputType.ESM];
|
|
494
|
+
}
|
|
495
|
+
get docs() {
|
|
496
|
+
return this.configFile[OutputType.Docs];
|
|
497
|
+
}
|
|
498
|
+
clarinetFile() {
|
|
499
|
+
return resolve(this.cwd, this.configFile.clarinet);
|
|
500
|
+
}
|
|
501
|
+
joinFromClarinet(filePath) {
|
|
502
|
+
return join(dirname(this.clarinetFile()), filePath);
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
function configFilePath(cwd) {
|
|
506
|
+
return resolve(cwd ?? process.cwd(), CONFIG_FILE);
|
|
507
|
+
}
|
|
508
|
+
async function saveConfig(config) {
|
|
509
|
+
const configToml = stringify({ ...config });
|
|
510
|
+
await writeFile$1(configFilePath(), configToml);
|
|
511
|
+
}
|
|
512
|
+
let sessionConfig;
|
|
513
|
+
async function getConfig(cwd) {
|
|
514
|
+
if (typeof sessionConfig !== "undefined") return sessionConfig;
|
|
515
|
+
const path = configFilePath(cwd);
|
|
516
|
+
if (await fileExists(path)) {
|
|
517
|
+
const parsed = ConfigFile(parse(await readFile(path, "utf-8")));
|
|
518
|
+
if (parsed instanceof type.errors) {
|
|
519
|
+
logger.error(`Error parsing Clarigen config: ${parsed.summary}`);
|
|
520
|
+
throw new Error(`Error parsing Clarigen config: ${parsed.summary}`);
|
|
521
|
+
}
|
|
522
|
+
sessionConfig = parsed;
|
|
523
|
+
} else sessionConfig = defaultConfigFile;
|
|
524
|
+
return sessionConfig;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
//#endregion
|
|
528
|
+
//#region src/files/docs.ts
|
|
529
|
+
async function generateDocs({ session, config }) {
|
|
530
|
+
const docs = config.configFile[OutputType.Docs];
|
|
531
|
+
const docsBase = docs === null || docs === void 0 ? void 0 : docs.output;
|
|
532
|
+
if (!docsBase) {
|
|
533
|
+
warnNoDocs();
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (extname(docsBase)) log.warn(`Docs output path ('${docsBase}') looks like a file - it needs to be a directory.`);
|
|
537
|
+
const excluded = Object.fromEntries((docs.exclude || []).map((e) => {
|
|
538
|
+
return [e, true];
|
|
539
|
+
}));
|
|
540
|
+
log.debug(`Generating docs at path \`${docsBase}\``);
|
|
541
|
+
const docsBaseFolder = config.outputResolve(OutputType.Docs, "./")[0];
|
|
542
|
+
const paths = await Promise.all(session.contracts.map(async (contract) => {
|
|
543
|
+
var _config$clarinet$cont;
|
|
544
|
+
const name = getContractName(contract.contract_id, false);
|
|
545
|
+
if (excluded[name]) return null;
|
|
546
|
+
const docFile = `${name}.md`;
|
|
547
|
+
const contractPathDef = (_config$clarinet$cont = config.clarinet.contracts) === null || _config$clarinet$cont === void 0 || (_config$clarinet$cont = _config$clarinet$cont[name]) === null || _config$clarinet$cont === void 0 ? void 0 : _config$clarinet$cont.path;
|
|
548
|
+
let contractFile;
|
|
549
|
+
if (contractPathDef) contractFile = relative(docsBaseFolder, config.joinFromClarinet(contractPathDef));
|
|
550
|
+
else log.debug(`Couldn't find contract file from Clarinet.toml for contract ${name}`);
|
|
551
|
+
const md = generateMarkdown({
|
|
552
|
+
contract,
|
|
553
|
+
contractFile
|
|
554
|
+
});
|
|
555
|
+
return (await config.writeOutput(OutputType.Docs, md, docFile))[0];
|
|
556
|
+
}));
|
|
557
|
+
const readme = generateReadme(session, excluded);
|
|
558
|
+
paths.push((await config.writeOutput(OutputType.Docs, readme, "README.md"))[0]);
|
|
559
|
+
await afterDocs(config);
|
|
560
|
+
}
|
|
561
|
+
function warnNoDocs() {
|
|
562
|
+
log.warn(`\nClarigen config file doesn't include an output directory for docs.
|
|
563
|
+
|
|
564
|
+
To generate docs, specify 'docs.output' in your config file:
|
|
565
|
+
|
|
566
|
+
[docs]
|
|
567
|
+
output = "docs/"
|
|
568
|
+
`.trimEnd());
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region src/declaration.ts
|
|
573
|
+
const jsTypeFromAbiType = (val, isArgument = false) => {
|
|
574
|
+
if (isClarityAbiPrimitive(val)) if (val === "uint128") {
|
|
575
|
+
if (isArgument) return "number | bigint";
|
|
576
|
+
return "bigint";
|
|
577
|
+
} else if (val === "int128") {
|
|
578
|
+
if (isArgument) return "number | bigint";
|
|
579
|
+
return "bigint";
|
|
580
|
+
} else if (val === "bool") return "boolean";
|
|
581
|
+
else if (val === "principal") return "string";
|
|
582
|
+
else if (val === "none") return "null";
|
|
583
|
+
else if (val === "trait_reference") return "string";
|
|
584
|
+
else throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(val)}`);
|
|
585
|
+
else if (isClarityAbiBuffer(val)) return "Uint8Array";
|
|
586
|
+
else if (isClarityAbiResponse(val)) return `Response<${jsTypeFromAbiType(val.response.ok, isArgument)}, ${jsTypeFromAbiType(val.response.error, isArgument)}>`;
|
|
587
|
+
else if (isClarityAbiOptional(val)) return `${jsTypeFromAbiType(val.optional, isArgument)} | null`;
|
|
588
|
+
else if (isClarityAbiTuple(val)) {
|
|
589
|
+
const tupleDefs = [];
|
|
590
|
+
val.tuple.forEach(({ name, type: type$1 }) => {
|
|
591
|
+
const camelName = toCamelCase(name);
|
|
592
|
+
const innerType = jsTypeFromAbiType(type$1, isArgument);
|
|
593
|
+
tupleDefs.push(`"${camelName}": ${innerType};`);
|
|
594
|
+
});
|
|
595
|
+
return `{
|
|
596
|
+
${tupleDefs.join("\n ")}
|
|
597
|
+
}`;
|
|
598
|
+
} else if (isClarityAbiList(val)) return `${jsTypeFromAbiType(val.list.type, isArgument)}[]`;
|
|
599
|
+
else if (isClarityAbiStringAscii(val)) return "string";
|
|
600
|
+
else if (isClarityAbiStringUtf8(val)) return "string";
|
|
601
|
+
else if (isClarityAbiTraitReference(val)) return "string";
|
|
602
|
+
else throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(val)}`);
|
|
603
|
+
};
|
|
604
|
+
function abiArgType(arg) {
|
|
605
|
+
const nativeType = jsTypeFromAbiType(arg.type, true);
|
|
606
|
+
const argName = getArgName(arg.name);
|
|
607
|
+
return `${argName}: TypedAbiArg<${nativeType}, "${argName}">`;
|
|
608
|
+
}
|
|
609
|
+
function abiFunctionType(abiFunction) {
|
|
610
|
+
const args = abiFunction.args.map(abiArgType);
|
|
611
|
+
const retType = jsTypeFromAbiType(abiFunction.outputs.type);
|
|
612
|
+
return `TypedAbiFunction<${`[${args.join(", ")}]`}, ${retType}>`;
|
|
613
|
+
}
|
|
614
|
+
function getArgName(name) {
|
|
615
|
+
const camel = toCamelCase(name);
|
|
616
|
+
return `${RESERVED[camel] ? "_" : ""}${camel}`;
|
|
617
|
+
}
|
|
618
|
+
function _hash(...words) {
|
|
619
|
+
const h = {};
|
|
620
|
+
for (const word of words) h[word] = true;
|
|
621
|
+
return h;
|
|
622
|
+
}
|
|
623
|
+
const RESERVED = _hash("break", "do", "in", "typeof", "case", "else", "instanceof", "var", "catch", "export", "new", "void", "class", "extends", "return", "while", "const", "finally", "super", "with", "continue", "for", "switch", "yield", "debugger", "function", "this", "default", "if", "throw", "delete", "import", "try", "enum", "await", "null", "true", "false");
|
|
624
|
+
|
|
625
|
+
//#endregion
|
|
626
|
+
//#region src/files/accounts.ts
|
|
627
|
+
function generateAccountsCode(accounts) {
|
|
628
|
+
const sortedAccounts = sortAccounts(accounts);
|
|
629
|
+
const namedAccounts = Object.fromEntries(sortedAccounts.map((a) => {
|
|
630
|
+
const { name, ...rest } = a;
|
|
631
|
+
return [name, rest];
|
|
632
|
+
}));
|
|
633
|
+
return JSON.stringify(namedAccounts);
|
|
634
|
+
}
|
|
635
|
+
function sortAccounts(accounts) {
|
|
636
|
+
return [...accounts].sort((a, b) => {
|
|
637
|
+
if (a.name < b.name) return -1;
|
|
638
|
+
return 1;
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region src/files/identifiers.ts
|
|
644
|
+
function generateIdentifiers(session) {
|
|
645
|
+
return Object.fromEntries(sortContracts(session.contracts).map((c) => {
|
|
646
|
+
return [getContractName(c.contract_id), c.contract_id];
|
|
647
|
+
}));
|
|
648
|
+
}
|
|
649
|
+
function generateIdentifiersCode(session) {
|
|
650
|
+
const identifiers = generateIdentifiers(session);
|
|
651
|
+
return `export const identifiers = ${JSON.stringify(identifiers)} as const`;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
//#endregion
|
|
655
|
+
//#region src/files/base.ts
|
|
656
|
+
function generateContractMeta(contract, constants) {
|
|
657
|
+
const abi = contract.contract_interface;
|
|
658
|
+
const functionLines = [];
|
|
659
|
+
const { functions, maps, variables, non_fungible_tokens, ...rest } = abi;
|
|
660
|
+
functions.forEach((func) => {
|
|
661
|
+
let functionLine = `${toCamelCase(func.name)}: `;
|
|
662
|
+
const funcDef = JSON.stringify(func);
|
|
663
|
+
functionLine += funcDef;
|
|
664
|
+
const functionType = abiFunctionType(func);
|
|
665
|
+
functionLine += ` as ${functionType}`;
|
|
666
|
+
functionLines.push(functionLine);
|
|
667
|
+
});
|
|
668
|
+
const mapLines = maps.map((map) => {
|
|
669
|
+
let mapLine = `${toCamelCase(map.name)}: `;
|
|
670
|
+
const keyType = jsTypeFromAbiType(map.key, true);
|
|
671
|
+
const valType = jsTypeFromAbiType(map.value);
|
|
672
|
+
mapLine += JSON.stringify(map);
|
|
673
|
+
mapLine += ` as TypedAbiMap<${keyType}, ${valType}>`;
|
|
674
|
+
return mapLine;
|
|
675
|
+
});
|
|
676
|
+
const otherAbi = JSON.stringify(rest);
|
|
677
|
+
const contractName = contract.contract_id.split(".")[1];
|
|
678
|
+
const variableLines = encodeVariables(variables);
|
|
679
|
+
const nftLines = non_fungible_tokens.map((nft) => {
|
|
680
|
+
return JSON.stringify(nft);
|
|
681
|
+
});
|
|
682
|
+
return `{
|
|
683
|
+
${serializeLines("functions", functionLines)}
|
|
684
|
+
${serializeLines("maps", mapLines)}
|
|
685
|
+
${serializeLines("variables", variableLines)}
|
|
686
|
+
constants: ${constants},
|
|
687
|
+
${serializeArray("non_fungible_tokens", nftLines)}
|
|
688
|
+
${otherAbi.slice(1, -1)},
|
|
689
|
+
contractName: '${contractName}',
|
|
690
|
+
}`;
|
|
691
|
+
}
|
|
692
|
+
const TYPE_IMPORTS = `import type { TypedAbiArg, TypedAbiFunction, TypedAbiMap, TypedAbiVariable, Response } from '@clarigen/core';`;
|
|
693
|
+
function generateBaseFile(session) {
|
|
694
|
+
return `
|
|
695
|
+
${TYPE_IMPORTS}
|
|
696
|
+
|
|
697
|
+
export const contracts = {
|
|
698
|
+
${sortContracts(session.contracts.map((c, i) => ({
|
|
699
|
+
...c,
|
|
700
|
+
constants: session.variables[i]
|
|
701
|
+
}))).map((contract) => {
|
|
702
|
+
const meta = generateContractMeta(contract, contract.constants);
|
|
703
|
+
const id = contract.contract_id.split(".")[1];
|
|
704
|
+
return `${toCamelCase(id)}: ${meta}`;
|
|
705
|
+
}).join(",\n")}
|
|
706
|
+
} as const;
|
|
707
|
+
|
|
708
|
+
export const accounts = ${generateAccountsCode(session.accounts)} as const;
|
|
709
|
+
|
|
710
|
+
${generateIdentifiersCode(session)}
|
|
711
|
+
|
|
712
|
+
export const simnet = {
|
|
713
|
+
accounts,
|
|
714
|
+
contracts,
|
|
715
|
+
identifiers,
|
|
716
|
+
} as const;
|
|
717
|
+
|
|
718
|
+
`;
|
|
719
|
+
}
|
|
720
|
+
function encodeVariables(variables) {
|
|
721
|
+
return variables.map((v) => {
|
|
722
|
+
let varLine = `${encodeVariableName(v.name)}: `;
|
|
723
|
+
const type$1 = jsTypeFromAbiType(v.type);
|
|
724
|
+
const varJSON = serialize(v);
|
|
725
|
+
varLine += `${varJSON} as TypedAbiVariable<${type$1}>`;
|
|
726
|
+
return varLine;
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
Uint8Array.prototype[inspect.custom] = function(depth, options) {
|
|
730
|
+
return `Uint8Array.from([${this.join(",")}])`;
|
|
731
|
+
};
|
|
732
|
+
function serialize(obj) {
|
|
733
|
+
return inspect(obj, {
|
|
734
|
+
showHidden: false,
|
|
735
|
+
compact: false,
|
|
736
|
+
depth: 100,
|
|
737
|
+
colors: false,
|
|
738
|
+
maxArrayLength: Infinity,
|
|
739
|
+
maxStringLength: Infinity,
|
|
740
|
+
breakLength: Infinity,
|
|
741
|
+
numericSeparator: true
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
function serializeLines(key, lines) {
|
|
745
|
+
return `"${key}": {
|
|
746
|
+
${lines.join(",\n ")}
|
|
747
|
+
},`;
|
|
748
|
+
}
|
|
749
|
+
function serializeArray(key, lines) {
|
|
750
|
+
return `"${key}": [
|
|
751
|
+
${lines.join(",\n ")}
|
|
752
|
+
],`;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region src/files/variables.ts
|
|
757
|
+
function clarityVersionForContract(contract) {
|
|
758
|
+
switch (contract.contract_interface.clarity_version) {
|
|
759
|
+
case "Clarity1": return 1;
|
|
760
|
+
case "Clarity2": return 2;
|
|
761
|
+
case "Clarity3": return 3;
|
|
762
|
+
case "Clarity4": return 4;
|
|
763
|
+
default: return 3;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function getVariablesV2(contract, simnet, verbose) {
|
|
767
|
+
const [deployer] = contract.contract_id.split(".");
|
|
768
|
+
const fakeId = `${getContractName(contract.contract_id)}-vars`;
|
|
769
|
+
logger.debug(`Deploying ${contract.contract_id} for variables.`);
|
|
770
|
+
if (!contract.source) {
|
|
771
|
+
logger.debug(`Contract ${getContractName(contract.contract_id)} has no source. Skipping variables.`);
|
|
772
|
+
return {};
|
|
773
|
+
}
|
|
774
|
+
if (contract.contract_interface.variables.length === 0) {
|
|
775
|
+
logger.info(`Contract ${getContractName(contract.contract_id, false)} has no variables`);
|
|
776
|
+
return {};
|
|
777
|
+
}
|
|
778
|
+
let varFn = `{\n`;
|
|
779
|
+
const varLines = contract.contract_interface.variables.map((variable) => {
|
|
780
|
+
let varLine = `${variable.name}: `;
|
|
781
|
+
if (variable.access === "constant") varLine += `${variable.name}`;
|
|
782
|
+
else varLine += `(var-get ${variable.name})`;
|
|
783
|
+
return varLine;
|
|
784
|
+
});
|
|
785
|
+
varFn += varLines.map((l) => ` ${l},`).join("\n");
|
|
786
|
+
varFn += "\n}";
|
|
787
|
+
const fullSrc = contract.source + `\n\n${varFn}`;
|
|
788
|
+
try {
|
|
789
|
+
const result = simnet.deployContract(fakeId, fullSrc, { clarityVersion: clarityVersionForContract(contract) }, deployer).result;
|
|
790
|
+
const varsAbi = { tuple: [] };
|
|
791
|
+
contract.contract_interface.variables.forEach((v) => {
|
|
792
|
+
const _v = v;
|
|
793
|
+
varsAbi.tuple.push({
|
|
794
|
+
type: _v.type,
|
|
795
|
+
name: _v.name
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
if (verbose) logger.info(cvToValue(result, true));
|
|
799
|
+
return cvToValue(result, true);
|
|
800
|
+
} catch (error) {
|
|
801
|
+
logger.warn({ err: error }, `Error getting variables for ${getContractName(contract.contract_id, false)}`);
|
|
802
|
+
return {};
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
function mapVariables(session, simnet) {
|
|
806
|
+
return session.contracts.map((contract) => {
|
|
807
|
+
return serialize(getVariablesV2(contract, simnet));
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
//#endregion
|
|
812
|
+
//#region src/files/esm.ts
|
|
813
|
+
async function parseDeployment(path) {
|
|
814
|
+
return parse$1(await readFile(path, "utf-8"));
|
|
815
|
+
}
|
|
816
|
+
const DEPLOYMENT_NETWORKS = [
|
|
817
|
+
"devnet",
|
|
818
|
+
"simnet",
|
|
819
|
+
"testnet",
|
|
820
|
+
"mainnet"
|
|
821
|
+
];
|
|
822
|
+
async function getDeployments(config) {
|
|
823
|
+
const entries = await Promise.all(DEPLOYMENT_NETWORKS.map(async (network) => {
|
|
824
|
+
const file = `default.${network}-plan.yaml`;
|
|
825
|
+
const path = join(dirname(config.clarinetFile()), "deployments", file);
|
|
826
|
+
let plan;
|
|
827
|
+
try {
|
|
828
|
+
plan = await parseDeployment(path);
|
|
829
|
+
} catch (_) {}
|
|
830
|
+
return [network, plan];
|
|
831
|
+
}));
|
|
832
|
+
return Object.fromEntries(entries);
|
|
833
|
+
}
|
|
834
|
+
async function generateESMFile({ baseFile, session, config }) {
|
|
835
|
+
const deployments = await getDeployments(config);
|
|
836
|
+
const contractDeployments = collectContractDeployments(session, deployments, config);
|
|
837
|
+
const simnet = generateSimnetCode(config, deployments, session);
|
|
838
|
+
return `${baseFile}
|
|
839
|
+
export const deployments = ${JSON.stringify(contractDeployments)} as const;
|
|
840
|
+
${simnet}
|
|
841
|
+
export const project = {
|
|
842
|
+
contracts,
|
|
843
|
+
deployments,
|
|
844
|
+
} as const;
|
|
845
|
+
`;
|
|
846
|
+
}
|
|
847
|
+
function insertNetworkId(deployments, identifier, network) {
|
|
848
|
+
const name = getContractName(identifier);
|
|
849
|
+
if (!deployments[name]) return;
|
|
850
|
+
if (deployments[name][network] === null) deployments[name][network] = identifier;
|
|
851
|
+
}
|
|
852
|
+
function collectContractDeployments(session, deployments, config) {
|
|
853
|
+
var _config$clarinet$proj;
|
|
854
|
+
const full = Object.fromEntries(sortContracts(session.contracts).map((contract) => {
|
|
855
|
+
return [getContractName(contract.contract_id), Object.fromEntries(DEPLOYMENT_NETWORKS.map((network) => {
|
|
856
|
+
const deployment = deployments[network];
|
|
857
|
+
if (typeof deployment === "undefined") return [network, null];
|
|
858
|
+
try {
|
|
859
|
+
const contractName = contract.contract_id.split(".")[1];
|
|
860
|
+
return [network, getIdentifierForDeploymentTx(getDeploymentContract(contractName, deployment))];
|
|
861
|
+
} catch (_) {
|
|
862
|
+
return [network, null];
|
|
863
|
+
}
|
|
864
|
+
}))];
|
|
865
|
+
}));
|
|
866
|
+
const deployer = session.accounts.find((a) => a.name === "deployer");
|
|
867
|
+
(_config$clarinet$proj = config.clarinet.project.requirements) === null || _config$clarinet$proj === void 0 || _config$clarinet$proj.forEach(({ contract_id }) => {
|
|
868
|
+
insertNetworkId(full, contract_id, "mainnet");
|
|
869
|
+
const contractName = contract_id.split(".")[1];
|
|
870
|
+
if (deployer) insertNetworkId(full, `${deployer.address}.${contractName}`, "devnet");
|
|
871
|
+
});
|
|
872
|
+
session.contracts.forEach((contract) => {
|
|
873
|
+
insertNetworkId(full, contract.contract_id, "devnet");
|
|
874
|
+
insertNetworkId(full, contract.contract_id, "simnet");
|
|
875
|
+
});
|
|
876
|
+
return full;
|
|
877
|
+
}
|
|
878
|
+
function collectDeploymentFiles(deployments, clarinetFolder, cwd) {
|
|
879
|
+
if (!deployments.simnet) return [];
|
|
880
|
+
const simnet = deployments.simnet;
|
|
881
|
+
return getContractTxs(simnet.plan.batches).map((tx) => {
|
|
882
|
+
return {
|
|
883
|
+
identifier: getIdentifierForDeploymentTx(tx),
|
|
884
|
+
file: relative(cwd, join(clarinetFolder, getDeploymentTxPath(tx)))
|
|
885
|
+
};
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
function generateSimnetCode(config, deployments, _session) {
|
|
889
|
+
var _config$esm;
|
|
890
|
+
if (!((_config$esm = config.esm) === null || _config$esm === void 0 ? void 0 : _config$esm.include_accounts)) return "";
|
|
891
|
+
const files = collectDeploymentFiles(deployments, dirname(config.clarinetFile()), config.cwd);
|
|
892
|
+
return `
|
|
893
|
+
export const simnetDeployment = ${JSON.stringify(files)};
|
|
894
|
+
`;
|
|
895
|
+
}
|
|
896
|
+
async function afterESM(config) {
|
|
897
|
+
var _config$esm2;
|
|
898
|
+
const command = (_config$esm2 = config.esm) === null || _config$esm2 === void 0 ? void 0 : _config$esm2.after;
|
|
899
|
+
if (!command) return;
|
|
900
|
+
logger.debug(`Running after ESM command: ${command}`);
|
|
901
|
+
const [cmd, ...args] = command.split(" ");
|
|
902
|
+
return new Promise((resolve$1, reject) => {
|
|
903
|
+
const child = spawn(cmd, args, {
|
|
904
|
+
cwd: config.cwd,
|
|
905
|
+
stdio: "inherit"
|
|
906
|
+
});
|
|
907
|
+
child.on("error", reject);
|
|
908
|
+
child.on("exit", (code) => {
|
|
909
|
+
if (code === 0) resolve$1();
|
|
910
|
+
else reject(/* @__PURE__ */ new Error(`Command failed with code ${code ?? "unknown"}`));
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
//#endregion
|
|
916
|
+
export { generateMarkdown as A, afterDocs as B, OutputType as C, saveConfig as D, getConfig as E, fileExists as F, traceParens as G, getFnName as H, sortContracts as I, logger as K, writeFile$1 as L, markdownFunction as M, cwdRelative as N, ClarinetConfig as O, encodeVariableName as P, FN_TYPES as R, ConfigFile as S, defaultConfigFile as T, isComment as U, createContractDocInfo as V, parseComments as W, getArgName as _, generateESMFile as a, CONFIG_FILE as b, getVariablesV2 as c, encodeVariables as d, generateBaseFile as f, abiFunctionType as g, abiArgType as h, collectDeploymentFiles as i, generateReadme as j, getClarinetConfig as k, mapVariables as l, serialize as m, afterESM as n, getDeployments as o, generateContractMeta as p, collectContractDeployments as r, parseDeployment as s, DEPLOYMENT_NETWORKS as t, TYPE_IMPORTS as u, jsTypeFromAbiType as v, configFilePath as w, Config as x, generateDocs as y, VAR_TYPES as z };
|
|
917
|
+
//# sourceMappingURL=esm-CO92uOgU.mjs.map
|