everything-dev 1.12.3 → 1.13.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.
Files changed (124) hide show
  1. package/cli.js +1 -1
  2. package/dist/app.cjs +24 -101
  3. package/dist/app.cjs.map +1 -1
  4. package/dist/app.mjs +25 -102
  5. package/dist/app.mjs.map +1 -1
  6. package/dist/cli/init.cjs +143 -66
  7. package/dist/cli/init.cjs.map +1 -1
  8. package/dist/cli/init.d.cts +1 -1
  9. package/dist/cli/init.d.cts.map +1 -1
  10. package/dist/cli/init.d.mts +1 -1
  11. package/dist/cli/init.d.mts.map +1 -1
  12. package/dist/cli/init.mjs +144 -67
  13. package/dist/cli/init.mjs.map +1 -1
  14. package/dist/cli/prompts.cjs +3 -3
  15. package/dist/cli/prompts.cjs.map +1 -1
  16. package/dist/cli/prompts.mjs +3 -3
  17. package/dist/cli/prompts.mjs.map +1 -1
  18. package/dist/cli/sync.cjs +15 -56
  19. package/dist/cli/sync.cjs.map +1 -1
  20. package/dist/cli/sync.mjs +15 -56
  21. package/dist/cli/sync.mjs.map +1 -1
  22. package/dist/cli/upgrade.cjs +3 -1
  23. package/dist/cli/upgrade.cjs.map +1 -1
  24. package/dist/cli/upgrade.mjs +3 -1
  25. package/dist/cli/upgrade.mjs.map +1 -1
  26. package/dist/config.cjs +223 -81
  27. package/dist/config.cjs.map +1 -1
  28. package/dist/config.d.cts +21 -5
  29. package/dist/config.d.cts.map +1 -1
  30. package/dist/config.d.mts +21 -5
  31. package/dist/config.d.mts.map +1 -1
  32. package/dist/config.mjs +217 -83
  33. package/dist/config.mjs.map +1 -1
  34. package/dist/contract.d.cts +104 -8
  35. package/dist/contract.d.cts.map +1 -1
  36. package/dist/contract.d.mts +104 -8
  37. package/dist/contract.d.mts.map +1 -1
  38. package/dist/host.cjs +34 -1
  39. package/dist/host.cjs.map +1 -1
  40. package/dist/host.d.cts.map +1 -1
  41. package/dist/host.d.mts.map +1 -1
  42. package/dist/host.mjs +34 -1
  43. package/dist/host.mjs.map +1 -1
  44. package/dist/index.cjs +17 -0
  45. package/dist/index.d.cts +5 -3
  46. package/dist/index.d.mts +5 -3
  47. package/dist/index.mjs +5 -3
  48. package/dist/merge.cjs +113 -0
  49. package/dist/merge.cjs.map +1 -0
  50. package/dist/merge.d.cts +7 -0
  51. package/dist/merge.d.cts.map +1 -0
  52. package/dist/merge.d.mts +7 -0
  53. package/dist/merge.d.mts.map +1 -0
  54. package/dist/merge.mjs +107 -0
  55. package/dist/merge.mjs.map +1 -0
  56. package/dist/plugin.cjs +117 -105
  57. package/dist/plugin.cjs.map +1 -1
  58. package/dist/plugin.d.cts +114 -8
  59. package/dist/plugin.d.cts.map +1 -1
  60. package/dist/plugin.d.mts +114 -8
  61. package/dist/plugin.d.mts.map +1 -1
  62. package/dist/plugin.mjs +117 -105
  63. package/dist/plugin.mjs.map +1 -1
  64. package/dist/service-descriptor.cjs +21 -0
  65. package/dist/service-descriptor.cjs.map +1 -1
  66. package/dist/service-descriptor.d.cts +23 -1
  67. package/dist/service-descriptor.d.cts.map +1 -1
  68. package/dist/service-descriptor.d.mts +23 -1
  69. package/dist/service-descriptor.d.mts.map +1 -1
  70. package/dist/service-descriptor.mjs +21 -0
  71. package/dist/service-descriptor.mjs.map +1 -1
  72. package/dist/shared.cjs +24 -2
  73. package/dist/shared.cjs.map +1 -1
  74. package/dist/shared.d.cts +3 -0
  75. package/dist/shared.d.cts.map +1 -1
  76. package/dist/shared.d.mts +3 -0
  77. package/dist/shared.d.mts.map +1 -1
  78. package/dist/shared.mjs +25 -3
  79. package/dist/shared.mjs.map +1 -1
  80. package/dist/sidebar.cjs +124 -0
  81. package/dist/sidebar.cjs.map +1 -0
  82. package/dist/sidebar.d.cts +8 -0
  83. package/dist/sidebar.d.cts.map +1 -0
  84. package/dist/sidebar.d.mts +8 -0
  85. package/dist/sidebar.d.mts.map +1 -0
  86. package/dist/sidebar.mjs +122 -0
  87. package/dist/sidebar.mjs.map +1 -0
  88. package/dist/types.cjs +104 -10
  89. package/dist/types.cjs.map +1 -1
  90. package/dist/types.d.cts +256 -29
  91. package/dist/types.d.cts.map +1 -1
  92. package/dist/types.d.mts +256 -29
  93. package/dist/types.d.mts.map +1 -1
  94. package/dist/types.mjs +100 -11
  95. package/dist/types.mjs.map +1 -1
  96. package/dist/utils/path-match.cjs +18 -0
  97. package/dist/utils/path-match.cjs.map +1 -0
  98. package/dist/utils/path-match.mjs +17 -0
  99. package/dist/utils/path-match.mjs.map +1 -0
  100. package/dist/utils/save-config.cjs +19 -0
  101. package/dist/utils/save-config.cjs.map +1 -0
  102. package/dist/utils/save-config.mjs +18 -0
  103. package/dist/utils/save-config.mjs.map +1 -0
  104. package/package.json +3 -2
  105. package/skills/dev-workflow/SKILL.md +8 -0
  106. package/skills/extends-config/SKILL.md +132 -0
  107. package/skills/init-upgrade/SKILL.md +128 -0
  108. package/skills/publish-sync/SKILL.md +30 -0
  109. package/src/app.ts +23 -118
  110. package/src/cli/init.ts +199 -100
  111. package/src/cli/prompts.ts +2 -2
  112. package/src/cli/sync.ts +27 -96
  113. package/src/cli/upgrade.ts +2 -0
  114. package/src/config.ts +356 -132
  115. package/src/host.ts +45 -0
  116. package/src/index.ts +1 -0
  117. package/src/merge.ts +198 -0
  118. package/src/plugin.ts +340 -318
  119. package/src/service-descriptor.ts +23 -0
  120. package/src/shared.ts +48 -5
  121. package/src/sidebar.ts +162 -0
  122. package/src/types.ts +134 -28
  123. package/src/utils/path-match.ts +16 -0
  124. package/src/utils/save-config.ts +20 -0
