@trustless-work/blocks 0.0.7 → 0.0.8
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/bin/index.js +485 -17
- package/package.json +1 -1
- package/templates/escrows/details/Actions.tsx +144 -149
- package/templates/escrows/details/Entities.tsx +1 -1
- package/templates/escrows/details/EntityCard.tsx +1 -3
- package/templates/escrows/details/EscrowDetailDialog.tsx +16 -16
- package/templates/escrows/details/GeneralInformation.tsx +19 -22
- package/templates/escrows/details/MilestoneCard.tsx +46 -47
- package/templates/escrows/details/MilestoneDetailDialog.tsx +1 -2
- package/templates/escrows/details/Milestones.tsx +0 -5
- package/templates/escrows/details/SuccessReleaseDialog.tsx +4 -6
- package/templates/escrows/escrows-by-role/cards/EscrowsCards.tsx +84 -49
- package/templates/escrows/escrows-by-role/cards/Filters.tsx +3 -5
- package/templates/escrows/escrows-by-role/table/EscrowsTable.tsx +8 -26
- package/templates/escrows/escrows-by-role/table/Filters.tsx +3 -5
- package/templates/escrows/escrows-by-signer/cards/EscrowsCards.tsx +89 -55
- package/templates/escrows/escrows-by-signer/cards/Filters.tsx +3 -5
- package/templates/escrows/escrows-by-signer/table/EscrowsTable.tsx +8 -24
- package/templates/escrows/escrows-by-signer/table/Filters.tsx +3 -5
- package/templates/escrows/multi-release/dispute-milestone/button/DisputeEscrow.tsx +98 -0
- package/templates/escrows/multi-release/initialize-escrow/dialog/InitializeEscrow.tsx +528 -0
- package/templates/escrows/multi-release/initialize-escrow/form/InitializeEscrow.tsx +506 -0
- package/templates/escrows/multi-release/initialize-escrow/shared/schema.ts +179 -0
- package/templates/escrows/multi-release/initialize-escrow/shared/useInitializeEscrow.ts +175 -0
- package/templates/escrows/multi-release/release-milestone/button/ReleaseEscrow.tsx +116 -0
- package/templates/escrows/multi-release/resolve-dispute/button/ResolveDispute.tsx +122 -0
- package/templates/escrows/multi-release/resolve-dispute/dialog/ResolveDispute.tsx +178 -0
- package/templates/escrows/multi-release/resolve-dispute/form/ResolveDispute.tsx +156 -0
- package/templates/escrows/multi-release/resolve-dispute/shared/schema.ts +85 -0
- package/templates/escrows/multi-release/resolve-dispute/shared/useResolveDispute.ts +105 -0
- package/templates/escrows/multi-release/update-escrow/dialog/UpdateEscrow.tsx +471 -0
- package/templates/escrows/multi-release/update-escrow/form/UpdateEscrow.tsx +449 -0
- package/templates/escrows/multi-release/update-escrow/shared/schema.ts +152 -0
- package/templates/escrows/multi-release/update-escrow/shared/useUpdateEscrow.ts +254 -0
- package/templates/escrows/{single-release → single-multi-release}/approve-milestone/button/ApproveMilestone.tsx +20 -7
- package/templates/escrows/{single-release → single-multi-release}/approve-milestone/dialog/ApproveMilestone.tsx +3 -3
- package/templates/escrows/{single-release → single-multi-release}/approve-milestone/form/ApproveMilestone.tsx +3 -3
- package/templates/escrows/{single-release/approve-milestone/shared → single-multi-release/approve-milestone}/useApproveMilestone.ts +16 -16
- package/templates/escrows/{single-release → single-multi-release}/change-milestone-status/button/ChangeMilestoneStatus.tsx +4 -4
- package/templates/escrows/{single-release → single-multi-release}/change-milestone-status/dialog/ChangeMilestoneStatus.tsx +4 -4
- package/templates/escrows/{single-release → single-multi-release}/change-milestone-status/form/ChangeMilestoneStatus.tsx +3 -3
- package/templates/escrows/{single-release/change-milestone-status/shared → single-multi-release/change-milestone-status}/useChangeMilestoneStatus.ts +1 -1
- package/templates/escrows/{single-release → single-multi-release}/fund-escrow/button/FundEscrow.tsx +3 -3
- package/templates/escrows/{single-release → single-multi-release}/fund-escrow/dialog/FundEscrow.tsx +3 -3
- package/templates/escrows/{single-release → single-multi-release}/fund-escrow/form/FundEscrow.tsx +3 -3
- package/templates/escrows/{single-release/fund-escrow/shared → single-multi-release/fund-escrow}/useFundEscrow.ts +1 -1
- package/templates/escrows/single-release/dispute-escrow/button/DisputeEscrow.tsx +2 -2
- package/templates/escrows/single-release/initialize-escrow/dialog/InitializeEscrow.tsx +14 -6
- package/templates/escrows/single-release/initialize-escrow/form/InitializeEscrow.tsx +14 -6
- package/templates/escrows/single-release/initialize-escrow/shared/schema.ts +0 -57
- package/templates/escrows/single-release/initialize-escrow/shared/useInitializeEscrow.ts +42 -1
- package/templates/escrows/single-release/release-escrow/button/ReleaseEscrow.tsx +2 -2
- package/templates/escrows/single-release/resolve-dispute/button/ResolveDispute.tsx +3 -3
- package/templates/escrows/single-release/resolve-dispute/dialog/ResolveDispute.tsx +3 -6
- package/templates/escrows/single-release/resolve-dispute/form/ResolveDispute.tsx +2 -2
- package/templates/escrows/single-release/resolve-dispute/shared/useResolveDispute.ts +14 -1
- package/templates/escrows/single-release/update-escrow/dialog/UpdateEscrow.tsx +2 -2
- package/templates/escrows/single-release/update-escrow/form/UpdateEscrow.tsx +2 -2
- package/templates/escrows/single-release/update-escrow/shared/useUpdateEscrow.ts +12 -7
- package/templates/providers/EscrowDialogsProvider.tsx +1 -3
- package/templates/providers/EscrowProvider.tsx +27 -4
- package/templates/providers/TrustlessWork.tsx +1 -1
- package/templates/escrows/details/ProgressEscrow.tsx +0 -191
- /package/templates/escrows/{single-release/approve-milestone/shared → single-multi-release/approve-milestone}/schema.ts +0 -0
- /package/templates/escrows/{single-release/change-milestone-status/shared → single-multi-release/change-milestone-status}/schema.ts +0 -0
- /package/templates/escrows/{single-release/fund-escrow/shared → single-multi-release/fund-escrow}/schema.ts +0 -0
package/bin/index.js
CHANGED
|
@@ -220,20 +220,211 @@ function parseFlags(argv) {
|
|
|
220
220
|
|
|
221
221
|
function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
222
222
|
const srcFile = path.join(TEMPLATES_DIR, `${name}.tsx`);
|
|
223
|
-
const
|
|
223
|
+
const requestedDir = path.join(TEMPLATES_DIR, name);
|
|
224
|
+
let srcDir = null;
|
|
225
|
+
if (fs.existsSync(requestedDir) && fs.lstatSync(requestedDir).isDirectory()) {
|
|
226
|
+
srcDir = requestedDir;
|
|
227
|
+
} else {
|
|
228
|
+
// Alias: allow multi-release/approve-milestone to fallback to existing source
|
|
229
|
+
if (name.startsWith("escrows/multi-release/approve-milestone")) {
|
|
230
|
+
const altMulti = path.join(
|
|
231
|
+
TEMPLATES_DIR,
|
|
232
|
+
"escrows",
|
|
233
|
+
"multi-release",
|
|
234
|
+
"approve-milestone"
|
|
235
|
+
);
|
|
236
|
+
const altSingle = path.join(
|
|
237
|
+
TEMPLATES_DIR,
|
|
238
|
+
"escrows",
|
|
239
|
+
"single-release",
|
|
240
|
+
"approve-milestone"
|
|
241
|
+
);
|
|
242
|
+
if (fs.existsSync(altMulti) && fs.lstatSync(altMulti).isDirectory()) {
|
|
243
|
+
srcDir = altMulti;
|
|
244
|
+
} else if (
|
|
245
|
+
fs.existsSync(altSingle) &&
|
|
246
|
+
fs.lstatSync(altSingle).isDirectory()
|
|
247
|
+
) {
|
|
248
|
+
srcDir = altSingle;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
224
252
|
const outRoot = path.join(PROJECT_ROOT, "src", "components", "tw-blocks");
|
|
225
253
|
|
|
226
254
|
const config = loadConfig();
|
|
227
255
|
const effectiveUiBase = uiBase || config.uiBase || "@/components/ui";
|
|
256
|
+
let currentEscrowType = null;
|
|
228
257
|
|
|
229
258
|
function writeTransformed(srcPath, destPath) {
|
|
230
259
|
const raw = fs.readFileSync(srcPath, "utf8");
|
|
231
|
-
|
|
260
|
+
let transformed = raw.replaceAll("__UI_BASE__", effectiveUiBase);
|
|
261
|
+
// Resolve details placeholders to either multi-release modules (if present) or local compat
|
|
262
|
+
const applyDetailsPlaceholders = (content) => {
|
|
263
|
+
const resolveImport = (segments, compatFile) => {
|
|
264
|
+
const realWithExt = path.join(
|
|
265
|
+
outRoot,
|
|
266
|
+
"escrows",
|
|
267
|
+
"multi-release",
|
|
268
|
+
...segments
|
|
269
|
+
);
|
|
270
|
+
const realCandidate = [
|
|
271
|
+
realWithExt,
|
|
272
|
+
realWithExt + ".tsx",
|
|
273
|
+
realWithExt + ".ts",
|
|
274
|
+
realWithExt + ".jsx",
|
|
275
|
+
realWithExt + ".js",
|
|
276
|
+
].find((p) => fs.existsSync(p));
|
|
277
|
+
const realNoExt = realCandidate
|
|
278
|
+
? realCandidate.replace(/\.(tsx|ts|jsx|js)$/i, "")
|
|
279
|
+
: null;
|
|
280
|
+
const compatWithExt = path.join(
|
|
281
|
+
path.dirname(destPath),
|
|
282
|
+
"compat",
|
|
283
|
+
compatFile
|
|
284
|
+
);
|
|
285
|
+
const compatCandidate = [
|
|
286
|
+
compatWithExt,
|
|
287
|
+
compatWithExt + ".tsx",
|
|
288
|
+
compatWithExt + ".ts",
|
|
289
|
+
compatWithExt + ".jsx",
|
|
290
|
+
compatWithExt + ".js",
|
|
291
|
+
].find((p) => fs.existsSync(p));
|
|
292
|
+
const compatNoExt = (compatCandidate || compatWithExt).replace(
|
|
293
|
+
/\.(tsx|ts|jsx|js)$/i,
|
|
294
|
+
""
|
|
295
|
+
);
|
|
296
|
+
const target = realNoExt || compatNoExt;
|
|
297
|
+
let rel = path.relative(path.dirname(destPath), target);
|
|
298
|
+
rel = rel.split(path.sep).join("/");
|
|
299
|
+
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
300
|
+
return rel;
|
|
301
|
+
};
|
|
302
|
+
return content
|
|
303
|
+
.replaceAll(
|
|
304
|
+
"__MR_RELEASE_MODULE__",
|
|
305
|
+
resolveImport(
|
|
306
|
+
["release-escrow", "button", "ReleaseEscrow"],
|
|
307
|
+
"ReleaseEscrow"
|
|
308
|
+
)
|
|
309
|
+
)
|
|
310
|
+
.replaceAll(
|
|
311
|
+
"__MR_DISPUTE_MODULE__",
|
|
312
|
+
resolveImport(
|
|
313
|
+
["dispute-escrow", "button", "DisputeEscrow"],
|
|
314
|
+
"DisputeEscrow"
|
|
315
|
+
)
|
|
316
|
+
)
|
|
317
|
+
.replaceAll(
|
|
318
|
+
"__MR_RESOLVE_MODULE__",
|
|
319
|
+
resolveImport(
|
|
320
|
+
["resolve-dispute", "dialog", "ResolveDispute"],
|
|
321
|
+
"ResolveDispute"
|
|
322
|
+
)
|
|
323
|
+
);
|
|
324
|
+
};
|
|
325
|
+
transformed = applyDetailsPlaceholders(transformed);
|
|
326
|
+
if (currentEscrowType) {
|
|
327
|
+
transformed = transformed.replaceAll(
|
|
328
|
+
"__ESCROW_TYPE__",
|
|
329
|
+
currentEscrowType
|
|
330
|
+
);
|
|
331
|
+
}
|
|
232
332
|
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
233
333
|
fs.writeFileSync(destPath, transformed, "utf8");
|
|
234
334
|
console.log(`✅ ${path.relative(PROJECT_ROOT, destPath)} created`);
|
|
235
335
|
}
|
|
236
336
|
|
|
337
|
+
// Generic: materialize any module from templates/escrows/shared/<module>
|
|
338
|
+
if (!srcDir) {
|
|
339
|
+
const m = name.match(
|
|
340
|
+
/^escrows\/(single-release|multi-release)\/([^\/]+)(?:\/(button|dialog|form))?$/
|
|
341
|
+
);
|
|
342
|
+
if (m) {
|
|
343
|
+
const releaseType = m[1];
|
|
344
|
+
const moduleName = m[2];
|
|
345
|
+
const variant = m[3] || null;
|
|
346
|
+
|
|
347
|
+
const sharedModuleDir = path.join(
|
|
348
|
+
TEMPLATES_DIR,
|
|
349
|
+
"escrows",
|
|
350
|
+
"shared",
|
|
351
|
+
moduleName
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
if (
|
|
355
|
+
fs.existsSync(sharedModuleDir) &&
|
|
356
|
+
fs.lstatSync(sharedModuleDir).isDirectory()
|
|
357
|
+
) {
|
|
358
|
+
currentEscrowType = releaseType;
|
|
359
|
+
const destBase = path.join(outRoot, "escrows", releaseType, moduleName);
|
|
360
|
+
|
|
361
|
+
function copyModuleRootFilesInto(targetDir) {
|
|
362
|
+
const entries = fs.readdirSync(sharedModuleDir, {
|
|
363
|
+
withFileTypes: true,
|
|
364
|
+
});
|
|
365
|
+
for (const entry of entries) {
|
|
366
|
+
if (entry.isDirectory()) continue;
|
|
367
|
+
if (!/\.(tsx?|jsx?)$/i.test(entry.name)) continue;
|
|
368
|
+
const entrySrc = path.join(sharedModuleDir, entry.name);
|
|
369
|
+
const entryDest = path.join(targetDir, entry.name);
|
|
370
|
+
writeTransformed(entrySrc, entryDest);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function copyVariant(variantName) {
|
|
375
|
+
const variantSrc = path.join(sharedModuleDir, variantName);
|
|
376
|
+
const variantDest = path.join(destBase, variantName);
|
|
377
|
+
fs.mkdirSync(variantDest, { recursive: true });
|
|
378
|
+
if (
|
|
379
|
+
fs.existsSync(variantSrc) &&
|
|
380
|
+
fs.lstatSync(variantSrc).isDirectory()
|
|
381
|
+
) {
|
|
382
|
+
const stack = [""];
|
|
383
|
+
while (stack.length) {
|
|
384
|
+
const rel = stack.pop();
|
|
385
|
+
const current = path.join(variantSrc, rel);
|
|
386
|
+
const entries = fs.readdirSync(current, { withFileTypes: true });
|
|
387
|
+
for (const entry of entries) {
|
|
388
|
+
const entryRel = path.join(rel, entry.name);
|
|
389
|
+
const entrySrc = path.join(variantSrc, entryRel);
|
|
390
|
+
const entryDest = path.join(variantDest, entryRel);
|
|
391
|
+
if (entry.isDirectory()) {
|
|
392
|
+
stack.push(entryRel);
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (/\.(tsx?|jsx?)$/i.test(entry.name)) {
|
|
396
|
+
writeTransformed(entrySrc, entryDest);
|
|
397
|
+
} else {
|
|
398
|
+
fs.mkdirSync(path.dirname(entryDest), { recursive: true });
|
|
399
|
+
fs.copyFileSync(entrySrc, entryDest);
|
|
400
|
+
console.log(
|
|
401
|
+
`✅ ${path.relative(PROJECT_ROOT, entryDest)} created`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// Always place module-level shared files into the variant directory
|
|
408
|
+
copyModuleRootFilesInto(variantDest);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (variant) {
|
|
412
|
+
copyVariant(variant);
|
|
413
|
+
} else {
|
|
414
|
+
const variants = ["button", "dialog", "form"];
|
|
415
|
+
for (const v of variants) copyVariant(v);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (shouldInstall && fs.existsSync(GLOBAL_DEPS_FILE)) {
|
|
419
|
+
const meta = JSON.parse(fs.readFileSync(GLOBAL_DEPS_FILE, "utf8"));
|
|
420
|
+
installDeps(meta);
|
|
421
|
+
}
|
|
422
|
+
currentEscrowType = null;
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
237
428
|
if (fs.existsSync(srcDir) && fs.lstatSync(srcDir).isDirectory()) {
|
|
238
429
|
const skipDetails =
|
|
239
430
|
name === "escrows/escrows-by-role" ||
|
|
@@ -326,17 +517,20 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
326
517
|
}
|
|
327
518
|
|
|
328
519
|
try {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
const isSingleReleaseInitDialog =
|
|
520
|
+
const isSRRoot = name === "escrows/single-release/approve-milestone";
|
|
521
|
+
const isSRDialog =
|
|
332
522
|
name === "escrows/single-release/approve-milestone/dialog";
|
|
333
|
-
const
|
|
334
|
-
|
|
523
|
+
const isSRForm = name === "escrows/single-release/approve-milestone/form";
|
|
524
|
+
|
|
525
|
+
const isMRRoot = name === "escrows/multi-release/approve-milestone";
|
|
526
|
+
const isMRDialog =
|
|
527
|
+
name === "escrows/multi-release/approve-milestone/dialog";
|
|
528
|
+
const isMRForm = name === "escrows/multi-release/approve-milestone/form";
|
|
335
529
|
|
|
336
530
|
const srcSharedDir = path.join(
|
|
337
531
|
TEMPLATES_DIR,
|
|
338
532
|
"escrows",
|
|
339
|
-
"
|
|
533
|
+
"shared",
|
|
340
534
|
"approve-milestone",
|
|
341
535
|
"shared"
|
|
342
536
|
);
|
|
@@ -352,12 +546,12 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
352
546
|
}
|
|
353
547
|
}
|
|
354
548
|
|
|
355
|
-
if (
|
|
549
|
+
if (isSRRoot || isMRRoot) {
|
|
356
550
|
copySharedInto(path.join(destDir, "dialog"));
|
|
357
551
|
copySharedInto(path.join(destDir, "form"));
|
|
358
|
-
} else if (
|
|
552
|
+
} else if (isSRDialog || isMRDialog) {
|
|
359
553
|
copySharedInto(destDir);
|
|
360
|
-
} else if (
|
|
554
|
+
} else if (isSRForm || isMRForm) {
|
|
361
555
|
copySharedInto(destDir);
|
|
362
556
|
}
|
|
363
557
|
} catch (e) {
|
|
@@ -535,6 +729,132 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
535
729
|
);
|
|
536
730
|
}
|
|
537
731
|
|
|
732
|
+
// Post-copy: materialize shared files for multi-release modules
|
|
733
|
+
try {
|
|
734
|
+
const isMultiInitRoot =
|
|
735
|
+
name === "escrows/multi-release/initialize-escrow";
|
|
736
|
+
const isMultiInitDialog =
|
|
737
|
+
name === "escrows/multi-release/initialize-escrow/dialog";
|
|
738
|
+
const isMultiInitForm =
|
|
739
|
+
name === "escrows/multi-release/initialize-escrow/form";
|
|
740
|
+
|
|
741
|
+
const srcSharedDir = path.join(
|
|
742
|
+
TEMPLATES_DIR,
|
|
743
|
+
"escrows",
|
|
744
|
+
"multi-release",
|
|
745
|
+
"initialize-escrow",
|
|
746
|
+
"shared"
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
function copyMultiInitSharedInto(targetDir) {
|
|
750
|
+
if (!fs.existsSync(srcSharedDir)) return;
|
|
751
|
+
const entries = fs.readdirSync(srcSharedDir, { withFileTypes: true });
|
|
752
|
+
for (const entry of entries) {
|
|
753
|
+
if (!/\.(tsx?|jsx?)$/i.test(entry.name)) continue;
|
|
754
|
+
const entrySrc = path.join(srcSharedDir, entry.name);
|
|
755
|
+
const entryDest = path.join(targetDir, entry.name);
|
|
756
|
+
writeTransformed(entrySrc, entryDest);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
if (isMultiInitRoot) {
|
|
761
|
+
copyMultiInitSharedInto(path.join(destDir, "dialog"));
|
|
762
|
+
copyMultiInitSharedInto(path.join(destDir, "form"));
|
|
763
|
+
} else if (isMultiInitDialog) {
|
|
764
|
+
copyMultiInitSharedInto(destDir);
|
|
765
|
+
} else if (isMultiInitForm) {
|
|
766
|
+
copyMultiInitSharedInto(destDir);
|
|
767
|
+
}
|
|
768
|
+
} catch (e) {
|
|
769
|
+
console.warn(
|
|
770
|
+
"⚠️ Failed to materialize shared multi-release initialize-escrow files:",
|
|
771
|
+
e?.message || e
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
try {
|
|
776
|
+
const isMultiResolveRoot =
|
|
777
|
+
name === "escrows/multi-release/resolve-dispute";
|
|
778
|
+
const isMultiResolveDialog =
|
|
779
|
+
name === "escrows/multi-release/resolve-dispute/dialog";
|
|
780
|
+
const isMultiResolveForm =
|
|
781
|
+
name === "escrows/multi-release/resolve-dispute/form";
|
|
782
|
+
|
|
783
|
+
const srcSharedDir = path.join(
|
|
784
|
+
TEMPLATES_DIR,
|
|
785
|
+
"escrows",
|
|
786
|
+
"multi-release",
|
|
787
|
+
"resolve-dispute",
|
|
788
|
+
"shared"
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
function copyMultiResolveSharedInto(targetDir) {
|
|
792
|
+
if (!fs.existsSync(srcSharedDir)) return;
|
|
793
|
+
const entries = fs.readdirSync(srcSharedDir, { withFileTypes: true });
|
|
794
|
+
for (const entry of entries) {
|
|
795
|
+
if (!/\.(tsx?|jsx?)$/i.test(entry.name)) continue;
|
|
796
|
+
const entrySrc = path.join(srcSharedDir, entry.name);
|
|
797
|
+
const entryDest = path.join(targetDir, entry.name);
|
|
798
|
+
writeTransformed(entrySrc, entryDest);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if (isMultiResolveRoot) {
|
|
803
|
+
copyMultiResolveSharedInto(path.join(destDir, "dialog"));
|
|
804
|
+
copyMultiResolveSharedInto(path.join(destDir, "form"));
|
|
805
|
+
} else if (isMultiResolveDialog) {
|
|
806
|
+
copyMultiResolveSharedInto(destDir);
|
|
807
|
+
} else if (isMultiResolveForm) {
|
|
808
|
+
copyMultiResolveSharedInto(destDir);
|
|
809
|
+
}
|
|
810
|
+
} catch (e) {
|
|
811
|
+
console.warn(
|
|
812
|
+
"⚠️ Failed to materialize shared multi-release resolve-dispute files:",
|
|
813
|
+
e?.message || e
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
try {
|
|
818
|
+
const isMultiUpdateRoot = name === "escrows/multi-release/update-escrow";
|
|
819
|
+
const isMultiUpdateDialog =
|
|
820
|
+
name === "escrows/multi-release/update-escrow/dialog";
|
|
821
|
+
const isMultiUpdateForm =
|
|
822
|
+
name === "escrows/multi-release/update-escrow/form";
|
|
823
|
+
|
|
824
|
+
const srcSharedDir = path.join(
|
|
825
|
+
TEMPLATES_DIR,
|
|
826
|
+
"escrows",
|
|
827
|
+
"multi-release",
|
|
828
|
+
"update-escrow",
|
|
829
|
+
"shared"
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
function copyMultiUpdateSharedInto(targetDir) {
|
|
833
|
+
if (!fs.existsSync(srcSharedDir)) return;
|
|
834
|
+
const entries = fs.readdirSync(srcSharedDir, { withFileTypes: true });
|
|
835
|
+
for (const entry of entries) {
|
|
836
|
+
if (!/\.(tsx?|jsx?)$/i.test(entry.name)) continue;
|
|
837
|
+
const entrySrc = path.join(srcSharedDir, entry.name);
|
|
838
|
+
const entryDest = path.join(targetDir, entry.name);
|
|
839
|
+
writeTransformed(entrySrc, entryDest);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
if (isMultiUpdateRoot) {
|
|
844
|
+
copyMultiUpdateSharedInto(path.join(destDir, "dialog"));
|
|
845
|
+
copyMultiUpdateSharedInto(path.join(destDir, "form"));
|
|
846
|
+
} else if (isMultiUpdateDialog) {
|
|
847
|
+
copyMultiUpdateSharedInto(destDir);
|
|
848
|
+
} else if (isMultiUpdateForm) {
|
|
849
|
+
copyMultiUpdateSharedInto(destDir);
|
|
850
|
+
}
|
|
851
|
+
} catch (e) {
|
|
852
|
+
console.warn(
|
|
853
|
+
"⚠️ Failed to materialize shared multi-release update-escrow files:",
|
|
854
|
+
e?.message || e
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
|
|
538
858
|
// If adding the whole single-release bundle, materialize all shared files
|
|
539
859
|
try {
|
|
540
860
|
if (name === "escrows/single-release") {
|
|
@@ -551,8 +871,8 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
551
871
|
const srcSharedDir = path.join(
|
|
552
872
|
TEMPLATES_DIR,
|
|
553
873
|
"escrows",
|
|
554
|
-
"single-release",
|
|
555
|
-
mod,
|
|
874
|
+
mod === "approve-milestone" ? "shared" : "single-release",
|
|
875
|
+
mod === "approve-milestone" ? "approve-milestone" : mod,
|
|
556
876
|
"shared"
|
|
557
877
|
);
|
|
558
878
|
if (!fs.existsSync(srcSharedDir)) continue;
|
|
@@ -580,6 +900,48 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
580
900
|
);
|
|
581
901
|
}
|
|
582
902
|
|
|
903
|
+
// If adding the whole multi-release bundle, materialize all shared files
|
|
904
|
+
try {
|
|
905
|
+
if (name === "escrows/multi-release") {
|
|
906
|
+
const modules = [
|
|
907
|
+
"initialize-escrow",
|
|
908
|
+
"resolve-dispute",
|
|
909
|
+
"update-escrow",
|
|
910
|
+
];
|
|
911
|
+
|
|
912
|
+
for (const mod of modules) {
|
|
913
|
+
const srcSharedDir = path.join(
|
|
914
|
+
TEMPLATES_DIR,
|
|
915
|
+
"escrows",
|
|
916
|
+
"multi-release",
|
|
917
|
+
mod,
|
|
918
|
+
"shared"
|
|
919
|
+
);
|
|
920
|
+
if (!fs.existsSync(srcSharedDir)) continue;
|
|
921
|
+
|
|
922
|
+
const targets = [
|
|
923
|
+
path.join(destDir, mod, "dialog"),
|
|
924
|
+
path.join(destDir, mod, "form"),
|
|
925
|
+
];
|
|
926
|
+
|
|
927
|
+
const entries = fs.readdirSync(srcSharedDir, { withFileTypes: true });
|
|
928
|
+
for (const entry of entries) {
|
|
929
|
+
if (!/\.(tsx?|jsx?)$/i.test(entry.name)) continue;
|
|
930
|
+
const entrySrc = path.join(srcSharedDir, entry.name);
|
|
931
|
+
for (const t of targets) {
|
|
932
|
+
const entryDest = path.join(t, entry.name);
|
|
933
|
+
writeTransformed(entrySrc, entryDest);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
} catch (e) {
|
|
939
|
+
console.warn(
|
|
940
|
+
"⚠️ Failed to materialize shared files for multi-release bundle:",
|
|
941
|
+
e?.message || e
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
|
|
583
945
|
// If adding the root escrows bundle, also materialize single-release shared files
|
|
584
946
|
try {
|
|
585
947
|
if (name === "escrows") {
|
|
@@ -597,8 +959,8 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
597
959
|
const srcSharedDir = path.join(
|
|
598
960
|
TEMPLATES_DIR,
|
|
599
961
|
"escrows",
|
|
600
|
-
"single-release",
|
|
601
|
-
mod,
|
|
962
|
+
mod === "approve-milestone" ? "shared" : "single-release",
|
|
963
|
+
mod === "approve-milestone" ? "approve-milestone" : mod,
|
|
602
964
|
"shared"
|
|
603
965
|
);
|
|
604
966
|
if (!fs.existsSync(srcSharedDir)) continue;
|
|
@@ -625,6 +987,49 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
|
|
|
625
987
|
e?.message || e
|
|
626
988
|
);
|
|
627
989
|
}
|
|
990
|
+
|
|
991
|
+
// If adding the root escrows bundle, also materialize multi-release shared files
|
|
992
|
+
try {
|
|
993
|
+
if (name === "escrows") {
|
|
994
|
+
const modules = [
|
|
995
|
+
"initialize-escrow",
|
|
996
|
+
"resolve-dispute",
|
|
997
|
+
"update-escrow",
|
|
998
|
+
];
|
|
999
|
+
|
|
1000
|
+
const baseTarget = path.join(destDir, "multi-release");
|
|
1001
|
+
for (const mod of modules) {
|
|
1002
|
+
const srcSharedDir = path.join(
|
|
1003
|
+
TEMPLATES_DIR,
|
|
1004
|
+
"escrows",
|
|
1005
|
+
"multi-release",
|
|
1006
|
+
mod,
|
|
1007
|
+
"shared"
|
|
1008
|
+
);
|
|
1009
|
+
if (!fs.existsSync(srcSharedDir)) continue;
|
|
1010
|
+
|
|
1011
|
+
const targets = [
|
|
1012
|
+
path.join(baseTarget, mod, "dialog"),
|
|
1013
|
+
path.join(baseTarget, mod, "form"),
|
|
1014
|
+
];
|
|
1015
|
+
|
|
1016
|
+
const entries = fs.readdirSync(srcSharedDir, { withFileTypes: true });
|
|
1017
|
+
for (const entry of entries) {
|
|
1018
|
+
if (!/\.(tsx?|jsx?)$/i.test(entry.name)) continue;
|
|
1019
|
+
const entrySrc = path.join(srcSharedDir, entry.name);
|
|
1020
|
+
for (const t of targets) {
|
|
1021
|
+
const entryDest = path.join(t, entry.name);
|
|
1022
|
+
writeTransformed(entrySrc, entryDest);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
} catch (e) {
|
|
1028
|
+
console.warn(
|
|
1029
|
+
"⚠️ Failed to materialize shared files for escrows root (multi-release):",
|
|
1030
|
+
e?.message || e
|
|
1031
|
+
);
|
|
1032
|
+
}
|
|
628
1033
|
} else if (fs.existsSync(srcFile)) {
|
|
629
1034
|
fs.mkdirSync(outRoot, { recursive: true });
|
|
630
1035
|
const destFile = path.join(outRoot, name + ".tsx");
|
|
@@ -652,7 +1057,69 @@ function copySharedDetailsInto(targetRelativeDir, { uiBase } = {}) {
|
|
|
652
1057
|
|
|
653
1058
|
function writeTransformed(srcPath, destPath) {
|
|
654
1059
|
const raw = fs.readFileSync(srcPath, "utf8");
|
|
655
|
-
|
|
1060
|
+
let transformed = raw.replaceAll("__UI_BASE__", effectiveUiBase);
|
|
1061
|
+
// Resolve details placeholders to either multi-release modules (if present) or local compat
|
|
1062
|
+
const resolveImport = (segments, compatFile) => {
|
|
1063
|
+
const realWithExt = path.join(
|
|
1064
|
+
outRoot,
|
|
1065
|
+
"escrows",
|
|
1066
|
+
"multi-release",
|
|
1067
|
+
...segments
|
|
1068
|
+
);
|
|
1069
|
+
const realCandidate = [
|
|
1070
|
+
realWithExt,
|
|
1071
|
+
realWithExt + ".tsx",
|
|
1072
|
+
realWithExt + ".ts",
|
|
1073
|
+
realWithExt + ".jsx",
|
|
1074
|
+
realWithExt + ".js",
|
|
1075
|
+
].find((p) => fs.existsSync(p));
|
|
1076
|
+
const realNoExt = realCandidate
|
|
1077
|
+
? realCandidate.replace(/\.(tsx|ts|jsx|js)$/i, "")
|
|
1078
|
+
: null;
|
|
1079
|
+
const compatWithExt = path.join(
|
|
1080
|
+
path.dirname(destPath),
|
|
1081
|
+
"compat",
|
|
1082
|
+
compatFile
|
|
1083
|
+
);
|
|
1084
|
+
const compatCandidate = [
|
|
1085
|
+
compatWithExt,
|
|
1086
|
+
compatWithExt + ".tsx",
|
|
1087
|
+
compatWithExt + ".ts",
|
|
1088
|
+
compatWithExt + ".jsx",
|
|
1089
|
+
compatWithExt + ".js",
|
|
1090
|
+
].find((p) => fs.existsSync(p));
|
|
1091
|
+
const compatNoExt = (compatCandidate || compatWithExt).replace(
|
|
1092
|
+
/\.(tsx|ts|jsx|js)$/i,
|
|
1093
|
+
""
|
|
1094
|
+
);
|
|
1095
|
+
const target = realNoExt || compatNoExt;
|
|
1096
|
+
let rel = path.relative(path.dirname(destPath), target);
|
|
1097
|
+
rel = rel.split(path.sep).join("/");
|
|
1098
|
+
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
1099
|
+
return rel;
|
|
1100
|
+
};
|
|
1101
|
+
transformed = transformed
|
|
1102
|
+
.replaceAll(
|
|
1103
|
+
"__MR_RELEASE_MODULE__",
|
|
1104
|
+
resolveImport(
|
|
1105
|
+
["release-escrow", "button", "ReleaseEscrow"],
|
|
1106
|
+
"ReleaseEscrow"
|
|
1107
|
+
)
|
|
1108
|
+
)
|
|
1109
|
+
.replaceAll(
|
|
1110
|
+
"__MR_DISPUTE_MODULE__",
|
|
1111
|
+
resolveImport(
|
|
1112
|
+
["dispute-escrow", "button", "DisputeEscrow"],
|
|
1113
|
+
"DisputeEscrow"
|
|
1114
|
+
)
|
|
1115
|
+
)
|
|
1116
|
+
.replaceAll(
|
|
1117
|
+
"__MR_RESOLVE_MODULE__",
|
|
1118
|
+
resolveImport(
|
|
1119
|
+
["resolve-dispute", "dialog", "ResolveDispute"],
|
|
1120
|
+
"ResolveDispute"
|
|
1121
|
+
)
|
|
1122
|
+
);
|
|
656
1123
|
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
657
1124
|
fs.writeFileSync(destPath, transformed, "utf8");
|
|
658
1125
|
console.log(`✅ ${path.relative(PROJECT_ROOT, destPath)} created`);
|
|
@@ -856,7 +1323,7 @@ if (args[0] === "init") {
|
|
|
856
1323
|
}
|
|
857
1324
|
|
|
858
1325
|
const addShadcn = await promptYesNo(
|
|
859
|
-
"Add shadcn components (button, input, form, card, sonner, checkbox, dialog, textarea, sonner, select, table, calendar, popover, separator, calendar-05, badge, sheet, tabs, avatar)?",
|
|
1326
|
+
"Add shadcn components (button, input, form, card, sonner, checkbox, dialog, textarea, sonner, select, table, calendar, popover, separator, calendar-05, badge, sheet, tabs, avatar, tooltip)?",
|
|
860
1327
|
true
|
|
861
1328
|
);
|
|
862
1329
|
if (addShadcn) {
|
|
@@ -883,6 +1350,7 @@ if (args[0] === "init") {
|
|
|
883
1350
|
"sheet",
|
|
884
1351
|
"tabs",
|
|
885
1352
|
"avatar",
|
|
1353
|
+
"tooltip",
|
|
886
1354
|
]);
|
|
887
1355
|
});
|
|
888
1356
|
} else {
|