spine-framework 0.1.61 → 0.2.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 (246) hide show
  1. package/.framework/cli/commands/create-app.ts +1 -1
  2. package/.framework/cli/commands/dev.ts +215 -33
  3. package/.framework/cli/index.ts +37 -63
  4. package/.framework/functions/_shared/app-manifest.ts +8 -15
  5. package/.framework/functions/_shared/db.ts +11 -15
  6. package/.framework/functions/_shared/index.ts +0 -9
  7. package/.framework/functions/_shared/principal.ts +4 -62
  8. package/.framework/functions/_shared/resolve-ids.ts +6 -6
  9. package/.framework/functions/_shared/webhook-registry.ts +1 -1
  10. package/.framework/functions/admin-funnel.ts +104 -0
  11. package/.framework/functions/admin-install-funnel.ts +225 -0
  12. package/.framework/functions/admin-signals.ts +241 -0
  13. package/.framework/migrations/001_schema.sql +406 -0
  14. package/.framework/migrations/002_rls_and_functions.sql +710 -0
  15. package/.framework/migrations/003_system_data.sql +520 -0
  16. package/.framework/migrations/004_enhancements.sql +43 -0
  17. package/.framework/public/_redirects +3 -0
  18. package/.framework/public/spine-logo.jpg +0 -0
  19. package/.framework/public/spine-logo.svg +3 -0
  20. package/{scripts → .framework/scripts}/assemble-frontend.sh +1 -1
  21. package/{scripts → .framework/scripts}/assemble-functions.sh +1 -1
  22. package/{scripts → .framework/scripts}/assemble.sh +2 -8
  23. package/{scripts → .framework/scripts}/check-core-integrity.sh +0 -0
  24. package/.framework/seeds/link_types/account_cli_instances.json +9 -0
  25. package/.framework/seeds/types/funnel_signal_use.json +98 -0
  26. package/.framework/seeds/types/spine_instance.json +109 -0
  27. package/.framework/src/App.tsx +6 -4
  28. package/.framework/src/components/ui/accordion.tsx +1 -1
  29. package/.framework/src/components/ui/alert-dialog.tsx +1 -1
  30. package/.framework/src/components/ui/aspect-ratio.tsx +1 -1
  31. package/.framework/src/components/ui/avatar.tsx +1 -1
  32. package/.framework/src/components/ui/badge.tsx +2 -2
  33. package/.framework/src/components/ui/breadcrumb.tsx +2 -2
  34. package/.framework/src/components/ui/button-group.tsx +2 -2
  35. package/.framework/src/components/ui/button.tsx +2 -2
  36. package/.framework/src/components/ui/chart.tsx +6 -1
  37. package/.framework/src/components/ui/checkbox.tsx +1 -1
  38. package/.framework/src/components/ui/collapsible.tsx +1 -1
  39. package/.framework/src/components/ui/context-menu.tsx +1 -1
  40. package/.framework/src/components/ui/dialog.tsx +1 -1
  41. package/.framework/src/components/ui/direction.tsx +17 -1
  42. package/.framework/src/components/ui/dropdown-menu.tsx +1 -1
  43. package/.framework/src/components/ui/hover-card.tsx +1 -1
  44. package/.framework/src/components/ui/item.tsx +2 -2
  45. package/.framework/src/components/ui/label.tsx +1 -1
  46. package/.framework/src/components/ui/menubar.tsx +1 -1
  47. package/.framework/src/components/ui/navigation-menu.tsx +1 -1
  48. package/.framework/src/components/ui/popover.tsx +1 -1
  49. package/.framework/src/components/ui/progress.tsx +1 -1
  50. package/.framework/src/components/ui/radio-group.tsx +1 -1
  51. package/.framework/src/components/ui/scroll-area.tsx +1 -1
  52. package/.framework/src/components/ui/select.tsx +1 -1
  53. package/.framework/src/components/ui/separator.tsx +1 -1
  54. package/.framework/src/components/ui/sheet.tsx +1 -1
  55. package/.framework/src/components/ui/sidebar.tsx +6 -6
  56. package/.framework/src/components/ui/slider.tsx +1 -1
  57. package/.framework/src/components/ui/switch.tsx +1 -1
  58. package/.framework/src/components/ui/tabs.tsx +1 -1
  59. package/.framework/src/components/ui/toggle-group.tsx +1 -1
  60. package/.framework/src/components/ui/toggle.tsx +1 -1
  61. package/.framework/src/components/ui/tooltip.tsx +1 -1
  62. package/.framework/src/pages/auth/LoginPage.tsx +10 -9
  63. package/LICENSE.md +193 -0
  64. package/README.md +254 -0
  65. package/custom/.devin/skills/install-app/SKILL.md +39 -0
  66. package/custom/.devin/workflows/app-install.yaml +83 -0
  67. package/custom/README.md +79 -0
  68. package/docs/APPS.md +232 -0
  69. package/docs/ARCHITECTURE.md +246 -0
  70. package/docs/INSTALL.md +155 -0
  71. package/docs/README.md +170 -0
  72. package/docs/design-schema-spec.md +1837 -0
  73. package/docs/dev-guides/01-create-an-app.md +183 -0
  74. package/docs/dev-guides/02-create-a-function.md +178 -0
  75. package/docs/dev-guides/03-create-a-component.md +178 -0
  76. package/docs/dev-guides/04-webhook-handlers.md +129 -0
  77. package/docs/dev-guides/05-testing.md +168 -0
  78. package/docs/dev-guides/README.md +40 -0
  79. package/docs/npm-packages-plan.md +288 -0
  80. package/docs/spine-core--api-reference.md +822 -0
  81. package/package.json +78 -144
  82. package/.framework/cli/bin.cjs +0 -14
  83. package/.framework/cli/commands/init.ts +0 -186
  84. package/.framework/cli/commands/install-app.ts +0 -565
  85. package/.framework/cli/commands/migrate.ts +0 -139
  86. package/.framework/cli/commands/status.ts +0 -197
  87. package/.framework/cli/commands/uninstall-app.ts +0 -166
  88. package/.framework/cli/welcome.cjs +0 -45
  89. package/.framework/docs/STABILITY.md +0 -52
  90. package/.framework/docs/examples/custom-app/README.md +0 -77
  91. package/.framework/docs/examples/custom-function/README.md +0 -27
  92. package/.framework/docs/examples/custom-function/handler.ts +0 -48
  93. package/.framework/docs/examples/custom-webhook/README.md +0 -68
  94. package/.framework/migrations/000_foundation.sql +0 -1266
  95. package/.framework/migrations/001_seed.sql +0 -163
  96. package/.framework/migrations/002_seed_constraints.sql +0 -19
  97. package/.framework/migrations/003_auth_user_trigger.sql +0 -67
  98. package/.framework/src/pages/auth/RegisterPage.tsx +0 -163
  99. package/STRUCTURE.md +0 -150
  100. package/bin/spine-framework.cjs +0 -62
  101. package/bin/welcome.cjs +0 -45
  102. package/bin/ws-shim.cjs +0 -8
  103. package/bin/ws-shim.ts +0 -10
  104. package/config/components.json +0 -25
  105. package/config/deno.lock +0 -108
  106. package/config/package-lock.json +0 -17183
  107. package/config/postcss.config.cjs +0 -10
  108. package/config/tailwind.config.cjs +0 -78
  109. package/config/tsconfig.build.json +0 -32
  110. package/config/tsconfig.cli.json +0 -18
  111. package/config/tsconfig.json +0 -41
  112. package/config/tsconfig.node.json +0 -17
  113. package/config/tsconfig.node.tsbuildinfo +0 -1
  114. package/config/tsconfig.tsbuildinfo +0 -1
  115. package/config/typedoc.json +0 -16
  116. package/config/vite.config.d.ts +0 -2
  117. package/config/vite.config.ts +0 -72
  118. package/dist/cli/commands/agents.d.ts +0 -39
  119. package/dist/cli/commands/agents.d.ts.map +0 -1
  120. package/dist/cli/commands/auth.d.ts +0 -36
  121. package/dist/cli/commands/auth.d.ts.map +0 -1
  122. package/dist/cli/commands/create-app.d.ts +0 -23
  123. package/dist/cli/commands/create-app.d.ts.map +0 -1
  124. package/dist/cli/commands/dev.d.ts +0 -24
  125. package/dist/cli/commands/dev.d.ts.map +0 -1
  126. package/dist/cli/commands/doctor.d.ts +0 -42
  127. package/dist/cli/commands/doctor.d.ts.map +0 -1
  128. package/dist/cli/commands/generate.d.ts +0 -36
  129. package/dist/cli/commands/generate.d.ts.map +0 -1
  130. package/dist/cli/commands/init.d.ts +0 -20
  131. package/dist/cli/commands/init.d.ts.map +0 -1
  132. package/dist/cli/commands/install-app.d.ts +0 -30
  133. package/dist/cli/commands/install-app.d.ts.map +0 -1
  134. package/dist/cli/commands/items.d.ts +0 -45
  135. package/dist/cli/commands/items.d.ts.map +0 -1
  136. package/dist/cli/commands/migrate.d.ts +0 -21
  137. package/dist/cli/commands/migrate.d.ts.map +0 -1
  138. package/dist/cli/commands/migrations.d.ts +0 -41
  139. package/dist/cli/commands/migrations.d.ts.map +0 -1
  140. package/dist/cli/commands/pipelines.d.ts +0 -40
  141. package/dist/cli/commands/pipelines.d.ts.map +0 -1
  142. package/dist/cli/commands/status.d.ts +0 -23
  143. package/dist/cli/commands/status.d.ts.map +0 -1
  144. package/dist/cli/commands/system.d.ts +0 -29
  145. package/dist/cli/commands/system.d.ts.map +0 -1
  146. package/dist/cli/commands/test.d.ts +0 -46
  147. package/dist/cli/commands/test.d.ts.map +0 -1
  148. package/dist/cli/commands/uninstall-app.d.ts +0 -23
  149. package/dist/cli/commands/uninstall-app.d.ts.map +0 -1
  150. package/dist/cli/context.d.ts +0 -88
  151. package/dist/cli/context.d.ts.map +0 -1
  152. package/dist/cli/env-loader.d.ts +0 -14
  153. package/dist/cli/env-loader.d.ts.map +0 -1
  154. package/dist/cli/index.d.ts +0 -41
  155. package/dist/cli/index.d.ts.map +0 -1
  156. package/dist/functions/_shared/agent-runner.d.ts +0 -156
  157. package/dist/functions/_shared/agent-runner.d.ts.map +0 -1
  158. package/dist/functions/_shared/app-manifest.d.ts +0 -68
  159. package/dist/functions/_shared/app-manifest.d.ts.map +0 -1
  160. package/dist/functions/_shared/audit.d.ts +0 -91
  161. package/dist/functions/_shared/audit.d.ts.map +0 -1
  162. package/dist/functions/_shared/db.d.ts +0 -125
  163. package/dist/functions/_shared/db.d.ts.map +0 -1
  164. package/dist/functions/_shared/index.d.ts +0 -299
  165. package/dist/functions/_shared/index.d.ts.map +0 -1
  166. package/dist/functions/_shared/middleware.d.ts +0 -315
  167. package/dist/functions/_shared/middleware.d.ts.map +0 -1
  168. package/dist/functions/_shared/permissions.d.ts +0 -626
  169. package/dist/functions/_shared/permissions.d.ts.map +0 -1
  170. package/dist/functions/_shared/pipeline-runner.d.ts +0 -124
  171. package/dist/functions/_shared/pipeline-runner.d.ts.map +0 -1
  172. package/dist/functions/_shared/principal.d.ts +0 -284
  173. package/dist/functions/_shared/principal.d.ts.map +0 -1
  174. package/dist/functions/_shared/resolve-ids.d.ts +0 -10
  175. package/dist/functions/_shared/resolve-ids.d.ts.map +0 -1
  176. package/dist/functions/_shared/schema-utils.d.ts +0 -181
  177. package/dist/functions/_shared/schema-utils.d.ts.map +0 -1
  178. package/dist/functions/_shared/testing.d.ts +0 -172
  179. package/dist/functions/_shared/testing.d.ts.map +0 -1
  180. package/dist/functions/_shared/trigger-engine.d.ts +0 -140
  181. package/dist/functions/_shared/trigger-engine.d.ts.map +0 -1
  182. package/dist/functions/_shared/webhook-registration.d.ts +0 -81
  183. package/dist/functions/_shared/webhook-registration.d.ts.map +0 -1
  184. package/dist/functions/_shared/webhook-registry.d.ts +0 -57
  185. package/dist/functions/_shared/webhook-registry.d.ts.map +0 -1
  186. package/dist/functions/account-nodes.d.ts +0 -48
  187. package/dist/functions/account-nodes.d.ts.map +0 -1
  188. package/dist/functions/admin-data.d.ts +0 -178
  189. package/dist/functions/admin-data.d.ts.map +0 -1
  190. package/dist/functions/ai-agents.d.ts +0 -125
  191. package/dist/functions/ai-agents.d.ts.map +0 -1
  192. package/dist/functions/api-keys.d.ts +0 -140
  193. package/dist/functions/api-keys.d.ts.map +0 -1
  194. package/dist/functions/apps.d.ts +0 -163
  195. package/dist/functions/apps.d.ts.map +0 -1
  196. package/dist/functions/auth.d.ts +0 -74
  197. package/dist/functions/auth.d.ts.map +0 -1
  198. package/dist/functions/debug-auth.d.ts +0 -33
  199. package/dist/functions/debug-auth.d.ts.map +0 -1
  200. package/dist/functions/embeddings.d.ts +0 -205
  201. package/dist/functions/embeddings.d.ts.map +0 -1
  202. package/dist/functions/integration-routes.d.ts +0 -45
  203. package/dist/functions/integration-routes.d.ts.map +0 -1
  204. package/dist/functions/integrations.d.ts +0 -124
  205. package/dist/functions/integrations.d.ts.map +0 -1
  206. package/dist/functions/item-progress.d.ts +0 -41
  207. package/dist/functions/item-progress.d.ts.map +0 -1
  208. package/dist/functions/logs.d.ts +0 -162
  209. package/dist/functions/logs.d.ts.map +0 -1
  210. package/dist/functions/observability.d.ts +0 -123
  211. package/dist/functions/observability.d.ts.map +0 -1
  212. package/dist/functions/pipeline-executions.d.ts +0 -190
  213. package/dist/functions/pipeline-executions.d.ts.map +0 -1
  214. package/dist/functions/pipelines.d.ts +0 -171
  215. package/dist/functions/pipelines.d.ts.map +0 -1
  216. package/dist/functions/prompt-configs.d.ts +0 -125
  217. package/dist/functions/prompt-configs.d.ts.map +0 -1
  218. package/dist/functions/roles.d.ts +0 -118
  219. package/dist/functions/roles.d.ts.map +0 -1
  220. package/dist/functions/system-cron.d.ts +0 -65
  221. package/dist/functions/system-cron.d.ts.map +0 -1
  222. package/dist/functions/system.d.ts +0 -29
  223. package/dist/functions/system.d.ts.map +0 -1
  224. package/dist/functions/tests.d.ts +0 -28
  225. package/dist/functions/tests.d.ts.map +0 -1
  226. package/dist/functions/timers.d.ts +0 -139
  227. package/dist/functions/timers.d.ts.map +0 -1
  228. package/dist/functions/triggers.d.ts +0 -203
  229. package/dist/functions/triggers.d.ts.map +0 -1
  230. package/dist/functions/types.d.ts +0 -151
  231. package/dist/functions/types.d.ts.map +0 -1
  232. package/dist/src/types/types.d.ts +0 -364
  233. package/dist/src/types/types.d.ts.map +0 -1
  234. package/index.html +0 -13
  235. package/netlify.toml +0 -36
  236. package/package-project.json +0 -64
  237. package/scripts/ingest-chunks.cjs +0 -202
  238. package/scripts/kb-chunk-parser.cjs +0 -312
  239. package/scripts/kb-chunk-parser.ts +0 -330
  240. package/scripts/load-test-app-install.ts +0 -484
  241. package/scripts/netlify-dev-wrapper.sh +0 -22
  242. package/vitest.config.ts +0 -45
  243. /package/{scripts → .framework/scripts}/app-install-cli.ts +0 -0
  244. /package/{scripts → .framework/scripts}/boundary-check.sh +0 -0
  245. /package/{scripts → .framework/scripts}/build-manifest.sh +0 -0
  246. /package/{scripts → .framework/scripts}/verify-integrity.sh +0 -0
