@clarigen/cli 4.0.1 → 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
package/dist/run-cli.cjs
CHANGED
|
@@ -1,1512 +1,243 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
const require_esm = require('./esm-CRbGFHSR.cjs');
|
|
3
|
+
let __clarigen_core = require("@clarigen/core");
|
|
4
|
+
let fs_promises = require("fs/promises");
|
|
5
|
+
let arktype = require("arktype");
|
|
6
|
+
let clipanion = require("clipanion");
|
|
7
|
+
let __stacks_clarinet_sdk = require("@stacks/clarinet-sdk");
|
|
8
|
+
let chokidar = require("chokidar");
|
|
9
|
+
chokidar = require_esm.__toESM(chokidar);
|
|
10
|
+
let node_path = require("node:path");
|
|
11
|
+
|
|
12
|
+
//#region src/commands/base-command.ts
|
|
13
|
+
var BaseCommand = class extends clipanion.Command {
|
|
14
|
+
verbose = clipanion.Option.Boolean("-v,--verbose", false, { description: "Enable verbose logging" });
|
|
15
|
+
preexecute() {
|
|
16
|
+
if (this.verbose) require_esm.logger.level = "debug";
|
|
17
|
+
}
|
|
18
|
+
async catch(error) {
|
|
19
|
+
if (error instanceof arktype.type.errors) {
|
|
20
|
+
require_esm.logger.error("Your configuration file is invalid.", error.summary);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
require_esm.logger.error(error);
|
|
24
|
+
if (error instanceof Error) require_esm.logger.error(error.stack);
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
16
27
|
};
|
|
17
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
-
mod
|
|
24
|
-
));
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// src/commands/session-info.ts
|
|
30
|
-
var import_clipanion2 = require("clipanion");
|
|
31
|
-
|
|
32
|
-
// src/config.ts
|
|
33
|
-
var import_arktype2 = require("arktype");
|
|
34
|
-
|
|
35
|
-
// src/logger.ts
|
|
36
|
-
var import_pino = require("pino");
|
|
37
|
-
var import_pino_pretty = __toESM(require("pino-pretty"), 1);
|
|
38
|
-
var colorizedClarigen = `\x1B[33m[Clarigen]\x1B[0m`;
|
|
39
|
-
var logger = (0, import_pino.pino)(
|
|
40
|
-
(0, import_pino_pretty.default)({
|
|
41
|
-
colorize: true,
|
|
42
|
-
ignore: "pid,hostname,time",
|
|
43
|
-
messageFormat: `${colorizedClarigen} {msg}`,
|
|
44
|
-
minimumLevel: "debug"
|
|
45
|
-
})
|
|
46
|
-
);
|
|
47
|
-
logger.level = "info";
|
|
48
|
-
var log = logger;
|
|
49
|
-
|
|
50
|
-
// src/utils.ts
|
|
51
|
-
var import_core = require("@clarigen/core");
|
|
52
|
-
var import_promises = require("fs/promises");
|
|
53
|
-
var import_path = require("path");
|
|
54
|
-
function encodeVariableName(name) {
|
|
55
|
-
if (/^[A-Z\-_]*$/.test(name)) return name.replaceAll("-", "_");
|
|
56
|
-
return (0, import_core.toCamelCase)(name);
|
|
57
|
-
}
|
|
58
|
-
async function fileExists(filename) {
|
|
59
|
-
try {
|
|
60
|
-
await (0, import_promises.stat)(filename);
|
|
61
|
-
return true;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async function writeFile(path, contents) {
|
|
67
|
-
const dir = (0, import_path.dirname)(path);
|
|
68
|
-
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
69
|
-
await (0, import_promises.writeFile)(path, contents, "utf-8");
|
|
70
|
-
return path;
|
|
71
|
-
}
|
|
72
|
-
function sortContracts(contracts) {
|
|
73
|
-
const nameSorted = [...contracts].sort((a, b) => {
|
|
74
|
-
if ((0, import_core.getContractName)(a.contract_id, false) < (0, import_core.getContractName)(b.contract_id, false)) {
|
|
75
|
-
return -1;
|
|
76
|
-
}
|
|
77
|
-
return 1;
|
|
78
|
-
});
|
|
79
|
-
return nameSorted;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// src/clarinet-config.ts
|
|
83
|
-
var import_arktype = require("arktype");
|
|
84
|
-
var import_promises2 = require("fs/promises");
|
|
85
|
-
var import_toml = require("@iarna/toml");
|
|
86
|
-
var ClarinetConfig = (0, import_arktype.type)({
|
|
87
|
-
project: (0, import_arktype.type)({
|
|
88
|
-
requirements: (0, import_arktype.type)({
|
|
89
|
-
contract_id: (0, import_arktype.type)("string").describe("Contract ID")
|
|
90
|
-
}).array().describe("Project requirements").optional(),
|
|
91
|
-
cache_location: (0, import_arktype.type)({
|
|
92
|
-
path: (0, import_arktype.type)("string").describe("Cache location path")
|
|
93
|
-
}).optional()
|
|
94
|
-
}),
|
|
95
|
-
contracts: (0, import_arktype.type)({
|
|
96
|
-
"[string]": (0, import_arktype.type)({
|
|
97
|
-
path: (0, import_arktype.type)("string").describe("Contract path")
|
|
98
|
-
})
|
|
99
|
-
}).optional()
|
|
100
|
-
});
|
|
101
|
-
async function getClarinetConfig(path) {
|
|
102
|
-
const file = await (0, import_promises2.readFile)(path, "utf-8");
|
|
103
|
-
const config = ClarinetConfig.assert((0, import_toml.parse)(file));
|
|
104
|
-
return config;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// src/config.ts
|
|
108
|
-
var import_path2 = require("path");
|
|
109
|
-
var import_toml2 = require("@iarna/toml");
|
|
110
|
-
var import_promises3 = require("fs/promises");
|
|
111
|
-
var CONFIG_FILE = "Clarigen.toml";
|
|
112
|
-
var typesSchema = (0, import_arktype2.type)({
|
|
113
|
-
"output?": (0, import_arktype2.type)("string").describe("Path to the output file"),
|
|
114
|
-
"outputs?": (0, import_arktype2.type)("string[]").describe("Paths to the output files"),
|
|
115
|
-
"include_accounts?": (0, import_arktype2.type)("boolean").describe("Include accounts in the output"),
|
|
116
|
-
"after?": (0, import_arktype2.type)("string").describe("Script to run after the output is generated"),
|
|
117
|
-
"include_boot_contracts?": (0, import_arktype2.type)("boolean").describe("Include boot contracts in the output"),
|
|
118
|
-
"watch_folders?": (0, import_arktype2.type)("string[]").describe("Folders to watch for changes")
|
|
119
|
-
}).optional();
|
|
120
|
-
var ConfigFile = (0, import_arktype2.type)({
|
|
121
|
-
clarinet: (0, import_arktype2.type)("string").describe("Path to the Clarinet config file"),
|
|
122
|
-
["types" /* ESM */]: typesSchema,
|
|
123
|
-
["esm" /* ESM_OLD */]: typesSchema,
|
|
124
|
-
["docs" /* Docs */]: (0, import_arktype2.type)({
|
|
125
|
-
"output?": (0, import_arktype2.type)("string").describe("Path to docs output folder. Defaults to ./docs"),
|
|
126
|
-
"outputs?": (0, import_arktype2.type)("string[]").describe("Paths to docs output folders"),
|
|
127
|
-
"exclude?": (0, import_arktype2.type)("string[]").describe("Contracts to exclude from docs generation"),
|
|
128
|
-
"after?": (0, import_arktype2.type)("string").describe("Script to run after docs are generated")
|
|
129
|
-
}).optional()
|
|
130
|
-
});
|
|
131
|
-
var defaultConfigFile = {
|
|
132
|
-
clarinet: "./Clarinet.toml"
|
|
133
|
-
};
|
|
134
|
-
var Config = class {
|
|
135
|
-
configFile;
|
|
136
|
-
clarinet;
|
|
137
|
-
cwd;
|
|
138
|
-
constructor(config, clarinet, cwd) {
|
|
139
|
-
this.configFile = config;
|
|
140
|
-
this.clarinet = clarinet;
|
|
141
|
-
this.cwd = cwd ?? process.cwd();
|
|
142
|
-
}
|
|
143
|
-
static async load(cwd) {
|
|
144
|
-
const config = await getConfig(cwd);
|
|
145
|
-
if (config["esm" /* ESM_OLD */]) {
|
|
146
|
-
config["types" /* ESM */] = config["esm" /* ESM_OLD */];
|
|
147
|
-
delete config["esm" /* ESM_OLD */];
|
|
148
|
-
}
|
|
149
|
-
const clarinet = await getClarinetConfig((0, import_path2.resolve)(cwd ?? "", config.clarinet));
|
|
150
|
-
return new this(config, clarinet, cwd);
|
|
151
|
-
}
|
|
152
|
-
getOutputs(type4) {
|
|
153
|
-
var _a, _b;
|
|
154
|
-
const singlePath = (_a = this.configFile[type4]) == null ? void 0 : _a.output;
|
|
155
|
-
const multiPath = ((_b = this.configFile[type4]) == null ? void 0 : _b.outputs) || [];
|
|
156
|
-
if (singlePath !== void 0) return [singlePath];
|
|
157
|
-
return multiPath;
|
|
158
|
-
}
|
|
159
|
-
outputResolve(type4, filePath) {
|
|
160
|
-
const outputs = this.getOutputs(type4);
|
|
161
|
-
if (!this.supports(type4)) return null;
|
|
162
|
-
return outputs.map((path) => {
|
|
163
|
-
return (0, import_path2.resolve)(this.cwd, path, filePath || "");
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
async writeOutput(type4, contents, filePath) {
|
|
167
|
-
const paths = this.outputResolve(type4, filePath);
|
|
168
|
-
if (paths === null) return null;
|
|
169
|
-
await Promise.all(
|
|
170
|
-
paths.map(async (path) => {
|
|
171
|
-
await writeFile(path, contents);
|
|
172
|
-
log.debug(`Generated ${type4} file at ${(0, import_path2.relative)(this.cwd, path)}`);
|
|
173
|
-
})
|
|
174
|
-
);
|
|
175
|
-
return paths;
|
|
176
|
-
}
|
|
177
|
-
supports(type4) {
|
|
178
|
-
return this.getOutputs(type4).length > 0;
|
|
179
|
-
}
|
|
180
|
-
type(type4) {
|
|
181
|
-
return this.configFile[type4];
|
|
182
|
-
}
|
|
183
|
-
get esm() {
|
|
184
|
-
return this.configFile["types" /* ESM */];
|
|
185
|
-
}
|
|
186
|
-
get docs() {
|
|
187
|
-
return this.configFile["docs" /* Docs */];
|
|
188
|
-
}
|
|
189
|
-
clarinetFile() {
|
|
190
|
-
return (0, import_path2.resolve)(this.cwd, this.configFile.clarinet);
|
|
191
|
-
}
|
|
192
|
-
joinFromClarinet(filePath) {
|
|
193
|
-
const baseDir = (0, import_path2.dirname)(this.clarinetFile());
|
|
194
|
-
return (0, import_path2.join)(baseDir, filePath);
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
function configFilePath(cwd) {
|
|
198
|
-
return (0, import_path2.resolve)(cwd ?? process.cwd(), CONFIG_FILE);
|
|
199
|
-
}
|
|
200
|
-
var sessionConfig;
|
|
201
|
-
async function getConfig(cwd) {
|
|
202
|
-
if (typeof sessionConfig !== "undefined") return sessionConfig;
|
|
203
|
-
const path = configFilePath(cwd);
|
|
204
|
-
if (await fileExists(path)) {
|
|
205
|
-
const toml = await (0, import_promises3.readFile)(path, "utf-8");
|
|
206
|
-
const parsedToml = (0, import_toml2.parse)(toml);
|
|
207
|
-
const parsed = ConfigFile(parsedToml);
|
|
208
|
-
if (parsed instanceof import_arktype2.type.errors) {
|
|
209
|
-
logger.error(`Error parsing Clarigen config: ${parsed.summary}`);
|
|
210
|
-
throw new Error(`Error parsing Clarigen config: ${parsed.summary}`);
|
|
211
|
-
}
|
|
212
|
-
sessionConfig = parsed;
|
|
213
|
-
} else {
|
|
214
|
-
sessionConfig = defaultConfigFile;
|
|
215
|
-
}
|
|
216
|
-
return sessionConfig;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// src/commands/base-command.ts
|
|
220
|
-
var import_clipanion = require("clipanion");
|
|
221
|
-
var import_arktype3 = require("arktype");
|
|
222
|
-
var BaseCommand = class extends import_clipanion.Command {
|
|
223
|
-
verbose = import_clipanion.Option.Boolean("-v,--verbose", false, {
|
|
224
|
-
description: "Enable verbose logging"
|
|
225
|
-
});
|
|
226
|
-
preexecute() {
|
|
227
|
-
if (this.verbose) {
|
|
228
|
-
logger.level = "debug";
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
232
|
-
async catch(error) {
|
|
233
|
-
if (error instanceof import_arktype3.type.errors) {
|
|
234
|
-
logger.error("Your configuration file is invalid.", error.summary);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
logger.error(error);
|
|
238
|
-
if (error instanceof Error) {
|
|
239
|
-
logger.error(error.stack);
|
|
240
|
-
}
|
|
241
|
-
throw error;
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
// src/commands/session-info.ts
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/commands/session-info.ts
|
|
246
31
|
var SessionInfoCommand = class extends BaseCommand {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
logger.info(config);
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
// src/commands/default-command.ts
|
|
260
|
-
var import_clipanion3 = require("clipanion");
|
|
261
|
-
|
|
262
|
-
// src/clarinet-sdk.ts
|
|
263
|
-
var import_clarinet_sdk = require("@stacks/clarinet-sdk");
|
|
264
|
-
var import_core7 = require("@clarigen/core");
|
|
265
|
-
var import_promises4 = require("fs/promises");
|
|
266
|
-
|
|
267
|
-
// src/files/variables.ts
|
|
268
|
-
var import_core6 = require("@clarigen/core");
|
|
269
|
-
|
|
270
|
-
// src/declaration.ts
|
|
271
|
-
var import_core2 = require("@clarigen/core");
|
|
272
|
-
var import_core3 = require("@clarigen/core");
|
|
273
|
-
var jsTypeFromAbiType = (val, isArgument = false) => {
|
|
274
|
-
if ((0, import_core2.isClarityAbiPrimitive)(val)) {
|
|
275
|
-
if (val === "uint128") {
|
|
276
|
-
if (isArgument) return "number | bigint";
|
|
277
|
-
return "bigint";
|
|
278
|
-
} else if (val === "int128") {
|
|
279
|
-
if (isArgument) return "number | bigint";
|
|
280
|
-
return "bigint";
|
|
281
|
-
} else if (val === "bool") {
|
|
282
|
-
return "boolean";
|
|
283
|
-
} else if (val === "principal") {
|
|
284
|
-
return "string";
|
|
285
|
-
} else if (val === "none") {
|
|
286
|
-
return "null";
|
|
287
|
-
} else if (val === "trait_reference") {
|
|
288
|
-
return "string";
|
|
289
|
-
} else {
|
|
290
|
-
throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(val)}`);
|
|
291
|
-
}
|
|
292
|
-
} else if ((0, import_core2.isClarityAbiBuffer)(val)) {
|
|
293
|
-
return "Uint8Array";
|
|
294
|
-
} else if ((0, import_core2.isClarityAbiResponse)(val)) {
|
|
295
|
-
const ok = jsTypeFromAbiType(val.response.ok, isArgument);
|
|
296
|
-
const err = jsTypeFromAbiType(val.response.error, isArgument);
|
|
297
|
-
return `Response<${ok}, ${err}>`;
|
|
298
|
-
} else if ((0, import_core2.isClarityAbiOptional)(val)) {
|
|
299
|
-
const innerType = jsTypeFromAbiType(val.optional, isArgument);
|
|
300
|
-
return `${innerType} | null`;
|
|
301
|
-
} else if ((0, import_core2.isClarityAbiTuple)(val)) {
|
|
302
|
-
const tupleDefs = [];
|
|
303
|
-
val.tuple.forEach(({ name, type: type4 }) => {
|
|
304
|
-
const camelName = (0, import_core3.toCamelCase)(name);
|
|
305
|
-
const innerType = jsTypeFromAbiType(type4, isArgument);
|
|
306
|
-
tupleDefs.push(`"${camelName}": ${innerType};`);
|
|
307
|
-
});
|
|
308
|
-
return `{
|
|
309
|
-
${tupleDefs.join("\n ")}
|
|
310
|
-
}`;
|
|
311
|
-
} else if ((0, import_core2.isClarityAbiList)(val)) {
|
|
312
|
-
const innerType = jsTypeFromAbiType(val.list.type, isArgument);
|
|
313
|
-
return `${innerType}[]`;
|
|
314
|
-
} else if ((0, import_core2.isClarityAbiStringAscii)(val)) {
|
|
315
|
-
return "string";
|
|
316
|
-
} else if ((0, import_core2.isClarityAbiStringUtf8)(val)) {
|
|
317
|
-
return "string";
|
|
318
|
-
} else if ((0, import_core2.isClarityAbiTraitReference)(val)) {
|
|
319
|
-
return "string";
|
|
320
|
-
} else {
|
|
321
|
-
throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(val)}`);
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
function abiArgType(arg) {
|
|
325
|
-
const nativeType = jsTypeFromAbiType(arg.type, true);
|
|
326
|
-
const argName = getArgName(arg.name);
|
|
327
|
-
return `${argName}: TypedAbiArg<${nativeType}, "${argName}">`;
|
|
328
|
-
}
|
|
329
|
-
function abiFunctionType(abiFunction) {
|
|
330
|
-
const args2 = abiFunction.args.map(abiArgType);
|
|
331
|
-
const retType = jsTypeFromAbiType(abiFunction.outputs.type);
|
|
332
|
-
const argsTuple = `[${args2.join(", ")}]`;
|
|
333
|
-
return `TypedAbiFunction<${argsTuple}, ${retType}>`;
|
|
334
|
-
}
|
|
335
|
-
function getArgName(name) {
|
|
336
|
-
const camel = (0, import_core3.toCamelCase)(name);
|
|
337
|
-
const prefix = RESERVED[camel] ? "_" : "";
|
|
338
|
-
return `${prefix}${camel}`;
|
|
339
|
-
}
|
|
340
|
-
function _hash(...words) {
|
|
341
|
-
const h = {};
|
|
342
|
-
for (const word of words) {
|
|
343
|
-
h[word] = true;
|
|
344
|
-
}
|
|
345
|
-
return h;
|
|
346
|
-
}
|
|
347
|
-
var RESERVED = _hash(
|
|
348
|
-
// Keywords, ES6 11.6.2.1, http://www.ecma-international.org/ecma-262/6.0/index.html#sec-keywords
|
|
349
|
-
"break",
|
|
350
|
-
"do",
|
|
351
|
-
"in",
|
|
352
|
-
"typeof",
|
|
353
|
-
"case",
|
|
354
|
-
"else",
|
|
355
|
-
"instanceof",
|
|
356
|
-
"var",
|
|
357
|
-
"catch",
|
|
358
|
-
"export",
|
|
359
|
-
"new",
|
|
360
|
-
"void",
|
|
361
|
-
"class",
|
|
362
|
-
"extends",
|
|
363
|
-
"return",
|
|
364
|
-
"while",
|
|
365
|
-
"const",
|
|
366
|
-
"finally",
|
|
367
|
-
"super",
|
|
368
|
-
"with",
|
|
369
|
-
"continue",
|
|
370
|
-
"for",
|
|
371
|
-
"switch",
|
|
372
|
-
"yield",
|
|
373
|
-
"debugger",
|
|
374
|
-
"function",
|
|
375
|
-
"this",
|
|
376
|
-
"default",
|
|
377
|
-
"if",
|
|
378
|
-
"throw",
|
|
379
|
-
"delete",
|
|
380
|
-
"import",
|
|
381
|
-
"try",
|
|
382
|
-
// Future Reserved Words, ES6 11.6.2.2
|
|
383
|
-
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-future-reserved-words
|
|
384
|
-
"enum",
|
|
385
|
-
"await",
|
|
386
|
-
// NullLiteral & BooleanLiteral
|
|
387
|
-
"null",
|
|
388
|
-
"true",
|
|
389
|
-
"false"
|
|
390
|
-
);
|
|
391
|
-
|
|
392
|
-
// src/files/base.ts
|
|
393
|
-
var import_core5 = require("@clarigen/core");
|
|
394
|
-
|
|
395
|
-
// src/files/accounts.ts
|
|
396
|
-
function generateAccountsCode(accounts) {
|
|
397
|
-
const sortedAccounts = sortAccounts(accounts);
|
|
398
|
-
const namedAccounts = Object.fromEntries(
|
|
399
|
-
sortedAccounts.map((a) => {
|
|
400
|
-
const { name, ...rest } = a;
|
|
401
|
-
return [name, rest];
|
|
402
|
-
})
|
|
403
|
-
);
|
|
404
|
-
return JSON.stringify(namedAccounts);
|
|
405
|
-
}
|
|
406
|
-
function sortAccounts(accounts) {
|
|
407
|
-
const nameSorted = [...accounts].sort((a, b) => {
|
|
408
|
-
if (a.name < b.name) {
|
|
409
|
-
return -1;
|
|
410
|
-
}
|
|
411
|
-
return 1;
|
|
412
|
-
});
|
|
413
|
-
return nameSorted;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// src/files/identifiers.ts
|
|
417
|
-
var import_core4 = require("@clarigen/core");
|
|
418
|
-
function generateIdentifiers(session) {
|
|
419
|
-
const identifiers = Object.fromEntries(
|
|
420
|
-
sortContracts(session.contracts).map((c) => {
|
|
421
|
-
const contractName = (0, import_core4.getContractName)(c.contract_id);
|
|
422
|
-
return [contractName, c.contract_id];
|
|
423
|
-
})
|
|
424
|
-
);
|
|
425
|
-
return identifiers;
|
|
426
|
-
}
|
|
427
|
-
function generateIdentifiersCode(session) {
|
|
428
|
-
const identifiers = generateIdentifiers(session);
|
|
429
|
-
return `export const identifiers = ${JSON.stringify(identifiers)} as const`;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// src/files/base.ts
|
|
433
|
-
var import_util = require("util");
|
|
434
|
-
function generateContractMeta(contract, constants) {
|
|
435
|
-
const abi = contract.contract_interface;
|
|
436
|
-
const functionLines = [];
|
|
437
|
-
const { functions, maps, variables, non_fungible_tokens, ...rest } = abi;
|
|
438
|
-
functions.forEach((func) => {
|
|
439
|
-
let functionLine = `${(0, import_core5.toCamelCase)(func.name)}: `;
|
|
440
|
-
const funcDef = JSON.stringify(func);
|
|
441
|
-
functionLine += funcDef;
|
|
442
|
-
const functionType = abiFunctionType(func);
|
|
443
|
-
functionLine += ` as ${functionType}`;
|
|
444
|
-
functionLines.push(functionLine);
|
|
445
|
-
});
|
|
446
|
-
const mapLines = maps.map((map) => {
|
|
447
|
-
let mapLine = `${(0, import_core5.toCamelCase)(map.name)}: `;
|
|
448
|
-
const keyType = jsTypeFromAbiType(map.key, true);
|
|
449
|
-
const valType = jsTypeFromAbiType(map.value);
|
|
450
|
-
mapLine += JSON.stringify(map);
|
|
451
|
-
mapLine += ` as TypedAbiMap<${keyType}, ${valType}>`;
|
|
452
|
-
return mapLine;
|
|
453
|
-
});
|
|
454
|
-
const otherAbi = JSON.stringify(rest);
|
|
455
|
-
const contractName = contract.contract_id.split(".")[1];
|
|
456
|
-
const variableLines = encodeVariables(variables);
|
|
457
|
-
const nftLines = non_fungible_tokens.map((nft) => {
|
|
458
|
-
return JSON.stringify(nft);
|
|
459
|
-
});
|
|
460
|
-
return `{
|
|
461
|
-
${serializeLines("functions", functionLines)}
|
|
462
|
-
${serializeLines("maps", mapLines)}
|
|
463
|
-
${serializeLines("variables", variableLines)}
|
|
464
|
-
constants: ${constants},
|
|
465
|
-
${serializeArray("non_fungible_tokens", nftLines)}
|
|
466
|
-
${otherAbi.slice(1, -1)},
|
|
467
|
-
contractName: '${contractName}',
|
|
468
|
-
}`;
|
|
469
|
-
}
|
|
470
|
-
var TYPE_IMPORTS = `import type { TypedAbiArg, TypedAbiFunction, TypedAbiMap, TypedAbiVariable, Response } from '@clarigen/core';`;
|
|
471
|
-
function generateBaseFile(session) {
|
|
472
|
-
const combined = session.contracts.map((c, i) => ({
|
|
473
|
-
...c,
|
|
474
|
-
constants: session.variables[i]
|
|
475
|
-
}));
|
|
476
|
-
const contractDefs = sortContracts(combined).map((contract) => {
|
|
477
|
-
const meta = generateContractMeta(contract, contract.constants);
|
|
478
|
-
const id = contract.contract_id.split(".")[1];
|
|
479
|
-
const keyName = (0, import_core5.toCamelCase)(id);
|
|
480
|
-
return `${keyName}: ${meta}`;
|
|
481
|
-
});
|
|
482
|
-
const file = `
|
|
483
|
-
${TYPE_IMPORTS}
|
|
484
|
-
|
|
485
|
-
export const contracts = {
|
|
486
|
-
${contractDefs.join(",\n")}
|
|
487
|
-
} as const;
|
|
488
|
-
|
|
489
|
-
export const accounts = ${generateAccountsCode(session.accounts)} as const;
|
|
490
|
-
|
|
491
|
-
${generateIdentifiersCode(session)}
|
|
492
|
-
|
|
493
|
-
export const simnet = {
|
|
494
|
-
accounts,
|
|
495
|
-
contracts,
|
|
496
|
-
identifiers,
|
|
497
|
-
} as const;
|
|
498
|
-
|
|
499
|
-
`;
|
|
500
|
-
return file;
|
|
501
|
-
}
|
|
502
|
-
function encodeVariables(variables) {
|
|
503
|
-
return variables.map((v) => {
|
|
504
|
-
let varLine = `${encodeVariableName(v.name)}: `;
|
|
505
|
-
const type4 = jsTypeFromAbiType(v.type);
|
|
506
|
-
const varJSON = serialize(v);
|
|
507
|
-
varLine += `${varJSON} as TypedAbiVariable<${type4}>`;
|
|
508
|
-
return varLine;
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
Uint8Array.prototype[import_util.inspect.custom] = function(depth, options) {
|
|
512
|
-
return `Uint8Array.from([${this.join(",")}])`;
|
|
32
|
+
static paths = [["session-info"]];
|
|
33
|
+
static usage = clipanion.Command.Usage({ description: "Log info about this project's Clarinet session" });
|
|
34
|
+
cwd = clipanion.Option.String({ required: false });
|
|
35
|
+
async execute() {
|
|
36
|
+
this.preexecute();
|
|
37
|
+
const config = await require_esm.Config.load(this.cwd);
|
|
38
|
+
require_esm.logger.info(config);
|
|
39
|
+
}
|
|
513
40
|
};
|
|
514
|
-
function serialize(obj) {
|
|
515
|
-
return (0, import_util.inspect)(obj, {
|
|
516
|
-
// showHidden: false,
|
|
517
|
-
// depth: 100,
|
|
518
|
-
// colors: false,
|
|
519
|
-
showHidden: false,
|
|
520
|
-
// iterableLimit: 100000,
|
|
521
|
-
compact: false,
|
|
522
|
-
// trailingComma: true,
|
|
523
|
-
depth: 100,
|
|
524
|
-
colors: false,
|
|
525
|
-
maxArrayLength: Infinity,
|
|
526
|
-
maxStringLength: Infinity,
|
|
527
|
-
breakLength: Infinity,
|
|
528
|
-
numericSeparator: true
|
|
529
|
-
// strAbbreviateSize: 100000,
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
function serializeLines(key, lines) {
|
|
533
|
-
return `"${key}": {
|
|
534
|
-
${lines.join(",\n ")}
|
|
535
|
-
},`;
|
|
536
|
-
}
|
|
537
|
-
function serializeArray(key, lines) {
|
|
538
|
-
return `"${key}": [
|
|
539
|
-
${lines.join(",\n ")}
|
|
540
|
-
],`;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// src/files/variables.ts
|
|
544
|
-
function clarityVersionForContract(contract) {
|
|
545
|
-
switch (contract.contract_interface.clarity_version) {
|
|
546
|
-
case "Clarity1":
|
|
547
|
-
return 1;
|
|
548
|
-
case "Clarity2":
|
|
549
|
-
return 2;
|
|
550
|
-
case "Clarity3":
|
|
551
|
-
return 3;
|
|
552
|
-
case "Clarity4":
|
|
553
|
-
return 4;
|
|
554
|
-
default:
|
|
555
|
-
return 3;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
function getVariablesV2(contract, simnet, verbose) {
|
|
559
|
-
const [deployer] = contract.contract_id.split(".");
|
|
560
|
-
const fakeId = `${(0, import_core6.getContractName)(contract.contract_id)}-vars`;
|
|
561
|
-
logger.debug(`Deploying ${contract.contract_id} for variables.`);
|
|
562
|
-
if (!contract.source) {
|
|
563
|
-
logger.debug(
|
|
564
|
-
`Contract ${(0, import_core6.getContractName)(contract.contract_id)} has no source. Skipping variables.`
|
|
565
|
-
);
|
|
566
|
-
return {};
|
|
567
|
-
}
|
|
568
|
-
if (contract.contract_interface.variables.length === 0) {
|
|
569
|
-
logger.info(`Contract ${(0, import_core6.getContractName)(contract.contract_id, false)} has no variables`);
|
|
570
|
-
return {};
|
|
571
|
-
}
|
|
572
|
-
let varFn = `{
|
|
573
|
-
`;
|
|
574
|
-
const varLines = contract.contract_interface.variables.map((variable) => {
|
|
575
|
-
let varLine = `${variable.name}: `;
|
|
576
|
-
if (variable.access === "constant") {
|
|
577
|
-
varLine += `${variable.name}`;
|
|
578
|
-
} else {
|
|
579
|
-
varLine += `(var-get ${variable.name})`;
|
|
580
|
-
}
|
|
581
|
-
return varLine;
|
|
582
|
-
});
|
|
583
|
-
varFn += varLines.map((l) => ` ${l},`).join("\n");
|
|
584
|
-
varFn += "\n}";
|
|
585
|
-
const fullSrc = contract.source + `
|
|
586
|
-
|
|
587
|
-
${varFn}`;
|
|
588
|
-
try {
|
|
589
|
-
const receipt = simnet.deployContract(
|
|
590
|
-
fakeId,
|
|
591
|
-
fullSrc,
|
|
592
|
-
{
|
|
593
|
-
clarityVersion: clarityVersionForContract(contract)
|
|
594
|
-
},
|
|
595
|
-
deployer
|
|
596
|
-
);
|
|
597
|
-
const result = receipt.result;
|
|
598
|
-
const varsAbi = {
|
|
599
|
-
tuple: []
|
|
600
|
-
};
|
|
601
|
-
contract.contract_interface.variables.forEach((v) => {
|
|
602
|
-
const _v = v;
|
|
603
|
-
varsAbi.tuple.push({
|
|
604
|
-
type: _v.type,
|
|
605
|
-
name: _v.name
|
|
606
|
-
});
|
|
607
|
-
});
|
|
608
|
-
if (verbose) {
|
|
609
|
-
logger.info((0, import_core6.cvToValue)(result, true));
|
|
610
|
-
}
|
|
611
|
-
return (0, import_core6.cvToValue)(result, true);
|
|
612
|
-
} catch (error) {
|
|
613
|
-
logger.warn(
|
|
614
|
-
{ err: error },
|
|
615
|
-
`Error getting variables for ${(0, import_core6.getContractName)(contract.contract_id, false)}`
|
|
616
|
-
);
|
|
617
|
-
return {};
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
function mapVariables(session, simnet) {
|
|
621
|
-
return session.contracts.map((contract) => {
|
|
622
|
-
const vars = getVariablesV2(contract, simnet);
|
|
623
|
-
return serialize(vars);
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
41
|
|
|
627
|
-
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/clarinet-sdk.ts
|
|
628
44
|
async function getSession(config) {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
contracts
|
|
672
|
-
};
|
|
673
|
-
const variables = mapVariables(session, simnet);
|
|
674
|
-
return {
|
|
675
|
-
session_id: 0,
|
|
676
|
-
accounts: allAccounts,
|
|
677
|
-
contracts,
|
|
678
|
-
variables
|
|
679
|
-
// variables: [],
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
// src/files/esm.ts
|
|
684
|
-
var import_promises5 = require("fs/promises");
|
|
685
|
-
var import_path3 = require("path");
|
|
686
|
-
var import_yaml = require("yaml");
|
|
687
|
-
|
|
688
|
-
// src/deployments.ts
|
|
689
|
-
function flatBatch(batches) {
|
|
690
|
-
const txs = [];
|
|
691
|
-
batches.forEach((batch) => txs.push(...batch.transactions));
|
|
692
|
-
return txs;
|
|
693
|
-
}
|
|
694
|
-
function getContractTxs(batches) {
|
|
695
|
-
const txs = flatBatch(batches);
|
|
696
|
-
return txs.filter(isContractTx);
|
|
697
|
-
}
|
|
698
|
-
function getDeploymentContract(contractName, deployment) {
|
|
699
|
-
const txs = flatBatch(deployment.plan.batches);
|
|
700
|
-
for (const tx of txs) {
|
|
701
|
-
if (!isContractTx(tx)) continue;
|
|
702
|
-
if ("requirement-publish" in tx) {
|
|
703
|
-
const [_, name] = tx["requirement-publish"]["contract-id"].split(".");
|
|
704
|
-
if (name === contractName) {
|
|
705
|
-
return tx;
|
|
706
|
-
}
|
|
707
|
-
} else if ("emulated-contract-publish" in tx) {
|
|
708
|
-
if (tx["emulated-contract-publish"]["contract-name"] === contractName) {
|
|
709
|
-
return tx;
|
|
710
|
-
}
|
|
711
|
-
} else if ("contract-publish" in tx) {
|
|
712
|
-
const contract = tx["contract-publish"];
|
|
713
|
-
if (contract["contract-name"] === contractName) {
|
|
714
|
-
return tx;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
throw new Error(`Unable to find deployment tx for contract '${contractName}'`);
|
|
719
|
-
}
|
|
720
|
-
function getDeploymentTxPath(tx) {
|
|
721
|
-
if (!isContractTx(tx)) {
|
|
722
|
-
throw new Error("Unable to get path for tx type.");
|
|
723
|
-
}
|
|
724
|
-
if ("requirement-publish" in tx) {
|
|
725
|
-
return tx["requirement-publish"].path;
|
|
726
|
-
} else if ("emulated-contract-publish" in tx) {
|
|
727
|
-
const contract = tx["emulated-contract-publish"];
|
|
728
|
-
return contract.path;
|
|
729
|
-
} else if ("contract-publish" in tx) {
|
|
730
|
-
const contract = tx["contract-publish"];
|
|
731
|
-
return contract.path;
|
|
732
|
-
}
|
|
733
|
-
throw new Error("Couldnt get path for deployment tx.");
|
|
734
|
-
}
|
|
735
|
-
function getIdentifier(tx) {
|
|
736
|
-
if (!isContractTx(tx)) {
|
|
737
|
-
throw new Error("Unable to get ID for tx type.");
|
|
738
|
-
}
|
|
739
|
-
if ("requirement-publish" in tx) {
|
|
740
|
-
const spec = tx["requirement-publish"];
|
|
741
|
-
const [_, name] = spec["contract-id"].split(".");
|
|
742
|
-
return `${spec["remap-sender"]}.${name}`;
|
|
743
|
-
} else if ("emulated-contract-publish" in tx) {
|
|
744
|
-
const contract = tx["emulated-contract-publish"];
|
|
745
|
-
return `${contract["emulated-sender"]}.${contract["contract-name"]}`;
|
|
746
|
-
} else if ("contract-publish" in tx) {
|
|
747
|
-
const contract = tx["contract-publish"];
|
|
748
|
-
return `${contract["expected-sender"]}.${contract["contract-name"]}`;
|
|
749
|
-
}
|
|
750
|
-
throw new Error(`Unable to find ID for contract.`);
|
|
751
|
-
}
|
|
752
|
-
function isContractTx(tx) {
|
|
753
|
-
if ("contract-call" in tx) return false;
|
|
754
|
-
if ("btc-transfer" in tx) return false;
|
|
755
|
-
if ("emulated-contract-call" in tx) return false;
|
|
756
|
-
return true;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
// src/files/esm.ts
|
|
760
|
-
var import_core8 = require("@clarigen/core");
|
|
761
|
-
var import_child_process = require("child_process");
|
|
762
|
-
async function parseDeployment(path) {
|
|
763
|
-
const contents = await (0, import_promises5.readFile)(path, "utf-8");
|
|
764
|
-
const parsed = (0, import_yaml.parse)(contents);
|
|
765
|
-
return parsed;
|
|
766
|
-
}
|
|
767
|
-
var DEPLOYMENT_NETWORKS = ["devnet", "simnet", "testnet", "mainnet"];
|
|
768
|
-
async function getDeployments(config) {
|
|
769
|
-
const entries = await Promise.all(
|
|
770
|
-
DEPLOYMENT_NETWORKS.map(async (network) => {
|
|
771
|
-
const file = `default.${network}-plan.yaml`;
|
|
772
|
-
const path = (0, import_path3.join)((0, import_path3.dirname)(config.clarinetFile()), "deployments", file);
|
|
773
|
-
let plan;
|
|
774
|
-
try {
|
|
775
|
-
plan = await parseDeployment(path);
|
|
776
|
-
} catch (_) {
|
|
777
|
-
}
|
|
778
|
-
return [network, plan];
|
|
779
|
-
})
|
|
780
|
-
);
|
|
781
|
-
return Object.fromEntries(entries);
|
|
782
|
-
}
|
|
783
|
-
async function generateESMFile({
|
|
784
|
-
baseFile,
|
|
785
|
-
session,
|
|
786
|
-
config
|
|
787
|
-
}) {
|
|
788
|
-
const deployments = await getDeployments(config);
|
|
789
|
-
const contractDeployments = collectContractDeployments(session, deployments, config);
|
|
790
|
-
const simnet = generateSimnetCode(config, deployments, session);
|
|
791
|
-
return `${baseFile}
|
|
792
|
-
export const deployments = ${JSON.stringify(contractDeployments)} as const;
|
|
793
|
-
${simnet}
|
|
794
|
-
export const project = {
|
|
795
|
-
contracts,
|
|
796
|
-
deployments,
|
|
797
|
-
} as const;
|
|
798
|
-
`;
|
|
799
|
-
}
|
|
800
|
-
function insertNetworkId(deployments, identifier, network) {
|
|
801
|
-
const name = (0, import_core8.getContractName)(identifier);
|
|
802
|
-
if (!deployments[name]) {
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
if (deployments[name][network] === null) {
|
|
806
|
-
deployments[name][network] = identifier;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
function collectContractDeployments(session, deployments, config) {
|
|
810
|
-
var _a;
|
|
811
|
-
const full = Object.fromEntries(
|
|
812
|
-
sortContracts(session.contracts).map((contract) => {
|
|
813
|
-
const contractName = (0, import_core8.getContractName)(contract.contract_id);
|
|
814
|
-
const contractDeployments = Object.fromEntries(
|
|
815
|
-
DEPLOYMENT_NETWORKS.map((network) => {
|
|
816
|
-
const deployment = deployments[network];
|
|
817
|
-
if (typeof deployment === "undefined") {
|
|
818
|
-
return [network, null];
|
|
819
|
-
}
|
|
820
|
-
try {
|
|
821
|
-
const contractName2 = contract.contract_id.split(".")[1];
|
|
822
|
-
const tx = getDeploymentContract(contractName2, deployment);
|
|
823
|
-
const id = getIdentifier(tx);
|
|
824
|
-
return [network, id];
|
|
825
|
-
} catch (_) {
|
|
826
|
-
return [network, null];
|
|
827
|
-
}
|
|
828
|
-
})
|
|
829
|
-
);
|
|
830
|
-
return [contractName, contractDeployments];
|
|
831
|
-
})
|
|
832
|
-
);
|
|
833
|
-
const deployer = session.accounts.find((a) => a.name === "deployer");
|
|
834
|
-
(_a = config.clarinet.project.requirements) == null ? void 0 : _a.forEach(({ contract_id }) => {
|
|
835
|
-
insertNetworkId(full, contract_id, "mainnet");
|
|
836
|
-
const contractName = contract_id.split(".")[1];
|
|
837
|
-
if (deployer) {
|
|
838
|
-
const devnetId = `${deployer.address}.${contractName}`;
|
|
839
|
-
insertNetworkId(full, devnetId, "devnet");
|
|
840
|
-
}
|
|
841
|
-
});
|
|
842
|
-
session.contracts.forEach((contract) => {
|
|
843
|
-
insertNetworkId(full, contract.contract_id, "devnet");
|
|
844
|
-
insertNetworkId(full, contract.contract_id, "simnet");
|
|
845
|
-
});
|
|
846
|
-
return full;
|
|
847
|
-
}
|
|
848
|
-
function collectDeploymentFiles(deployments, clarinetFolder, cwd) {
|
|
849
|
-
if (!deployments.simnet) return [];
|
|
850
|
-
const simnet = deployments.simnet;
|
|
851
|
-
const txs = getContractTxs(simnet.plan.batches);
|
|
852
|
-
const entries = txs.map((tx) => {
|
|
853
|
-
const id = getIdentifier(tx);
|
|
854
|
-
const contractFile = getDeploymentTxPath(tx);
|
|
855
|
-
return {
|
|
856
|
-
identifier: id,
|
|
857
|
-
file: (0, import_path3.relative)(cwd, (0, import_path3.join)(clarinetFolder, contractFile))
|
|
858
|
-
};
|
|
859
|
-
});
|
|
860
|
-
return entries;
|
|
861
|
-
}
|
|
862
|
-
function generateSimnetCode(config, deployments, _session) {
|
|
863
|
-
var _a;
|
|
864
|
-
if (!((_a = config.esm) == null ? void 0 : _a.include_accounts)) return "";
|
|
865
|
-
const clarinetFolder = (0, import_path3.dirname)(config.clarinetFile());
|
|
866
|
-
const files = collectDeploymentFiles(deployments, clarinetFolder, config.cwd);
|
|
867
|
-
return `
|
|
868
|
-
export const simnetDeployment = ${JSON.stringify(files)};
|
|
869
|
-
`;
|
|
870
|
-
}
|
|
871
|
-
async function afterESM(config) {
|
|
872
|
-
var _a;
|
|
873
|
-
const command = (_a = config.esm) == null ? void 0 : _a.after;
|
|
874
|
-
if (!command) return;
|
|
875
|
-
logger.debug(`Running after ESM command: ${command}`);
|
|
876
|
-
const parts = command.split(" ");
|
|
877
|
-
const [cmd, ...args2] = parts;
|
|
878
|
-
return new Promise((resolve3, reject) => {
|
|
879
|
-
const child = (0, import_child_process.spawn)(cmd, args2, {
|
|
880
|
-
cwd: config.cwd,
|
|
881
|
-
stdio: "inherit"
|
|
882
|
-
});
|
|
883
|
-
child.on("error", reject);
|
|
884
|
-
child.on("exit", (code) => {
|
|
885
|
-
if (code === 0) {
|
|
886
|
-
resolve3();
|
|
887
|
-
} else {
|
|
888
|
-
reject(new Error(`Command failed with code ${code ?? "unknown"}`));
|
|
889
|
-
}
|
|
890
|
-
});
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
// src/commands/default-command.ts
|
|
895
|
-
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
896
|
-
var import_node_path = require("path");
|
|
45
|
+
const simnet = await (0, __stacks_clarinet_sdk.initSimnet)(config.clarinetFile(), true);
|
|
46
|
+
const interfaces = simnet.getContractsInterfaces();
|
|
47
|
+
const allAccounts = [...simnet.getAccounts().entries()].map(([name, address]) => {
|
|
48
|
+
const resultCV = (0, __clarigen_core.hexToCvValue)(simnet.runSnippet(`(stx-get-balance '${address})`));
|
|
49
|
+
if (typeof resultCV !== "bigint") throw new Error(`Unexpected result type for \`(stx-get-balance \`, got ${resultCV}`);
|
|
50
|
+
return {
|
|
51
|
+
name,
|
|
52
|
+
address,
|
|
53
|
+
balance: resultCV.toString()
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
const contracts = (await Promise.all([...interfaces.entries()].map(async ([contract_id, contract_interface]) => {
|
|
57
|
+
var _config$esm, _config$clarinet$cont;
|
|
58
|
+
if (contract_id.startsWith(__clarigen_core.MAINNET_BURN_ADDRESS) && ((_config$esm = config.esm) === null || _config$esm === void 0 ? void 0 : _config$esm.include_boot_contracts) !== true || contract_id.startsWith(__clarigen_core.TESTNET_BURN_ADDRESS)) return;
|
|
59
|
+
const name = (0, __clarigen_core.getContractName)(contract_id, false);
|
|
60
|
+
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;
|
|
61
|
+
let source;
|
|
62
|
+
if (contractPathDef) source = await (0, fs_promises.readFile)(config.joinFromClarinet(contractPathDef), "utf-8");
|
|
63
|
+
return {
|
|
64
|
+
contract_id,
|
|
65
|
+
contract_interface: {
|
|
66
|
+
...contract_interface,
|
|
67
|
+
epoch: contract_interface.epoch,
|
|
68
|
+
clarity_version: contract_interface.clarity_version
|
|
69
|
+
},
|
|
70
|
+
source: source ?? ""
|
|
71
|
+
};
|
|
72
|
+
}))).filter((x) => x !== void 0);
|
|
73
|
+
return {
|
|
74
|
+
session_id: 0,
|
|
75
|
+
accounts: allAccounts,
|
|
76
|
+
contracts,
|
|
77
|
+
variables: require_esm.mapVariables({
|
|
78
|
+
session_id: 0,
|
|
79
|
+
accounts: allAccounts,
|
|
80
|
+
contracts
|
|
81
|
+
}, simnet)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/commands/default-command.ts
|
|
897
87
|
async function generate(config) {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
});
|
|
88
|
+
const session = await getSession(config);
|
|
89
|
+
const baseFile = require_esm.generateBaseFile(session);
|
|
90
|
+
if (config.supports(require_esm.OutputType.ESM)) {
|
|
91
|
+
const esmFile = await require_esm.generateESMFile({
|
|
92
|
+
baseFile,
|
|
93
|
+
session,
|
|
94
|
+
config
|
|
95
|
+
});
|
|
96
|
+
await config.writeOutput(require_esm.OutputType.ESM, esmFile);
|
|
97
|
+
await require_esm.afterESM(config);
|
|
98
|
+
}
|
|
99
|
+
if (!config.supports(require_esm.OutputType.ESM)) require_esm.logger.warn("no config for ESM outputs. Not outputting any generated types.");
|
|
100
|
+
require_esm.logger.info("Types generated!");
|
|
101
|
+
}
|
|
102
|
+
async function watch$1(config, cwd) {
|
|
103
|
+
return new Promise(async (resolve, reject) => {
|
|
104
|
+
var _config$esm;
|
|
105
|
+
try {
|
|
106
|
+
await generate(config);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
require_esm.logger.error({ error }, "Error generating types");
|
|
109
|
+
}
|
|
110
|
+
const clarinetFolder = (0, node_path.dirname)(config.clarinetFile());
|
|
111
|
+
const contractsFolder = (0, node_path.join)(clarinetFolder, "/contracts/**/*.clar");
|
|
112
|
+
const relativeFolder = (0, node_path.relative)(cwd || process.cwd(), contractsFolder);
|
|
113
|
+
const watchFolders = ((_config$esm = config.esm) === null || _config$esm === void 0 ? void 0 : _config$esm.watch_folders) ?? [];
|
|
114
|
+
watchFolders.push(relativeFolder);
|
|
115
|
+
require_esm.logger.info(`Watching for changes in ${watchFolders}`);
|
|
116
|
+
const watcher = chokidar.default.watch(watchFolders, {
|
|
117
|
+
persistent: true,
|
|
118
|
+
cwd: clarinetFolder
|
|
119
|
+
});
|
|
120
|
+
let running = false;
|
|
121
|
+
let start = 0;
|
|
122
|
+
require_esm.logger.level;
|
|
123
|
+
watcher.on("change", (path) => {
|
|
124
|
+
if (!running) {
|
|
125
|
+
start = Date.now();
|
|
126
|
+
require_esm.logger.info(`File ${path} has been changed. Generating types.`);
|
|
127
|
+
running = true;
|
|
128
|
+
generate(config).catch((e) => {
|
|
129
|
+
require_esm.logger.error({ error: e }, "Error generating types");
|
|
130
|
+
}).then(() => {
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
process.stdout.moveCursor(0, -1);
|
|
133
|
+
process.stdout.clearLine(1);
|
|
134
|
+
const elapsed = Date.now() - start;
|
|
135
|
+
require_esm.logger.info(`Types generated (${(elapsed / 1e3).toFixed(2)}s). Watching for changes...`);
|
|
136
|
+
running = false;
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
953
142
|
}
|
|
954
143
|
var DefaultCommand = class extends BaseCommand {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
if (this.watch) {
|
|
976
|
-
await watch(config, this.cwd);
|
|
977
|
-
} else {
|
|
978
|
-
await generate(config);
|
|
979
|
-
}
|
|
980
|
-
}
|
|
144
|
+
static paths = [clipanion.Command.Default, ["generate"]];
|
|
145
|
+
static usage = clipanion.Command.Usage({
|
|
146
|
+
description: "Generate types for your Clarity contracts",
|
|
147
|
+
examples: [
|
|
148
|
+
["Basic usage:", "clarigen"],
|
|
149
|
+
["When your `Clarigen.toml` is in a different directory:", "clarigen /path/to/your/project"],
|
|
150
|
+
["Watch for changes and regenerate types:", "clarigen --watch"]
|
|
151
|
+
]
|
|
152
|
+
});
|
|
153
|
+
cwd = clipanion.Option.String({ required: false });
|
|
154
|
+
watch = clipanion.Option.Boolean("-w,--watch", {
|
|
155
|
+
description: "Watch for changes and regenerate types",
|
|
156
|
+
required: false
|
|
157
|
+
});
|
|
158
|
+
async execute() {
|
|
159
|
+
this.preexecute();
|
|
160
|
+
const config = await require_esm.Config.load(this.cwd);
|
|
161
|
+
if (this.watch) await watch$1(config, this.cwd);
|
|
162
|
+
else await generate(config);
|
|
163
|
+
}
|
|
981
164
|
};
|
|
982
165
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
var
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
comments = [];
|
|
1033
|
-
} else {
|
|
1034
|
-
const abiFn = findAbiItemByName(abi, name);
|
|
1035
|
-
if (!abiFn) {
|
|
1036
|
-
console.debug(`[claridoc]: Unable to find ABI for function \`${name}\`. Probably a bug.`);
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
parensCount = traceParens(line, 0);
|
|
1040
|
-
const metaComments = parseComments(comments, abiFn);
|
|
1041
|
-
currentFn = {
|
|
1042
|
-
abi: abiFn,
|
|
1043
|
-
comments: metaComments,
|
|
1044
|
-
startLine: lineNumber,
|
|
1045
|
-
source: [line]
|
|
1046
|
-
};
|
|
1047
|
-
if (parensCount === 0) {
|
|
1048
|
-
pushItem(contract, currentFn);
|
|
1049
|
-
currentFn = void 0;
|
|
1050
|
-
}
|
|
1051
|
-
comments = [];
|
|
1052
|
-
}
|
|
1053
|
-
});
|
|
1054
|
-
return contract;
|
|
1055
|
-
}
|
|
1056
|
-
function pushItem(contract, item) {
|
|
1057
|
-
if ("args" in item.abi) {
|
|
1058
|
-
contract.functions.push(item);
|
|
1059
|
-
} else if ("key" in item.abi) {
|
|
1060
|
-
contract.maps.push(item);
|
|
1061
|
-
} else if ("access" in item.abi) {
|
|
1062
|
-
contract.variables.push(item);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
function clarityNameMatcher(line) {
|
|
1066
|
-
return /[\w|\-|\?|\!]+/.exec(line);
|
|
1067
|
-
}
|
|
1068
|
-
function findItemNameFromLine(line) {
|
|
1069
|
-
const fnType = FN_TYPES.find((type4) => {
|
|
1070
|
-
return line.startsWith(`(define-${type4}`);
|
|
1071
|
-
});
|
|
1072
|
-
if (fnType) {
|
|
1073
|
-
const prefix = `(define-${fnType} (`;
|
|
1074
|
-
const startString = line.slice(prefix.length);
|
|
1075
|
-
const match = clarityNameMatcher(startString);
|
|
1076
|
-
if (!match) {
|
|
1077
|
-
console.debug(`[claridocs]: Unable to determine function name from line:
|
|
1078
|
-
\`${line}\``);
|
|
1079
|
-
return;
|
|
1080
|
-
}
|
|
1081
|
-
return match[0];
|
|
1082
|
-
}
|
|
1083
|
-
for (const type4 of VAR_TYPES) {
|
|
1084
|
-
const prefix = `(define-${type4} `;
|
|
1085
|
-
if (!line.startsWith(prefix)) continue;
|
|
1086
|
-
const startString = line.slice(prefix.length);
|
|
1087
|
-
const match = clarityNameMatcher(startString);
|
|
1088
|
-
if (!match) {
|
|
1089
|
-
console.debug(`[claridocs]: Unable to determine ${type4} name from line:
|
|
1090
|
-
\`${line}\``);
|
|
1091
|
-
return;
|
|
1092
|
-
}
|
|
1093
|
-
return match[0];
|
|
1094
|
-
}
|
|
1095
|
-
return void 0;
|
|
1096
|
-
}
|
|
1097
|
-
function findAbiItemByName(abi, name) {
|
|
1098
|
-
const fn = abi.functions.find((fn2) => {
|
|
1099
|
-
return fn2.name === name;
|
|
1100
|
-
});
|
|
1101
|
-
if (fn) return fn;
|
|
1102
|
-
const map = abi.maps.find((m) => m.name === name);
|
|
1103
|
-
if (map) return map;
|
|
1104
|
-
const v = abi.variables.find((v2) => v2.name === name);
|
|
1105
|
-
return v;
|
|
1106
|
-
}
|
|
1107
|
-
function isComment(line) {
|
|
1108
|
-
return line.startsWith(";;");
|
|
1109
|
-
}
|
|
1110
|
-
function traceParens(line, count) {
|
|
1111
|
-
let newCount = count;
|
|
1112
|
-
line.split("").forEach((char) => {
|
|
1113
|
-
if (char === "(") newCount++;
|
|
1114
|
-
if (char === ")") newCount--;
|
|
1115
|
-
});
|
|
1116
|
-
return newCount;
|
|
1117
|
-
}
|
|
1118
|
-
function parseComments(comments, abi) {
|
|
1119
|
-
let curParam;
|
|
1120
|
-
const parsed = {
|
|
1121
|
-
text: [],
|
|
1122
|
-
params: {}
|
|
1123
|
-
};
|
|
1124
|
-
comments.forEach((line) => {
|
|
1125
|
-
const paramMatches = /\s*@param\s([\w|\-]+)([;|-|\s]*)(.*)/.exec(line);
|
|
1126
|
-
if (paramMatches === null) {
|
|
1127
|
-
if (!curParam || line.trim() === "") {
|
|
1128
|
-
curParam = void 0;
|
|
1129
|
-
parsed.text.push(line);
|
|
1130
|
-
} else {
|
|
1131
|
-
parsed.params[curParam].comments.push(line);
|
|
1132
|
-
}
|
|
1133
|
-
return;
|
|
1134
|
-
}
|
|
1135
|
-
if (!("args" in abi)) return;
|
|
1136
|
-
const [_full, name, _separator, rest] = paramMatches;
|
|
1137
|
-
const arg = abi.args.find((arg2) => arg2.name === name);
|
|
1138
|
-
if (!arg) {
|
|
1139
|
-
console.debug(`[claridocs]: Unable to find ABI for @param ${name}`);
|
|
1140
|
-
return;
|
|
1141
|
-
}
|
|
1142
|
-
curParam = name;
|
|
1143
|
-
parsed.params[curParam] = {
|
|
1144
|
-
abi: arg,
|
|
1145
|
-
comments: [rest]
|
|
1146
|
-
};
|
|
1147
|
-
});
|
|
1148
|
-
if ("args" in abi) {
|
|
1149
|
-
abi.args.forEach((arg) => {
|
|
1150
|
-
if (!parsed.params[arg.name]) {
|
|
1151
|
-
parsed.params[arg.name] = {
|
|
1152
|
-
abi: arg,
|
|
1153
|
-
comments: []
|
|
1154
|
-
};
|
|
1155
|
-
}
|
|
1156
|
-
});
|
|
1157
|
-
}
|
|
1158
|
-
return parsed;
|
|
1159
|
-
}
|
|
1160
|
-
async function afterDocs(config) {
|
|
1161
|
-
var _a;
|
|
1162
|
-
const command = (_a = config.docs) == null ? void 0 : _a.after;
|
|
1163
|
-
if (!command) return;
|
|
1164
|
-
logger.debug(`Running after docs command: ${command}`);
|
|
1165
|
-
const parts = command.split(" ");
|
|
1166
|
-
const [cmd, ...args2] = parts;
|
|
1167
|
-
return new Promise((resolve3, reject) => {
|
|
1168
|
-
const child = (0, import_child_process2.spawn)(cmd, args2, {
|
|
1169
|
-
cwd: config.cwd,
|
|
1170
|
-
stdio: "inherit"
|
|
1171
|
-
});
|
|
1172
|
-
child.on("error", reject);
|
|
1173
|
-
child.on("exit", (code) => {
|
|
1174
|
-
if (code === 0) {
|
|
1175
|
-
resolve3();
|
|
1176
|
-
} else {
|
|
1177
|
-
reject(new Error(`Command failed with code ${code ?? "unknown"}`));
|
|
1178
|
-
}
|
|
1179
|
-
});
|
|
1180
|
-
});
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
// src/docs/markdown.ts
|
|
1184
|
-
var import_path4 = require("path");
|
|
1185
|
-
function generateMarkdown({
|
|
1186
|
-
contract,
|
|
1187
|
-
contractFile,
|
|
1188
|
-
withToc = true
|
|
1189
|
-
}) {
|
|
1190
|
-
const contractName = (0, import_core9.getContractName)(contract.contract_id, false);
|
|
1191
|
-
const doc = createContractDocInfo({
|
|
1192
|
-
contractSrc: contract.source,
|
|
1193
|
-
abi: contract.contract_interface
|
|
1194
|
-
});
|
|
1195
|
-
const functions = doc.functions.map((fn) => markdownFunction(fn, contractFile));
|
|
1196
|
-
const maps = doc.maps.map((map) => markdownMap(map, contractFile));
|
|
1197
|
-
const vars = doc.variables.filter((v) => v.abi.access === "variable").map((v) => markdownVar(v, contractFile));
|
|
1198
|
-
const constants = doc.variables.filter((v) => v.abi.access === "constant").map((v) => markdownVar(v, contractFile));
|
|
1199
|
-
let fileLine = "";
|
|
1200
|
-
if (contractFile) {
|
|
1201
|
-
const fileName = (0, import_path4.basename)(contractFile);
|
|
1202
|
-
fileLine = `
|
|
1203
|
-
[\`${fileName}\`](${contractFile})`;
|
|
1204
|
-
}
|
|
1205
|
-
return `
|
|
1206
|
-
# ${contractName}
|
|
1207
|
-
${fileLine}
|
|
1208
|
-
|
|
1209
|
-
${doc.comments.join("\n\n")}
|
|
1210
|
-
|
|
1211
|
-
${withToc ? markdownTOC(doc) : ""}
|
|
1212
|
-
|
|
1213
|
-
## Functions
|
|
1214
|
-
|
|
1215
|
-
${functions.join("\n\n")}
|
|
1216
|
-
|
|
1217
|
-
## Maps
|
|
1218
|
-
|
|
1219
|
-
${maps.join("\n\n")}
|
|
1220
|
-
|
|
1221
|
-
## Variables
|
|
1222
|
-
|
|
1223
|
-
${vars.join("\n\n")}
|
|
1224
|
-
|
|
1225
|
-
## Constants
|
|
1226
|
-
|
|
1227
|
-
${constants.join("\n\n")}
|
|
1228
|
-
`;
|
|
1229
|
-
}
|
|
1230
|
-
function markdownFunction(fn, contractFile) {
|
|
1231
|
-
const params = mdParams(fn);
|
|
1232
|
-
const returnType = (0, import_core9.getTypeString)(fn.abi.outputs.type);
|
|
1233
|
-
const paramSigs = fn.abi.args.map((arg) => {
|
|
1234
|
-
return `(${arg.name} ${(0, import_core9.getTypeString)(arg.type)})`;
|
|
1235
|
-
});
|
|
1236
|
-
const startLine = fn.startLine + 1;
|
|
1237
|
-
let link = "";
|
|
1238
|
-
if (contractFile) {
|
|
1239
|
-
link = `[View in file](${contractFile}#L${startLine})`;
|
|
1240
|
-
}
|
|
1241
|
-
const source = `<details>
|
|
1242
|
-
<summary>Source code:</summary>
|
|
1243
|
-
|
|
1244
|
-
\`\`\`clarity
|
|
1245
|
-
${fn.source.join("\n")}
|
|
1246
|
-
\`\`\`
|
|
1247
|
-
</details>
|
|
1248
|
-
`;
|
|
1249
|
-
const sig = `(define-${fn.abi.access.replace("_", "-")} (${fn.abi.name} (${paramSigs.join(
|
|
1250
|
-
" "
|
|
1251
|
-
)}) ${returnType})`;
|
|
1252
|
-
return `### ${fn.abi.name}
|
|
1253
|
-
|
|
1254
|
-
${link}
|
|
1255
|
-
|
|
1256
|
-
\`${sig}\`
|
|
1257
|
-
|
|
1258
|
-
${fn.comments.text.join("\n")}
|
|
1259
|
-
|
|
1260
|
-
${source}
|
|
1261
|
-
|
|
1262
|
-
${params}`;
|
|
1263
|
-
}
|
|
1264
|
-
function mdParams(fn) {
|
|
1265
|
-
if (fn.abi.args.length === 0) return "";
|
|
1266
|
-
const hasDescription = Object.values(fn.comments.params).some((p) => p.comments.length > 0);
|
|
1267
|
-
const params = Object.values(fn.comments.params).map((p) => markdownParam(p, hasDescription));
|
|
1268
|
-
return `**Parameters:**
|
|
1269
|
-
|
|
1270
|
-
| Name | Type | ${hasDescription ? "Description |" : ""}
|
|
1271
|
-
| --- | --- | ${hasDescription ? "--- |" : ""}
|
|
1272
|
-
${params.join("\n")}`;
|
|
1273
|
-
}
|
|
1274
|
-
function markdownParam(param, withDescription) {
|
|
1275
|
-
const typeString = (0, import_core9.getTypeString)(param.abi.type);
|
|
1276
|
-
const base = `| ${param.abi.name} | ${typeString} |`;
|
|
1277
|
-
if (!withDescription) return base;
|
|
1278
|
-
return `${base} ${param.comments.join(" ")} |`;
|
|
1279
|
-
}
|
|
1280
|
-
function markdownMap(map, contractFile) {
|
|
1281
|
-
const startLine = map.startLine + 1;
|
|
1282
|
-
let link = "";
|
|
1283
|
-
if (contractFile) {
|
|
1284
|
-
link = `[View in file](${contractFile}#L${startLine})`;
|
|
1285
|
-
}
|
|
1286
|
-
return `### ${map.abi.name}
|
|
1287
|
-
|
|
1288
|
-
${map.comments.text.join("\n")}
|
|
1289
|
-
|
|
1290
|
-
\`\`\`clarity
|
|
1291
|
-
${map.source.join("\n")}
|
|
1292
|
-
\`\`\`
|
|
1293
|
-
|
|
1294
|
-
${link}`;
|
|
1295
|
-
}
|
|
1296
|
-
function markdownVar(variable, contractFile) {
|
|
1297
|
-
const startLine = variable.startLine + 1;
|
|
1298
|
-
let link = "";
|
|
1299
|
-
if (contractFile) {
|
|
1300
|
-
link = `[View in file](${contractFile}#L${startLine})`;
|
|
1301
|
-
}
|
|
1302
|
-
const sig = variable.abi.access === "variable" ? (0, import_core9.getTypeString)(variable.abi.type) : "";
|
|
1303
|
-
return `### ${variable.abi.name}
|
|
1304
|
-
|
|
1305
|
-
${sig}
|
|
1306
|
-
|
|
1307
|
-
${variable.comments.text.join("\n")}
|
|
1308
|
-
|
|
1309
|
-
\`\`\`clarity
|
|
1310
|
-
${variable.source.join("\n")}
|
|
1311
|
-
\`\`\`
|
|
1312
|
-
|
|
1313
|
-
${link}`;
|
|
1314
|
-
}
|
|
1315
|
-
function markdownTOC(contract) {
|
|
1316
|
-
const publics = contract.functions.filter((fn) => fn.abi.access === "public");
|
|
1317
|
-
const readOnly = contract.functions.filter((fn) => fn.abi.access === "read_only");
|
|
1318
|
-
const privates = contract.functions.filter((fn) => fn.abi.access === "private");
|
|
1319
|
-
const maps = contract.maps;
|
|
1320
|
-
const constants = contract.variables.filter((v) => v.abi.access === "constant");
|
|
1321
|
-
const vars = contract.variables.filter((v) => v.abi.access === "variable");
|
|
1322
|
-
function tocLine(fn) {
|
|
1323
|
-
const name = fn.abi.name;
|
|
1324
|
-
return `- [\`${name}\`](#${name.toLowerCase().replaceAll("?", "")})`;
|
|
1325
|
-
}
|
|
1326
|
-
return `**Public functions:**
|
|
1327
|
-
|
|
1328
|
-
${publics.map(tocLine).join("\n")}
|
|
1329
|
-
|
|
1330
|
-
**Read-only functions:**
|
|
1331
|
-
|
|
1332
|
-
${readOnly.map(tocLine).join("\n")}
|
|
1333
|
-
|
|
1334
|
-
**Private functions:**
|
|
1335
|
-
|
|
1336
|
-
${privates.map(tocLine).join("\n")}
|
|
1337
|
-
|
|
1338
|
-
**Maps**
|
|
1339
|
-
|
|
1340
|
-
${maps.map(tocLine).join("\n")}
|
|
1341
|
-
|
|
1342
|
-
**Variables**
|
|
1343
|
-
|
|
1344
|
-
${vars.map(tocLine).join("\n")}
|
|
1345
|
-
|
|
1346
|
-
**Constants**
|
|
1347
|
-
|
|
1348
|
-
${constants.map(tocLine).join("\n")}
|
|
1349
|
-
`;
|
|
1350
|
-
}
|
|
1351
|
-
function generateReadme(session, excluded) {
|
|
1352
|
-
const contractLines = [];
|
|
1353
|
-
sortContracts(session.contracts).forEach((contract) => {
|
|
1354
|
-
const name = (0, import_core9.getContractName)(contract.contract_id, false);
|
|
1355
|
-
if (excluded[name]) return;
|
|
1356
|
-
const fileName = `${name}.md`;
|
|
1357
|
-
const line = `- [\`${name}\`](${fileName})`;
|
|
1358
|
-
contractLines.push(line);
|
|
1359
|
-
});
|
|
1360
|
-
const fileContents = `# Contracts
|
|
1361
|
-
|
|
1362
|
-
${contractLines.join("\n")}
|
|
1363
|
-
`;
|
|
1364
|
-
return fileContents;
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
// src/files/docs.ts
|
|
1368
|
-
async function generateDocs({
|
|
1369
|
-
session,
|
|
1370
|
-
config
|
|
1371
|
-
}) {
|
|
1372
|
-
const docs = config.configFile["docs" /* Docs */];
|
|
1373
|
-
const docsBase = docs == null ? void 0 : docs.output;
|
|
1374
|
-
if (!docsBase) {
|
|
1375
|
-
warnNoDocs();
|
|
1376
|
-
return;
|
|
1377
|
-
}
|
|
1378
|
-
const docsPathExt = (0, import_path5.extname)(docsBase);
|
|
1379
|
-
if (docsPathExt) {
|
|
1380
|
-
log.warn(`Docs output path ('${docsBase}') looks like a file - it needs to be a directory.`);
|
|
1381
|
-
}
|
|
1382
|
-
const excluded = Object.fromEntries(
|
|
1383
|
-
(docs.exclude || []).map((e) => {
|
|
1384
|
-
return [e, true];
|
|
1385
|
-
})
|
|
1386
|
-
);
|
|
1387
|
-
log.debug(`Generating docs at path \`${docsBase}\``);
|
|
1388
|
-
const docsBaseFolder = config.outputResolve("docs" /* Docs */, "./")[0];
|
|
1389
|
-
const paths = await Promise.all(
|
|
1390
|
-
session.contracts.map(async (contract) => {
|
|
1391
|
-
var _a, _b;
|
|
1392
|
-
const name = (0, import_core10.getContractName)(contract.contract_id, false);
|
|
1393
|
-
if (excluded[name]) return null;
|
|
1394
|
-
const docFile = `${name}.md`;
|
|
1395
|
-
const contractPathDef = (_b = (_a = config.clarinet.contracts) == null ? void 0 : _a[name]) == null ? void 0 : _b.path;
|
|
1396
|
-
let contractFile;
|
|
1397
|
-
if (contractPathDef) {
|
|
1398
|
-
const contractPathFull = config.joinFromClarinet(contractPathDef);
|
|
1399
|
-
contractFile = (0, import_path5.relative)(docsBaseFolder, contractPathFull);
|
|
1400
|
-
} else {
|
|
1401
|
-
log.debug(`Couldn't find contract file from Clarinet.toml for contract ${name}`);
|
|
1402
|
-
}
|
|
1403
|
-
const md = generateMarkdown({ contract, contractFile });
|
|
1404
|
-
const path = await config.writeOutput("docs" /* Docs */, md, docFile);
|
|
1405
|
-
return path[0];
|
|
1406
|
-
})
|
|
1407
|
-
);
|
|
1408
|
-
const readme = generateReadme(session, excluded);
|
|
1409
|
-
paths.push((await config.writeOutput("docs" /* Docs */, readme, "README.md"))[0]);
|
|
1410
|
-
await afterDocs(config);
|
|
1411
|
-
}
|
|
1412
|
-
function warnNoDocs() {
|
|
1413
|
-
log.warn(
|
|
1414
|
-
`
|
|
1415
|
-
Clarigen config file doesn't include an output directory for docs.
|
|
1416
|
-
|
|
1417
|
-
To generate docs, specify 'docs.output' in your config file:
|
|
1418
|
-
|
|
1419
|
-
[docs]
|
|
1420
|
-
output = "docs/"
|
|
1421
|
-
`.trimEnd()
|
|
1422
|
-
);
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
// src/commands/docs-command.ts
|
|
1426
|
-
var import_node_path2 = require("path");
|
|
1427
|
-
var import_chokidar2 = __toESM(require("chokidar"), 1);
|
|
1428
|
-
async function watch2(config, cwd) {
|
|
1429
|
-
return new Promise(async (resolve3, reject) => {
|
|
1430
|
-
var _a;
|
|
1431
|
-
const session = await getSession(config);
|
|
1432
|
-
try {
|
|
1433
|
-
await generateDocs({
|
|
1434
|
-
session,
|
|
1435
|
-
config
|
|
1436
|
-
});
|
|
1437
|
-
} catch (error) {
|
|
1438
|
-
logger.error({ error }, "Error generating types");
|
|
1439
|
-
}
|
|
1440
|
-
const clarinetFolder = (0, import_node_path2.dirname)(config.clarinetFile());
|
|
1441
|
-
const contractsFolder = (0, import_node_path2.join)(clarinetFolder, "/contracts/**/*.clar");
|
|
1442
|
-
const relativeFolder = (0, import_node_path2.relative)(cwd || process.cwd(), contractsFolder);
|
|
1443
|
-
const watchFolders = ((_a = config.esm) == null ? void 0 : _a.watch_folders) ?? [];
|
|
1444
|
-
watchFolders.push(relativeFolder);
|
|
1445
|
-
logger.info(`Watching for changes in ${watchFolders}`);
|
|
1446
|
-
const watcher = import_chokidar2.default.watch(watchFolders, { persistent: true, cwd: clarinetFolder });
|
|
1447
|
-
let running = false;
|
|
1448
|
-
let start = 0;
|
|
1449
|
-
const isVerbose = logger.level !== "info";
|
|
1450
|
-
watcher.on("change", async (path) => {
|
|
1451
|
-
if (!running) {
|
|
1452
|
-
start = Date.now();
|
|
1453
|
-
logger.info(`File ${path} has been changed. Generating types.`);
|
|
1454
|
-
running = true;
|
|
1455
|
-
const session2 = await getSession(config);
|
|
1456
|
-
void generateDocs({
|
|
1457
|
-
session: session2,
|
|
1458
|
-
config
|
|
1459
|
-
}).catch((e) => {
|
|
1460
|
-
logger.error({ error: e }, "Error generating types");
|
|
1461
|
-
}).then(() => {
|
|
1462
|
-
setTimeout(() => {
|
|
1463
|
-
process.stdout.moveCursor(0, -1);
|
|
1464
|
-
process.stdout.clearLine(1);
|
|
1465
|
-
const elapsed = Date.now() - start;
|
|
1466
|
-
logger.info(
|
|
1467
|
-
`Docs generated (${(elapsed / 1e3).toFixed(2)}s). Watching for changes...`
|
|
1468
|
-
);
|
|
1469
|
-
running = false;
|
|
1470
|
-
});
|
|
1471
|
-
});
|
|
1472
|
-
}
|
|
1473
|
-
});
|
|
1474
|
-
});
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/commands/docs-command.ts
|
|
168
|
+
async function watch(config, cwd) {
|
|
169
|
+
return new Promise(async (resolve, reject) => {
|
|
170
|
+
var _config$esm;
|
|
171
|
+
const session = await getSession(config);
|
|
172
|
+
try {
|
|
173
|
+
await require_esm.generateDocs({
|
|
174
|
+
session,
|
|
175
|
+
config
|
|
176
|
+
});
|
|
177
|
+
} catch (error) {
|
|
178
|
+
require_esm.logger.error({ error }, "Error generating types");
|
|
179
|
+
}
|
|
180
|
+
const clarinetFolder = (0, node_path.dirname)(config.clarinetFile());
|
|
181
|
+
const contractsFolder = (0, node_path.join)(clarinetFolder, "/contracts/**/*.clar");
|
|
182
|
+
const relativeFolder = (0, node_path.relative)(cwd || process.cwd(), contractsFolder);
|
|
183
|
+
const watchFolders = ((_config$esm = config.esm) === null || _config$esm === void 0 ? void 0 : _config$esm.watch_folders) ?? [];
|
|
184
|
+
watchFolders.push(relativeFolder);
|
|
185
|
+
require_esm.logger.info(`Watching for changes in ${watchFolders}`);
|
|
186
|
+
const watcher = chokidar.default.watch(watchFolders, {
|
|
187
|
+
persistent: true,
|
|
188
|
+
cwd: clarinetFolder
|
|
189
|
+
});
|
|
190
|
+
let running = false;
|
|
191
|
+
let start = 0;
|
|
192
|
+
require_esm.logger.level;
|
|
193
|
+
watcher.on("change", async (path) => {
|
|
194
|
+
if (!running) {
|
|
195
|
+
start = Date.now();
|
|
196
|
+
require_esm.logger.info(`File ${path} has been changed. Generating types.`);
|
|
197
|
+
running = true;
|
|
198
|
+
require_esm.generateDocs({
|
|
199
|
+
session: await getSession(config),
|
|
200
|
+
config
|
|
201
|
+
}).catch((e) => {
|
|
202
|
+
require_esm.logger.error({ error: e }, "Error generating types");
|
|
203
|
+
}).then(() => {
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
process.stdout.moveCursor(0, -1);
|
|
206
|
+
process.stdout.clearLine(1);
|
|
207
|
+
const elapsed = Date.now() - start;
|
|
208
|
+
require_esm.logger.info(`Docs generated (${(elapsed / 1e3).toFixed(2)}s). Watching for changes...`);
|
|
209
|
+
running = false;
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
1475
215
|
}
|
|
1476
216
|
var DocsCommand = class extends BaseCommand {
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
variables: []
|
|
1497
|
-
},
|
|
1498
|
-
config
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
217
|
+
static paths = [["docs"]];
|
|
218
|
+
static usage = BaseCommand.Usage({ description: "Generate markdown documentation for your Clarity contracts" });
|
|
219
|
+
cwd = clipanion.Option.String({ required: false });
|
|
220
|
+
watch = clipanion.Option.Boolean("-w,--watch", {
|
|
221
|
+
description: "Watch for changes and regenerate docs",
|
|
222
|
+
required: false
|
|
223
|
+
});
|
|
224
|
+
async execute() {
|
|
225
|
+
this.preexecute();
|
|
226
|
+
const config = await require_esm.Config.load(this.cwd);
|
|
227
|
+
if (this.watch) await watch(config, this.cwd);
|
|
228
|
+
else await require_esm.generateDocs({
|
|
229
|
+
session: {
|
|
230
|
+
...await getSession(config),
|
|
231
|
+
variables: []
|
|
232
|
+
},
|
|
233
|
+
config
|
|
234
|
+
});
|
|
235
|
+
}
|
|
1502
236
|
};
|
|
1503
237
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
// src/generated/init-config.ts
|
|
1509
|
-
var tomlInit = `
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/generated/init-config.ts
|
|
240
|
+
const tomlInit = `
|
|
1510
241
|
# Set to your project's Clarinet config file
|
|
1511
242
|
clarinet = "./Clarinet.toml"
|
|
1512
243
|
|
|
@@ -1538,53 +269,53 @@ output = "docs"
|
|
|
1538
269
|
# after = "npm run prettier -w ./docs"
|
|
1539
270
|
`;
|
|
1540
271
|
|
|
1541
|
-
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region src/commands/init-config-command.ts
|
|
1542
274
|
var InitConfigCommand = class extends BaseCommand {
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
return 1;
|
|
1558
|
-
}
|
|
1559
|
-
logger.debug(`Writing configuration file to ${path}`);
|
|
1560
|
-
await (0, import_promises6.writeFile)(path, tomlInit, "utf-8");
|
|
1561
|
-
}
|
|
275
|
+
static paths = [["init-config"], ["init"]];
|
|
276
|
+
static usage = { description: "Initialize a Clarigen configuration file" };
|
|
277
|
+
cwd = clipanion.Option.String({ required: false });
|
|
278
|
+
overwrite = clipanion.Option.Boolean("--overwrite", false, { description: "Overwrite the configuration file if it already exists" });
|
|
279
|
+
async execute() {
|
|
280
|
+
this.preexecute();
|
|
281
|
+
const path = require_esm.configFilePath(this.cwd);
|
|
282
|
+
if (await require_esm.fileExists(path) && !this.overwrite) {
|
|
283
|
+
require_esm.logger.warn("Configuration file already exists. Use --overwrite to overwrite it.");
|
|
284
|
+
return 1;
|
|
285
|
+
}
|
|
286
|
+
require_esm.logger.debug(`Writing configuration file to ${path}`);
|
|
287
|
+
await (0, fs_promises.writeFile)(path, tomlInit, "utf-8");
|
|
288
|
+
}
|
|
1562
289
|
};
|
|
1563
290
|
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/generated/version.ts
|
|
293
|
+
const version = "4.0.2-alpha.0";
|
|
294
|
+
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region src/run-cli.ts
|
|
297
|
+
const [node, script, ...args] = process.argv;
|
|
298
|
+
const cli = new clipanion.Cli({
|
|
299
|
+
binaryLabel: "Clarigen",
|
|
300
|
+
binaryName: "clarigen",
|
|
301
|
+
binaryVersion: version
|
|
1573
302
|
});
|
|
1574
|
-
cli.register(
|
|
1575
|
-
cli.register(
|
|
303
|
+
cli.register(clipanion.Builtins.HelpCommand);
|
|
304
|
+
cli.register(clipanion.Builtins.VersionCommand);
|
|
1576
305
|
cli.register(DefaultCommand);
|
|
1577
306
|
cli.register(DocsCommand);
|
|
1578
307
|
cli.register(InitConfigCommand);
|
|
1579
308
|
cli.register(SessionInfoCommand);
|
|
1580
309
|
async function run() {
|
|
1581
|
-
|
|
310
|
+
await cli.runExit(args, clipanion.Cli.defaultContext);
|
|
1582
311
|
}
|
|
1583
312
|
process.on("SIGINT", () => {
|
|
1584
|
-
|
|
1585
|
-
|
|
313
|
+
require_esm.logger.info("Bye! 👋");
|
|
314
|
+
process.exit();
|
|
1586
315
|
});
|
|
1587
316
|
run().catch(console.error).finally(() => {
|
|
1588
|
-
|
|
317
|
+
process.exit();
|
|
1589
318
|
});
|
|
319
|
+
|
|
320
|
+
//#endregion
|
|
1590
321
|
//# sourceMappingURL=run-cli.cjs.map
|