package/dist/merge.mjs ADDED
@@ -0,0 +1,107 @@
1
+ import { createDefu } from "defu";
2
+
3
+ //#region src/merge.ts
4
+ const BOS_CONFIG_ORDER = [
5
+ "extends",
6
+ "account",
7
+ "domain",
8
+ "testnet",
9
+ "staging",
10
+ "repository",
11
+ "app",
12
+ "plugins",
13
+ "shared"
14
+ ];
15
+ const ARRAY_UNION_KEYS = new Set(["secrets"]);
16
+ function isPlainObject(value) {
17
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
18
+ }
19
+ function unionArrays(a, b) {
20
+ const aArr = Array.isArray(a) ? a : [];
21
+ const bArr = Array.isArray(b) ? b : [];
22
+ if (aArr.length === 0 && bArr.length === 0) return void 0;
23
+ const seen = /* @__PURE__ */ new Set();
24
+ const result = [];
25
+ for (const item of [...aArr, ...bArr]) {
26
+ if (typeof item === "string") {
27
+ if (seen.has(item)) continue;
28
+ seen.add(item);
29
+ }
30
+ result.push(item);
31
+ }
32
+ return result;
33
+ }
34
+ function cleanNullSentinels(obj) {
35
+ const out = {};
36
+ for (const [key, value] of Object.entries(obj)) {
37
+ if (value === null || value === void 0) continue;
38
+ if (isPlainObject(value)) {
39
+ const cleaned = cleanNullSentinels(value);
40
+ if (Object.keys(cleaned).length > 0) out[key] = cleaned;
41
+ } else out[key] = value;
42
+ }
43
+ return out;
44
+ }
45
+ const bosConfigMerger = createDefu((obj, key, value) => {
46
+ if (obj[key] === null) return true;
47
+ if (value === null) {
48
+ obj[key] = null;
49
+ return true;
50
+ }
51
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
52
+ if (ARRAY_UNION_KEYS.has(key)) obj[key] = unionArrays(obj[key], value);
53
+ else obj[key] = value;
54
+ return true;
55
+ }
56
+ return false;
57
+ });
58
+ function resolveExtendsRef(extendsField, env) {
59
+ if (!extendsField) return void 0;
60
+ if (typeof extendsField === "string") return extendsField;
61
+ return extendsField[env] ?? extendsField.production ?? Object.values(extendsField).find(Boolean);
62
+ }
63
+ function mergeBosConfigWithExtends(parent, child) {
64
+ const merged = bosConfigMerger(child, parent);
65
+ if (isPlainObject(parent.plugins) && isPlainObject(child.plugins)) {
66
+ const plugins = { ...parent.plugins };
67
+ for (const [key, rawValue] of Object.entries(child.plugins)) {
68
+ const value = rawValue;
69
+ if (value === null || value === false) delete plugins[key];
70
+ else if (isPlainObject(plugins[key]) && isPlainObject(value)) plugins[key] = bosConfigMerger(value, plugins[key]);
71
+ else plugins[key] = value;
72
+ }
73
+ merged.plugins = plugins;
74
+ } else if (child.plugins !== void 0) merged.plugins = cleanNullSentinels(child.plugins);
75
+ const mergedRecord = merged;
76
+ if (isPlainObject(mergedRecord.app)) for (const entryVal of Object.values(mergedRecord.app)) {
77
+ if (!isPlainObject(entryVal)) continue;
78
+ for (const secretKey of ARRAY_UNION_KEYS) if (Array.isArray(entryVal[secretKey])) entryVal[secretKey] = unionArrays(entryVal[secretKey], [])?.filter(Boolean) ?? entryVal[secretKey];
79
+ }
80
+ if (isPlainObject(mergedRecord.plugins)) for (const pluginVal of Object.values(mergedRecord.plugins)) {
81
+ if (!isPlainObject(pluginVal)) continue;
82
+ for (const secretKey of ARRAY_UNION_KEYS) if (Array.isArray(pluginVal[secretKey])) pluginVal[secretKey] = unionArrays(pluginVal[secretKey], [])?.filter(Boolean) ?? pluginVal[secretKey];
83
+ }
84
+ return rebuildOrderedConfig(mergedRecord);
85
+ }
86
+ function mergeBosConfigWithTemplate(local, template) {
87
+ return rebuildOrderedConfig(mergeJsonValuesPreservingLocalOrder(local, template));
88
+ }
89
+ function mergeJsonValuesPreservingLocalOrder(local, template) {
90
+ if (isPlainObject(local) && isPlainObject(template)) {
91
+ const merged = {};
92
+ for (const key of Object.keys(local)) merged[key] = mergeJsonValuesPreservingLocalOrder(local[key], template[key]);
93
+ for (const key of Object.keys(template)) if (!(key in merged)) merged[key] = template[key];
94
+ return merged;
95
+ }
96
+ return local ?? template;
97
+ }
98
+ function rebuildOrderedConfig(config) {
99
+ const ordered = {};
100
+ for (const key of BOS_CONFIG_ORDER) if (key in config) ordered[key] = config[key];
101
+ for (const key of Object.keys(config)) if (!BOS_CONFIG_ORDER.includes(key)) ordered[key] = config[key];
102
+ return ordered;
103
+ }
104
+
105
+ //#endregion
106
+ export { BOS_CONFIG_ORDER, isPlainObject, mergeBosConfigWithExtends, mergeBosConfigWithTemplate, rebuildOrderedConfig, resolveExtendsRef };
107
+ //# sourceMappingURL=merge.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.mjs","names":[],"sources":["../src/merge.ts"],"sourcesContent":["import { createDefu } from \"defu\";\nimport type { BosConfigInput, ExtendsConfig } from \"./types\";\n\nexport const BOS_CONFIG_ORDER = [\n \"extends\",\n \"account\",\n \"domain\",\n \"testnet\",\n \"staging\",\n \"repository\",\n \"app\",\n \"plugins\",\n \"shared\",\n] as const;\n\nexport type BosConfigFieldName = (typeof BOS_CONFIG_ORDER)[number];\n\nexport type BosEnv = \"development\" | \"production\" | \"staging\";\n\nexport interface ResolvedConfigMeta {\n env: BosEnv;\n resolvedAt: string;\n extendsChain: string[];\n source?: string;\n}\n\nconst ARRAY_UNION_KEYS = new Set([\"secrets\"]);\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction unionArrays(a: unknown, b: unknown): unknown[] | undefined {\n const aArr = Array.isArray(a) ? a : [];\n const bArr = Array.isArray(b) ? b : [];\n if (aArr.length === 0 && bArr.length === 0) return undefined;\n const seen = new Set<string>();\n const result: unknown[] = [];\n for (const item of [...aArr, ...bArr]) {\n if (typeof item === \"string\") {\n if (seen.has(item)) continue;\n seen.add(item);\n }\n result.push(item);\n }\n return result;\n}\n\nfunction cleanNullSentinels(obj: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value === null || value === undefined) continue;\n if (isPlainObject(value)) {\n const cleaned = cleanNullSentinels(value);\n if (Object.keys(cleaned).length > 0) {\n out[key] = cleaned;\n }\n } else {\n out[key] = value;\n }\n }\n return out;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst bosConfigMerger = createDefu((obj: any, key: any, value: any): boolean | undefined => {\n if (obj[key] === null) return true;\n if (value === null) {\n obj[key] = null;\n return true;\n }\n if (Array.isArray(obj[key]) && Array.isArray(value)) {\n if (ARRAY_UNION_KEYS.has(key)) {\n obj[key] = unionArrays(obj[key], value);\n } else {\n obj[key] = value;\n }\n return true;\n }\n return false;\n});\n\nexport function resolveExtendsRef(\n extendsField: string | ExtendsConfig | undefined,\n env: BosEnv,\n): string | undefined {\n if (!extendsField) return undefined;\n if (typeof extendsField === \"string\") return extendsField;\n return extendsField[env] ?? extendsField.production ?? Object.values(extendsField).find(Boolean);\n}\n\nexport function mergeBosConfigWithExtends(\n parent: BosConfigInput,\n child: BosConfigInput,\n): BosConfigInput {\n const merged = bosConfigMerger(child, parent) as BosConfigInput;\n\n if (isPlainObject(parent.plugins) && isPlainObject(child.plugins)) {\n const plugins: Record<string, unknown> = { ...parent.plugins };\n for (const [key, rawValue] of Object.entries(child.plugins)) {\n const value = rawValue as unknown;\n if (value === null || value === false) {\n delete plugins[key];\n } else if (isPlainObject(plugins[key]) && isPlainObject(value)) {\n plugins[key] = bosConfigMerger(\n value as Record<string, unknown>,\n plugins[key] as Record<string, unknown>,\n );\n } else {\n plugins[key] = value;\n }\n }\n (merged as Record<string, unknown>).plugins = plugins;\n } else if (child.plugins !== undefined) {\n (merged as Record<string, unknown>).plugins = cleanNullSentinels(\n child.plugins as Record<string, unknown>,\n );\n }\n\n const mergedRecord = merged as Record<string, unknown>;\n\n if (isPlainObject(mergedRecord.app)) {\n for (const entryVal of Object.values(mergedRecord.app as Record<string, unknown>)) {\n if (!isPlainObject(entryVal)) continue;\n for (const secretKey of ARRAY_UNION_KEYS) {\n if (Array.isArray(entryVal[secretKey])) {\n entryVal[secretKey] =\n (unionArrays(entryVal[secretKey] as unknown[], []) as string[] | undefined)?.filter(\n Boolean,\n ) ?? entryVal[secretKey];\n }\n }\n }\n }\n\n if (isPlainObject(mergedRecord.plugins)) {\n for (const pluginVal of Object.values(mergedRecord.plugins as Record<string, unknown>)) {\n if (!isPlainObject(pluginVal)) continue;\n for (const secretKey of ARRAY_UNION_KEYS) {\n if (Array.isArray(pluginVal[secretKey])) {\n pluginVal[secretKey] =\n (unionArrays(pluginVal[secretKey] as unknown[], []) as string[] | undefined)?.filter(\n Boolean,\n ) ?? pluginVal[secretKey];\n }\n }\n }\n }\n\n return rebuildOrderedConfig(mergedRecord) as BosConfigInput;\n}\n\nexport function mergeBosConfigWithTemplate(\n local: BosConfigInput,\n template: BosConfigInput,\n): BosConfigInput {\n const merged = mergeJsonValuesPreservingLocalOrder(local, template) as BosConfigInput;\n return rebuildOrderedConfig(merged as Record<string, unknown>) as BosConfigInput;\n}\n\nfunction mergeJsonValuesPreservingLocalOrder(local: unknown, template: unknown): unknown {\n if (isPlainObject(local) && isPlainObject(template)) {\n const merged: Record<string, unknown> = {};\n for (const key of Object.keys(local)) {\n merged[key] = mergeJsonValuesPreservingLocalOrder(\n local[key],\n (template as Record<string, unknown>)[key],\n );\n }\n for (const key of Object.keys(template as Record<string, unknown>)) {\n if (!(key in merged)) {\n merged[key] = (template as Record<string, unknown>)[key];\n }\n }\n return merged;\n }\n return local ?? template;\n}\n\nexport function rebuildOrderedConfig<T extends Record<string, unknown>>(config: T): T {\n const ordered: Record<string, unknown> = {};\n\n for (const key of BOS_CONFIG_ORDER) {\n if (key in config) {\n ordered[key] = config[key];\n }\n }\n\n for (const key of Object.keys(config)) {\n if (!BOS_CONFIG_ORDER.includes(key as BosConfigFieldName)) {\n ordered[key] = config[key];\n }\n }\n\n return ordered as T;\n}\n\nexport { bosConfigMerger };\n"],"mappings":"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"}
package/dist/plugin.cjs CHANGED
@@ -6,6 +6,7 @@ const require_config = require('./config.cjs');
6
6
  const require_contract = require('./contract.cjs');
