@latticexyz/cli 1.40.0 → 1.41.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-AER7UDD4.js +0 -0
  3. package/dist/chunk-ATAWDHWC.js +67 -0
  4. package/dist/{chunk-6AQ6LFVZ.js → chunk-GR245KYP.js} +95 -1
  5. package/dist/{chunk-S3V3XX7N.js → chunk-SLIMIO4Z.js} +1 -1
  6. package/dist/{chunk-JNGSW4AP.js → chunk-XRS7KWBZ.js} +139 -85
  7. package/dist/chunk-YZATC2M3.js +397 -0
  8. package/dist/chunk-ZYDMYSTH.js +1178 -0
  9. package/dist/config/index.d.ts +427 -3
  10. package/dist/config/index.js +26 -3
  11. package/dist/deploy-v2-b7b3207d.d.ts +92 -0
  12. package/dist/index.d.ts +110 -3
  13. package/dist/index.js +53 -8
  14. package/dist/mud.js +172 -46
  15. package/dist/utils/deprecated/index.js +2 -2
  16. package/dist/utils/index.d.ts +5 -44
  17. package/dist/utils/index.js +18 -3
  18. package/package.json +13 -9
  19. package/src/commands/deploy-v2.ts +100 -0
  20. package/src/commands/deprecated/call-system.ts +1 -1
  21. package/src/commands/deprecated/deploy-contracts.ts +1 -1
  22. package/src/commands/deprecated/test.ts +9 -6
  23. package/src/commands/deprecated/trace.ts +1 -1
  24. package/src/commands/gas-report.ts +1 -1
  25. package/src/commands/index.ts +2 -0
  26. package/src/commands/tablegen.ts +4 -18
  27. package/src/config/commonSchemas.ts +16 -0
  28. package/src/config/index.ts +8 -0
  29. package/src/config/loadStoreConfig.ts +2 -88
  30. package/src/config/loadWorldConfig.test-d.ts +11 -0
  31. package/src/config/loadWorldConfig.ts +178 -0
  32. package/src/config/{loadStoreConfig.test-d.ts → parseStoreConfig.test-d.ts} +5 -2
  33. package/src/config/parseStoreConfig.ts +174 -0
  34. package/src/config/validation.ts +46 -0
  35. package/src/constants.ts +1 -0
  36. package/src/index.ts +15 -5
  37. package/src/mud.ts +4 -0
  38. package/src/{render-table → render-solidity}/common.ts +37 -11
  39. package/src/{render-table → render-solidity}/field.ts +29 -20
  40. package/src/{render-table → render-solidity}/record.ts +3 -8
  41. package/src/{render-table → render-solidity}/renderTable.ts +38 -11
  42. package/src/{render-table → render-solidity}/renderTablesFromConfig.ts +37 -27
  43. package/src/render-solidity/renderTypes.ts +19 -0
  44. package/src/render-solidity/renderTypesFromConfig.ts +13 -0
  45. package/src/render-solidity/tablegen.ts +35 -0
  46. package/src/{render-table → render-solidity}/types.ts +25 -0
  47. package/src/render-solidity/userType.ts +100 -0
  48. package/src/utils/deploy-v2.ts +345 -0
  49. package/src/utils/deprecated/build.ts +1 -1
  50. package/src/utils/deprecated/typegen.ts +1 -1
  51. package/src/utils/errors.ts +12 -2
  52. package/src/utils/execLog.ts +22 -0
  53. package/src/utils/foundry.ts +94 -0
  54. package/src/utils/index.ts +2 -1
  55. package/dist/chunk-B6VWCGHZ.js +0 -199
  56. package/dist/chunk-JKAA3WMC.js +0 -55
  57. package/dist/chunk-PJ6GS2R4.js +0 -22
  58. package/dist/chunk-UC3QPOON.js +0 -35
  59. package/dist/loadStoreConfig-37f99136.d.ts +0 -164
  60. package/dist/render-table/index.d.ts +0 -29
  61. package/dist/render-table/index.js +0 -24
  62. package/dist/renderTable-9e6410c5.d.ts +0 -72
  63. package/src/utils/forgeConfig.ts +0 -45
  64. /package/src/{render-table → render-solidity}/index.ts +0 -0
