@ankhorage/studio 0.0.20 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +1 -2
  2. package/dist/cli/index.d.ts +4 -4
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +81 -56
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/core/constants.d.ts.map +1 -1
  7. package/dist/core/constants.js +17 -6
  8. package/dist/core/constants.js.map +1 -1
  9. package/dist/hooks/useProjects.js +1 -1
  10. package/dist/hooks/useProjects.js.map +1 -1
  11. package/dist/host/createStudioHost.d.ts +13 -0
  12. package/dist/host/createStudioHost.d.ts.map +1 -0
  13. package/dist/host/createStudioHost.js +16 -0
  14. package/dist/host/createStudioHost.js.map +1 -0
  15. package/dist/host/http/security.d.ts +2 -0
  16. package/dist/host/http/security.d.ts.map +1 -0
  17. package/dist/host/http/security.js +55 -0
  18. package/dist/host/http/security.js.map +1 -0
  19. package/dist/host/http/server.d.ts +16 -0
  20. package/dist/host/http/server.d.ts.map +1 -0
  21. package/dist/host/http/server.js +549 -0
  22. package/dist/host/http/server.js.map +1 -0
  23. package/dist/host/layout/auth/resolveAuthLayoutPlan.d.ts +38 -0
  24. package/dist/host/layout/auth/resolveAuthLayoutPlan.d.ts.map +1 -0
  25. package/dist/host/layout/auth/resolveAuthLayoutPlan.js +262 -0
  26. package/dist/host/layout/auth/resolveAuthLayoutPlan.js.map +1 -0
  27. package/dist/host/layout/layoutGenerator.d.ts +19 -0
  28. package/dist/host/layout/layoutGenerator.d.ts.map +1 -0
  29. package/dist/host/layout/layoutGenerator.js +418 -0
  30. package/dist/host/layout/layoutGenerator.js.map +1 -0
  31. package/dist/host/layout/templates/auth/adapter.d.ts +6 -0
  32. package/dist/host/layout/templates/auth/adapter.d.ts.map +1 -0
  33. package/dist/host/layout/templates/auth/adapter.js +94 -0
  34. package/dist/host/layout/templates/auth/adapter.js.map +1 -0
  35. package/dist/host/layout/templates/auth/screen.d.ts +12 -0
  36. package/dist/host/layout/templates/auth/screen.d.ts.map +1 -0
  37. package/dist/host/layout/templates/auth/screen.js +648 -0
  38. package/dist/host/layout/templates/auth/screen.js.map +1 -0
  39. package/dist/host/layout/templates/auth/session.d.ts +2 -0
  40. package/dist/host/layout/templates/auth/session.d.ts.map +1 -0
  41. package/dist/host/layout/templates/auth/session.js +326 -0
  42. package/dist/host/layout/templates/auth/session.js.map +1 -0
  43. package/dist/host/layout/templates/auth/signOut.d.ts +2 -0
  44. package/dist/host/layout/templates/auth/signOut.d.ts.map +1 -0
  45. package/dist/host/layout/templates/auth/signOut.js +43 -0
  46. package/dist/host/layout/templates/auth/signOut.js.map +1 -0
  47. package/dist/host/layout/templates/index.d.ts +11 -0
  48. package/dist/host/layout/templates/index.d.ts.map +1 -0
  49. package/dist/host/layout/templates/index.js +10 -0
  50. package/dist/host/layout/templates/index.js.map +1 -0
  51. package/dist/host/layout/templates/navigation.d.ts +16 -0
  52. package/dist/host/layout/templates/navigation.d.ts.map +1 -0
  53. package/dist/host/layout/templates/navigation.js +332 -0
  54. package/dist/host/layout/templates/navigation.js.map +1 -0
  55. package/dist/host/layout/templates/nestedLayout.d.ts +7 -0
  56. package/dist/host/layout/templates/nestedLayout.d.ts.map +1 -0
  57. package/dist/host/layout/templates/nestedLayout.js +56 -0
  58. package/dist/host/layout/templates/nestedLayout.js.map +1 -0
  59. package/dist/host/layout/templates/redirect.d.ts +2 -0
  60. package/dist/host/layout/templates/redirect.d.ts.map +1 -0
  61. package/dist/host/layout/templates/redirect.js +10 -0
  62. package/dist/host/layout/templates/redirect.js.map +1 -0
  63. package/dist/host/layout/templates/rootLayout.d.ts +28 -0
  64. package/dist/host/layout/templates/rootLayout.d.ts.map +1 -0
  65. package/dist/host/layout/templates/rootLayout.js +507 -0
  66. package/dist/host/layout/templates/rootLayout.js.map +1 -0
  67. package/dist/host/layout/templates/screen.d.ts +6 -0
  68. package/dist/host/layout/templates/screen.d.ts.map +1 -0
  69. package/dist/host/layout/templates/screen.js +94 -0
  70. package/dist/host/layout/templates/screen.js.map +1 -0
  71. package/dist/host/layout/templates/utils/routes.d.ts +3 -0
  72. package/dist/host/layout/templates/utils/routes.d.ts.map +1 -0
  73. package/dist/host/layout/templates/utils/routes.js +15 -0
  74. package/dist/host/layout/templates/utils/routes.js.map +1 -0
  75. package/dist/host/layout/templates/utils/strings.d.ts +3 -0
  76. package/dist/host/layout/templates/utils/strings.d.ts.map +1 -0
  77. package/dist/host/layout/templates/utils/strings.js +7 -0
  78. package/dist/host/layout/templates/utils/strings.js.map +1 -0
  79. package/dist/host/layout/utils/escapeStringLiteral.d.ts +2 -0
  80. package/dist/host/layout/utils/escapeStringLiteral.d.ts.map +1 -0
  81. package/dist/host/layout/utils/escapeStringLiteral.js +8 -0
  82. package/dist/host/layout/utils/escapeStringLiteral.js.map +1 -0
  83. package/dist/host/manifestSystem/auth/index.d.ts +2 -0
  84. package/dist/host/manifestSystem/auth/index.d.ts.map +1 -0
  85. package/dist/host/manifestSystem/auth/index.js +2 -0
  86. package/dist/host/manifestSystem/auth/index.js.map +1 -0
  87. package/dist/host/manifestSystem/auth/shared/global.auth.system.tpl.d.ts +4 -0
  88. package/dist/host/manifestSystem/auth/shared/global.auth.system.tpl.d.ts.map +1 -0
  89. package/dist/host/manifestSystem/auth/shared/global.auth.system.tpl.js +7 -0
  90. package/dist/host/manifestSystem/auth/shared/global.auth.system.tpl.js.map +1 -0
  91. package/dist/host/manifestSystem/auth/shared/index.d.ts +3 -0
  92. package/dist/host/manifestSystem/auth/shared/index.d.ts.map +1 -0
  93. package/dist/host/manifestSystem/auth/shared/index.js +8 -0
  94. package/dist/host/manifestSystem/auth/shared/index.js.map +1 -0
  95. package/dist/host/manifestSystem/index.d.ts +5 -0
  96. package/dist/host/manifestSystem/index.d.ts.map +1 -0
  97. package/dist/host/manifestSystem/index.js +23 -0
  98. package/dist/host/manifestSystem/index.js.map +1 -0
  99. package/dist/host/manifestSystem/types.d.ts +8 -0
  100. package/dist/host/manifestSystem/types.d.ts.map +1 -0
  101. package/dist/host/manifestSystem/types.js +2 -0
  102. package/dist/host/manifestSystem/types.js.map +1 -0
  103. package/dist/host/modules/catalog.d.ts +40 -0
  104. package/dist/host/modules/catalog.d.ts.map +1 -0
  105. package/dist/host/modules/catalog.js +112 -0
  106. package/dist/host/modules/catalog.js.map +1 -0
  107. package/dist/host/modules/layout.d.ts +7 -0
  108. package/dist/host/modules/layout.d.ts.map +1 -0
  109. package/dist/host/modules/layout.js +2 -0
  110. package/dist/host/modules/layout.js.map +1 -0
  111. package/dist/host/modules/runtime/LocalFsTargetAdapter.d.ts +34 -0
  112. package/dist/host/modules/runtime/LocalFsTargetAdapter.d.ts.map +1 -0
  113. package/dist/host/modules/runtime/LocalFsTargetAdapter.js +85 -0
  114. package/dist/host/modules/runtime/LocalFsTargetAdapter.js.map +1 -0
  115. package/dist/host/orchestrator/generatedAppFiles.d.ts +8 -0
  116. package/dist/host/orchestrator/generatedAppFiles.d.ts.map +1 -0
  117. package/dist/host/orchestrator/generatedAppFiles.js +125 -0
  118. package/dist/host/orchestrator/generatedAppFiles.js.map +1 -0
  119. package/dist/host/orchestrator/generatedRouteCleanup.d.ts +5 -0
  120. package/dist/host/orchestrator/generatedRouteCleanup.d.ts.map +1 -0
  121. package/dist/host/orchestrator/generatedRouteCleanup.js +117 -0
  122. package/dist/host/orchestrator/generatedRouteCleanup.js.map +1 -0
  123. package/dist/host/orchestrator/infraGenerator.d.ts +35 -0
  124. package/dist/host/orchestrator/infraGenerator.d.ts.map +1 -0
  125. package/dist/host/orchestrator/infraGenerator.js +135 -0
  126. package/dist/host/orchestrator/infraGenerator.js.map +1 -0
  127. package/dist/host/orchestrator/infraRuntime.d.ts +38 -0
  128. package/dist/host/orchestrator/infraRuntime.d.ts.map +1 -0
  129. package/dist/host/orchestrator/infraRuntime.js +227 -0
  130. package/dist/host/orchestrator/infraRuntime.js.map +1 -0
  131. package/dist/host/orchestrator/infraValidation.d.ts +3 -0
  132. package/dist/host/orchestrator/infraValidation.d.ts.map +1 -0
  133. package/dist/host/orchestrator/infraValidation.js +59 -0
  134. package/dist/host/orchestrator/infraValidation.js.map +1 -0
  135. package/dist/host/orchestrator/moduleManager.d.ts +86 -0
  136. package/dist/host/orchestrator/moduleManager.d.ts.map +1 -0
  137. package/dist/host/orchestrator/moduleManager.js +312 -0
  138. package/dist/host/orchestrator/moduleManager.js.map +1 -0
  139. package/dist/host/orchestrator/projectDeletion.d.ts +27 -0
  140. package/dist/host/orchestrator/projectDeletion.d.ts.map +1 -0
  141. package/dist/host/orchestrator/projectDeletion.js +242 -0
  142. package/dist/host/orchestrator/projectDeletion.js.map +1 -0
  143. package/dist/host/orchestrator/projectManager.d.ts +87 -0
  144. package/dist/host/orchestrator/projectManager.d.ts.map +1 -0
  145. package/dist/host/orchestrator/projectManager.js +371 -0
  146. package/dist/host/orchestrator/projectManager.js.map +1 -0
  147. package/dist/host/orchestrator/projectPaths.d.ts +4 -0
  148. package/dist/host/orchestrator/projectPaths.d.ts.map +1 -0
  149. package/dist/host/orchestrator/projectPaths.js +25 -0
  150. package/dist/host/orchestrator/projectPaths.js.map +1 -0
  151. package/dist/host/orchestrator/projectStore.d.ts +24 -0
  152. package/dist/host/orchestrator/projectStore.d.ts.map +1 -0
  153. package/dist/host/orchestrator/projectStore.js +155 -0
  154. package/dist/host/orchestrator/projectStore.js.map +1 -0
  155. package/dist/host/orchestrator/resolveMutations.d.ts +3 -0
  156. package/dist/host/orchestrator/resolveMutations.d.ts.map +1 -0
  157. package/dist/host/orchestrator/resolveMutations.js +12 -0
  158. package/dist/host/orchestrator/resolveMutations.js.map +1 -0
  159. package/dist/host/orchestrator/scaffolder.d.ts +33 -0
  160. package/dist/host/orchestrator/scaffolder.d.ts.map +1 -0
  161. package/dist/host/orchestrator/scaffolder.js +246 -0
  162. package/dist/host/orchestrator/scaffolder.js.map +1 -0
  163. package/dist/host/orchestrator/templates.d.ts +83 -0
  164. package/dist/host/orchestrator/templates.d.ts.map +1 -0
  165. package/dist/host/orchestrator/templates.js +355 -0
  166. package/dist/host/orchestrator/templates.js.map +1 -0
  167. package/dist/host/orchestrator/workspaceRuntime.d.ts +2 -0
  168. package/dist/host/orchestrator/workspaceRuntime.d.ts.map +1 -0
  169. package/dist/host/orchestrator/workspaceRuntime.js +82 -0
  170. package/dist/host/orchestrator/workspaceRuntime.js.map +1 -0
  171. package/dist/host/templateRegistry/index.d.ts +16 -0
  172. package/dist/host/templateRegistry/index.d.ts.map +1 -0
  173. package/dist/host/templateRegistry/index.js +74 -0
  174. package/dist/host/templateRegistry/index.js.map +1 -0
  175. package/dist/host/utils/requirementsInference.d.ts +4 -0
  176. package/dist/host/utils/requirementsInference.d.ts.map +1 -0
  177. package/dist/host/utils/requirementsInference.js +49 -0
  178. package/dist/host/utils/requirementsInference.js.map +1 -0
  179. package/dist/host/utils/trimOutput.d.ts +7 -0
  180. package/dist/host/utils/trimOutput.d.ts.map +1 -0
  181. package/dist/host/utils/trimOutput.js +32 -0
  182. package/dist/host/utils/trimOutput.js.map +1 -0
  183. package/dist/host/utils/workspaceRoot.d.ts +2 -0
  184. package/dist/host/utils/workspaceRoot.d.ts.map +1 -0
  185. package/dist/host/utils/workspaceRoot.js +33 -0
  186. package/dist/host/utils/workspaceRoot.js.map +1 -0
  187. package/dist/host/zoraExtensions/index.d.ts +11 -0
  188. package/dist/host/zoraExtensions/index.d.ts.map +1 -0
  189. package/dist/host/zoraExtensions/index.js +54 -0
  190. package/dist/host/zoraExtensions/index.js.map +1 -0
  191. package/dist/runtime/appExtensionRegistry.d.ts +3 -0
  192. package/dist/runtime/appExtensionRegistry.d.ts.map +1 -0
  193. package/dist/runtime/appExtensionRegistry.js +8 -0
  194. package/dist/runtime/appExtensionRegistry.js.map +1 -0
  195. package/dist/runtime/index.d.ts +8 -4
  196. package/dist/runtime/index.d.ts.map +1 -1
  197. package/dist/runtime/index.js +8 -4
  198. package/dist/runtime/index.js.map +1 -1
  199. package/dist/runtime/registry.d.ts +7 -0
  200. package/dist/runtime/registry.d.ts.map +1 -0
  201. package/dist/runtime/registry.js +7 -0
  202. package/dist/runtime/registry.js.map +1 -0
  203. package/dist/runtime/runtimeActions.d.ts +19 -0
  204. package/dist/runtime/runtimeActions.d.ts.map +1 -0
  205. package/dist/runtime/runtimeActions.js +5 -0
  206. package/dist/runtime/runtimeActions.js.map +1 -0
  207. package/dist/runtime/useRuntimeAction.d.ts +10 -0
  208. package/dist/runtime/useRuntimeAction.d.ts.map +1 -0
  209. package/dist/runtime/useRuntimeAction.js +30 -0
  210. package/dist/runtime/useRuntimeAction.js.map +1 -0
  211. package/package.json +35 -3