7
7
  const require_api_contract = require('./api-contract.cjs');
8
8
  const require_app = require('./app.cjs');
9
+ const require_save_config = require('./utils/save-config.cjs');
9
10
  const require_cli_init = require('./cli/init.cjs');
10
11
  const require_prompts = require('./cli/prompts.cjs');
11
12
  const require_status = require('./cli/status.cjs');
@@ -17,6 +18,7 @@ const require_service_descriptor = require('./service-descriptor.cjs');
17
18
  const require_dev_session = require('./dev-session.cjs');
18
19
  const require_near_cli = require('./near-cli.cjs');
19
20
  const require_shared = require('./shared.cjs');
21
+ const require_sidebar = require('./sidebar.cjs');
20
22
  const require_run = require('./utils/run.cjs');
21
23
  let node_fs = require("node:fs");
22
24
  let node_path = require("node:path");
@@ -58,6 +60,10 @@ const buildCommands = {
58
60
  }
59
61
  };
60
62
  const PUBLISH_FUNCTION_NAMES = ["__fastdata_kv"];
63
+ function getPluginRef(entry) {
64
+ if (!entry || typeof entry === "string") return null;
65
+ return entry;
66
+ }
61
67
  function parseSourceMode(value, defaultValue) {
62
68
  if (value === "local" || value === "remote") return value;
63
69
  return defaultValue;
@@ -85,7 +91,7 @@ function resolveWorkspaceTarget(key, bosConfig, runtimeConfig, configDir) {
85
91
  path: `${configDir}/${key}`
86
92
  };
87
93
  }