@@ -0,0 +1,397 @@
1
+ import {
2
+ NotESMConfigError,
3
+ NotInsideProjectError,
4
+ SchemaType,
5
+ UnrecognizedSystemErrorFactory,
6
+ fromZodErrorCustom,
7
+ getStaticByteLength
8
+ } from "./chunk-GR245KYP.js";
9
+
10
+ // src/config/validation.ts
11
+ import { ethers } from "ethers";
12
+ import { ZodIssueCode } from "zod";
13
+ function validateName(name, ctx) {
14
+ if (!/^\w+$/.test(name)) {
15
+ ctx.addIssue({
16
+ code: ZodIssueCode.custom,
17
+ message: `Name must contain only alphanumeric & underscore characters`
18
+ });
19
+ }
20
+ }
21
+ function validateCapitalizedName(name, ctx) {
22
+ validateName(name, ctx);
23
+ if (!/^[A-Z]/.test(name)) {
24
+ ctx.addIssue({
25
+ code: ZodIssueCode.custom,
26
+ message: `Name must start with a capital letter`
27
+ });
28
+ }
29
+ }
30
+ function validateUncapitalizedName(name, ctx) {
31
+ validateName(name, ctx);
32
+ if (!/^[a-z]/.test(name)) {
33
+ ctx.addIssue({
34
+ code: ZodIssueCode.custom,
35
+ message: `Name must start with a lowercase letter`
36
+ });
37
+ }
38
+ }
39
+ function validateEnum(members, ctx) {
40
+ if (members.length === 0) {
41
+ ctx.addIssue({
42
+ code: ZodIssueCode.custom,
43
+ message: `Enum must not be empty`
44
+ });
45
+ }
46
+ if (members.length >= 256) {
47
+ ctx.addIssue({
48
+ code: ZodIssueCode.custom,
49
+ message: `Length of enum must be < 256`
50
+ });
51
+ }
52
+ const duplicates = getDuplicates(members);
53
+ if (duplicates.length > 0) {
54
+ ctx.addIssue({
55
+ code: ZodIssueCode.custom,
56
+ message: `Enum must not have duplicate names for: ${duplicates.join(", ")}`
57
+ });
58
+ }
59
+ }
60
+ function _factoryForValidateRoute(requireNonEmpty, requireSingleLevel) {
61
+ return (route, ctx) => {
62
+ if (route === "") {
63
+ if (requireNonEmpty) {
64
+ ctx.addIssue({
65
+ code: ZodIssueCode.custom,
66
+ message: `Route must not be empty`
67
+ });
68
+ }
69
+ return;
70
+ }
71
+ if (route[0] !== "/") {
72
+ ctx.addIssue({
73
+ code: ZodIssueCode.custom,
74
+ message: `Route must start with "/"`
75
+ });
76
+ }
77
+ if (route[route.length - 1] === "/") {
78
+ ctx.addIssue({
79
+ code: ZodIssueCode.custom,
80
+ message: `Route must not end with "/"`
81
+ });
82
+ }
83
+ const parts = route.split("/");
84
+ if (requireSingleLevel && parts.length > 2) {
85
+ ctx.addIssue({
86
+ code: ZodIssueCode.custom,
87
+ message: `Route must only have one level (e.g. "/foo")`
88
+ });
89
+ }
90
+ for (let i = 1; i < parts.length; i++) {
91
+ if (parts[i] === "") {
92
+ ctx.addIssue({
93
+ code: ZodIssueCode.custom,
94
+ message: `Route must not contain empty route fragments (e.g. "//")`
95
+ });
96
+ }
97
+ if (!/^\w+$/.test(parts[i])) {
98
+ ctx.addIssue({
99
+ code: ZodIssueCode.custom,
100
+ message: `Route must contain only alphanumeric & underscore characters`
101
+ });
102
+ }
103
+ }
104
+ };
105
+ }
106
+ var validateRoute = _factoryForValidateRoute(true, false);
107
+ var validateBaseRoute = _factoryForValidateRoute(false, false);
108
+ var validateSingleLevelRoute = _factoryForValidateRoute(true, true);
109
+ function validateEthereumAddress(address, ctx) {
110
+ if (!ethers.utils.isAddress(address)) {
111
+ ctx.addIssue({
112
+ code: ZodIssueCode.custom,
113
+ message: `Address must be a valid Ethereum address`
114
+ });
115
+ }
116
+ }
117
+ function getDuplicates(array) {
118
+ const checked = /* @__PURE__ */ new Set();
119
+ const duplicates = /* @__PURE__ */ new Set();
120
+ for (const element of array) {
121
+ if (checked.has(element)) {
122
+ duplicates.add(element);
123
+ }
124
+ checked.add(element);
125
+ }
126
+ return [...duplicates];
127
+ }
128
+
129
+ // src/config/commonSchemas.ts
130
+ import { z } from "zod";
131
+ var ObjectName = z.string().superRefine(validateCapitalizedName);
132
+ var ValueName = z.string().superRefine(validateUncapitalizedName);
133
+ var AnyCaseName = z.string().superRefine(validateName);
134
+ var UserEnum = z.array(ObjectName).superRefine(validateEnum);
135
+ var OrdinaryRoute = z.string().superRefine(validateRoute);
136
+ var SingleLevelRoute = z.string().superRefine(validateSingleLevelRoute);
137
+ var BaseRoute = z.string().superRefine(validateBaseRoute);
138
+ var EthereumAddress = z.string().superRefine(validateEthereumAddress);
139
+ var StaticSchemaType = z.nativeEnum(SchemaType).refine((arg) => getStaticByteLength(arg) > 0, "SchemaType must be static");
140
+
141
+ // src/config/parseStoreConfig.ts
142
+ import { z as z2, ZodIssueCode as ZodIssueCode2 } from "zod";
143
+ var TableName = ObjectName;
144
+ var KeyName = ValueName;
145
+ var ColumnName = ValueName;
146
+ var UserEnumName = ObjectName;
147
+ var FieldData = z2.union([z2.nativeEnum(SchemaType), UserEnumName]);
148
+ var PrimaryKey = z2.union([StaticSchemaType, UserEnumName]);
149
+ var PrimaryKeys = z2.record(KeyName, PrimaryKey).default({ key: 95 /* BYTES32 */ });
150
+ var Schema = z2.record(ColumnName, FieldData).refine((arg) => Object.keys(arg).length > 0, "Table schema may not be empty");
151
+ var TableDataFull = z2.object({
152
+ directory: OrdinaryRoute.default("/tables"),
153
+ route: BaseRoute.optional(),
154
+ tableIdArgument: z2.boolean().default(false),
155
+ storeArgument: z2.boolean().default(false),
156
+ primaryKeys: PrimaryKeys,
157
+ schema: Schema,
158
+ dataStruct: z2.boolean().optional()
159
+ }).transform((arg) => {
160
+ if (Object.keys(arg.schema).length === 1) {
161
+ arg.dataStruct ??= false;
162
+ } else {
163
+ arg.dataStruct ??= true;
164
+ }
165
+ return arg;
166
+ });
167
+ var TableDataShorthand = FieldData.transform((fieldData) => {
168
+ return TableDataFull.parse({
169
+ schema: {
170
+ value: fieldData
171
+ }
172
+ });
173
+ });
174
+ var TablesRecord = z2.record(TableName, z2.union([TableDataShorthand, TableDataFull])).transform((tables) => {
175
+ for (const tableName of Object.keys(tables)) {
176
+ const table = tables[tableName];
177
+ table.route ??= `/${tableName}`;
178
+ tables[tableName] = table;
179
+ }
180
+ return tables;
181
+ });
182
+ var StoreConfigUnrefined = z2.object({
183
+ baseRoute: BaseRoute.default(""),
184
+ storeImportPath: z2.string().default("@latticexyz/store/src/"),
185
+ tables: TablesRecord,
186
+ userTypes: z2.object({
187
+ path: OrdinaryRoute.default("/types"),
188
+ enums: z2.record(UserEnumName, UserEnum).default({})
189
+ }).default({})
190
+ });
191
+ var StoreConfig = StoreConfigUnrefined.superRefine(validateStoreConfig);
192
+ async function parseStoreConfig(config) {
193
+ return StoreConfig.parse(config);
194
+ }
195
+ function validateStoreConfig(config, ctx) {
196
+ for (const table of Object.values(config.tables)) {
197
+ const primaryKeyNames = Object.keys(table.primaryKeys);
198
+ const fieldNames = Object.keys(table.schema);
199
+ const duplicateVariableNames = getDuplicates([...primaryKeyNames, ...fieldNames]);
200
+ if (duplicateVariableNames.length > 0) {
201
+ ctx.addIssue({
202
+ code: ZodIssueCode2.custom,
203
+ message: `Field and primary key names within one table must be unique: ${duplicateVariableNames.join(", ")}`
204
+ });
205
+ }
206
+ }
207
+ const tableNames = Object.keys(config.tables);
208
+ const userTypeNames = Object.keys(config.userTypes.enums);
209
+ const globalNames = [...tableNames, ...userTypeNames];
210
+ const duplicateGlobalNames = getDuplicates(globalNames);
211
+ if (duplicateGlobalNames.length > 0) {
212
+ ctx.addIssue({
213
+ code: ZodIssueCode2.custom,
214
+ message: `Table and enum names must be globally unique: ${duplicateGlobalNames.join(", ")}`
215
+ });
216
+ }
217
+ for (const table of Object.values(config.tables)) {
218
+ for (const primaryKeyType of Object.values(table.primaryKeys)) {
219
+ validateIfUserType(userTypeNames, primaryKeyType, ctx);
220
+ }
221
+ for (const fieldType of Object.values(table.schema)) {
222
+ validateIfUserType(userTypeNames, fieldType, ctx);
223
+ }
224
+ }
225
+ }
226
+ function validateIfUserType(userTypeNames, type, ctx) {
227
+ if (typeof type === "string" && !userTypeNames.includes(type)) {
228
+ ctx.addIssue({
229
+ code: ZodIssueCode2.custom,
230
+ message: `User type ${type} is not defined in userTypes`
231
+ });
232
+ }
233
+ }
234
+
235
+ // src/config/loadConfig.ts
236
+ import { findUp } from "find-up";
237
+ import path from "path";
238
+ var configFiles = ["mud.config.ts", "mud.config.mts"];
239
+ async function loadConfig(configPath) {
240
+ configPath = await resolveConfigPath(configPath);
241
+ try {
242
+ return (await import(configPath)).default;
243
+ } catch (error) {
244
+ if (error instanceof SyntaxError && error.message === "Cannot use import statement outside a module") {
245
+ throw new NotESMConfigError();
246
+ } else {
247
+ throw error;
248
+ }
249
+ }
250
+ }
251
+ async function resolveConfigPath(configPath) {
252
+ if (configPath === void 0) {
253
+ configPath = await getUserConfigPath();
254
+ } else {
255
+ if (!path.isAbsolute(configPath)) {
256
+ configPath = path.join(process.cwd(), configPath);
257
+ configPath = path.normalize(configPath);
258
+ }
259
+ }
260
+ return configPath;
261
+ }
262
+ async function getUserConfigPath() {
263
+ const tsConfigPath = await findUp(configFiles);
264
+ if (tsConfigPath === void 0) {
265
+ throw new NotInsideProjectError();
266
+ }
267
+ return tsConfigPath;
268
+ }
269
+
270
+ // src/config/loadStoreConfig.ts
271
+ import { ZodError } from "zod";
272
+ async function loadStoreConfig(configPath) {
273
+ const config = await loadConfig(configPath);
274
+ try {
275
+ return parseStoreConfig(config);
276
+ } catch (error) {
277
+ if (error instanceof ZodError) {
278
+ throw fromZodErrorCustom(error, "StoreConfig Validation Error");
279
+ } else {
280
+ throw error;
281
+ }
282
+ }
283
+ }
284
+
285
+ // src/config/loadWorldConfig.ts
286
+ import { z as z3, ZodError as ZodError2 } from "zod";
287
+ var SystemName = ObjectName;
288
+ var SystemRoute = BaseRoute.optional();
289
+ var SystemAccessList = z3.array(SystemName.or(EthereumAddress)).default([]);
290
+ var SystemConfig = z3.intersection(
291
+ z3.object({
292
+ route: SystemRoute
293
+ }),
294
+ z3.discriminatedUnion("openAccess", [
295
+ z3.object({
296
+ openAccess: z3.literal(true)
297
+ }),
298
+ z3.object({
299
+ openAccess: z3.literal(false),
300
+ accessList: SystemAccessList
301
+ })
302
+ ])
303
+ );
304
+ var WorldConfig = z3.object({
305
+ baseRoute: BaseRoute.default(""),
306
+ worldContractName: z3.string().optional(),
307
+ overrideSystems: z3.record(SystemName, SystemConfig).default({}),
308
+ excludeSystems: z3.array(SystemName).default([]),
309
+ postDeployScript: z3.string().default("PostDeploy"),
310
+ deploymentInfoDirectory: z3.string().default(".")
311
+ });
312
+ function resolveSystemConfig(systemName, config, existingContracts) {
313
+ const route = config?.route ?? `/${systemName}`;
314
+ const openAccess = config?.openAccess ?? true;
315
+ const accessListAddresses = [];
316
+ const accessListSystems = [];
317
+ const accessList = config && !config.openAccess ? config.accessList : [];
318
+ for (const accessListItem of accessList) {
319
+ if (accessListItem.startsWith("0x")) {
320
+ accessListAddresses.push(accessListItem);
321
+ } else {
322
+ if (existingContracts && !existingContracts.includes(accessListItem)) {
323
+ throw UnrecognizedSystemErrorFactory(["overrideSystems", systemName, "accessList"], accessListItem);
324
+ }
325
+ accessListSystems.push(accessListItem);
326
+ }
327
+ }
328
+ return { route, openAccess, accessListAddresses, accessListSystems };
329
+ }
330
+ function resolveWorldConfig(config, existingContracts) {
331
+ const defaultSystemNames = existingContracts?.filter((name) => name.endsWith("System") && name !== "System") ?? [];
332
+ const overriddenSystemNames = Object.keys(config.overrideSystems);
333
+ if (existingContracts) {
334
+ for (const systemName of overriddenSystemNames) {
335
+ if (!existingContracts.includes(systemName) || systemName === "World") {
336
+ throw UnrecognizedSystemErrorFactory(["overrideSystems", systemName], systemName);
337
+ }
338
+ }
339
+ }
340
+ const systemNames = [.../* @__PURE__ */ new Set([...defaultSystemNames, ...overriddenSystemNames])].filter(
341
+ (name) => !config.excludeSystems.includes(name)
342
+ );
343
+ const resolvedSystems = systemNames.reduce((acc, systemName) => {
344
+ return {
345
+ ...acc,
346
+ [systemName]: resolveSystemConfig(systemName, config.overrideSystems[systemName], existingContracts)
347
+ };
348
+ }, {});
349
+ const { overrideSystems, excludeSystems, ...otherConfig } = config;
350
+ return { ...otherConfig, systems: resolvedSystems };
351
+ }
352
+ async function loadWorldConfig(configPath, existingContracts) {
353
+ const config = await loadConfig(configPath);
354
+ try {
355
+ const parsedConfig = WorldConfig.parse(config);
356
+ return resolveWorldConfig(parsedConfig, existingContracts);
357
+ } catch (error) {
358
+ if (error instanceof ZodError2) {
359
+ throw fromZodErrorCustom(error, "WorldConfig Validation Error");
360
+ } else {
361
+ throw error;
362
+ }
363
+ }
364
+ }
365
+ async function parseWorldConfig(config) {
366
+ return WorldConfig.parse(config);
367
+ }
368
+
369
+ export {
370
+ validateName,
371
+ validateCapitalizedName,
372
+ validateUncapitalizedName,
373
+ validateEnum,
374
+ validateRoute,
375
+ validateBaseRoute,
376
+ validateSingleLevelRoute,
377
+ validateEthereumAddress,
378
+ getDuplicates,
379
+ ObjectName,
380
+ ValueName,
381
+ AnyCaseName,
382
+ UserEnum,
383
+ OrdinaryRoute,
384
+ SingleLevelRoute,
385
+ BaseRoute,
386
+ EthereumAddress,
387
+ StaticSchemaType,
388
+ StoreConfig,
389
+ parseStoreConfig,
390
+ loadConfig,
391
+ loadStoreConfig,
392
+ WorldConfig,
393
+ resolveSystemConfig,
394
+ resolveWorldConfig,
395
+ loadWorldConfig,
396
+ parseWorldConfig
397
+ };