@@ -1,484 +0,0 @@
1
- #!/usr/bin/env tsx
2
-
3
- /**
4
- * Load Testing for App Installation System
5
- * Tests performance with large installations and concurrent operations
6
- */
7
-
8
- import { readFileSync, existsSync } from 'fs'
9
- import { resolve, dirname } from 'path'
10
- import { program } from 'commander'
11
- import yaml from 'js-yaml'
12
- import { performance } from 'perf_hooks'
13
-
14
- // Fix __dirname for ES modules
15
- import { fileURLToPath } from 'url'
16
- const __filename = fileURLToPath(import.meta.url)
17
- const __dirname = dirname(__filename)
18
-
19
- interface LoadTestConfig {
20
- concurrentInstalls: number
21
- totalApps: number
22
- appComplexity: 'simple' | 'medium' | 'complex'
23
- testDuration: number // seconds
24
- reportInterval: number // seconds
25
- }
26
-
27
- interface TestResult {
28
- appId: string
29
- startTime: number
30
- endTime: number
31
- duration: number
32
- success: boolean
33
- error?: string
34
- steps: {
35
- validation: number
36
- packInstallation: number
37
- appCreation: number
38
- migrations: number
39
- verification: number
40
- }
41
- }
42
-
43
- interface LoadTestReport {
44
- config: LoadTestConfig
45
- results: TestResult[]
46
- summary: {
47
- totalTests: number
48
- successfulTests: number
49
- failedTests: number
50
- averageDuration: number
51
- minDuration: number
52
- maxDuration: number
53
- throughput: number // tests per second
54
- errors: Array<{ error: string; count: number }>
55
- }
56
- performance: {
57
- validation: { avg: number; min: number; max: number }
58
- packInstallation: { avg: number; min: number; max: number }
59
- appCreation: { avg: number; min: number; max: number }
60
- migrations: { avg: number; min: number; max: number }
61
- verification: { avg: number; min: number; max: number }
62
- }
63
- }
64
-
65
- class LoadTestRunner {
66
- private config: LoadTestConfig
67
- private results: TestResult[] = []
68
- private running = false
69
- private startTime = 0
70
-
71
- constructor(config: LoadTestConfig) {
72
- this.config = config
73
- }
74
-
75
- /**
76
- * Generate test app installation YAML
77
- */
78
- private generateTestApp(index: number): string {
79
- const complexity = this.config.appComplexity
80
- const baseApp = {
81
- app: {
82
- name: `Load Test App ${index}`,
83
- slug: `load-test-app-${index}`,
84
- version: "1.0.0",
85
- external_app_id: `load-test-${index}`,
86
- description: `Load testing app ${index}`,
87
- author: "Load Test Runner"
88
- },
89
- installation: {
90
- pack_installation: {
91
- account_id: "${TARGET_ACCOUNT_ID}",
92
- external_app_id: `load-test-${index}`,
93
- external_app_version: "1.0.0",
94
- install_mode: "full",
95
- manifest_version: 1
96
- },
97
- app_creation: [
98
- {
99
- slug: `load-test-app-${index}`,
100
- name: `Load Test App ${index}`,
101
- installed_pack_id: "${PACK_INSTALLATION_ID}",
102
- min_role: "member",
103
- nav_items: [
104
- {
105
- key: "dashboard",
106
- to: `/load-test-${index}`,
107
- label: "Dashboard",
108
- icon: "layout-dashboard",
109
- min_role: "member"
110
- }
111
- ]
112
- }
113
- ],
114
- migrations: [],
115
- verification: [
116
- { check: "app_definition_exists", slug: `load-test-app-${index}` }
117
- ]
118
- }
119
- }
120
-
121
- // Add complexity-based migrations
122
- if (complexity === 'medium') {
123
- baseApp.installation.migrations = [
124
- {
125
- file: `migrations/001_app_${index}_setup.sql`,
126
- description: `Create app ${index} item types and views`,
127
- rollback_file: `migrations/rollback_001_app_${index}_setup.sql`
128
- },
129
- {
130
- file: `migrations/002_app_${index}_data.sql`,
131
- description: `Seed app ${index} categories and templates`,
132
- dependencies: [`001_app_${index}_setup`]
133
- }
134
- ]
135
- baseApp.installation.verification.push(
136
- { check: "item_type_exists", slug: `app_${index}_item` },
137
- { check: "view_exists", slug: `app_${index}_dashboard` }
138
- )
139
- } else if (complexity === 'complex') {
140
- baseApp.installation.migrations = [
141
- {
142
- file: `migrations/001_app_${index}_setup.sql`,
143
- description: `Create app ${index} item types and views`,
144
- rollback_file: `migrations/rollback_001_app_${index}_setup.sql`
145
- },
146
- {
147
- file: `migrations/002_app_${index}_tables.sql`,
148
- description: `Create app ${index} custom tables`,
149
- dependencies: [`001_app_${index}_setup`]
150
- },
151
- {
152
- file: `migrations/003_app_${index}_data.sql`,
153
- description: `Seed app ${index} categories and templates`,
154
- dependencies: [`001_app_${index}_setup`, `002_app_${index}_tables`]
155
- },
156
- {
157
- file: `migrations/004_app_${index}_automations.sql`,
158
- description: `Create app ${index} automation rules`,
159
- dependencies: [`002_app_${index}_tables`, `003_app_${index}_data`]
160
- }
161
- ]
162
- baseApp.installation.verification.push(
163
- { check: "item_type_exists", slug: `app_${index}_item` },
164
- { check: "view_exists", slug: `app_${index}_dashboard` },
165
- { check: "view_exists", slug: `app_${index}_list` },
166
- { check: "integration_exists", integration_id: `app_${index}_integration` }
167
- )
168
- baseApp.installation.app_creation[0].nav_items.push(
169
- { key: "list", to: `/load-test-${index}/list`, label: "List", icon: "list", min_role: "member" },
170
- { key: "settings", to: `/load-test-${index}/settings`, label: "Settings", icon: "settings", min_role: "admin" }
171
- )
172
- }
173
-
174
- return yaml.dump(baseApp)
175
- }
176
-
177
- /**
178
- * Simulate app installation steps
179
- */
180
- private async simulateInstallation(appIndex: number): Promise<TestResult> {
181
- const result: TestResult = {
182
- appId: `load-test-app-${appIndex}`,
183
- startTime: performance.now(),
184
- endTime: 0,
185
- duration: 0,
186
- success: false,
187
- steps: {
188
- validation: 0,
189
- packInstallation: 0,
190
- appCreation: 0,
191
- migrations: 0,
192
- verification: 0
193
- }
194
- }
195
-
196
- try {
197
- // Generate test app YAML
198
- const appYaml = this.generateTestApp(appIndex)
199
-
200
- // Step 1: Validation (simulate schema validation)
201
- const validationStart = performance.now()
202
- await this.simulateValidation(appYaml)
203
- result.steps.validation = performance.now() - validationStart
204
-
205
- // Step 2: Pack Installation
206
- const packStart = performance.now()
207
- await this.simulatePackInstallation(result.appId)
208
- result.steps.packInstallation = performance.now() - packStart
209
-
210
- // Step 3: App Creation
211
- const appStart = performance.now()
212
- await this.simulateAppCreation(result.appId)
213
- result.steps.appCreation = performance.now() - appStart
214
-
215
- // Step 4: Migrations
216
- const migrationsStart = performance.now()
217
- const migrationCount = this.config.appComplexity === 'simple' ? 0 :
218
- this.config.appComplexity === 'medium' ? 2 : 4
219
- await this.simulateMigrations(result.appId, migrationCount)
220
- result.steps.migrations = performance.now() - migrationsStart
221
-
222
- // Step 5: Verification
223
- const verificationStart = performance.now()
224
- const verificationCount = this.config.appComplexity === 'simple' ? 1 :
225
- this.config.appComplexity === 'medium' ? 3 : 5
226
- await this.simulateVerification(result.appId, verificationCount)
227
- result.steps.verification = performance.now() - verificationStart
228
-
229
- result.success = true
230
- } catch (error) {
231
- result.error = error instanceof Error ? error.message : String(error)
232
- }
233
-
234
- result.endTime = performance.now()
235
- result.duration = result.endTime - result.startTime
236
-
237
- return result
238
- }
239
-
240
- /**
241
- * Simulate validation step
242
- */
243
- private async simulateValidation(appYaml: string): Promise<void> {
244
- // Simulate YAML parsing and schema validation
245
- const complexity = this.config.appComplexity
246
- const delay = complexity === 'simple' ? 10 : complexity === 'medium' ? 25 : 50
247
-
248
- await this.sleep(delay)
249
-
250
- // Parse YAML to simulate actual validation work
251
- yaml.load(appYaml)
252
- }
253
-
254
- /**
255
- * Simulate pack installation
256
- */
257
- private async simulatePackInstallation(appId: string): Promise<void> {
258
- // Simulate database insert for installed_packs
259
- const complexity = this.config.appComplexity
260
- const delay = complexity === 'simple' ? 20 : complexity === 'medium' ? 40 : 80
261
-
262
- await this.sleep(delay)
263
- }
264
-
265
- /**
266
- * Simulate app creation
267
- */
268
- private async simulateAppCreation(appId: string): Promise<void> {
269
- // Simulate app_definitions creation
270
- const complexity = this.config.appComplexity
271
- const delay = complexity === 'simple' ? 15 : complexity === 'medium' ? 30 : 60
272
-
273
- await this.sleep(delay)
274
- }
275
-
276
- /**
277
- * Simulate migrations
278
- */
279
- private async simulateMigrations(appId: string, count: number): Promise<void> {
280
- // Simulate running SQL migrations
281
- for (let i = 0; i < count; i++) {
282
- const delay = this.config.appComplexity === 'simple' ? 10 :
283
- this.config.appComplexity === 'medium' ? 25 : 50
284
- await this.sleep(delay)
285
- }
286
- }
287
-
288
- /**
289
- * Simulate verification steps
290
- */
291
- private async simulateVerification(appId: string, count: number): Promise<void> {
292
- // Simulate verification checks
293
- for (let i = 0; i < count; i++) {
294
- await this.sleep(5)
295
- }
296
- }
297
-
298
- /**
299
- * Sleep helper
300
- */
301
- private sleep(ms: number): Promise<void> {
302
- return new Promise(resolve => setTimeout(resolve, ms))
303
- }
304
-
305
- /**
306
- * Run concurrent load test
307
- */
308
- async runLoadTest(): Promise<LoadTestReport> {
309
- console.log(`🚀 Starting load test...`)
310
- console.log(`Configuration:`, this.config)
311
-
312
- this.running = true
313
- this.startTime = performance.now()
314
- this.results = []
315
-
316
- const concurrentBatches = Math.ceil(this.config.totalApps / this.config.concurrentInstalls)
317
-
318
- for (let batch = 0; batch < concurrentBatches; batch++) {
319
- const startIndex = batch * this.config.concurrentInstalls
320
- const endIndex = Math.min(startIndex + this.config.concurrentInstalls, this.config.totalApps)
321
- const batchSize = endIndex - startIndex
322
-
323
- console.log(`📦 Running batch ${batch + 1}/${concurrentBatches} (${batchSize} apps)`)
324
-
325
- // Run installations concurrently
326
- const batchPromises = []
327
- for (let i = startIndex; i < endIndex; i++) {
328
- batchPromises.push(this.simulateInstallation(i))
329
- }
330
-
331
- const batchResults = await Promise.all(batchPromises)
332
- this.results.push(...batchResults)
333
-
334
- // Report progress
335
- const completed = this.results.length
336
- const successRate = (this.results.filter(r => r.success).length / this.results.length * 100).toFixed(1)
337
- console.log(`✅ Completed ${completed}/${this.config.totalApps} apps (${successRate}% success rate)`)
338
-
339
- // Check if we should stop due to time limit
340
- const elapsed = (performance.now() - this.startTime) / 1000
341
- if (elapsed >= this.config.testDuration) {
342
- console.log(`⏰ Time limit reached, stopping test`)
343
- break
344
- }
345
- }
346
-
347
- this.running = false
348
- return this.generateReport()
349
- }
350
-
351
- /**
352
- * Generate comprehensive report
353
- */
354
- private generateReport(): LoadTestReport {
355
- const successfulTests = this.results.filter(r => r.success)
356
- const failedTests = this.results.filter(r => !r.success)
357
-
358
- const durations = successfulTests.map(r => r.duration)
359
- const avgDuration = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0
360
- const minDuration = durations.length > 0 ? Math.min(...durations) : 0
361
- const maxDuration = durations.length > 0 ? Math.max(...durations) : 0
362
-
363
- const totalElapsed = (performance.now() - this.startTime) / 1000
364
- const throughput = this.results.length / totalElapsed
365
-
366
- // Error aggregation
367
- const errorMap = new Map<string, number>()
368
- for (const test of failedTests) {
369
- const error = test.error || 'Unknown error'
370
- errorMap.set(error, (errorMap.get(error) || 0) + 1)
371
- }
372
-
373
- const errors = Array.from(errorMap.entries()).map(([error, count]) => ({ error, count }))
374
-
375
- // Step performance analysis
376
- const stepPerformance = {
377
- validation: this.calculateStepPerformance('validation'),
378
- packInstallation: this.calculateStepPerformance('packInstallation'),
379
- appCreation: this.calculateStepPerformance('appCreation'),
380
- migrations: this.calculateStepPerformance('migrations'),
381
- verification: this.calculateStepPerformance('verification')
382
- }
383
-
384
- return {
385
- config: this.config,
386
- results: this.results,
387
- summary: {
388
- totalTests: this.results.length,
389
- successfulTests: successfulTests.length,
390
- failedTests: failedTests.length,
391
- averageDuration: avgDuration,
392
- minDuration,
393
- maxDuration,
394
- throughput,
395
- errors
396
- },
397
- performance: stepPerformance
398
- }
399
- }
400
-
401
- /**
402
- * Calculate performance metrics for a specific step
403
- */
404
- private calculateStepPerformance(step: keyof TestResult['steps']) {
405
- const values = this.results.filter(r => r.success).map(r => r.steps[step])
406
- return {
407
- avg: values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0,
408
- min: values.length > 0 ? Math.min(...values) : 0,
409
- max: values.length > 0 ? Math.max(...values) : 0
410
- }
411
- }
412
- }
413
-
414
- /**
415
- * Pretty print report
416
- */
417
- function printReport(report: LoadTestReport): void {
418
- console.log('\n' + '='.repeat(80))
419
- console.log('📊 LOAD TEST REPORT')
420
- console.log('='.repeat(80))
421
-
422
- console.log('\n🔧 Configuration:')
423
- console.log(` Concurrent Installs: ${report.config.concurrentInstalls}`)
424
- console.log(` Total Apps: ${report.config.totalApps}`)
425
- console.log(` App Complexity: ${report.config.appComplexity}`)
426
- console.log(` Test Duration: ${report.config.testDuration}s`)
427
-
428
- console.log('\n📈 Summary:')
429
- console.log(` Total Tests: ${report.summary.totalTests}`)
430
- console.log(` Successful: ${report.summary.successfulTests} (${(report.summary.successfulTests / report.summary.totalTests * 100).toFixed(1)}%)`)
431
- console.log(` Failed: ${report.summary.failedTests} (${(report.summary.failedTests / report.summary.totalTests * 100).toFixed(1)}%)`)
432
- console.log(` Average Duration: ${report.summary.averageDuration.toFixed(2)}ms`)
433
- console.log(` Min Duration: ${report.summary.minDuration.toFixed(2)}ms`)
434
- console.log(` Max Duration: ${report.summary.maxDuration.toFixed(2)}ms`)
435
- console.log(` Throughput: ${report.summary.throughput.toFixed(2)} tests/second`)
436
-
437
- if (report.summary.errors.length > 0) {
438
- console.log('\n❌ Errors:')
439
- report.summary.errors.forEach(({ error, count }) => {
440
- console.log(` ${error}: ${count}`)
441
- })
442
- }
443
-
444
- console.log('\n⚡ Step Performance:')
445
- Object.entries(report.performance).forEach(([step, perf]) => {
446
- console.log(` ${step}:`)
447
- console.log(` Avg: ${perf.avg.toFixed(2)}ms`)
448
- console.log(` Min: ${perf.min.toFixed(2)}ms`)
449
- console.log(` Max: ${perf.max.toFixed(2)}ms`)
450
- })
451
-
452
- console.log('\n' + '='.repeat(80))
453
- }
454
-
455
- // CLI setup
456
- program
457
- .name('load-test-app-install')
458
- .description('Load testing for Spine app installation system')
459
- .version('1.0.0')
460
- .option('-c, --concurrent <number>', 'Number of concurrent installations', '10')
461
- .option('-t, --total <number>', 'Total number of apps to install', '100')
462
- .option('-x, --complexity <type>', 'App complexity (simple, medium, complex)', 'medium')
463
- .option('-d, --duration <seconds>', 'Maximum test duration in seconds', '300')
464
- .option('-r, --report-interval <seconds>', 'Progress report interval', '10')
465
- .action(async (options) => {
466
- const config: LoadTestConfig = {
467
- concurrentInstalls: parseInt(options.concurrent),
468
- totalApps: parseInt(options.total),
469
- appComplexity: options.complexity as 'simple' | 'medium' | 'complex',
470
- testDuration: parseInt(options.duration),
471
- reportInterval: parseInt(options.reportInterval)
472
- }
473
-
474
- const runner = new LoadTestRunner(config)
475
- const report = await runner.runLoadTest()
476
- printReport(report)
477
-
478
- // Exit with error code if there were failures
479
- if (report.summary.failedTests > 0) {
480
- process.exit(1)
481
- }
482
- })
483
-
484
- program.parse()
@@ -1,22 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # Netlify Dev Wrapper - Start dev server for Spine.
4
- #
5
- # Purpose: Execute Vite directly to avoid npx/npm indirection issues under Netlify CLI.
6
- # - Called by: netlify dev (via netlify.toml [dev].command)
7
- # - .framework/ is the working core directory
8
- #
9
- # Integration: Part of the development workflow, bridges Netlify CLI and Vite.
10
- #
11
- # Dependencies: vite, netlify CLI
12
-
13
- set -euo pipefail
14
-
15
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
16
- PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
17
-
18
- echo "Starting Netlify dev for Spine..."
19
-
20
- # Start Vite dev server directly (.assembled/src is now the root)
21
- echo " Starting Vite on port 3001..."
22
- exec "$PROJECT_ROOT/node_modules/.bin/vite" --config "$PROJECT_ROOT/config/vite.config.ts"
package/vitest.config.ts DELETED
@@ -1,45 +0,0 @@
1
- import { defineConfig } from 'vitest/config'
2
- import { readFileSync, existsSync } from 'fs'
3
- import { resolve } from 'path'
4
-
5
- // Load .xenv.test so integration tests get real DB credentials before any
6
- // worker module graph (db.ts, principal.ts) evaluates createClient() calls.
7
- const xenvTest = resolve(__dirname, '.framework/.xenv.test')
8
- if (existsSync(xenvTest)) {
9
- for (const line of readFileSync(xenvTest, 'utf8').split('\n')) {
10
- const t = line.trim()
11
- if (!t || t.startsWith('#')) continue
12
- const eq = t.indexOf('=')
13
- if (eq === -1) continue
14
- const k = t.slice(0, eq).trim()
15
- const v = t.slice(eq + 1).trim().replace(/^["']|["']$/g, '')
16
- if (!process.env[k]) process.env[k] = v
17
- }
18
- }
19
-
20
- export default defineConfig({
21
- test: {
22
- // Stub SUPABASE_URL etc. before any module is imported
23
- setupFiles: ['.framework/tests/setup.ts'],
24
- // Each test file gets its own module instance (important for vi.mock isolation)
25
- isolate: true,
26
- // Allow .ts extension imports (tsx-style)
27
- environment: 'node',
28
- // Resolve .ts imports as themselves (no .js→.ts rewriting needed in tests)
29
- include: [
30
- '.framework/tests/unit/**/*.test.ts',
31
- '.framework/tests/integration/**/*.test.ts',
32
- '.framework/tests/api/**/*.test.ts'
33
- ],
34
- // Global test timeout — integration + API tests may hit Supabase / local server
35
- testTimeout: 20000,
36
- // Don't fail the suite on integration tests if env isn't configured
37
- passWithNoTests: true,
38
- // Persist results to public.test_runs after every run
39
- reporters: ['default', './.framework/tests/reporter.ts']
40
- },
41
- resolve: {
42
- // Allow bare .ts imports (the CLI + shared code uses these)
43
- extensions: ['.ts', '.js', '.json']
44
- }
45
- })