88
- const pluginPath = (runtimeConfig?.plugins?.[key])?.localPath ?? require_config.resolveLocalDevelopmentPath(bosConfig?.plugins?.[key]?.development, configDir);
94
+ const pluginPath = (runtimeConfig?.plugins?.[key])?.localPath ?? require_config.resolveLocalDevelopmentPath(getPluginRef(bosConfig?.plugins?.[key])?.development, configDir);
89
95
  if (pluginPath) return {
90
96
  key,
91
97
  kind: "plugin",
@@ -123,29 +129,25 @@ function defaultPluginKey(source) {
123
129
  }
124
130
  }
125
131
  function pluginLocalPath(configDir, attachment) {
126
- const source = attachment.development ?? attachment.production;
132
+ const ref = getPluginRef(attachment);
133
+ const source = ref?.development ?? ref?.production;
127
134
  if (!source?.startsWith("local:")) return null;
128
135
  return (0, node_path.join)(configDir, source.slice(6));
129
136
  }
130
- async function saveBosConfig(configDir, config) {
131
- const filePath = (0, node_path.join)(configDir, "bos.config.json");
132
- const next = `${JSON.stringify(config, null, 2)}\n`;
133
- try {
134
- if ((0, node_fs.readFileSync)(filePath, "utf8") === next) return;
135
- } catch {}
136
- (0, node_fs.writeFileSync)(filePath, next);
137
- }
138
137
  function listPluginAttachments(config) {
139
- return Object.entries(config?.plugins ?? {}).map(([key, attachment]) => ({
140
- key,
141
- development: attachment.development,
142
- production: attachment.production,
143
- localPath: attachment.development?.startsWith("local:") ? attachment.development.slice(6) : void 0,
144
- source: attachment.development?.startsWith("local:") ? "local" : "remote",
145
- integrity: attachment.integrity,
146
- version: attachment.version,
147
- name: attachment.name
148
- })).sort((a, b) => a.key.localeCompare(b.key));
138
+ return Object.entries(config?.plugins ?? {}).map(([key, attachment]) => {
139
+ const ref = getPluginRef(attachment);
140
+ return {
141
+ key,
142
+ development: ref?.development,
143
+ production: ref?.production,
144
+ localPath: ref?.development?.startsWith("local:") ? ref.development.slice(6) : void 0,
145
+ source: ref?.development?.startsWith("local:") ? "local" : "remote",
146
+ integrity: ref?.integrity,
147
+ version: ref?.version,
148
+ name: ref?.name
149
+ };
150
+ }).sort((a, b) => a.key.localeCompare(b.key));
149
151
  }
