everything-dev 1.15.0 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/init.cjs +6 -18
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +6 -18
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/prompts.cjs +8 -8
- package/dist/cli/prompts.cjs.map +1 -1
- package/dist/cli/prompts.mjs +8 -8
- package/dist/cli/prompts.mjs.map +1 -1
- package/dist/cli/upgrade.cjs +75 -7
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +74 -8
- package/dist/cli/upgrade.mjs.map +1 -1
- package/dist/cli.cjs +2 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +2 -0
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +2 -24
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -25
- package/dist/config.mjs.map +1 -1
- package/dist/contract.cjs +2 -0
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +10 -6
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +10 -6
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.meta.cjs +2 -2
- package/dist/contract.meta.cjs.map +1 -1
- package/dist/contract.meta.d.cts +2 -2
- package/dist/contract.meta.d.mts +2 -2
- package/dist/contract.meta.mjs +2 -2
- package/dist/contract.meta.mjs.map +1 -1
- package/dist/contract.mjs +2 -0
- package/dist/contract.mjs.map +1 -1
- package/dist/fastkv.cjs +0 -45
- package/dist/fastkv.cjs.map +1 -1
- package/dist/fastkv.d.cts +1 -19
- package/dist/fastkv.d.cts.map +1 -1
- package/dist/fastkv.d.mts +1 -19
- package/dist/fastkv.d.mts.map +1 -1
- package/dist/fastkv.mjs +1 -44
- package/dist/fastkv.mjs.map +1 -1
- package/dist/index.cjs +0 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/merge.cjs +6 -11
- package/dist/merge.cjs.map +1 -1
- package/dist/merge.d.cts +1 -1
- package/dist/merge.d.cts.map +1 -1
- package/dist/merge.d.mts +1 -1
- package/dist/merge.d.mts.map +1 -1
- package/dist/merge.mjs +6 -11
- package/dist/merge.mjs.map +1 -1
- package/dist/near-cli.cjs +29 -52
- package/dist/near-cli.cjs.map +1 -1
- package/dist/near-cli.mjs +29 -52
- package/dist/near-cli.mjs.map +1 -1
- package/dist/plugin.cjs +36 -38
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +6 -4
- package/dist/plugin.d.mts +6 -4
- package/dist/plugin.mjs +36 -38
- package/dist/plugin.mjs.map +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/package.json +2 -1
- package/src/cli/init.ts +4 -24
- package/src/cli/prompts.ts +12 -8
- package/src/cli/upgrade.ts +117 -6
- package/src/cli.ts +6 -0
- package/src/config.ts +5 -34
- package/src/contract.meta.ts +2 -2
- package/src/contract.ts +2 -0
- package/src/fastkv.ts +0 -72
- package/src/merge.ts +8 -19
- package/src/near-cli.ts +42 -69
- package/src/plugin.ts +53 -47
package/src/cli/upgrade.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { existsSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
3
5
|
import { glob } from "glob";
|
|
4
6
|
import type { UpgradeOptions, UpgradeResult } from "../contract";
|
|
7
|
+
import { resolveExtendsRef } from "../merge";
|
|
8
|
+
import { saveBosConfig } from "../utils/save-config";
|
|
5
9
|
import { readInstalledFrameworkVersion } from "./framework-version";
|
|
6
|
-
import { runBunInstall, runTypesGen } from "./init";
|
|
10
|
+
import { fetchParentConfig, runBunInstall, runTypesGen } from "./init";
|
|
7
11
|
import { syncTemplate } from "./sync";
|
|
8
12
|
|
|
9
13
|
const FRAMEWORK_PACKAGES = ["everything-dev", "every-plugin"];
|
|
@@ -47,6 +51,105 @@ interface NpmPackageInfo {
|
|
|
47
51
|
version: string;
|
|
48
52
|
}
|
|
49
53
|
|
|
54
|
+
function getExtendsRef(config: Record<string, unknown>): string | undefined {
|
|
55
|
+
if (typeof config.extends === "string") {
|
|
56
|
+
return config.extends;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (config.extends && typeof config.extends === "object") {
|
|
60
|
+
return resolveExtendsRef(config.extends as Record<string, string>, "production");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function parseBosRef(ref: string): { account: string; gateway: string } | null {
|
|
67
|
+
const match = ref.match(/^bos:\/\/([^/]+)\/(.+)$/);
|
|
68
|
+
if (!match?.[1] || !match[2]) return null;
|
|
69
|
+
return { account: match[1], gateway: match[2] };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function loadParentPluginOptions(projectDir: string): Promise<{
|
|
73
|
+
localConfig: Record<string, unknown>;
|
|
74
|
+
parentPlugins: Record<string, unknown>;
|
|
75
|
+
newPluginKeys: string[];
|
|
76
|
+
} | null> {
|
|
77
|
+
const configPath = join(projectDir, "bos.config.json");
|
|
78
|
+
if (!existsSync(configPath)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const localConfig = JSON.parse(readFileSync(configPath, "utf-8")) as Record<string, unknown>;
|
|
83
|
+
const extendsRef = getExtendsRef(localConfig);
|
|
84
|
+
if (!extendsRef?.startsWith("bos://")) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const parsed = parseBosRef(extendsRef);
|
|
89
|
+
if (!parsed) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let parentConfig: Record<string, unknown>;
|
|
94
|
+
try {
|
|
95
|
+
parentConfig = await fetchParentConfig(parsed.account, parsed.gateway);
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const parentPlugins =
|
|
101
|
+
parentConfig.plugins && typeof parentConfig.plugins === "object"
|
|
102
|
+
? (parentConfig.plugins as Record<string, unknown>)
|
|
103
|
+
: {};
|
|
104
|
+
const localPlugins =
|
|
105
|
+
localConfig.plugins && typeof localConfig.plugins === "object"
|
|
106
|
+
? (localConfig.plugins as Record<string, unknown>)
|
|
107
|
+
: {};
|
|
108
|
+
|
|
109
|
+
const newPluginKeys = Object.keys(parentPlugins).filter((key) => !(key in localPlugins));
|
|
110
|
+
return { localConfig, parentPlugins, newPluginKeys };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function addSelectedParentPlugins(projectDir: string): Promise<string[]> {
|
|
114
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const pluginOptions = await loadParentPluginOptions(projectDir);
|
|
119
|
+
if (!pluginOptions || pluginOptions.newPluginKeys.length === 0) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const selectedValue = await p.multiselect({
|
|
124
|
+
message: "Select new plugins from parent:",
|
|
125
|
+
options: pluginOptions.newPluginKeys.map((key) => ({ value: key, label: key })),
|
|
126
|
+
required: false,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (p.isCancel(selectedValue)) {
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const selected = selectedValue as string[];
|
|
134
|
+
if (selected.length === 0) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const localPlugins =
|
|
139
|
+
pluginOptions.localConfig.plugins && typeof pluginOptions.localConfig.plugins === "object"
|
|
140
|
+
? (pluginOptions.localConfig.plugins as Record<string, unknown>)
|
|
141
|
+
: {};
|
|
142
|
+
const nextPlugins = { ...localPlugins };
|
|
143
|
+
for (const key of selected) {
|
|
144
|
+
nextPlugins[key] = pluginOptions.parentPlugins[key];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
pluginOptions.localConfig.plugins = nextPlugins;
|
|
148
|
+
await saveBosConfig(projectDir, pluginOptions.localConfig);
|
|
149
|
+
|
|
150
|
+
return selected;
|
|
151
|
+
}
|
|
152
|
+
|
|
50
153
|
async function fetchLatestNpmVersion(packageName: string): Promise<string | null> {
|
|
51
154
|
try {
|
|
52
155
|
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
@@ -269,6 +372,7 @@ export async function upgradeTemplate(
|
|
|
269
372
|
|
|
270
373
|
if (options.dryRun) {
|
|
271
374
|
let changelogUrl: string | undefined;
|
|
375
|
+
const pluginOptions = options.noSync ? null : await loadParentPluginOptions(projectDir);
|
|
272
376
|
if (hasUpdates) {
|
|
273
377
|
const configPath = join(projectDir, "bos.config.json");
|
|
274
378
|
let parentConfig: Record<string, unknown> | null = null;
|
|
@@ -289,6 +393,7 @@ export async function upgradeTemplate(
|
|
|
289
393
|
...packages,
|
|
290
394
|
...catalogVersionUpdates.map((u) => ({ name: u.name, from: u.from, to: u.to })),
|
|
291
395
|
],
|
|
396
|
+
availablePlugins: pluginOptions?.newPluginKeys,
|
|
292
397
|
changelogUrl,
|
|
293
398
|
};
|
|
294
399
|
}
|
|
@@ -315,13 +420,13 @@ export async function upgradeTemplate(
|
|
|
315
420
|
}
|
|
316
421
|
}
|
|
317
422
|
|
|
318
|
-
if (hasUpdates && !options.noInstall) {
|
|
319
|
-
await runBunInstall(projectDir);
|
|
320
|
-
await runTypesGen(projectDir);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
423
|
let syncResult: UpgradeResult["sync"];
|
|
424
|
+
let addedPlugins: string[] = [];
|
|
324
425
|
if (!options.noSync) {
|
|
426
|
+
if (!options.dryRun) {
|
|
427
|
+
addedPlugins = await addSelectedParentPlugins(projectDir);
|
|
428
|
+
}
|
|
429
|
+
|
|
325
430
|
syncResult = await syncTemplate(projectDir, {
|
|
326
431
|
dryRun: false,
|
|
327
432
|
force: options.force,
|
|
@@ -329,6 +434,11 @@ export async function upgradeTemplate(
|
|
|
329
434
|
});
|
|
330
435
|
}
|
|
331
436
|
|
|
437
|
+
if ((hasUpdates || addedPlugins.length > 0) && !options.noInstall) {
|
|
438
|
+
await runBunInstall(projectDir);
|
|
439
|
+
await runTypesGen(projectDir);
|
|
440
|
+
}
|
|
441
|
+
|
|
332
442
|
const migratedFiles = await rewriteLegacyUiImports(projectDir);
|
|
333
443
|
for (const file of OBSOLETE_FILES) {
|
|
334
444
|
const filePath = join(projectDir, file);
|
|
@@ -359,6 +469,7 @@ export async function upgradeTemplate(
|
|
|
359
469
|
],
|
|
360
470
|
sync: syncResult,
|
|
361
471
|
migrated: migratedFiles.length > 0 ? migratedFiles : undefined,
|
|
472
|
+
selectedPlugins: addedPlugins.length > 0 ? addedPlugins : undefined,
|
|
362
473
|
changelogUrl,
|
|
363
474
|
};
|
|
364
475
|
}
|
package/src/cli.ts
CHANGED
|
@@ -240,6 +240,12 @@ async function main() {
|
|
|
240
240
|
if (result.changelogUrl) {
|
|
241
241
|
console.log(` ${colors.dim("Changelog:")} ${result.changelogUrl}`);
|
|
242
242
|
}
|
|
243
|
+
if (result.availablePlugins && result.availablePlugins.length > 0) {
|
|
244
|
+
console.log(` ${colors.dim("New parent plugins:")} ${result.availablePlugins.join(", ")}`);
|
|
245
|
+
}
|
|
246
|
+
if (result.selectedPlugins && result.selectedPlugins.length > 0) {
|
|
247
|
+
console.log(` ${colors.dim("Added plugins:")} ${result.selectedPlugins.join(", ")}`);
|
|
248
|
+
}
|
|
243
249
|
if (result.sync) {
|
|
244
250
|
const sync = result.sync;
|
|
245
251
|
if (sync.updated.length > 0) {
|
package/src/config.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
-
import { fetchBosConfigFromFastKv
|
|
3
|
+
import { fetchBosConfigFromFastKv } from "./fastkv";
|
|
4
4
|
import {
|
|
5
5
|
type BosEnv,
|
|
6
6
|
isPlainObject,
|
|
@@ -546,31 +546,6 @@ async function resolveRemotePluginRuntimeName(baseUrl: string, fallback: string)
|
|
|
546
546
|
}
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
-
interface ResolvedBosPlugin {
|
|
550
|
-
url: string;
|
|
551
|
-
integrity?: string;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
async function resolveBosPluginUrl(bosUrl: string): Promise<ResolvedBosPlugin | null> {
|
|
555
|
-
const parsed = parsePluginBosUrl(bosUrl);
|
|
556
|
-
if (!parsed) return null;
|
|
557
|
-
|
|
558
|
-
try {
|
|
559
|
-
const entry = await fetchPluginFromRegistry(parsed.accountId, parsed.pluginName);
|
|
560
|
-
if (!entry) return null;
|
|
561
|
-
|
|
562
|
-
const cdnUrl = entry.metadata.cdnUrl;
|
|
563
|
-
if (!cdnUrl) return null;
|
|
564
|
-
|
|
565
|
-
return {
|
|
566
|
-
url: cdnUrl,
|
|
567
|
-
integrity: entry.metadata.integrity ?? undefined,
|
|
568
|
-
};
|
|
569
|
-
} catch {
|
|
570
|
-
return null;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
549
|
async function buildRuntimePluginConfig(
|
|
575
550
|
pluginId: string,
|
|
576
551
|
config: BosConfigInput,
|
|
@@ -586,16 +561,12 @@ async function buildRuntimePluginConfig(
|
|
|
586
561
|
const sourceProduction = typeof source.production === "string" ? source.production : undefined;
|
|
587
562
|
const proxy = typeof apiConfig.proxy === "string" ? apiConfig.proxy : undefined;
|
|
588
563
|
const development = apiDevelopment ?? sourceDevelopment;
|
|
589
|
-
|
|
564
|
+
const production = apiProduction ?? sourceProduction;
|
|
590
565
|
|
|
591
566
|
if (production?.startsWith("bos://")) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
if (resolved.integrity && env === "production") {
|
|
596
|
-
source.integrity = resolved.integrity;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
567
|
+
throw new Error(
|
|
568
|
+
`Plugin "${pluginId}" has unsupported production target "${production}". Use extends: "bos://account/domain" for plugin configs or a CDN URL for production.`,
|
|
569
|
+
);
|
|
599
570
|
}
|
|
600
571
|
|
|
601
572
|
const runtimeTarget =
|
package/src/contract.meta.ts
CHANGED
|
@@ -44,7 +44,7 @@ export const cliCommandMeta = {
|
|
|
44
44
|
fields: {
|
|
45
45
|
source: {
|
|
46
46
|
positional: true,
|
|
47
|
-
description: "Plugin source (local:path, bos://account/
|
|
47
|
+
description: "Plugin source (local:path, bos://account/domain, or URL)",
|
|
48
48
|
},
|
|
49
49
|
as: { description: "Plugin alias" },
|
|
50
50
|
production: { description: "Production URL override" },
|
|
@@ -113,7 +113,7 @@ export const cliCommandMeta = {
|
|
|
113
113
|
upgrade: {
|
|
114
114
|
commandPath: ["upgrade"],
|
|
115
115
|
summary: "Upgrade framework packages and sync template files",
|
|
116
|
-
interactive:
|
|
116
|
+
interactive: true,
|
|
117
117
|
fields: {
|
|
118
118
|
dryRun: { description: "Preview changes without writing" },
|
|
119
119
|
force: { description: "Overwrite user-modified files during sync" },
|
package/src/contract.ts
CHANGED
|
@@ -201,6 +201,8 @@ export const UpgradeResultSchema = z.object({
|
|
|
201
201
|
),
|
|
202
202
|
sync: SyncResultSchema.optional(),
|
|
203
203
|
migrated: z.array(z.string()).optional(),
|
|
204
|
+
availablePlugins: z.array(z.string()).optional(),
|
|
205
|
+
selectedPlugins: z.array(z.string()).optional(),
|
|
204
206
|
changelogUrl: z.string().optional(),
|
|
205
207
|
error: z.string().optional(),
|
|
206
208
|
});
|
package/src/fastkv.ts
CHANGED
|
@@ -139,78 +139,6 @@ export interface PluginManifest {
|
|
|
139
139
|
additionalExports?: Array<{ path: string; exports: string[]; sha256: string }>;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
export interface PluginMetadata {
|
|
143
|
-
title: string | null;
|
|
144
|
-
description: string | null;
|
|
145
|
-
repoUrl: string | null;
|
|
146
|
-
version: string;
|
|
147
|
-
publishedAt: string;
|
|
148
|
-
cdnUrl: string;
|
|
149
|
-
integrity: string | null;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export interface PluginRegistryEntry {
|
|
153
|
-
manifest: PluginManifest;
|
|
154
|
-
metadata: PluginMetadata;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export function parsePluginBosUrl(
|
|
158
|
-
source: string,
|
|
159
|
-
): { accountId: string; pluginName: string } | null {
|
|
160
|
-
if (!source.startsWith("bos://")) return null;
|
|
161
|
-
const match = source.match(/^bos:\/\/([^/]+)\/plugins\/([^/]+)$/);
|
|
162
|
-
if (!match?.[1] || !match[2]) return null;
|
|
163
|
-
return { accountId: match[1], pluginName: match[2] };
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
async function fetchKvValue(accountId: string, key: string): Promise<unknown | null> {
|
|
167
|
-
const payload = await fetchJson<FastKvListResponse>(
|
|
168
|
-
`${getFastKvBaseUrlForAccount(accountId)}/v0/latest/${encodeURIComponent(getRegistryNamespaceForAccount(accountId))}/${encodeURIComponent(accountId)}`,
|
|
169
|
-
{
|
|
170
|
-
method: "POST",
|
|
171
|
-
body: JSON.stringify({ key, limit: 1 }),
|
|
172
|
-
},
|
|
173
|
-
);
|
|
174
|
-
const value = payload?.entries?.find(Boolean)?.value;
|
|
175
|
-
if (value == null) return null;
|
|
176
|
-
if (typeof value === "string") {
|
|
177
|
-
try {
|
|
178
|
-
return JSON.parse(value);
|
|
179
|
-
} catch {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return value;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export async function fetchPluginFromRegistry(
|
|
187
|
-
accountId: string,
|
|
188
|
-
pluginName: string,
|
|
189
|
-
): Promise<PluginRegistryEntry | null> {
|
|
190
|
-
const manifestKey = `plugins/${accountId}/${pluginName}/manifest.json`;
|
|
191
|
-
const metadataKey = `plugins/${accountId}/${pluginName}/metadata`;
|
|
192
|
-
|
|
193
|
-
const [rawManifest, rawMetadata] = await Promise.all([
|
|
194
|
-
fetchKvValue(accountId, manifestKey),
|
|
195
|
-
fetchKvValue(accountId, metadataKey),
|
|
196
|
-
]);
|
|
197
|
-
|
|
198
|
-
if (!rawManifest || typeof rawManifest !== "object") return null;
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
manifest: rawManifest as PluginManifest,
|
|
202
|
-
metadata: (rawMetadata ?? {
|
|
203
|
-
title: null,
|
|
204
|
-
description: null,
|
|
205
|
-
repoUrl: null,
|
|
206
|
-
version: "",
|
|
207
|
-
publishedAt: "",
|
|
208
|
-
cdnUrl: "",
|
|
209
|
-
integrity: null,
|
|
210
|
-
}) as PluginMetadata,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
|
|
214
142
|
export async function fetchRemotePluginManifest(cdnUrl: string): Promise<PluginManifest | null> {
|
|
215
143
|
try {
|
|
216
144
|
const baseUrl = cdnUrl.replace(/\/$/, "");
|
package/src/merge.ts
CHANGED
|
@@ -5,6 +5,8 @@ export const BOS_CONFIG_ORDER = [
|
|
|
5
5
|
"extends",
|
|
6
6
|
"account",
|
|
7
7
|
"domain",
|
|
8
|
+
"title",
|
|
9
|
+
"description",
|
|
8
10
|
"testnet",
|
|
9
11
|
"staging",
|
|
10
12
|
"repository",
|
|
@@ -93,28 +95,15 @@ export function mergeBosConfigWithExtends(
|
|
|
93
95
|
parent: BosConfigInput,
|
|
94
96
|
child: BosConfigInput,
|
|
95
97
|
): BosConfigInput {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
for (const [key, rawValue] of Object.entries(child.plugins)) {
|
|
101
|
-
const value = rawValue as unknown;
|
|
102
|
-
if (value === null || value === false) {
|
|
103
|
-
delete plugins[key];
|
|
104
|
-
} else if (isPlainObject(plugins[key]) && isPlainObject(value)) {
|
|
105
|
-
plugins[key] = bosConfigMerger(
|
|
106
|
-
value as Record<string, unknown>,
|
|
107
|
-
plugins[key] as Record<string, unknown>,
|
|
108
|
-
);
|
|
109
|
-
} else {
|
|
110
|
-
plugins[key] = value;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
(merged as Record<string, unknown>).plugins = plugins;
|
|
114
|
-
} else if (child.plugins !== undefined) {
|
|
98
|
+
const { plugins: _ignoredParentPlugins, ...parentWithoutPlugins } = parent;
|
|
99
|
+
const merged = bosConfigMerger(child, parentWithoutPlugins) as BosConfigInput;
|
|
100
|
+
|
|
101
|
+
if (child.plugins !== undefined && isPlainObject(child.plugins)) {
|
|
115
102
|
(merged as Record<string, unknown>).plugins = cleanNullSentinels(
|
|
116
103
|
child.plugins as Record<string, unknown>,
|
|
117
104
|
);
|
|
105
|
+
} else {
|
|
106
|
+
delete (merged as Record<string, unknown>).plugins;
|
|
118
107
|
}
|
|
119
108
|
|
|
120
109
|
const mergedRecord = merged as Record<string, unknown>;
|
package/src/near-cli.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
1
|
import { generateKeyPairSync } from "node:crypto";
|
|
3
2
|
import { Effect } from "effect";
|
|
3
|
+
import { execa } from "execa";
|
|
4
4
|
|
|
5
5
|
export interface NearTransactionConfig {
|
|
6
6
|
account: string;
|
|
@@ -112,49 +112,34 @@ export function generateNearKeyPair(): NearKeyPair {
|
|
|
112
112
|
|
|
113
113
|
const checkNearCliInstalled = Effect.tryPromise({
|
|
114
114
|
try: async () => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
try {
|
|
116
|
+
await execa("near", ["--version"], { stdio: "pipe" });
|
|
117
|
+
return true;
|
|
118
|
+
} catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
120
121
|
},
|
|
121
122
|
catch: () => new Error("Failed to check NEAR CLI"),
|
|
122
123
|
});
|
|
123
124
|
|
|
124
125
|
const installNearCli = Effect.tryPromise({
|
|
125
126
|
try: async () => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
"sh",
|
|
129
|
-
["-c", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`],
|
|
130
|
-
{
|
|
131
|
-
stdio: "inherit",
|
|
132
|
-
},
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
proc.on("close", (code) => {
|
|
136
|
-
if (code === 0) resolve();
|
|
137
|
-
else reject(new NearCliInstallError(`Installer exited with code ${code}`));
|
|
138
|
-
});
|
|
139
|
-
proc.on("error", (err) => reject(new NearCliInstallError(err.message)));
|
|
127
|
+
await execa("sh", ["-c", `curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`], {
|
|
128
|
+
stdio: "inherit",
|
|
140
129
|
});
|
|
141
130
|
},
|
|
142
|
-
catch: (error) =>
|
|
131
|
+
catch: (error) => {
|
|
132
|
+
if (error instanceof Error && "exitCode" in error) {
|
|
133
|
+
return new NearCliInstallError(
|
|
134
|
+
`Installer exited with code ${(error as { exitCode: number }).exitCode}`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return new NearCliInstallError(error instanceof Error ? error.message : String(error));
|
|
138
|
+
},
|
|
143
139
|
});
|
|
144
140
|
|
|
145
141
|
async function runNearCommand(args: string[]): Promise<void> {
|
|
146
|
-
await
|
|
147
|
-
const proc = spawn("near", args, {
|
|
148
|
-
stdio: "inherit",
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
proc.on("close", (code) => {
|
|
152
|
-
if (code === 0) resolve();
|
|
153
|
-
else reject(new Error(`near ${args.join(" ")} failed with exit code ${code}`));
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
proc.on("error", (err) => reject(new Error(err.message)));
|
|
157
|
-
});
|
|
142
|
+
await execa("near", args, { stdio: "inherit" });
|
|
158
143
|
}
|
|
159
144
|
|
|
160
145
|
export const ensureNearCli = Effect.gen(function* () {
|
|
@@ -209,43 +194,31 @@ export const executeTransaction = (
|
|
|
209
194
|
|
|
210
195
|
const output = yield* Effect.tryPromise({
|
|
211
196
|
try: async () => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
proc.stdout?.on("data", (data) => {
|
|
219
|
-
const text = data.toString();
|
|
220
|
-
stdout += text;
|
|
221
|
-
process.stdout.write(text);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
proc.stderr?.on("data", (data) => {
|
|
225
|
-
const text = data.toString();
|
|
226
|
-
stderr += text;
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
proc.on("close", (code) => {
|
|
230
|
-
const combined = `${stdout}\n${stderr}`;
|
|
231
|
-
const txHashMatch = combined.match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
|
|
232
|
-
const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);
|
|
233
|
-
const hasTransactionFailed = /Transaction failed/i.test(combined);
|
|
234
|
-
const softSuccess =
|
|
235
|
-
Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;
|
|
236
|
-
|
|
237
|
-
if (code === 0 || softSuccess) {
|
|
238
|
-
if (softSuccess) {
|
|
239
|
-
console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);
|
|
240
|
-
}
|
|
241
|
-
resolve(combined);
|
|
242
|
-
} else {
|
|
243
|
-
reject(new NearTransactionError(stderr || `Transaction failed with code ${code}`));
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
proc.on("error", (err) => reject(new NearTransactionError(err.message)));
|
|
197
|
+
const result = await execa("near", args, {
|
|
198
|
+
stdin: "inherit",
|
|
199
|
+
stdout: "pipe",
|
|
200
|
+
stderr: "pipe",
|
|
201
|
+
reject: false,
|
|
248
202
|
});
|
|
203
|
+
|
|
204
|
+
process.stdout.write(result.stdout);
|
|
205
|
+
const combined = `${result.stdout}\n${result.stderr}`;
|
|
206
|
+
const txHashMatch = combined.match(/Transaction ID:\s*([A-Za-z0-9]+)/i);
|
|
207
|
+
const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined);
|
|
208
|
+
const hasTransactionFailed = /Transaction failed/i.test(combined);
|
|
209
|
+
const softSuccess =
|
|
210
|
+
Boolean(txHashMatch?.[1]) && hasCodeDoesNotExist && hasTransactionFailed;
|
|
211
|
+
|
|
212
|
+
if (result.exitCode === 0 || softSuccess) {
|
|
213
|
+
if (softSuccess) {
|
|
214
|
+
console.log(` ${txHashMatch?.[1]} — FastDATA CodeDoesNotExist (expected)`);
|
|
215
|
+
}
|
|
216
|
+
return combined;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
throw new NearTransactionError(
|
|
220
|
+
result.stderr || `Transaction failed with code ${result.exitCode}`,
|
|
221
|
+
);
|
|
249
222
|
},
|
|
250
223
|
catch: (error) => error as Error,
|
|
251
224
|
});
|