@@ -0,0 +1,371 @@
1
+ import { resolveExpoRuntimePlan } from '@ankhorage/expo-runtime/planning';
2
+ import { promises as fs } from 'fs';
3
+ import path from 'path';
4
+ import { LayoutGenerator } from '../layout/layoutGenerator';
5
+ import { applySystemTemplates } from '../manifestSystem';
6
+ import { resolveZoraExtensionsForTemplateSelection } from '../zoraExtensions';
7
+ import { syncGeneratedRouteFiles } from './generatedRouteCleanup';
8
+ import { getProjectInfrastructureStatus, syncProjectInfrastructure } from './infraGenerator';
9
+ import { runProjectInfraScript } from './infraRuntime';
10
+ import { cleanupProjectGeneratedAppImage, stopProjectSupabaseContainers } from './projectDeletion';
11
+ import { getAppsRoot, getProjectPath } from './projectPaths';
12
+ import { ProjectStore } from './projectStore';
13
+ import { resolveModuleLayoutMutations } from './resolveMutations';
14
+ import { ProjectScaffolder } from './scaffolder';
15
+ import { runWorkspaceInstall } from './workspaceRuntime';
16
+ export class ProjectManager {
17
+ rootPath;
18
+ store;
19
+ scaffolder;
20
+ layout;
21
+ appsRoot;
22
+ constructor(rootPath) {
23
+ this.rootPath = rootPath;
24
+ this.appsRoot = getAppsRoot(rootPath);
25
+ this.store = new ProjectStore(rootPath);
26
+ this.scaffolder = new ProjectScaffolder(rootPath);
27
+ this.layout = new LayoutGenerator();
28
+ }
29
+ // =========================================================================
30
+ // PROJECT LIFECYCLE (PUBLIC API)
31
+ // =========================================================================
32
+ async listProjects() {
33
+ return this.store.listProjects();
34
+ }
35
+ async deleteProject(projectId) {
36
+ const projectPath = getProjectPath(this.rootPath, projectId);
37
+ const warnings = [];
38
+ let infraDown = false;
39
+ const supabaseCleanup = await stopProjectSupabaseContainers({ projectId });
40
+ warnings.push(...supabaseCleanup.warnings);
41
+ if (await exists(projectPath)) {
42
+ const manifest = await this.store.readManifest(projectId);
43
+ const infraStatus = await getProjectInfrastructureStatus({
44
+ projectId,
45
+ projectPath,
46
+ manifest,
47
+ });
48
+ if (!infraStatus.skipped && infraStatus.hasDeployment && infraStatus.target) {
49
+ // Regenerate once to ensure teardown scripts exist before invoking down lifecycle.
50
+ await syncProjectInfrastructure({
51
+ projectId,
52
+ projectPath,
53
+ manifest,
54
+ });
55
+ try {
56
+ await runProjectInfraScript({
57
+ rootPath: this.rootPath,
58
+ projectId,
59
+ target: infraStatus.target,
60
+ script: 'down',
61
+ });
62
+ infraDown = true;
63
+ }
64
+ catch (error) {
65
+ const message = error instanceof Error ? error.message : String(error);
66
+ warnings.push(`Infrastructure teardown failed: ${message}`);
67
+ }
68
+ const imageCleanup = await cleanupProjectGeneratedAppImage({
69
+ projectPath,
70
+ target: infraStatus.target,
71
+ });
72
+ warnings.push(...imageCleanup.warnings);
73
+ }
74
+ }
75
+ await this.store.deleteProject(projectId);
76
+ return {
77
+ success: true,
78
+ infraDown,
79
+ warnings,
80
+ };
81
+ }
82
+ async createProject(name, templateSelection, onProjectCreated, options = {}) {
83
+ const { includeStudio = true } = options;
84
+ const slug = slugify(name);
85
+ const projectPath = getProjectPath(this.rootPath, slug);
86
+ if (await exists(projectPath)) {
87
+ throw new Error(`Project ID '${slug}' is already taken.`);
88
+ }
89
+ const templateData = this.scaffolder.getTemplate(templateSelection);
90
+ const scaffoldManifest = applySystemTemplates(templateData);
91
+ const zoraExtensions = resolveZoraExtensionsForTemplateSelection(templateSelection);
92
+ // 1) scaffold base project
93
+ await this.scaffolder.scaffoldProject(projectPath, name, slug, {
94
+ includeStudio,
95
+ authProvider: resolveGeneratedAuthProvider(scaffoldManifest),
96
+ runtimePlan: resolveExpoRuntimePlan(scaffoldManifest),
97
+ storageProvider: resolveGeneratedStorageProvider(scaffoldManifest),
98
+ splashScreen: scaffoldManifest.splashScreen ?? null,
99
+ zoraExtensions,
100
+ });
101
+ // 2) layout generation from template + mutations
102
+ // IMPORTANT: ProjectManager no longer resolves module layout mutations itself.
103
+ // The orchestrator should pass mutations when calling rebuild/sync.
104
+ // For creation we default to "no mutations"; your template-driven module installs
105
+ // will run via orchestrator anyway.
106
+ const manifest = await this.scaffolder.finalizeManifest(projectPath, templateData, name, slug);
107
+ const runtimePlan = resolveExpoRuntimePlan(manifest);
108
+ // 3) generate router files based on manifest (no module layout mutations at creation)
109
+ await this.writeGeneratedFiles(projectPath, manifest, [], { includeStudio, runtimePlan });
110
+ // 4) generate infrastructure artifacts from infra manifest
111
+ await syncProjectInfrastructure({
112
+ projectId: slug,
113
+ projectPath,
114
+ manifest,
115
+ });
116
+ // 5) hook for orchestrator (e.g. registry generation)
117
+ if (onProjectCreated) {
118
+ await onProjectCreated(slug);
119
+ }
120
+ return { success: true, id: slug, path: projectPath };
121
+ }
122
+ async installWorkspacePackages() {
123
+ await runWorkspaceInstall(this.rootPath);
124
+ return { success: true };
125
+ }
126
+ // =========================================================================
127
+ // MANIFEST (PUBLIC API)
128
+ // =========================================================================
129
+ async getProjectManifest(projectId) {
130
+ return this.store.readManifest(projectId);
131
+ }
132
+ async getStudioManifest(projectId) {
133
+ return this.store.readStudioManifest(projectId);
134
+ }
135
+ async updateStudioManifestIfExists(projectId, updater) {
136
+ const hasDraft = await this.store.hasStudioManifest(projectId);
137
+ if (!hasDraft) {
138
+ return { updated: false };
139
+ }
140
+ const current = await this.store.readStudioManifest(projectId);
141
+ const next = updater(current);
142
+ await this.store.writeStudioManifest(projectId, next);
143
+ return { updated: true };
144
+ }
145
+ /**
146
+ * Save manifest and (optionally) regenerate router files immediately.
147
+ *
148
+ * We take `mutations` as input to keep module boundaries clean.
149
+ */
150
+ async saveProjectManifest(args) {
151
+ const { projectId, manifest, mutations, regenerateRouterFiles = true } = args;
152
+ const projectPath = getProjectPath(this.rootPath, projectId);
153
+ const normalizedManifest = applySystemTemplates(manifest);
154
+ const updated = await this.store.writeManifest(projectId, normalizedManifest);
155
+ await this.store.deleteStudioManifest(projectId);
156
+ const runtimePlan = resolveExpoRuntimePlan(updated);
157
+ if (regenerateRouterFiles) {
158
+ const resolvedIncludeStudio = await this.shouldIncludeStudio(projectPath);
159
+ await this.syncProjectScaffold(projectPath, projectId, updated, resolvedIncludeStudio, runtimePlan);
160
+ await this.writeGeneratedFiles(projectPath, updated, mutations, {
161
+ includeStudio: resolvedIncludeStudio,
162
+ runtimePlan,
163
+ });
164
+ }
165
+ await syncProjectInfrastructure({
166
+ projectId,
167
+ projectPath,
168
+ manifest: updated,
169
+ });
170
+ return { success: true };
171
+ }
172
+ async saveStudioManifest(args) {
173
+ const { projectId, manifest } = args;
174
+ const normalizedManifest = applySystemTemplates(manifest);
175
+ await this.store.writeStudioManifest(projectId, normalizedManifest);
176
+ return { success: true };
177
+ }
178
+ async syncStudioRuntime(args) {
179
+ const { projectId, manifest } = args;
180
+ const normalizedManifest = applySystemTemplates(manifest);
181
+ const projectPath = getProjectPath(this.rootPath, projectId);
182
+ const includeStudio = await this.shouldIncludeStudio(projectPath);
183
+ const runtimePlan = resolveExpoRuntimePlan(normalizedManifest);
184
+ await this.store.writeStudioManifest(projectId, normalizedManifest);
185
+ await this.syncProjectScaffold(projectPath, projectId, normalizedManifest, includeStudio, runtimePlan);
186
+ await this.writeGeneratedFiles(projectPath, normalizedManifest, resolveModuleLayoutMutations(normalizedManifest.infra.plugins), {
187
+ includeStudio,
188
+ runtimePlan,
189
+ });
190
+ await syncProjectInfrastructure({
191
+ projectId,
192
+ projectPath,
193
+ manifest: normalizedManifest,
194
+ });
195
+ return { success: true };
196
+ }
197
+ /**
198
+ * Rebuild only the root layout file from manifest + mutations.
199
+ */
200
+ async rebuildRootLayout(args) {
201
+ const { projectId, mutations } = args;
202
+ const manifest = await this.getProjectManifest(projectId);
203
+ const projectPath = getProjectPath(this.rootPath, projectId);
204
+ const runtimePlan = resolveExpoRuntimePlan(manifest);
205
+ const rootOnly = this.layout
206
+ .generateAll(projectPath, manifest, mutations, {
207
+ includeStudio: await this.shouldIncludeStudio(projectPath),
208
+ runtimePlan,
209
+ })
210
+ .filter((f) => f.path === 'src/app/_layout.tsx');
211
+ for (const f of rootOnly) {
212
+ await this.writeText(path.join(projectPath, f.path), f.content);
213
+ }
214
+ return { success: true };
215
+ }
216
+ async syncProject(args) {
217
+ const { projectId, mutations, includeStudio } = args;
218
+ const projectPath = getProjectPath(this.rootPath, projectId);
219
+ const hasStudioManifest = await this.store.hasStudioManifest(projectId);
220
+ const manifest = hasStudioManifest
221
+ ? await this.store.readStudioManifest(projectId)
222
+ : await this.getProjectManifest(projectId);
223
+ const normalizedManifest = applySystemTemplates(manifest);
224
+ const resolvedIncludeStudio = await this.shouldIncludeStudio(projectPath, includeStudio);
225
+ const runtimePlan = resolveExpoRuntimePlan(normalizedManifest);
226
+ if (hasStudioManifest || normalizedManifest !== manifest) {
227
+ await this.store.writeManifest(projectId, normalizedManifest);
228
+ await this.store.deleteStudioManifest(projectId);
229
+ }
230
+ await this.syncProjectScaffold(projectPath, projectId, normalizedManifest, resolvedIncludeStudio, runtimePlan);
231
+ await this.writeGeneratedFiles(projectPath, normalizedManifest, mutations, {
232
+ includeStudio: resolvedIncludeStudio,
233
+ runtimePlan,
234
+ });
235
+ await syncProjectInfrastructure({
236
+ projectId,
237
+ projectPath,
238
+ manifest: normalizedManifest,
239
+ });
240
+ return { success: true };
241
+ }
242
+ async regenerateInfrastructure(projectId) {
243
+ const projectPath = getProjectPath(this.rootPath, projectId);
244
+ const manifest = await this.getProjectManifest(projectId);
245
+ return syncProjectInfrastructure({
246
+ projectId,
247
+ projectPath,
248
+ manifest,
249
+ });
250
+ }
251
+ async getInfrastructureStatus(projectId) {
252
+ const projectPath = getProjectPath(this.rootPath, projectId);
253
+ const manifest = await this.getProjectManifest(projectId);
254
+ return getProjectInfrastructureStatus({
255
+ projectId,
256
+ projectPath,
257
+ manifest,
258
+ });
259
+ }
260
+ // =========================================================================
261
+ // LOCALIZATION (PUBLIC API)
262
+ // =========================================================================
263
+ async getLocalizationLocales(projectId) {
264
+ const localesPath = path.join(getProjectPath(this.rootPath, projectId), 'src/modules/localization/locales');
265
+ if (!(await exists(localesPath)))
266
+ return [];
267
+ const entries = await fs.readdir(localesPath);
268
+ return entries
269
+ .filter((e) => e.endsWith('.json'))
270
+ .map((e) => e.replace('.json', ''))
271
+ .sort();
272
+ }
273
+ async getLocalizationLocale(projectId, locale) {
274
+ this.validateLocale(locale);
275
+ const localePath = path.join(getProjectPath(this.rootPath, projectId), `src/modules/localization/locales/${locale}.json`);
276
+ if (!(await exists(localePath)))
277
+ return {};
278
+ const content = await fs.readFile(localePath, 'utf8');
279
+ const parsed = JSON.parse(content);
280
+ if (!isStringRecord(parsed)) {
281
+ throw new Error(`Invalid localization dictionary for locale: ${locale}`);
282
+ }
283
+ return parsed;
284
+ }
285
+ async saveLocalizationLocale(projectId, locale, dict) {
286
+ this.validateLocale(locale);
287
+ const localePath = path.join(getProjectPath(this.rootPath, projectId), `src/modules/localization/locales/${locale}.json`);
288
+ await this.writeText(localePath, JSON.stringify(dict, null, 2) + '\n');
289
+ return { success: true };
290
+ }
291
+ validateLocale(locale) {
292
+ if (!/^[a-z]{2,3}([-_][a-zA-Z0-9]+)*$/.test(locale)) {
293
+ throw new Error(`Invalid locale format: ${locale}`);
294
+ }
295
+ }
296
+ // =========================================================================
297
+ // INTERNAL
298
+ // =========================================================================
299
+ async writeGeneratedFiles(projectPath, manifest, mutations, options) {
300
+ const generated = this.layout.generateAll(projectPath, manifest, mutations, {
301
+ includeStudio: options.includeStudio,
302
+ runtimePlan: options.runtimePlan,
303
+ });
304
+ const generatedPaths = generated.map((file) => file.path);
305
+ for (const f of generated) {
306
+ await this.writeText(path.join(projectPath, f.path), f.content);
307
+ }
308
+ await syncGeneratedRouteFiles({
309
+ projectPath,
310
+ generatedPaths,
311
+ });
312
+ }
313
+ async writeText(absPath, content) {
314
+ await fs.mkdir(path.dirname(absPath), { recursive: true });
315
+ await fs.writeFile(absPath, content, 'utf8');
316
+ }
317
+ async shouldIncludeStudio(projectPath, requested) {
318
+ if (requested === false) {
319
+ return false;
320
+ }
321
+ return requested ?? (await exists(path.join(projectPath, 'src/studio')));
322
+ }
323
+ async syncProjectScaffold(projectPath, projectId, manifest, includeStudio, runtimePlan) {
324
+ await this.scaffolder.syncProjectScaffold(projectPath, manifest.metadata.name, projectId, {
325
+ includeStudio,
326
+ authProvider: resolveGeneratedAuthProvider(manifest),
327
+ runtimePlan,
328
+ storageProvider: resolveGeneratedStorageProvider(manifest),
329
+ splashScreen: manifest.splashScreen ?? null,
330
+ });
331
+ }
332
+ }
333
+ function isStringRecord(value) {
334
+ return (typeof value === 'object' &&
335
+ value !== null &&
336
+ !Array.isArray(value) &&
337
+ Object.values(value).every((entry) => typeof entry === 'string'));
338
+ }
339
+ function slugify(name) {
340
+ return (name
341
+ .trim()
342
+ .toLowerCase()
343
+ .replace(/[^a-z0-9-]/g, '-')
344
+ .replace(/-+/g, '-')
345
+ .replace(/^-|-$/g, '') || 'untitled-app');
346
+ }
347
+ async function exists(p) {
348
+ try {
349
+ await fs.access(p);
350
+ return true;
351
+ }
352
+ catch {
353
+ return false;
354
+ }
355
+ }
356
+ function resolveGeneratedAuthProvider(manifest) {
357
+ const { auth } = manifest.infra;
358
+ if (auth?.scope === 'global' && auth.provider === 'supabase') {
359
+ return 'supabase';
360
+ }
361
+ return null;
362
+ }
363
+ function resolveGeneratedStorageProvider(manifest) {
364
+ const { auth, database, storage } = manifest.infra;
365
+ if (storage?.provider !== 'auto') {
366
+ return null;
367
+ }
368
+ const usesSupabase = auth?.provider === 'supabase' || database?.provider === 'supabase';
369
+ return usesSupabase ? 'supabase' : null;
370
+ }
371
+ //# sourceMappingURL=projectManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectManager.js","sourceRoot":"","sources":["../../../src/host/orchestrator/projectManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAChG,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,yCAAyC,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,8BAA8B,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,+BAA+B,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAuB,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,OAAO,cAAc;IAOI;IANZ,KAAK,CAAe;IACpB,UAAU,CAAoB;IAC9B,MAAM,CAAkB;IAExB,QAAQ,CAAS;IAElC,YAA6B,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAC3C,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,UAAU,GAAG,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACtC,CAAC;IAED,4EAA4E;IAC5E,kCAAkC;IAClC,4EAA4E;IAE5E,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACnC,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,MAAM,eAAe,GAAG,MAAM,6BAA6B,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAE3C,IAAI,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YAC1D,MAAM,WAAW,GAAG,MAAM,8BAA8B,CAAC;gBACvD,SAAS;gBACT,WAAW;gBACX,QAAQ;aACT,CAAC,CAAC;YAEH,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;gBAC5E,mFAAmF;gBACnF,MAAM,yBAAyB,CAAC;oBAC9B,SAAS;oBACT,WAAW;oBACX,QAAQ;iBACT,CAAC,CAAC;gBAEH,IAAI,CAAC;oBACH,MAAM,qBAAqB,CAAC;wBAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,SAAS;wBACT,MAAM,EAAE,WAAW,CAAC,MAAM;wBAC1B,MAAM,EAAE,MAAM;qBACf,CAAC,CAAC;oBACH,SAAS,GAAG,IAAI,CAAC;gBACnB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACvE,QAAQ,CAAC,IAAI,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC;gBAC9D,CAAC;gBAED,MAAM,YAAY,GAAG,MAAM,+BAA+B,CAAC;oBACzD,WAAW;oBACX,MAAM,EAAE,WAAW,CAAC,MAAM;iBAC3B,CAAC,CAAC;gBACH,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAE1C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,SAAS;YACT,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,IAAY,EACZ,iBAA2C,EAC3C,gBAAuD,EACvD,UAAuC,EAAE;QAEzC,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAExD,IAAI,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,qBAAqB,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QACpE,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QAC5D,MAAM,cAAc,GAAG,yCAAyC,CAAC,iBAAiB,CAAC,CAAC;QAEpF,2BAA2B;QAC3B,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;YAC7D,aAAa;YACb,YAAY,EAAE,4BAA4B,CAAC,gBAAgB,CAAC;YAC5D,WAAW,EAAE,sBAAsB,CAAC,gBAAgB,CAAC;YACrD,eAAe,EAAE,+BAA+B,CAAC,gBAAgB,CAAC;YAClE,YAAY,EAAE,gBAAgB,CAAC,YAAY,IAAI,IAAI;YACnD,cAAc;SACf,CAAC,CAAC;QAEH,iDAAiD;QACjD,+EAA+E;QAC/E,oEAAoE;QACpE,kFAAkF;QAClF,oCAAoC;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/F,MAAM,WAAW,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAErD,sFAAsF;QACtF,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC;QAE1F,2DAA2D;QAC3D,MAAM,yBAAyB,CAAC;YAC9B,SAAS,EAAE,IAAI;YACf,WAAW;YACX,QAAQ;SACT,CAAC,CAAC;QAEH,sDAAsD;QACtD,IAAI,gBAAgB,EAAE,CAAC;YACrB,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,wBAAwB;QAC5B,MAAM,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,4EAA4E;IAC5E,yBAAyB;IACzB,4EAA4E;IAE5E,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,SAAiB;QACvC,OAAO,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,SAAiB,EACjB,OAA+C;QAE/C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC5B,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACtD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB,CAAC,IAKzB;QACC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QAE9E,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC9E,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAEpD,IAAI,qBAAqB,EAAE,CAAC;YAC1B,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;YAC1E,MAAM,IAAI,CAAC,mBAAmB,CAC5B,WAAW,EACX,SAAS,EACT,OAAO,EACP,qBAAqB,EACrB,WAAW,CACZ,CAAC;YACF,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE;gBAC9D,aAAa,EAAE,qBAAqB;gBACpC,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;QAED,MAAM,yBAAyB,CAAC;YAC9B,SAAS;YACT,WAAW;YACX,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAkD;QACzE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QACrC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QACpE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,IAAkD;QACxE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;QACrC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;QAE/D,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QACpE,MAAM,IAAI,CAAC,mBAAmB,CAC5B,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,WAAW,CACZ,CAAC;QACF,MAAM,IAAI,CAAC,mBAAmB,CAC5B,WAAW,EACX,kBAAkB,EAClB,4BAA4B,CAAC,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,EAC9D;YACE,aAAa;YACb,WAAW;SACZ,CACF,CAAC;QACF,MAAM,yBAAyB,CAAC;YAC9B,SAAS;YACT,WAAW;YACX,QAAQ,EAAE,kBAAkB;SAC7B,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,IAAwD;QAC9E,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAEtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM;aACzB,WAAW,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE;YAC7C,aAAa,EAAE,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC;YAC1D,WAAW;SACZ,CAAC;aACD,MAAM,CAAC,CAAC,CAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,qBAAqB,CAAC,CAAC;QAErE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAIjB;QACC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;QAErD,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,iBAAiB;YAChC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,CAAC;YAChD,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QACzF,MAAM,WAAW,GAAG,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;QAE/D,IAAI,iBAAiB,IAAI,kBAAkB,KAAK,QAAQ,EAAE,CAAC;YACzD,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;YAC9D,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,IAAI,CAAC,mBAAmB,CAC5B,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,CACZ,CAAC;QAEF,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAE;YACzE,aAAa,EAAE,qBAAqB;YACpC,WAAW;SACZ,CAAC,CAAC;QACH,MAAM,yBAAyB,CAAC;YAC9B,SAAS;YACT,WAAW;YACX,QAAQ,EAAE,kBAAkB;SAC7B,CAAC,CAAC;QAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,wBAAwB,CAAC,SAAiB;QAC9C,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAE1D,OAAO,yBAAyB,CAAC;YAC/B,SAAS;YACT,WAAW;YACX,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,SAAiB;QAC7C,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAE1D,OAAO,8BAA8B,CAAC;YACpC,SAAS;YACT,WAAW;YACX,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,6BAA6B;IAC7B,4EAA4E;IAE5E,KAAK,CAAC,sBAAsB,CAAC,SAAiB;QAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EACxC,kCAAkC,CACnC,CAAC;QAEF,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAE5C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9C,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;aAClC,IAAI,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,SAAiB,EAAE,MAAc;QAC3D,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EACxC,oCAAoC,MAAM,OAAO,CAClD,CAAC;QAEF,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAE3C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE5C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,+CAA+C,MAAM,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,SAAiB,EAAE,MAAc,EAAE,IAA4B;QAC1F,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,EACxC,oCAAoC,MAAM,OAAO,CAClD,CAAC;QAEF,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACvE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAEO,cAAc,CAAC,MAAc;QACnC,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,YAAY;IACZ,4EAA4E;IAEpE,KAAK,CAAC,mBAAmB,CAC/B,WAAmB,EACnB,QAAqB,EACrB,SAA2B,EAC3B,OAAiE;QAEjE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE;YAC1E,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE1D,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,uBAAuB,CAAC;YAC5B,WAAW;YACX,cAAc;SACf,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,OAAe,EAAE,OAAe;QACtD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,WAAmB,EAAE,SAAmB;QACxE,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,SAAS,IAAI,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAC/B,WAAmB,EACnB,SAAiB,EACjB,QAAqB,EACrB,aAAsB,EACtB,WAA4B;QAE5B,MAAM,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE;YACxF,aAAa;YACb,YAAY,EAAE,4BAA4B,CAAC,QAAQ,CAAC;YACpD,WAAW;YACX,eAAe,EAAE,+BAA+B,CAAC,QAAQ,CAAC;YAC1D,YAAY,EAAE,QAAQ,CAAC,YAAY,IAAI,IAAI;SAC5C,CAAC,CAAC;IACL,CAAC;CACF;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CACjE,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,CACL,IAAI;SACD,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,cAAc,CAC3C,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CAAC,QAAqB;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC;IAChC,IAAI,IAAI,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC7D,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,+BAA+B,CAAC,QAAqB;IAC5D,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC;IACnD,IAAI,OAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,EAAE,QAAQ,KAAK,UAAU,IAAI,QAAQ,EAAE,QAAQ,KAAK,UAAU,CAAC;IACxF,OAAO,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function getAppsRoot(rootPath: string): string;
2
+ export declare function assertProjectId(projectId: string): string;
3
+ export declare function getProjectPath(rootPath: string, projectId: string): string;
4
+ //# sourceMappingURL=projectPaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectPaths.d.ts","sourceRoot":"","sources":["../../../src/host/orchestrator/projectPaths.ts"],"names":[],"mappings":"AAKA,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,UAE3C;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,UAUhD;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAQjE"}
@@ -0,0 +1,25 @@
1
+ import path from 'node:path';
2
+ const PROJECT_ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u;
3
+ const RESERVED_PROJECT_IDS = new Set(['studio']);
4
+ export function getAppsRoot(rootPath) {
5
+ return path.join(rootPath, 'apps');
6
+ }
7
+ export function assertProjectId(projectId) {
8
+ if (projectId.length === 0 ||
9
+ path.basename(projectId) !== projectId ||
10
+ !PROJECT_ID_PATTERN.test(projectId) ||
11
+ RESERVED_PROJECT_IDS.has(projectId)) {
12
+ throw new Error(`Invalid project id: ${projectId}`);
13
+ }
14
+ return projectId;
15
+ }
16
+ export function getProjectPath(rootPath, projectId) {
17
+ const appsRoot = path.resolve(getAppsRoot(rootPath));
18
+ const safeId = assertProjectId(projectId);
19
+ const projectPath = path.resolve(appsRoot, safeId);
20
+ if (path.dirname(projectPath) !== appsRoot) {
21
+ throw new Error('Security check failed: project path escaped the workspace apps directory.');
22
+ }
23
+ return projectPath;
24
+ }
25
+ //# sourceMappingURL=projectPaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectPaths.js","sourceRoot":"","sources":["../../../src/host/orchestrator/projectPaths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,kBAAkB,GAAG,oCAAoC,CAAC;AAChE,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEjD,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IACE,SAAS,CAAC,MAAM,KAAK,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,SAAS;QACtC,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC;QACnC,oBAAoB,CAAC,GAAG,CAAC,SAAS,CAAC,EACnC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,SAAiB;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { AppManifest } from '@ankhorage/contracts';
2
+ export interface ProjectSummary {
3
+ id: string;
4
+ name: string;
5
+ path: string;
6
+ version: string;
7
+ isAnkhApp: boolean;
8
+ }
9
+ export declare class ProjectStore {
10
+ private readonly rootPath;
11
+ constructor(rootPath: string);
12
+ private getProjectPath;
13
+ private getManifestPath;
14
+ private getStudioManifestPath;
15
+ listProjects(): Promise<ProjectSummary[]>;
16
+ deleteProject(projectId: string): Promise<boolean>;
17
+ readManifest(projectId: string): Promise<AppManifest>;
18
+ readStudioManifest(projectId: string): Promise<AppManifest>;
19
+ hasStudioManifest(projectId: string): Promise<boolean>;
20
+ writeManifest(projectId: string, manifest: AppManifest): Promise<AppManifest>;
21
+ writeStudioManifest(projectId: string, manifest: AppManifest): Promise<AppManifest>;
22
+ deleteStudioManifest(projectId: string): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=projectStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectStore.d.ts","sourceRoot":"","sources":["../../../src/host/orchestrator/projectStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMxD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAE7C,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,qBAAqB;IAIvB,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAuDzC,aAAa,CAAC,SAAS,EAAE,MAAM;IAM/B,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAoBrD,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS3D,iBAAiB,CAAC,SAAS,EAAE,MAAM;IAInC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW;IAqBtD,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW;IAsB5D,oBAAoB,CAAC,SAAS,EAAE,MAAM;CAM7C"}
@@ -0,0 +1,155 @@
1
+ import { promises as fs } from 'fs';
2
+ import path from 'path';
3
+ import { getProjectPath } from './projectPaths';
4
+ export class ProjectStore {
5
+ rootPath;
6
+ constructor(rootPath) {
7
+ this.rootPath = rootPath;
8
+ }
9
+ getProjectPath(projectId) {
10
+ return getProjectPath(this.rootPath, projectId);
11
+ }
12
+ getManifestPath(projectId) {
13
+ return path.join(this.getProjectPath(projectId), 'ankh.config.json');
14
+ }
15
+ getStudioManifestPath(projectId) {
16
+ return path.join(this.getProjectPath(projectId), '.ankh', 'studio.manifest.json');
17
+ }
18
+ async listProjects() {
19
+ const appsRoot = path.join(this.rootPath, 'apps');
20
+ try {
21
+ const entries = await fs.readdir(appsRoot, { withFileTypes: true });
22
+ const dirs = entries
23
+ .filter((entry) => entry.isDirectory() && entry.name !== 'studio')
24
+ .map((entry) => entry.name);
25
+ const results = await Promise.all(dirs.map(async (id) => {
26
+ try {
27
+ const projectPath = getProjectPath(this.rootPath, id);
28
+ const pkgJsonPath = path.join(projectPath, 'package.json');
29
+ const ankhConfigPath = path.join(projectPath, 'ankh.config.json');
30
+ const hasPkg = await exists(pkgJsonPath);
31
+ if (!hasPkg)
32
+ return null;
33
+ let name = id;
34
+ let version = '0.0.0';
35
+ let isAnkhApp = false;
36
+ if (await exists(ankhConfigPath)) {
37
+ try {
38
+ const { metadata: { name: metaName, version: metaVersion }, } = JSON.parse(await fs.readFile(ankhConfigPath, 'utf8'));
39
+ name = metaName;
40
+ version = metaVersion;
41
+ isAnkhApp = true;
42
+ }
43
+ catch {
44
+ // ignore invalid json in listing (no side effects!)
45
+ }
46
+ }
47
+ return { id, name, path: projectPath, version, isAnkhApp };
48
+ }
49
+ catch {
50
+ // If getProjectPath throws or any other unexpected error occurs for a single project,
51
+ // treat it as an unlistable project and skip it. This preserves robustness:
52
+ // problematic projects are ignored while valid ones are still listed.
53
+ //
54
+ // The outer try/catch still provides a catch-all that returns [] if a
55
+ // top-level failure occurs (e.g. reading the apps directory itself fails).
56
+ return null;
57
+ }
58
+ }));
59
+ // Filter out nulls (skipped projects)
60
+ return results.filter((p) => p !== null);
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ }
66
+ async deleteProject(projectId) {
67
+ const projectPath = this.getProjectPath(projectId);
68
+ await fs.rm(projectPath, { recursive: true, force: true });
69
+ return true;
70
+ }
71
+ async readManifest(projectId) {
72
+ const projectPath = this.getProjectPath(projectId);
73
+ const manifestPath = this.getManifestPath(projectId);
74
+ if (!(await exists(projectPath))) {
75
+ throw new Error(`Project '${projectId}' not found.`);
76
+ }
77
+ if (await exists(manifestPath)) {
78
+ return JSON.parse(await fs.readFile(manifestPath, 'utf8'));
79
+ }
80
+ return {
81
+ /** @todo e.g. 'plugins' missing, check this and cleanup */
82
+ metadata: { name: projectId, slug: projectId },
83
+ screens: {},
84
+ navigator: { type: 'stack', routes: [{ name: 'index', screenId: 'index' }] },
85
+ };
86
+ }
87
+ async readStudioManifest(projectId) {
88
+ const studioManifestPath = this.getStudioManifestPath(projectId);
89
+ if (await exists(studioManifestPath)) {
90
+ return JSON.parse(await fs.readFile(studioManifestPath, 'utf8'));
91
+ }
92
+ return this.readManifest(projectId);
93
+ }
94
+ async hasStudioManifest(projectId) {
95
+ return exists(this.getStudioManifestPath(projectId));
96
+ }
97
+ async writeManifest(projectId, manifest) {
98
+ const projectPath = this.getProjectPath(projectId);
99
+ const manifestPath = this.getManifestPath(projectId);
100
+ if (!(await exists(projectPath))) {
101
+ throw new Error(`Project '${projectId}' not found.`);
102
+ }
103
+ const updated = {
104
+ ...manifest,
105
+ metadata: {
106
+ ...manifest.metadata,
107
+ slug: projectId,
108
+ updated: new Date().toISOString(),
109
+ },
110
+ };
111
+ await writeJsonAtomic(manifestPath, updated);
112
+ return updated;
113
+ }
114
+ async writeStudioManifest(projectId, manifest) {
115
+ const projectPath = this.getProjectPath(projectId);
116
+ const studioManifestPath = this.getStudioManifestPath(projectId);
117
+ if (!(await exists(projectPath))) {
118
+ throw new Error(`Project '${projectId}' not found.`);
119
+ }
120
+ const updated = {
121
+ ...manifest,
122
+ metadata: {
123
+ ...manifest.metadata,
124
+ slug: projectId,
125
+ updated: new Date().toISOString(),
126
+ },
127
+ };
128
+ await fs.mkdir(path.dirname(studioManifestPath), { recursive: true });
129
+ await writeJsonAtomic(studioManifestPath, updated);
130
+ return updated;
131
+ }
132
+ async deleteStudioManifest(projectId) {
133
+ const studioManifestPath = this.getStudioManifestPath(projectId);
134
+ if (await exists(studioManifestPath)) {
135
+ await fs.rm(studioManifestPath, { force: true });
136
+ }
137
+ }
138
+ }
139
+ async function exists(p) {
140
+ try {
141
+ await fs.access(p);
142
+ return true;
143
+ }
144
+ catch {
145
+ return false;
146
+ }
147
+ }
148
+ async function writeJsonAtomic(filePath, value) {
149
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
150
+ const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
151
+ await fs.writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}
152
+ `, 'utf8');
153
+ await fs.rename(temporaryPath, filePath);
154
+ }
155
+ //# sourceMappingURL=projectStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectStore.js","sourceRoot":"","sources":["../../../src/host/orchestrator/projectStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { LayoutMutation } from '../modules/layout';
2
+ export declare function resolveModuleLayoutMutations(moduleIds: string[]): LayoutMutation[];
3
+ //# sourceMappingURL=resolveMutations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveMutations.d.ts","sourceRoot":"","sources":["../../../src/host/orchestrator/resolveMutations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CASlF"}
@@ -0,0 +1,12 @@
1
+ import { MODULE_CATALOG } from '../modules/catalog';
2
+ export function resolveModuleLayoutMutations(moduleIds) {
3
+ const mutations = [];
4
+ for (const id of moduleIds) {
5
+ const module = MODULE_CATALOG[id];
6
+ if (module?.layout) {
7
+ mutations.push(module.layout);
8
+ }
9
+ }
10
+ return mutations;
11
+ }
12
+ //# sourceMappingURL=resolveMutations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveMutations.js","sourceRoot":"","sources":["../../../src/host/orchestrator/resolveMutations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,MAAM,UAAU,4BAA4B,CAAC,SAAmB;IAC9D,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;YACnB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}