150
152
  async function refreshApiContractBridge(configDir, env = "development") {
151
153
  const refreshed = await require_config.loadConfig({
@@ -158,6 +160,7 @@ async function refreshApiContractBridge(configDir, env = "development") {
158
160
  runtimeConfig: refreshed.runtime,
159
161
  apiBaseUrl: refreshed.runtime.api.url
160
162
  });
163
+ require_sidebar.writePluginSidebarGen(configDir, refreshed.config);
161
164
  }
162
165
  function extractPublishedUrl(output) {
163
166
  const match = output.match(/https?:\/\/[^\s"'<>]+/g);
@@ -239,7 +242,8 @@ async function buildWorkspaceTargets(opts) {
239
242
  if ((await require_shared.syncAndGenerateSharedUi({
240
243
  configDir: opts.configDir,
241
244
  hostMode: "local",
242
- bosConfig: opts.bosConfig ?? void 0
245
+ bosConfig: opts.bosConfig ?? void 0,
246
+ extendsChain: []
243
247
  })).catalogChanged) await require_run.run("bun", ["install"], { cwd: opts.configDir });
244
248
  if (existing.some((entry) => entry.key === "api")) await buildEveryPluginQuietly(opts.configDir);
245
249
  await buildEverythingDevQuietly(opts.configDir);
@@ -296,76 +300,40 @@ var plugin_default = (0, every_plugin.createPlugin)({
296
300
  key: "",
297
301
  error: "No bos.config.json found"
298
302
  };
299
- const pluginRef = require_fastkv.parsePluginBosUrl(input.source);
300
- let production = input.production ?? input.source;
301
- let integrity;
302
- let version;
303
- let name;
304
- if (pluginRef) try {
305
- const entry = await require_fastkv.fetchPluginFromRegistry(pluginRef.accountId, pluginRef.pluginName);
306
- if (!entry) return {
307
- status: "error",
308
- key: "",
309
- error: `Plugin not found in registry: bos://${pluginRef.accountId}/plugins/${pluginRef.pluginName}`
310
- };
311
- const manifest = entry.manifest;
312
- if (manifest.schemaVersion !== 1 || manifest.kind !== "every-plugin/manifest" || !manifest.plugin?.name || !manifest.plugin?.version || !manifest.runtime?.remoteEntry) return {
313
- status: "error",
314
- key: "",
315
- error: `Invalid plugin manifest for bos://${pluginRef.accountId}/plugins/${pluginRef.pluginName}`
316
- };
317
- production = entry.metadata.cdnUrl || input.production || input.source;
318
- name = manifest.plugin.name;
319
- version = manifest.plugin.version;
320
- } catch (error) {
321
- return {
322
- status: "error",
323
- key: "",
324
- error: `Failed to resolve plugin from registry: ${error instanceof Error ? error.message : error}`
325
- };
326
- }
327
- if (!input.source.startsWith("local:") && !pluginRef && production.startsWith("https://")) try {
328
- const manifest = await require_fastkv.fetchRemotePluginManifest(production);
329
- if (manifest) {
330
- name = manifest.plugin.name;
331
- version = manifest.plugin.version;
332
- }
333
- } catch {
334
- console.warn(`[plugin add] Could not fetch manifest from ${production}`);
335
- }
336
- if (!input.source.startsWith("local:") && production.startsWith("https://")) try {
337
- const computed = await require_integrity.computeSriHashForUrl(production);
338
- if (computed) integrity = computed;
339
- } catch {
340
- console.warn(`[plugin add] Could not compute integrity for ${production}`);
341
- }
342
- const key = sanitizePluginKey(input.as ?? (pluginRef ? pluginRef.pluginName : defaultPluginKey(input.source)));
303
+ const isBosRef = input.source.startsWith("bos://");
304
+ const isLocal = input.source.startsWith("local:");
305
+ const key = sanitizePluginKey(input.as ?? (isBosRef ? input.source.split("/").pop() ?? "plugin" : defaultPluginKey(input.source)));
343
306
  const existing = deps.bosConfig.plugins?.[key];
307
+ const existingEntry = existing && typeof existing === "object" ? existing : {};
344
308
  const nextPlugins = { ...deps.bosConfig.plugins ?? {} };
345
- nextPlugins[key] = input.source.startsWith("local:") ? {
346
- ...existing ?? {},
309
+ if (isBosRef) nextPlugins[key] = {
310
+ ...existingEntry,
311
+ extends: input.source
312
+ };
313
+ else if (isLocal) nextPlugins[key] = {
314
+ ...existingEntry,
347
315
  development: input.source,
348
- production: input.production ?? existing?.production
349
- } : {
350
- ...existing ?? {},
351
- production,
352
- ...integrity ? { integrity } : {},
353
- ...name ? { name } : {},
354
- ...version ? { version } : {}
316
+ ...existingEntry.extends ? {} : {}
317
+ };
318
+ else nextPlugins[key] = {
319
+ ...existingEntry,
320
+ production: input.production ?? input.source
355
321
  };
356
322
  deps.bosConfig = {
357
323
  ...deps.bosConfig,
358
324
  plugins: nextPlugins
359
325
  };
360
- await saveBosConfig(deps.configDir, deps.bosConfig);
326
+ await require_save_config.saveBosConfig(deps.configDir, deps.bosConfig);
361
327
  await refreshApiContractBridge(deps.configDir);
328
+ const stored = deps.bosConfig.plugins?.[key];
329
+ const storedObj = stored && typeof stored === "object" ? stored : {};
362
330
  return {
363
331
  status: "added",
364
332
  key,
365
- development: deps.bosConfig.plugins?.[key]?.development,
366
- production: deps.bosConfig.plugins?.[key]?.production,
367
- integrity,
368
- version
333
+ development: storedObj.development,
334
+ production: storedObj.production,
335
+ integrity: storedObj.integrity,
336
+ version: storedObj.version
369
337
  };
370
338
  }),
371
339
  pluginRemove: builder.pluginRemove.handler(async ({ input }) => {
@@ -385,7 +353,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
385
353
  ...deps.bosConfig,
386
354
  plugins: Object.keys(nextPlugins).length > 0 ? nextPlugins : void 0
387
355
  };
388
- await saveBosConfig(deps.configDir, deps.bosConfig);
356
+ await require_save_config.saveBosConfig(deps.configDir, deps.bosConfig);
389
357
  await refreshApiContractBridge(deps.configDir);
390
358
  return {
391
359
  status: "removed",
@@ -410,6 +378,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
410
378
  key: input.key,
411
379
  error: `Plugin '${input.key}' is not configured`
412
380
  };
381
+ const attachmentRef = getPluginRef(attachment);
413
382
  const localPath = pluginLocalPath(deps.configDir, attachment);
414
383
  if (!localPath) return {
415
384
  status: "error",
@@ -442,29 +411,36 @@ var plugin_default = (0, every_plugin.createPlugin)({
442
411
  let publishedUrl = extractPublishedUrl(`${stdout}\n${stderr}`);
443
412
  let manifest = null;
444
413
  if (publishedUrl) manifest = await require_fastkv.fetchRemotePluginManifest(publishedUrl);
445
- else if (attachment.production) {
446
- manifest = await require_fastkv.fetchRemotePluginManifest(attachment.production);
447
- if (manifest) publishedUrl = attachment.production;
414
+ else if (attachmentRef?.production) {
415
+ manifest = await require_fastkv.fetchRemotePluginManifest(attachmentRef.production);
416
+ if (manifest) publishedUrl = attachmentRef.production;
448
417
  }
449
418
  const integrity = publishedUrl ? await require_integrity.computeSriHashForUrl(publishedUrl) : null;
450
419
  const version = manifest?.plugin.version ?? pkgJson.version;
451
420
  if (publishedUrl) {
452
- deps.bosConfig = {
453
- ...deps.bosConfig,
454
- plugins: {
455
- ...deps.bosConfig.plugins ?? {},
456
- [input.key]: {
457
- ...deps.bosConfig.plugins?.[input.key] ?? {},
458
- production: publishedUrl,
459
- ...integrity ? { integrity } : {},
460
- ...manifest?.plugin.name ? { name: manifest.plugin.name } : {},
461
- ...version ? { version } : {}
462
- }
463
- }
464
- };
465
- await saveBosConfig(deps.configDir, deps.bosConfig);
421
+ const pluginConfigPath = (0, node_path.join)(localPath, "bos.config.json");
422
+ if ((0, node_fs.existsSync)(pluginConfigPath)) try {
423
+ const pluginConfig = JSON.parse((0, node_fs.readFileSync)(pluginConfigPath, "utf-8"));
424
+ if (!pluginConfig.app) pluginConfig.app = {};
425
+ const app = pluginConfig.app;
426
+ if (!app.api) app.api = {};
427
+ const api = app.api;
428
+ api.production = publishedUrl;
429
+ if (integrity) api.integrity = integrity;
430
+ else delete api.integrity;
431
+ (0, node_fs.writeFileSync)(pluginConfigPath, `${JSON.stringify(pluginConfig, null, 2)}\n`);
432
+ console.log(` ✅ Updated ${pluginConfigPath}: app.api.production`);
433
+ } catch (err) {
434
+ console.error(` ❌ Failed to update plugin bos.config.json:`, err instanceof Error ? err.message : err);
435
+ }
466
436
  const account = deps.bosConfig.account;
467
437
  const network = require_network.getNetworkIdForAccount(account);
438
+ let pluginDomain;
439
+ if ((0, node_fs.existsSync)(pluginConfigPath)) try {
440
+ const pluginConfig = JSON.parse((0, node_fs.readFileSync)(pluginConfigPath, "utf-8"));
441
+ if (typeof pluginConfig.domain === "string") pluginDomain = pluginConfig.domain;
442
+ } catch {}
443
+ if (!pluginDomain) pluginDomain = `${input.key}.${deps.bosConfig.domain ?? "everything.dev"}`;
468
444
  if (manifest && version) try {
469
445
  const registryEntries = {
470
446
  [`plugins/${account}/${input.key}/manifest.json`]: JSON.stringify(manifest),
@@ -479,6 +455,11 @@ var plugin_default = (0, every_plugin.createPlugin)({
479
455
  }),
480
456
  [`plugins/${account}/${input.key}/versions/${version}/manifest.json`]: JSON.stringify(manifest)
481
457
  };
458
+ if ((0, node_fs.existsSync)(pluginConfigPath)) try {
459
+ const publishedPluginConfig = JSON.parse((0, node_fs.readFileSync)(pluginConfigPath, "utf-8"));
460
+ delete publishedPluginConfig.development;
461
+ registryEntries[`apps/${account}/${pluginDomain}/bos.config.json`] = JSON.stringify(publishedPluginConfig);
462
+ } catch {}
482
463
  const payload = JSON.stringify(registryEntries);
483
464
  const argsBase64 = Buffer.from(payload).toString("base64");
484
465
  const privateKey = process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
@@ -507,7 +488,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
507
488
  key: input.key,
508
489
  path: localPath,
509
490
  script,
510
- production: publishedUrl ?? attachment.production,
491
+ production: publishedUrl ?? attachmentRef?.production,
511
492
  integrity: integrity ?? void 0,
512
493
  version: version ?? void 0
513
494
  };
@@ -524,13 +505,18 @@ var plugin_default = (0, every_plugin.createPlugin)({
524
505
  if ((await require_shared.syncAndGenerateSharedUi({
525
506
  configDir: deps.configDir,
526
507
  hostMode: hostSource,
527
- bosConfig: deps.bosConfig ?? void 0
508
+ bosConfig: deps.bosConfig ?? void 0,
509
+ extendsChain: []
528
510
  })).catalogChanged) await require_run.run("bun", ["install"], { cwd: deps.configDir });
529
511
  if (apiSource === "local" && !proxy || localPackages.some((pkg) => pkg.startsWith("plugin:"))) await buildEveryPluginQuietly(deps.configDir);
530
512
  await buildEverythingDevQuietly(deps.configDir);
531
513
  const refreshed = await require_config.loadConfig({ cwd: deps.configDir });
532
514
  deps.bosConfig = refreshed?.config ?? deps.bosConfig;
533
515
  deps.runtimeConfig = refreshed?.runtime ?? deps.runtimeConfig;
516
+ if (deps.bosConfig) {
517
+ require_config.writeResolvedConfig(deps.configDir, deps.bosConfig, "development", refreshed?.source.extended);
518
+ require_sidebar.writePluginSidebarGen(deps.configDir, deps.bosConfig);
519
+ }
534
520
  if (!deps.bosConfig) return {
535
521
  status: "error",
536
522
  description: "No bos.config.json found",
@@ -618,6 +604,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
618
604
  env: "production",
619
605
  plugins: runtimePlugins
620
606
  });
607
+ require_sidebar.writePluginSidebarGen(deps.configDir, config);
621
608
  const productionEnv = {};
622
609
  const warnings = [];
623
610
  if (!process.env.CORS_ORIGIN && config.domain) {
@@ -677,6 +664,9 @@ var plugin_default = (0, every_plugin.createPlugin)({
677
664
  built: [],
678
665
  skipped: []
679
666
  };
667
+ const buildEnv = input.deploy ? "production" : "development";
668
+ require_config.writeResolvedConfig(deps.configDir, deps.bosConfig, buildEnv);
669
+ require_sidebar.writePluginSidebarGen(deps.configDir, deps.bosConfig);
680
670
  const targets = selectWorkspaceTargets(input.packages, deps.bosConfig);
681
671
  if (targets.length === 0) return {
682
672
  status: "error",
@@ -688,7 +678,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
688
678
  apiSource: deps.bosConfig.app.api?.development ? "local" : "remote",
689
679
  authSource: deps.bosConfig.app.auth?.development ? "local" : "remote",
690
680
  hostSource: deps.bosConfig.app.host?.development ? "local" : "remote",
691
- env: "development",
681
+ env: buildEnv,
692
682
  plugins: deps.runtimeConfig?.plugins
693
683
  });
694
684
  await require_api_contract.syncApiContractBridge({
@@ -758,7 +748,20 @@ var plugin_default = (0, every_plugin.createPlugin)({
758
748
  publishConfig = refreshed.config;
759
749
  }
760
750
  }
761
- const payload = JSON.stringify({ [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishConfig) });
751
+ const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishConfig) };
752
+ for (const [pluginKey, pluginEntry] of Object.entries(publishConfig.plugins ?? {})) {
753
+ const pluginRef = getPluginRef(pluginEntry);
754
+ if (!pluginRef?.development?.startsWith("local:")) continue;
755
+ const pluginConfigPath = (0, node_path.join)((0, node_path.join)(deps.configDir, pluginRef.development.slice(6)), "bos.config.json");
756
+ if (!(0, node_fs.existsSync)(pluginConfigPath)) continue;
757
+ try {
758
+ const pluginConfig = JSON.parse((0, node_fs.readFileSync)(pluginConfigPath, "utf-8"));
759
+ const pluginDomain = typeof pluginConfig.domain === "string" ? pluginConfig.domain : `${pluginKey}.${gateway}`;
760
+ delete pluginConfig.development;
761
+ registryEntries[`apps/${account}/${pluginDomain}/bos.config.json`] = JSON.stringify(pluginConfig);
762
+ } catch {}
763
+ }
764
+ const payload = JSON.stringify(registryEntries);
762
765
  const argsBase64 = Buffer.from(payload).toString("base64");
763
766
  const privateKey = input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
764
767
  try {
@@ -882,7 +885,7 @@ var plugin_default = (0, every_plugin.createPlugin)({
882
885
  extendsAccount = extendsAccount || "dev.everything.near";
883
886
  extendsGateway = extendsGateway || "everything.dev";
884
887
  directory = directory || domain || extendsGateway;
885
- plugins = plugins?.length ? plugins : ["_template"];
888
+ plugins = plugins?.length ? plugins : ["settings"];
886
889
  try {
887
890
  await require_cli_init.fetchParentConfig(extendsAccount, extendsGateway);
888
891
  } catch {
@@ -919,8 +922,9 @@ var plugin_default = (0, every_plugin.createPlugin)({
919
922
  error: "No .templatekeep found in template source"
920
923
  };
921
924
  const pluginRoutes = {};
922
- if (parentConfig.plugins) {
923
- for (const [key, ref] of Object.entries(parentConfig.plugins)) if (ref.routes && ref.routes.length > 0) pluginRoutes[key] = ref.routes;
925
+ if (parentConfig.plugins) for (const [key, entry] of Object.entries(parentConfig.plugins)) {
926
+ const entryRef = getPluginRef(entry);
927
+ if (entryRef?.routes && entryRef.routes.length > 0) pluginRoutes[key] = entryRef.routes;
924
928
  }
925
929
  const s = _clack_prompts.spinner();
926
930
  s.start("Setting up project");
@@ -950,6 +954,8 @@ var plugin_default = (0, every_plugin.createPlugin)({
950
954
  await require_cli_init.runTypesGen(directory);
951
955
  await require_cli_init.generateDatabaseMigrations(directory);
952
956
  }
957
+ const initConfig = await require_config.loadConfig({ cwd: directory });
958
+ if (initConfig?.config) require_sidebar.writePluginSidebarGen(directory, initConfig.config);
953
959
  s.stop("Project initialized");
954
960
  return {
955
961
  status: "initialized",
@@ -990,7 +996,13 @@ var plugin_default = (0, every_plugin.createPlugin)({
990
996
  added: [],
991
997
  error: "No bos.config.json found in current directory"
992
998
  };
993
- return await require_sync.syncTemplate((0, node_path.resolve)((0, node_path.dirname)(configPath)), input);
999
+ const projectDir = (0, node_path.resolve)((0, node_path.dirname)(configPath));
1000
+ const result = await require_sync.syncTemplate(projectDir, input);
1001
+ if (result.status === "synced" || result.status === "dry-run") {
1002
+ const syncedConfig = await require_config.loadConfig({ cwd: projectDir });
1003
+ if (syncedConfig?.config) require_sidebar.writePluginSidebarGen(projectDir, syncedConfig.config);
1004
+ }
1005
+ return result;
994
1006
  } catch (error) {
995
1007
  return {
996
1008
  status: "error",