everything-dev 1.12.4 → 1.14.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/app.cjs +17 -5
- package/dist/app.cjs.map +1 -1
- package/dist/app.mjs +17 -5
- package/dist/app.mjs.map +1 -1
- package/dist/cli/init.cjs +151 -74
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +1 -1
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts +1 -1
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +152 -75
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/prompts.cjs +3 -3
- package/dist/cli/prompts.cjs.map +1 -1
- package/dist/cli/prompts.mjs +3 -3
- package/dist/cli/prompts.mjs.map +1 -1
- package/dist/cli/status.cjs +22 -0
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.mjs +22 -0
- package/dist/cli/status.mjs.map +1 -1
- package/dist/cli/sync.cjs +15 -56
- package/dist/cli/sync.cjs.map +1 -1
- package/dist/cli/sync.mjs +15 -56
- package/dist/cli/sync.mjs.map +1 -1
- package/dist/cli/upgrade.cjs +59 -5
- package/dist/cli/upgrade.cjs.map +1 -1
- package/dist/cli/upgrade.mjs +59 -5
- package/dist/cli/upgrade.mjs.map +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +206 -69
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +13 -6
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +13 -6
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +201 -71
- package/dist/config.mjs.map +1 -1
- package/dist/contract.d.cts +106 -10
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +106 -10
- package/dist/contract.d.mts.map +1 -1
- package/dist/host.cjs +34 -1
- package/dist/host.cjs.map +1 -1
- package/dist/host.d.cts.map +1 -1
- package/dist/host.d.mts.map +1 -1
- package/dist/host.mjs +34 -1
- package/dist/host.mjs.map +1 -1
- package/dist/index.cjs +16 -0
- package/dist/index.d.cts +5 -3
- package/dist/index.d.mts +5 -3
- package/dist/index.mjs +5 -3
- package/dist/internal/manifest-normalizer.cjs +14 -1
- package/dist/internal/manifest-normalizer.cjs.map +1 -1
- package/dist/internal/manifest-normalizer.mjs +14 -1
- package/dist/internal/manifest-normalizer.mjs.map +1 -1
- package/dist/merge.cjs +113 -0
- package/dist/merge.cjs.map +1 -0
- package/dist/merge.d.cts +7 -0
- package/dist/merge.d.cts.map +1 -0
- package/dist/merge.d.mts +7 -0
- package/dist/merge.d.mts.map +1 -0
- package/dist/merge.mjs +107 -0
- package/dist/merge.mjs.map +1 -0
- package/dist/orchestrator.d.cts +1 -1
- package/dist/orchestrator.d.mts +1 -1
- package/dist/plugin.cjs +117 -105
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +115 -9
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +115 -9
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +117 -105
- package/dist/plugin.mjs.map +1 -1
- package/dist/service-descriptor.cjs +21 -0
- package/dist/service-descriptor.cjs.map +1 -1
- package/dist/service-descriptor.d.cts +23 -1
- package/dist/service-descriptor.d.cts.map +1 -1
- package/dist/service-descriptor.d.mts +23 -1
- package/dist/service-descriptor.d.mts.map +1 -1
- package/dist/service-descriptor.mjs +21 -0
- package/dist/service-descriptor.mjs.map +1 -1
- package/dist/shared.cjs +24 -2
- package/dist/shared.cjs.map +1 -1
- package/dist/shared.d.cts +3 -0
- package/dist/shared.d.cts.map +1 -1
- package/dist/shared.d.mts +3 -0
- package/dist/shared.d.mts.map +1 -1
- package/dist/shared.mjs +25 -3
- package/dist/shared.mjs.map +1 -1
- package/dist/sidebar.cjs +124 -0
- package/dist/sidebar.cjs.map +1 -0
- package/dist/sidebar.d.cts +8 -0
- package/dist/sidebar.d.cts.map +1 -0
- package/dist/sidebar.d.mts +8 -0
- package/dist/sidebar.d.mts.map +1 -0
- package/dist/sidebar.mjs +122 -0
- package/dist/sidebar.mjs.map +1 -0
- package/dist/types.cjs +104 -10
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +256 -29
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +256 -29
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +100 -11
- package/dist/types.mjs.map +1 -1
- package/dist/utils/path-match.cjs +18 -0
- package/dist/utils/path-match.cjs.map +1 -0
- package/dist/utils/path-match.mjs +17 -0
- package/dist/utils/path-match.mjs.map +1 -0
- package/dist/utils/save-config.cjs +19 -0
- package/dist/utils/save-config.cjs.map +1 -0
- package/dist/utils/save-config.mjs +18 -0
- package/dist/utils/save-config.mjs.map +1 -0
- package/package.json +6 -6
- package/skills/dev-workflow/SKILL.md +8 -0
- package/skills/extends-config/SKILL.md +132 -0
- package/skills/init-upgrade/SKILL.md +128 -0
- package/skills/publish-sync/SKILL.md +30 -0
- package/src/app.ts +15 -5
- package/src/cli/init.ts +207 -108
- package/src/cli/prompts.ts +2 -2
- package/src/cli/status.ts +20 -0
- package/src/cli/sync.ts +27 -96
- package/src/cli/upgrade.ts +65 -3
- package/src/cli.ts +1 -1
- package/src/config.ts +306 -119
- package/src/host.ts +45 -0
- package/src/index.ts +1 -0
- package/src/internal/manifest-normalizer.ts +16 -4
- package/src/merge.ts +198 -0
- package/src/plugin.ts +340 -318
- package/src/service-descriptor.ts +23 -0
- package/src/shared.ts +48 -5
- package/src/sidebar.ts +162 -0
- package/src/types.ts +134 -28
- package/src/utils/path-match.ts +16 -0
- package/src/utils/save-config.ts +20 -0
- package/cli.js +0 -10
|
@@ -205,6 +205,29 @@ export function buildServiceDescriptorMap(
|
|
|
205
205
|
defaultPort: resolvedPort,
|
|
206
206
|
readinessPath: "/remoteEntry.js",
|
|
207
207
|
});
|
|
208
|
+
|
|
209
|
+
if (pluginConfig.ui?.localPath && pluginConfig.ui.source === "local") {
|
|
210
|
+
const uiKey = `plugin-ui:${pluginId}`;
|
|
211
|
+
const uiPort = pluginConfig.ui.port ?? pluginBasePort;
|
|
212
|
+
pluginBasePort = uiPort + 1;
|
|
213
|
+
|
|
214
|
+
map.set(uiKey, {
|
|
215
|
+
key: uiKey,
|
|
216
|
+
source: pluginConfig.ui.source,
|
|
217
|
+
url: pluginConfig.ui.url,
|
|
218
|
+
entry: pluginConfig.ui.entry,
|
|
219
|
+
name: pluginConfig.ui.name,
|
|
220
|
+
localPath: pluginConfig.ui.localPath,
|
|
221
|
+
port: uiPort,
|
|
222
|
+
integrity: pluginConfig.ui.integrity,
|
|
223
|
+
command: "bun",
|
|
224
|
+
args: ["run", "dev"],
|
|
225
|
+
readyPatterns: PLUGIN_READY_PATTERNS,
|
|
226
|
+
errorPatterns: PLUGIN_ERROR_PATTERNS,
|
|
227
|
+
defaultPort: uiPort,
|
|
228
|
+
readinessPath: "/remoteEntry.js",
|
|
229
|
+
});
|
|
230
|
+
}
|
|
208
231
|
}
|
|
209
232
|
}
|
|
210
233
|
|
package/src/shared.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
+
import { type BosEnv, type ResolvedConfigMeta, rebuildOrderedConfig } from "./merge";
|
|
4
5
|
import type { BosConfig, SharedDepConfig } from "./types";
|
|
6
|
+
import { BosConfigSchema } from "./types";
|
|
7
|
+
|
|
8
|
+
interface PackageJson {
|
|
9
|
+
name?: string;
|
|
10
|
+
private?: boolean;
|
|
11
|
+
version?: string;
|
|
12
|
+
workspaces?: {
|
|
13
|
+
packages?: string[];
|
|
14
|
+
catalog?: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
dependencies?: Record<string, string>;
|
|
17
|
+
devDependencies?: Record<string, string>;
|
|
18
|
+
scripts?: Record<string, string>;
|
|
19
|
+
}
|
|
5
20
|
|
|
6
21
|
export interface SharedUiResolvedDep {
|
|
7
22
|
name: string;
|
|
@@ -77,15 +92,24 @@ export async function syncAndGenerateSharedUi(opts: {
|
|
|
77
92
|
configDir: string;
|
|
78
93
|
hostMode: "local" | "remote";
|
|
79
94
|
bosConfig?: BosConfig;
|
|
95
|
+
env?: BosEnv;
|
|
96
|
+
extendsChain?: string[];
|
|
80
97
|
}): Promise<SharedSyncResult> {
|
|
81
98
|
const bosConfigPath = join(opts.configDir, "bos.config.json");
|
|
99
|
+
const resolvedConfigPath = join(opts.configDir, ".bos", "bos.resolved-config.json");
|
|
82
100
|
const packageJsonPath = join(opts.configDir, "package.json");
|
|
83
101
|
const generatedPath = join(opts.configDir, ".bos", "generated", "shared-ui.json");
|
|
84
102
|
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
let bosConfig: BosConfig;
|
|
104
|
+
if (opts.bosConfig) {
|
|
105
|
+
bosConfig = opts.bosConfig;
|
|
106
|
+
} else {
|
|
107
|
+
const raw = JSON.parse(readFileSync(bosConfigPath, "utf-8")) as Record<string, unknown>;
|
|
108
|
+
bosConfig = BosConfigSchema.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
let pkgJson: PackageJson = {};
|
|
87
111
|
try {
|
|
88
|
-
pkgJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
112
|
+
pkgJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as PackageJson;
|
|
89
113
|
} catch {
|
|
90
114
|
// package.json might not exist
|
|
91
115
|
}
|
|
@@ -130,7 +154,26 @@ export async function syncAndGenerateSharedUi(opts: {
|
|
|
130
154
|
const catalogChanged = nextPkg !== originalPkg;
|
|
131
155
|
|
|
132
156
|
if (bosConfigChanged) {
|
|
133
|
-
|
|
157
|
+
if (mode === "catalog->bos") {
|
|
158
|
+
const resolvedDir = dirname(resolvedConfigPath);
|
|
159
|
+
if (!existsSync(resolvedDir)) {
|
|
160
|
+
mkdirSync(resolvedDir, { recursive: true });
|
|
161
|
+
}
|
|
162
|
+
const ordered = rebuildOrderedConfig(bosConfig);
|
|
163
|
+
const meta: ResolvedConfigMeta = {
|
|
164
|
+
env: opts.env ?? "development",
|
|
165
|
+
resolvedAt: new Date().toISOString(),
|
|
166
|
+
extendsChain: opts.extendsChain ?? [],
|
|
167
|
+
source: "shared-sync",
|
|
168
|
+
};
|
|
169
|
+
const resolvedOutput = {
|
|
170
|
+
_resolved: meta,
|
|
171
|
+
...ordered,
|
|
172
|
+
};
|
|
173
|
+
writeFileIfChanged(resolvedConfigPath, `${JSON.stringify(resolvedOutput, null, 2)}\n`);
|
|
174
|
+
} else {
|
|
175
|
+
writeFileIfChanged(bosConfigPath, `${JSON.stringify(bosConfig, null, 2)}\n`);
|
|
176
|
+
}
|
|
134
177
|
}
|
|
135
178
|
if (catalogChanged) {
|
|
136
179
|
writeFileIfChanged(packageJsonPath, `${JSON.stringify(pkgJson, null, 2)}\n`);
|
package/src/sidebar.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import type { BosConfig, SidebarItem } from "./types";
|
|
4
|
+
|
|
5
|
+
const ICON_IMPORTS: Record<string, string> = {
|
|
6
|
+
Home: "lucide-react",
|
|
7
|
+
Globe: "lucide-react",
|
|
8
|
+
FolderKanban: "lucide-react",
|
|
9
|
+
Building2: "lucide-react",
|
|
10
|
+
Settings: "lucide-react",
|
|
11
|
+
User: "lucide-react",
|
|
12
|
+
Users: "lucide-react",
|
|
13
|
+
Shield: "lucide-react",
|
|
14
|
+
LayoutDashboard: "lucide-react",
|
|
15
|
+
CreditCard: "lucide-react",
|
|
16
|
+
Bell: "lucide-react",
|
|
17
|
+
Key: "lucide-react",
|
|
18
|
+
FileText: "lucide-react",
|
|
19
|
+
Database: "lucide-react",
|
|
20
|
+
Activity: "lucide-react",
|
|
21
|
+
BarChart3: "lucide-react",
|
|
22
|
+
Zap: "lucide-react",
|
|
23
|
+
Terminal: "lucide-react",
|
|
24
|
+
Code: "lucide-react",
|
|
25
|
+
Package: "lucide-react",
|
|
26
|
+
Store: "lucide-react",
|
|
27
|
+
ShoppingBag: "lucide-react",
|
|
28
|
+
Wallet: "lucide-react",
|
|
29
|
+
Coins: "lucide-react",
|
|
30
|
+
Plug: "lucide-react",
|
|
31
|
+
Link: "lucide-react",
|
|
32
|
+
ExternalLink: "lucide-react",
|
|
33
|
+
Puzzle: "lucide-react",
|
|
34
|
+
Layers: "lucide-react",
|
|
35
|
+
Grid3X3: "lucide-react",
|
|
36
|
+
AppWindow: "lucide-react",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function resolveIconModule(iconName: string): string {
|
|
40
|
+
if (ICON_IMPORTS[iconName]) return ICON_IMPORTS[iconName];
|
|
41
|
+
return "lucide-react";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function collectIconImports(items: SidebarItem[]): Map<string, Set<string>> {
|
|
45
|
+
const moduleMap = new Map<string, Set<string>>();
|
|
46
|
+
for (const item of items) {
|
|
47
|
+
const module = resolveIconModule(item.icon);
|
|
48
|
+
if (!moduleMap.has(module)) moduleMap.set(module, new Set());
|
|
49
|
+
moduleMap.get(module)!.add(item.icon);
|
|
50
|
+
}
|
|
51
|
+
return moduleMap;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function generatePluginSidebarContent(config: BosConfig, configDir?: string): string {
|
|
55
|
+
const coreItems: SidebarItem[] = [{ icon: "Home", label: "home", to: "/", roleRequired: "anon" }];
|
|
56
|
+
|
|
57
|
+
if (config.app.auth?.sidebar) {
|
|
58
|
+
for (const item of config.app.auth.sidebar) {
|
|
59
|
+
coreItems.push({
|
|
60
|
+
...item,
|
|
61
|
+
to: item.to ?? "/auth",
|
|
62
|
+
roleRequired: item.roleRequired ?? "member",
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const pluginItems: SidebarItem[] = [];
|
|
68
|
+
if (config.plugins) {
|
|
69
|
+
for (const [key, entry] of Object.entries(config.plugins)) {
|
|
70
|
+
let sidebar: SidebarItem[] | undefined;
|
|
71
|
+
|
|
72
|
+
if (typeof entry === "object" && entry.sidebar) {
|
|
73
|
+
sidebar = entry.sidebar;
|
|
74
|
+
} else if (
|
|
75
|
+
typeof entry === "object" &&
|
|
76
|
+
entry.development?.startsWith("local:") &&
|
|
77
|
+
configDir
|
|
78
|
+
) {
|
|
79
|
+
const localPath = join(configDir, entry.development.slice("local:".length).trim());
|
|
80
|
+
const pluginConfigPath = join(localPath, "bos.config.json");
|
|
81
|
+
if (existsSync(pluginConfigPath)) {
|
|
82
|
+
try {
|
|
83
|
+
const pluginConfig = JSON.parse(readFileSync(pluginConfigPath, "utf-8")) as {
|
|
84
|
+
sidebar?: SidebarItem[];
|
|
85
|
+
};
|
|
86
|
+
if (pluginConfig.sidebar) {
|
|
87
|
+
sidebar = pluginConfig.sidebar;
|
|
88
|
+
}
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!sidebar) continue;
|
|
94
|
+
for (const item of sidebar) {
|
|
95
|
+
pluginItems.push({
|
|
96
|
+
...item,
|
|
97
|
+
to: item.to ?? `/${key}`,
|
|
98
|
+
roleRequired: item.roleRequired ?? "member",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const allItems = [...coreItems, ...pluginItems];
|
|
105
|
+
const moduleMap = collectIconImports(allItems);
|
|
106
|
+
|
|
107
|
+
const importLines: string[] = [];
|
|
108
|
+
for (const [module, icons] of moduleMap) {
|
|
109
|
+
const iconList = [...icons].join(", ");
|
|
110
|
+
importLines.push(`import { ${iconList} } from "${module}";`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const itemsCode = allItems
|
|
114
|
+
.map(
|
|
115
|
+
(item) =>
|
|
116
|
+
` { icon: ${item.icon}, label: "${item.label}", to: "${item.to}" as const, roleRequired: "${item.roleRequired}" as const },`,
|
|
117
|
+
)
|
|
118
|
+
.join("\n");
|
|
119
|
+
|
|
120
|
+
return `// Auto-generated by bos sync/pluginAdd/pluginRemove. Do not edit.
|
|
121
|
+
${importLines.join("\n")}
|
|
122
|
+
|
|
123
|
+
export type SidebarRole = "anon" | "member" | "admin";
|
|
124
|
+
|
|
125
|
+
export interface SidebarItem {
|
|
126
|
+
icon: React.ComponentType<{ className?: string }>;
|
|
127
|
+
label: string;
|
|
128
|
+
to: string;
|
|
129
|
+
roleRequired: SidebarRole;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export const pluginSidebarItems: SidebarItem[] = [
|
|
133
|
+
${itemsCode}
|
|
134
|
+
];
|
|
135
|
+
`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function writePluginSidebarGen(configDir: string, config: BosConfig): string {
|
|
139
|
+
const outputPath = join(configDir, "ui/src/lib/plugin-sidebar.gen.ts");
|
|
140
|
+
|
|
141
|
+
const content = generatePluginSidebarContent(config, configDir);
|
|
142
|
+
|
|
143
|
+
const outputDir = dirname(outputPath);
|
|
144
|
+
if (!existsSync(outputDir)) {
|
|
145
|
+
mkdirSync(outputDir, { recursive: true });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let existingContent: string | null = null;
|
|
149
|
+
try {
|
|
150
|
+
existingContent = existsSync(outputPath)
|
|
151
|
+
? // eslint-disable-next-line no-restricted-syntax
|
|
152
|
+
readFileSync(outputPath, "utf-8")
|
|
153
|
+
: null;
|
|
154
|
+
} catch {
|
|
155
|
+
// file doesn't exist yet
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (existingContent === content) return outputPath;
|
|
159
|
+
|
|
160
|
+
writeFileSync(outputPath, content);
|
|
161
|
+
return outputPath;
|
|
162
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
import { z } from "./sdk";
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
development?: string;
|
|
15
|
-
production?: string;
|
|
16
|
-
integrity?: string;
|
|
17
|
-
name?: string;
|
|
18
|
-
version?: string;
|
|
19
|
-
proxy?: string;
|
|
20
|
-
variables?: Record<string, string>;
|
|
21
|
-
secrets?: string[];
|
|
22
|
-
app?: Record<string, Record<string, unknown>>;
|
|
23
|
-
shared?: Record<string, Record<string, Record<string, unknown>>>;
|
|
24
|
-
plugins?: Record<string, BosConfigInput>;
|
|
25
|
-
}
|
|
3
|
+
export const ExtendsSchema = z.union([
|
|
4
|
+
z.string(),
|
|
5
|
+
z.object({
|
|
6
|
+
development: z.string().optional(),
|
|
7
|
+
production: z.string().optional(),
|
|
8
|
+
staging: z.string().optional(),
|
|
9
|
+
}),
|
|
10
|
+
]);
|
|
11
|
+
export type Extends = z.infer<typeof ExtendsSchema>;
|
|
12
|
+
export type ExtendsConfig = Extract<Extends, Record<string, string | undefined>>;
|
|
26
13
|
|
|
27
14
|
export const SourceModeSchema = z.enum(["local", "remote"]);
|
|
28
15
|
export type SourceMode = z.infer<typeof SourceModeSchema>;
|
|
@@ -48,6 +35,17 @@ export const FederationEntrySchema = z.object({
|
|
|
48
35
|
});
|
|
49
36
|
export type FederationEntry = z.infer<typeof FederationEntrySchema>;
|
|
50
37
|
|
|
38
|
+
export const SidebarRoleSchema = z.enum(["anon", "member", "admin"]);
|
|
39
|
+
export type SidebarRole = z.infer<typeof SidebarRoleSchema>;
|
|
40
|
+
|
|
41
|
+
export const SidebarItemSchema = z.object({
|
|
42
|
+
icon: z.string(),
|
|
43
|
+
label: z.string(),
|
|
44
|
+
to: z.string().optional(),
|
|
45
|
+
roleRequired: SidebarRoleSchema.optional(),
|
|
46
|
+
});
|
|
47
|
+
export type SidebarItem = z.infer<typeof SidebarItemSchema>;
|
|
48
|
+
|
|
51
49
|
export const ApiPluginConfigSchema = z.object({
|
|
52
50
|
name: z.string(),
|
|
53
51
|
development: z.string().optional(),
|
|
@@ -56,11 +54,20 @@ export const ApiPluginConfigSchema = z.object({
|
|
|
56
54
|
proxy: z.string().optional(),
|
|
57
55
|
variables: z.record(z.string(), z.string()).optional(),
|
|
58
56
|
secrets: z.array(z.string()).optional(),
|
|
57
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
59
58
|
});
|
|
60
59
|
export type ApiPluginConfig = z.infer<typeof ApiPluginConfigSchema>;
|
|
61
60
|
|
|
61
|
+
export const PluginUiConfigSchema = z.object({
|
|
62
|
+
name: z.string(),
|
|
63
|
+
development: z.string().optional(),
|
|
64
|
+
production: z.string().optional(),
|
|
65
|
+
integrity: z.string().optional(),
|
|
66
|
+
});
|
|
67
|
+
export type PluginUiConfig = z.infer<typeof PluginUiConfigSchema>;
|
|
68
|
+
|
|
62
69
|
export const BosPluginRefSchema = z.object({
|
|
63
|
-
extends:
|
|
70
|
+
extends: ExtendsSchema.optional(),
|
|
64
71
|
development: z.string().optional(),
|
|
65
72
|
production: z.string().optional(),
|
|
66
73
|
integrity: z.string().optional(),
|
|
@@ -70,8 +77,25 @@ export const BosPluginRefSchema = z.object({
|
|
|
70
77
|
variables: z.record(z.string(), z.string()).optional(),
|
|
71
78
|
secrets: z.array(z.string()).optional(),
|
|
72
79
|
routes: z.array(z.string()).optional(),
|
|
80
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
81
|
+
app: z.record(z.string(), z.unknown()).optional(),
|
|
82
|
+
shared: z.record(z.string(), z.record(z.string(), SharedConfigSchema)).optional(),
|
|
83
|
+
plugins: z.record(z.string(), z.unknown()).optional(),
|
|
73
84
|
});
|
|
74
85
|
export type BosPluginRef = z.infer<typeof BosPluginRefSchema>;
|
|
86
|
+
export type PluginEntryValue = string | BosPluginRef;
|
|
87
|
+
export type PluginEntries = Record<string, PluginEntryValue>;
|
|
88
|
+
|
|
89
|
+
const PluginRuntimeUiSchema = z.object({
|
|
90
|
+
name: z.string(),
|
|
91
|
+
url: z.string(),
|
|
92
|
+
entry: z.string(),
|
|
93
|
+
source: SourceModeSchema,
|
|
94
|
+
localPath: z.string().optional(),
|
|
95
|
+
port: z.number().optional(),
|
|
96
|
+
integrity: z.string().optional(),
|
|
97
|
+
});
|
|
98
|
+
export type PluginRuntimeUi = z.infer<typeof PluginRuntimeUiSchema>;
|
|
75
99
|
|
|
76
100
|
export const RuntimePluginConfigSchema = z.object({
|
|
77
101
|
name: z.string(),
|
|
@@ -84,6 +108,9 @@ export const RuntimePluginConfigSchema = z.object({
|
|
|
84
108
|
variables: z.record(z.string(), z.string()).optional(),
|
|
85
109
|
secrets: z.array(z.string()).optional(),
|
|
86
110
|
integrity: z.string().optional(),
|
|
111
|
+
ui: PluginRuntimeUiSchema.optional(),
|
|
112
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
113
|
+
routes: z.array(z.string()).optional(),
|
|
87
114
|
});
|
|
88
115
|
export type RuntimePluginConfig = z.infer<typeof RuntimePluginConfigSchema>;
|
|
89
116
|
|
|
@@ -119,15 +146,74 @@ export const BosStagingSchema = z.object({
|
|
|
119
146
|
});
|
|
120
147
|
export type BosStaging = z.infer<typeof BosStagingSchema>;
|
|
121
148
|
|
|
149
|
+
const BosConfigInputAppEntrySchema = z.record(z.string(), z.unknown());
|
|
150
|
+
export type BosConfigInputAppEntry = z.infer<typeof BosConfigInputAppEntrySchema>;
|
|
151
|
+
|
|
152
|
+
export const BosConfigInputSchema: z.ZodType<BosConfigInput> = z.lazy(() =>
|
|
153
|
+
z.object({
|
|
154
|
+
extends: ExtendsSchema.optional(),
|
|
155
|
+
account: z.string().optional(),
|
|
156
|
+
domain: z.string().optional(),
|
|
157
|
+
testnet: z.string().optional(),
|
|
158
|
+
template: z.string().optional(),
|
|
159
|
+
gateway: z
|
|
160
|
+
.object({
|
|
161
|
+
development: z.string().optional(),
|
|
162
|
+
production: z.string().optional(),
|
|
163
|
+
account: z.string().optional(),
|
|
164
|
+
})
|
|
165
|
+
.optional(),
|
|
166
|
+
development: z.string().optional(),
|
|
167
|
+
production: z.string().optional(),
|
|
168
|
+
integrity: z.string().optional(),
|
|
169
|
+
name: z.string().optional(),
|
|
170
|
+
version: z.string().optional(),
|
|
171
|
+
proxy: z.string().optional(),
|
|
172
|
+
variables: z.record(z.string(), z.string()).optional(),
|
|
173
|
+
secrets: z.array(z.string()).optional(),
|
|
174
|
+
routes: z.array(z.string()).optional(),
|
|
175
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
176
|
+
app: z.record(z.string(), BosConfigInputAppEntrySchema).optional(),
|
|
177
|
+
shared: z.record(z.string(), z.record(z.string(), SharedConfigSchema)).optional(),
|
|
178
|
+
plugins: z.record(z.string(), z.union([z.string(), BosConfigInputSchema])).optional(),
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
export interface BosConfigInput {
|
|
183
|
+
extends?: string | ExtendsConfig;
|
|
184
|
+
account?: string;
|
|
185
|
+
domain?: string;
|
|
186
|
+
testnet?: string;
|
|
187
|
+
template?: string;
|
|
188
|
+
gateway?: {
|
|
189
|
+
development?: string;
|
|
190
|
+
production?: string;
|
|
191
|
+
account?: string;
|
|
192
|
+
};
|
|
193
|
+
development?: string;
|
|
194
|
+
production?: string;
|
|
195
|
+
integrity?: string;
|
|
196
|
+
name?: string;
|
|
197
|
+
version?: string;
|
|
198
|
+
proxy?: string;
|
|
199
|
+
variables?: Record<string, string>;
|
|
200
|
+
secrets?: string[];
|
|
201
|
+
routes?: string[];
|
|
202
|
+
sidebar?: SidebarItem[];
|
|
203
|
+
app?: Record<string, BosConfigInputAppEntry>;
|
|
204
|
+
shared?: Record<string, Record<string, SharedDepConfig>>;
|
|
205
|
+
plugins?: Record<string, string | BosConfigInput>;
|
|
206
|
+
}
|
|
207
|
+
|
|
122
208
|
export const BosConfigSchema = z.object({
|
|
123
209
|
account: z.string(),
|
|
124
|
-
extends:
|
|
210
|
+
extends: ExtendsSchema.optional(),
|
|
125
211
|
domain: z.string().optional(),
|
|
126
212
|
testnet: z.string().optional(),
|
|
127
213
|
staging: BosStagingSchema.optional(),
|
|
128
214
|
repository: z.string().optional(),
|
|
129
215
|
shared: z.record(z.string(), z.record(z.string(), SharedConfigSchema)).optional(),
|
|
130
|
-
plugins: z.record(z.string(), BosPluginRefSchema).optional(),
|
|
216
|
+
plugins: z.record(z.string(), z.union([z.string(), BosPluginRefSchema])).optional(),
|
|
131
217
|
app: z.object({
|
|
132
218
|
host: HostConfigSchema,
|
|
133
219
|
ui: UiConfigSchema,
|
|
@@ -138,7 +224,7 @@ export const BosConfigSchema = z.object({
|
|
|
138
224
|
export type BosConfig = z.infer<typeof BosConfigSchema>;
|
|
139
225
|
|
|
140
226
|
export const RuntimeConfigSchema = z.object({
|
|
141
|
-
env: z.enum(["development", "production"]),
|
|
227
|
+
env: z.enum(["development", "production", "staging"]),
|
|
142
228
|
account: z.string(),
|
|
143
229
|
domain: z.string().optional(),
|
|
144
230
|
networkId: z.enum(["mainnet", "testnet"]),
|
|
@@ -175,6 +261,7 @@ export const RuntimeConfigSchema = z.object({
|
|
|
175
261
|
proxy: z.string().optional(),
|
|
176
262
|
variables: z.record(z.string(), z.string()).optional(),
|
|
177
263
|
secrets: z.array(z.string()).optional(),
|
|
264
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
178
265
|
}).optional(),
|
|
179
266
|
plugins: z.record(z.string(), RuntimePluginConfigSchema).optional(),
|
|
180
267
|
});
|
|
@@ -182,7 +269,7 @@ export type RuntimeConfig = z.infer<typeof RuntimeConfigSchema>;
|
|
|
182
269
|
|
|
183
270
|
export const ClientRuntimeConfigSchema = z.object({
|
|
184
271
|
cspNonce: z.string().optional(),
|
|
185
|
-
env: z.enum(["development", "production"]),
|
|
272
|
+
env: z.enum(["development", "production", "staging"]),
|
|
186
273
|
account: z.string(),
|
|
187
274
|
networkId: z.enum(["mainnet", "testnet"]),
|
|
188
275
|
hostUrl: z.string().optional(),
|
|
@@ -208,6 +295,15 @@ export const ClientRuntimeConfigSchema = z.object({
|
|
|
208
295
|
integrity: z.string().optional(),
|
|
209
296
|
})
|
|
210
297
|
.optional(),
|
|
298
|
+
auth: z
|
|
299
|
+
.object({
|
|
300
|
+
name: z.string(),
|
|
301
|
+
url: z.string(),
|
|
302
|
+
entry: z.string(),
|
|
303
|
+
integrity: z.string().optional(),
|
|
304
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
305
|
+
})
|
|
306
|
+
.optional(),
|
|
211
307
|
plugins: z
|
|
212
308
|
.record(
|
|
213
309
|
z.string(),
|
|
@@ -216,6 +312,16 @@ export const ClientRuntimeConfigSchema = z.object({
|
|
|
216
312
|
url: z.string(),
|
|
217
313
|
entry: z.string(),
|
|
218
314
|
integrity: z.string().optional(),
|
|
315
|
+
ui: z
|
|
316
|
+
.object({
|
|
317
|
+
name: z.string(),
|
|
318
|
+
url: z.string(),
|
|
319
|
+
entry: z.string(),
|
|
320
|
+
source: SourceModeSchema,
|
|
321
|
+
integrity: z.string().optional(),
|
|
322
|
+
})
|
|
323
|
+
.optional(),
|
|
324
|
+
sidebar: z.array(SidebarItemSchema).optional(),
|
|
219
325
|
}),
|
|
220
326
|
)
|
|
221
327
|
.optional(),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function isPathExcluded(filePath: string, excludePatterns: string[]): boolean {
|
|
2
|
+
if (excludePatterns.length === 0) return false;
|
|
3
|
+
for (const pattern of excludePatterns) {
|
|
4
|
+
if (pattern.endsWith("/**")) {
|
|
5
|
+
const prefix = pattern.slice(0, -3);
|
|
6
|
+
if (filePath.startsWith(`${prefix}/`) || filePath === prefix) return true;
|
|
7
|
+
} else if (pattern.endsWith("/*")) {
|
|
8
|
+
const prefix = pattern.slice(0, -2);
|
|
9
|
+
const slashIdx = filePath.indexOf("/", prefix.length + 1);
|
|
10
|
+
if (filePath.startsWith(`${prefix}/`) && slashIdx === -1) return true;
|
|
11
|
+
} else if (filePath === pattern || filePath.startsWith(`${pattern}/`)) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { rebuildOrderedConfig } from "../merge";
|
|
4
|
+
import type { BosConfig } from "../types";
|
|
5
|
+
|
|
6
|
+
export async function saveBosConfig(
|
|
7
|
+
configDir: string,
|
|
8
|
+
config: BosConfig | Record<string, unknown>,
|
|
9
|
+
): Promise<void> {
|
|
10
|
+
const filePath = join(configDir, "bos.config.json");
|
|
11
|
+
const ordered = rebuildOrderedConfig(config as Record<string, unknown>);
|
|
12
|
+
const next = `${JSON.stringify(ordered, null, 2)}\n`;
|
|
13
|
+
try {
|
|
14
|
+
if (readFileSync(filePath, "utf8") === next) return;
|
|
15
|
+
} catch {
|
|
16
|
+
// file does not exist yet
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
writeFileSync(filePath, next);
|
|
20
|
+
}
|
package/cli.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const distEntry = join(__dirname, "dist", "cli.js");
|
|
8
|
-
const srcEntry = join(__dirname, "src", "cli.ts");
|
|
9
|
-
|
|
10
|
-
await import(existsSync(distEntry) ? distEntry : srcEntry);
|