insforge 1.2.10 → 1.3.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 (335) hide show
  1. package/.claude-plugin/marketplace.json +20 -20
  2. package/.dockerignore +60 -60
  3. package/.env.example +83 -77
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +65 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -63
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +44 -44
  15. package/CLAUDE_PLUGIN.md +104 -104
  16. package/CODE_OF_CONDUCT.md +128 -128
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -30
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -182
  23. package/assets/Dark.svg +23 -23
  24. package/auth/package.json +28 -28
  25. package/auth/src/lib/broadcastService.ts +117 -115
  26. package/auth/src/pages/SignInPage.tsx +60 -57
  27. package/auth/src/pages/SignUpPage.tsx +60 -57
  28. package/auth/tsconfig.json +32 -32
  29. package/auth/tsconfig.node.json +11 -11
  30. package/backend/package.json +78 -75
  31. package/backend/src/api/routes/ai/index.routes.ts +3 -3
  32. package/backend/src/api/routes/auth/index.routes.ts +667 -570
  33. package/backend/src/api/routes/auth/oauth.routes.ts +473 -448
  34. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  35. package/backend/src/api/routes/database/index.routes.ts +78 -1
  36. package/backend/src/api/routes/database/records.routes.ts +10 -10
  37. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  38. package/backend/src/api/routes/docs/index.routes.ts +75 -76
  39. package/backend/src/api/routes/email/index.routes.ts +35 -0
  40. package/backend/src/api/routes/functions/index.routes.ts +18 -12
  41. package/backend/src/api/routes/metadata/index.routes.ts +12 -0
  42. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  43. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  44. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  45. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  46. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  47. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  48. package/backend/src/infra/database/database.manager.ts +14 -1
  49. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  50. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  51. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  52. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  53. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  54. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  55. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  56. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  57. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  58. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  59. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  60. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  61. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  62. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  63. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  64. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  65. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  66. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  67. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  68. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  69. package/backend/src/infra/security/token.manager.ts +219 -125
  70. package/backend/src/infra/socket/socket.manager.ts +198 -64
  71. package/backend/src/providers/ai/openrouter.provider.ts +12 -9
  72. package/backend/src/providers/email/base.provider.ts +4 -7
  73. package/backend/src/providers/email/cloud.provider.ts +84 -0
  74. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  75. package/backend/src/providers/oauth/index.ts +1 -0
  76. package/backend/src/server.ts +317 -284
  77. package/backend/src/services/ai/ai-model.service.ts +5 -5
  78. package/backend/src/services/ai/chat-completion.service.ts +4 -4
  79. package/backend/src/services/ai/image-generation.service.ts +3 -3
  80. package/backend/src/services/auth/auth.service.ts +14 -0
  81. package/backend/src/services/database/database-table.service.ts +0 -9
  82. package/backend/src/services/database/database.service.ts +127 -0
  83. package/backend/src/services/email/email.service.ts +5 -7
  84. package/backend/src/services/realtime/index.ts +3 -0
  85. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  86. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  87. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  88. package/backend/src/types/auth.ts +11 -0
  89. package/backend/src/types/realtime.ts +18 -0
  90. package/backend/src/types/socket.ts +7 -31
  91. package/backend/src/utils/cookies.ts +35 -0
  92. package/backend/src/utils/s3-config-loader.ts +64 -0
  93. package/backend/src/utils/seed.ts +301 -298
  94. package/backend/src/utils/sql-parser.ts +90 -0
  95. package/backend/tests/README.md +133 -133
  96. package/backend/tests/cleanup-all-test-data.sh +230 -230
  97. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  98. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  99. package/backend/tests/local/test-ai-config.sh +129 -129
  100. package/backend/tests/local/test-ai-usage.sh +80 -80
  101. package/backend/tests/local/test-auth-router.sh +143 -143
  102. package/backend/tests/local/test-database-router.sh +222 -222
  103. package/backend/tests/local/test-e2e.sh +240 -240
  104. package/backend/tests/local/test-fk-errors.sh +96 -96
  105. package/backend/tests/local/test-functions.sh +123 -123
  106. package/backend/tests/local/test-id-field.sh +200 -200
  107. package/backend/tests/local/test-logs.sh +132 -132
  108. package/backend/tests/local/test-public-bucket.sh +264 -264
  109. package/backend/tests/local/test-secrets.sh +249 -249
  110. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  111. package/backend/tests/local/test-traditional-rest.sh +208 -208
  112. package/backend/tests/manual/README.md +50 -50
  113. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  114. package/backend/tests/manual/seed-large-table.sql +100 -100
  115. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  116. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  117. package/backend/tests/manual/test-database-advance.sh +296 -296
  118. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  119. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  120. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  121. package/backend/tests/manual/test-universal-storage.sh +263 -263
  122. package/backend/tests/manual/test-users.sql +17 -17
  123. package/backend/tests/run-all-tests.sh +139 -139
  124. package/backend/tests/setup.ts +0 -0
  125. package/backend/tests/test-config.sh +338 -338
  126. package/backend/tests/unit/analyze-query.test.ts +697 -0
  127. package/backend/tsconfig.json +22 -22
  128. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  129. package/claude-plugin/README.md +133 -133
  130. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -270
  131. package/docker-compose.prod.yml +204 -200
  132. package/docker-compose.yml +232 -228
  133. package/docker-init/db/db-init.sql +97 -97
  134. package/docker-init/db/jwt.sql +5 -5
  135. package/docker-init/db/postgresql.conf +16 -16
  136. package/docker-init/logs/vector.yml +236 -236
  137. package/docs/README.md +44 -44
  138. package/docs/agent-docs/real-time.md +269 -0
  139. package/docs/changelog.mdx +119 -67
  140. package/docs/core-concepts/ai/architecture.mdx +372 -372
  141. package/docs/core-concepts/ai/sdk.mdx +213 -213
  142. package/docs/core-concepts/authentication/architecture.mdx +278 -278
  143. package/docs/core-concepts/authentication/sdk.mdx +414 -414
  144. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -529
  145. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -221
  146. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -184
  147. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -129
  148. package/docs/core-concepts/database/architecture.mdx +255 -255
  149. package/docs/core-concepts/database/sdk.mdx +382 -382
  150. package/docs/core-concepts/email/architecture.mdx +101 -0
  151. package/docs/core-concepts/email/sdk.mdx +53 -0
  152. package/docs/core-concepts/functions/architecture.mdx +105 -105
  153. package/docs/core-concepts/functions/sdk.mdx +184 -184
  154. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  155. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  156. package/docs/core-concepts/storage/architecture.mdx +243 -243
  157. package/docs/core-concepts/storage/sdk.mdx +253 -253
  158. package/docs/deployment/README.md +94 -94
  159. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  160. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  161. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  162. package/docs/deployment/deploy-to-render.md +441 -441
  163. package/docs/deprecated/insforge-auth-api.md +214 -214
  164. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  165. package/docs/deprecated/insforge-db-api.md +358 -358
  166. package/docs/deprecated/insforge-db-sdk.md +139 -139
  167. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  168. package/docs/deprecated/insforge-debug.md +64 -64
  169. package/docs/deprecated/insforge-instructions.md +123 -123
  170. package/docs/deprecated/insforge-project.md +117 -117
  171. package/docs/deprecated/insforge-storage-api.md +278 -278
  172. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  173. package/docs/docs.json +232 -210
  174. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  175. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  176. package/docs/examples/framework-guides/react.mdx +165 -165
  177. package/docs/examples/framework-guides/svelte.mdx +153 -153
  178. package/docs/examples/framework-guides/vue.mdx +159 -159
  179. package/docs/examples/overview.mdx +67 -67
  180. package/docs/favicon.svg +19 -19
  181. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  182. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  183. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  184. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  185. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  186. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  187. package/docs/images/icons/ai.svg +4 -4
  188. package/docs/images/logos/nextjs.svg +4 -4
  189. package/docs/images/logos/nuxt.svg +4 -4
  190. package/docs/images/logos/react.svg +5 -5
  191. package/docs/images/logos/svelte.svg +4 -4
  192. package/docs/images/logos/vue.svg +5 -5
  193. package/docs/insforge-instructions-sdk.md +89 -88
  194. package/docs/introduction.mdx +45 -45
  195. package/docs/logo/dark.svg +22 -22
  196. package/docs/logo/light.svg +20 -20
  197. package/docs/partnership.mdx +651 -646
  198. package/docs/quickstart.mdx +82 -82
  199. package/docs/showcase.mdx +52 -52
  200. package/docs/snippets/sdk-installation.mdx +21 -21
  201. package/docs/snippets/service-icons.mdx +27 -27
  202. package/examples/oauth/frontend-oauth-example.html +250 -250
  203. package/examples/response-examples.md +443 -443
  204. package/frontend/components.json +17 -17
  205. package/frontend/package.json +69 -69
  206. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  207. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  208. package/frontend/src/assets/icons/checked.svg +3 -3
  209. package/frontend/src/assets/icons/connected.svg +3 -3
  210. package/frontend/src/assets/icons/error.svg +3 -3
  211. package/frontend/src/assets/icons/loader.svg +9 -9
  212. package/frontend/src/assets/icons/pencil.svg +4 -4
  213. package/frontend/src/assets/icons/refresh.svg +4 -4
  214. package/frontend/src/assets/icons/step_active.svg +3 -3
  215. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  216. package/frontend/src/assets/icons/warning.svg +3 -3
  217. package/frontend/src/assets/logos/apple.svg +3 -3
  218. package/frontend/src/assets/logos/claude_code.svg +3 -3
  219. package/frontend/src/assets/logos/cline.svg +6 -6
  220. package/frontend/src/assets/logos/cursor.svg +20 -20
  221. package/frontend/src/assets/logos/discord.svg +8 -8
  222. package/frontend/src/assets/logos/facebook.svg +3 -3
  223. package/frontend/src/assets/logos/gemini.svg +19 -19
  224. package/frontend/src/assets/logos/github.svg +5 -5
  225. package/frontend/src/assets/logos/google.svg +13 -13
  226. package/frontend/src/assets/logos/grok.svg +10 -10
  227. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  228. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  229. package/frontend/src/assets/logos/instagram.svg +1 -1
  230. package/frontend/src/assets/logos/linkedin.svg +3 -3
  231. package/frontend/src/assets/logos/openai.svg +10 -10
  232. package/frontend/src/assets/logos/roo_code.svg +9 -9
  233. package/frontend/src/assets/logos/spotify.svg +16 -16
  234. package/frontend/src/assets/logos/tiktok.svg +5 -5
  235. package/frontend/src/assets/logos/trae.svg +3 -3
  236. package/frontend/src/assets/logos/windsurf.svg +10 -10
  237. package/frontend/src/assets/logos/x.svg +3 -3
  238. package/frontend/src/components/layout/AppHeader.tsx +9 -10
  239. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  240. package/frontend/src/features/auth/components/UsersDataGrid.tsx +6 -0
  241. package/frontend/src/features/auth/helpers.tsx +8 -0
  242. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  243. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  244. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  245. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  246. package/frontend/src/features/database/hooks/useTables.ts +32 -28
  247. package/frontend/src/features/database/index.ts +1 -0
  248. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -37
  249. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +35 -47
  250. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +43 -54
  251. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  252. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +35 -47
  253. package/frontend/src/features/database/services/advance.service.ts +0 -26
  254. package/frontend/src/features/database/services/database.service.ts +55 -0
  255. package/frontend/src/features/database/services/table.service.ts +0 -6
  256. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  257. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +11 -9
  258. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  259. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  260. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  261. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  262. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  263. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  264. package/frontend/src/features/realtime/index.ts +11 -0
  265. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  266. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  267. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  268. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  269. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  270. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +3 -3
  271. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +1 -35
  272. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  273. package/frontend/src/lib/routing/AppRoutes.tsx +35 -20
  274. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  275. package/frontend/src/lib/utils/menuItems.ts +24 -0
  276. package/frontend/src/lib/utils/utils.ts +14 -1
  277. package/frontend/tsconfig.json +25 -25
  278. package/frontend/tsconfig.node.json +9 -9
  279. package/functions/deno.json +24 -24
  280. package/functions/server.ts +315 -315
  281. package/i18n/README.ar.md +130 -130
  282. package/i18n/README.de.md +130 -130
  283. package/i18n/README.es.md +154 -154
  284. package/i18n/README.fr.md +134 -134
  285. package/i18n/README.hi.md +129 -129
  286. package/i18n/README.ja.md +174 -174
  287. package/i18n/README.ko.md +136 -136
  288. package/i18n/README.pt-BR.md +131 -131
  289. package/i18n/README.ru.md +129 -129
  290. package/i18n/README.zh-CN.md +133 -133
  291. package/openapi/ai.yaml +715 -715
  292. package/openapi/auth.yaml +1244 -1244
  293. package/openapi/email.yaml +158 -0
  294. package/openapi/functions.yaml +475 -475
  295. package/openapi/health.yaml +29 -29
  296. package/openapi/logs.yaml +223 -223
  297. package/openapi/metadata.yaml +177 -177
  298. package/openapi/realtime.yaml +699 -0
  299. package/openapi/records.yaml +381 -381
  300. package/openapi/secrets.yaml +370 -370
  301. package/openapi/storage.yaml +875 -875
  302. package/openapi/tables.yaml +463 -463
  303. package/package.json +97 -97
  304. package/shared-schemas/package.json +31 -31
  305. package/shared-schemas/src/ai.schema.ts +63 -59
  306. package/shared-schemas/src/auth-api.schema.ts +352 -339
  307. package/shared-schemas/src/auth.schema.ts +1 -1
  308. package/shared-schemas/src/database-api.schema.ts +32 -1
  309. package/shared-schemas/src/database.schema.ts +39 -0
  310. package/shared-schemas/src/docs.schema.ts +26 -0
  311. package/shared-schemas/src/email-api.schema.ts +30 -0
  312. package/shared-schemas/src/index.ts +4 -0
  313. package/shared-schemas/src/metadata.schema.ts +9 -0
  314. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  315. package/shared-schemas/src/realtime.schema.ts +143 -0
  316. package/shared-schemas/tsconfig.json +21 -21
  317. package/tsconfig.json +7 -7
  318. package/zeabur/README.md +13 -13
  319. package/zeabur/template.yml +1032 -1032
  320. package/.cursor/rules/cursor-rules.mdc +0 -94
  321. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  322. package/test-gemini.sh +0 -35
  323. package/test-usage-admin.sh +0 -57
  324. package/test-usage.sh +0 -50
  325. /package/frontend/src/features/ai/{page → pages}/AIPage.tsx +0 -0
  326. /package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +0 -0
  327. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  328. /package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +0 -0
  329. /package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +0 -0
  330. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  331. /package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +0 -0
  332. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  333. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  334. /package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +0 -0
  335. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -1,297 +1,297 @@
1
- #!/bin/bash
2
-
3
- # Test script for database advance functionality
4
- # Tests rawSQL, export, and import operations
5
-
6
- # Configuration
7
- BASE_URL="http://localhost:7130/api/database/advance"
8
- TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwicm9sZSI6InByb2plY3RfYWRtaW4iLCJpYXQiOjE3NTY0MDM2NTUsImV4cCI6MTc1NzAwODQ1NX0.UhLvS5f4vdzsR0bZLmHvQ-MX6WPoPieTZ4H7sxjRYGM"
9
-
10
- # Colors for output
11
- RED='\033[0;31m'
12
- GREEN='\033[0;32m'
13
- YELLOW='\033[1;33m'
14
- BLUE='\033[0;34m'
15
- NC='\033[0m' # No Color
16
-
17
- echo "========================================="
18
- echo "Database Advance Operations Test Script"
19
- echo "========================================="
20
- echo "Base URL: $BASE_URL"
21
- echo "Testing rawSQL, export, and import operations..."
22
- echo "========================================="
23
- echo ""
24
-
25
- # Function to test rawSQL endpoint
26
- test_rawsql() {
27
- local test_name="$1"
28
- local request_body="$2"
29
- local description="$3"
30
-
31
- echo -e "${BLUE}Test: $test_name${NC}"
32
- echo -e "${YELLOW}Description: $description${NC}"
33
- echo "Request body: $request_body"
34
- echo ""
35
-
36
- # Make the API request
37
- RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/rawsql" \
38
- -H "Content-Type: application/json" \
39
- -H "Authorization: Bearer $TOKEN" \
40
- -d "$request_body" 2>&1)
41
-
42
- # Extract HTTP code and response body
43
- HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
44
- RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
45
-
46
- echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
47
-
48
- if [ "$HTTP_CODE" = "200" ]; then
49
- echo -e "${GREEN}✓ Request successful${NC}"
50
- echo ""
51
- echo -e "${BLUE}Response:${NC}"
52
- echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
53
- else
54
- echo -e "${RED}✗ Request failed${NC}"
55
- echo ""
56
- echo -e "${RED}Response:${NC}"
57
- echo "$RESPONSE_BODY"
58
- fi
59
-
60
- echo ""
61
- echo "----------------------------------------"
62
- echo ""
63
- }
64
-
65
- # Function to make API request and show results
66
- test_export() {
67
- local test_name="$1"
68
- local request_body="$2"
69
- local description="$3"
70
-
71
- echo -e "${BLUE}Test: $test_name${NC}"
72
- echo -e "${YELLOW}Description: $description${NC}"
73
- echo "Request body: $request_body"
74
- echo ""
75
-
76
- # Make the API request
77
- RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/export" \
78
- -H "Content-Type: application/json" \
79
- -H "Authorization: Bearer $TOKEN" \
80
- -d "$request_body" 2>&1)
81
-
82
- # Extract HTTP code and response body
83
- HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
84
- RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
85
-
86
- echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
87
-
88
- if [ "$HTTP_CODE" = "200" ]; then
89
- echo -e "${GREEN}✓ Request successful${NC}"
90
- echo ""
91
- echo -e "${BLUE}Response:${NC}"
92
- echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
93
- else
94
- echo -e "${RED}✗ Request failed${NC}"
95
- echo ""
96
- echo -e "${RED}Response:${NC}"
97
- echo "$RESPONSE_BODY"
98
- fi
99
-
100
- echo ""
101
- echo "----------------------------------------"
102
- echo ""
103
- }
104
-
105
- # Function to test import endpoint with file upload
106
- test_import() {
107
- local test_name="$1"
108
- local file_path="$2"
109
- local truncate_option="$3"
110
- local description="$4"
111
-
112
- echo -e "${BLUE}Test: $test_name${NC}"
113
- echo -e "${YELLOW}Description: $description${NC}"
114
- echo "File: $file_path"
115
- echo "Truncate: $truncate_option"
116
- echo ""
117
-
118
- # Check if file exists
119
- if [ ! -f "$file_path" ]; then
120
- echo -e "${RED}✗ File not found: $file_path${NC}"
121
- echo ""
122
- echo "----------------------------------------"
123
- echo ""
124
- return 1
125
- fi
126
-
127
- # Make the API request with file upload
128
- RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/import" \
129
- -H "Authorization: Bearer $TOKEN" \
130
- -F "file=@$file_path" \
131
- -F "truncate=$truncate_option" 2>&1)
132
-
133
- # Extract HTTP code and response body
134
- HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
135
- RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
136
-
137
- echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
138
-
139
- if [ "$HTTP_CODE" = "200" ]; then
140
- echo -e "${GREEN}✓ Request successful${NC}"
141
- echo ""
142
- echo -e "${BLUE}Response:${NC}"
143
- echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
144
- else
145
- echo -e "${RED}✗ Request failed${NC}"
146
- echo ""
147
- echo -e "${RED}Response:${NC}"
148
- echo "$RESPONSE_BODY"
149
- fi
150
-
151
- echo ""
152
- echo "----------------------------------------"
153
- echo ""
154
- }
155
-
156
- # ===========================================
157
- # RAW SQL TESTS
158
- # ===========================================
159
-
160
- echo -e "${GREEN}=== RAW SQL TESTS ===${NC}"
161
- echo ""
162
-
163
- # Test 1: Check if posts table exists
164
- test_rawsql \
165
- "Check Posts Table Existence" \
166
- '{"query": "SELECT tablename FROM pg_tables WHERE schemaname = '\''public'\'' AND tablename = '\''posts'\'';"}' \
167
- "Verify that the posts table exists before creating index"
168
-
169
- # Test 2: Check existing indexes on posts table
170
- test_rawsql \
171
- "Check Existing Indexes on Posts" \
172
- '{"query": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '\''posts'\'';"}' \
173
- "List all existing indexes on the posts table"
174
-
175
- # Test 3: Create index on posts.title column
176
- test_rawsql \
177
- "Create Title Index on Posts" \
178
- '{"query": "CREATE INDEX IF NOT EXISTS idx_posts_title ON posts(title);"}' \
179
- "Create an index on the title column of the posts table for better query performance"
180
-
181
- # Test 4: Verify the index was created
182
- test_rawsql \
183
- "Verify Title Index Creation" \
184
- '{"query": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '\''posts'\'' AND indexname = '\''idx_posts_title'\'';"}' \
185
- "Confirm that the title index was successfully created"
186
-
187
- # Test 5: Test a simple SELECT query
188
- test_rawsql \
189
- "Simple Select Query" \
190
- '{"query": "SELECT COUNT(*) as total_posts FROM posts;"}' \
191
- "Count total number of posts in the table"
192
-
193
- echo -e "${GREEN}=== EXPORT TESTS ===${NC}"
194
- echo ""
195
-
196
- # Test 6: Export users table in SQL format with data
197
- test_export \
198
- "Users Table - SQL with Data" \
199
- '{"tables": ["users"], "format": "sql", "includeData": true}' \
200
- "Export users table as SQL with both schema and data"
201
-
202
- # Test 7: Export users table in SQL format without data (schema only)
203
- test_export \
204
- "Users Table - SQL Schema Only" \
205
- '{"tables": ["users"], "format": "sql", "includeData": false}' \
206
- "Export users table as SQL with schema only, no data"
207
-
208
- # Test 8: Export users table in JSON format with data
209
- test_export \
210
- "Users Table - JSON with Data" \
211
- '{"tables": ["users"], "format": "json", "includeData": true}' \
212
- "Export users table as JSON with both schema and data"
213
-
214
- # Test 9: Export users table in JSON format without data (schema only)
215
- test_export \
216
- "Users Table - JSON Schema Only" \
217
- '{"tables": ["users"], "format": "json", "includeData": false}' \
218
- "Export users table as JSON with schema only, no data"
219
-
220
- # Test 10: Export all tables in SQL format (default behavior)
221
- test_export \
222
- "All Tables - SQL Format" \
223
- '{"format": "sql"}' \
224
- "Export all tables as SQL with default settings"
225
-
226
- # Test 11: Test with invalid table name
227
- test_export \
228
- "Invalid Table Name" \
229
- '{"tables": ["nonexistent_table"], "format": "sql"}' \
230
- "Test error handling with non-existent table"
231
-
232
- # Test 12: Test with invalid format
233
- test_export \
234
- "Invalid Format" \
235
- '{"tables": ["users"], "format": "xml"}' \
236
- "Test validation with invalid format"
237
-
238
- # Test 12.5: Export posts table in SQL format with data
239
- test_export \
240
- "All Tables - SQL with Data" \
241
- '{"format": "sql", "includeData": false}' \
242
- "Export all tables as SQL with both schema and data"
243
-
244
- echo -e "${GREEN}=== IMPORT TESTS ===${NC}"
245
- echo ""
246
-
247
- # Define the path to the SQL file
248
- SQL_FILE_PATH="$(dirname "$0")/test-users.sql"
249
-
250
- # Test 13: Import users.sql without truncate
251
- test_import \
252
- "Import Users SQL - No Truncate" \
253
- "$SQL_FILE_PATH" \
254
- "false" \
255
- "Import users table structure from SQL file without truncating existing data"
256
-
257
- # Test 14: Import users.sql with truncate
258
- test_import \
259
- "Import Users SQL - With Truncate" \
260
- "$SQL_FILE_PATH" \
261
- "true" \
262
- "Import users table structure from SQL file with truncating existing data"
263
-
264
- # Test 15: Test with non-existent file
265
- test_import \
266
- "Import Non-existent File" \
267
- "$(dirname "$0")/nonexistent.sql" \
268
- "false" \
269
- "Test error handling with non-existent SQL file"
270
-
271
- echo "========================================="
272
- echo "Database Advance Tests Complete"
273
- echo "========================================="
274
- echo ""
275
- echo -e "${GREEN}All tests have been executed.${NC}"
276
- echo "Check the responses above to verify all functionality."
277
- echo ""
278
- echo "Key things to verify:"
279
- echo ""
280
- echo -e "${BLUE}Raw SQL Tests:${NC}"
281
- echo "- Posts table existence check"
282
- echo "- Index creation and verification"
283
- echo "- SQL execution with proper responses"
284
- echo ""
285
- echo -e "${BLUE}Export Tests:${NC}"
286
- echo "- SQL exports should contain CREATE TABLE statements"
287
- echo "- When includeData=true, INSERT statements should be present"
288
- echo "- When includeData=false, only schema should be exported"
289
- echo "- JSON exports should have 'schema' and 'rows' properties"
290
- echo "- Invalid requests should return appropriate error messages"
291
- echo ""
292
- echo -e "${BLUE}Import Tests:${NC}"
293
- echo "- File uploads should be processed correctly"
294
- echo "- SQL files should be executed and tables created"
295
- echo "- Truncate option should control data preservation"
296
- echo "- Error handling should work for missing files"
1
+ #!/bin/bash
2
+
3
+ # Test script for database advance functionality
4
+ # Tests rawSQL, export, and import operations
5
+
6
+ # Configuration
7
+ BASE_URL="http://localhost:7130/api/database/advance"
8
+ TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwicm9sZSI6InByb2plY3RfYWRtaW4iLCJpYXQiOjE3NTY0MDM2NTUsImV4cCI6MTc1NzAwODQ1NX0.UhLvS5f4vdzsR0bZLmHvQ-MX6WPoPieTZ4H7sxjRYGM"
9
+
10
+ # Colors for output
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ YELLOW='\033[1;33m'
14
+ BLUE='\033[0;34m'
15
+ NC='\033[0m' # No Color
16
+
17
+ echo "========================================="
18
+ echo "Database Advance Operations Test Script"
19
+ echo "========================================="
20
+ echo "Base URL: $BASE_URL"
21
+ echo "Testing rawSQL, export, and import operations..."
22
+ echo "========================================="
23
+ echo ""
24
+
25
+ # Function to test rawSQL endpoint
26
+ test_rawsql() {
27
+ local test_name="$1"
28
+ local request_body="$2"
29
+ local description="$3"
30
+
31
+ echo -e "${BLUE}Test: $test_name${NC}"
32
+ echo -e "${YELLOW}Description: $description${NC}"
33
+ echo "Request body: $request_body"
34
+ echo ""
35
+
36
+ # Make the API request
37
+ RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/rawsql" \
38
+ -H "Content-Type: application/json" \
39
+ -H "Authorization: Bearer $TOKEN" \
40
+ -d "$request_body" 2>&1)
41
+
42
+ # Extract HTTP code and response body
43
+ HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
44
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
45
+
46
+ echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
47
+
48
+ if [ "$HTTP_CODE" = "200" ]; then
49
+ echo -e "${GREEN}✓ Request successful${NC}"
50
+ echo ""
51
+ echo -e "${BLUE}Response:${NC}"
52
+ echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
53
+ else
54
+ echo -e "${RED}✗ Request failed${NC}"
55
+ echo ""
56
+ echo -e "${RED}Response:${NC}"
57
+ echo "$RESPONSE_BODY"
58
+ fi
59
+
60
+ echo ""
61
+ echo "----------------------------------------"
62
+ echo ""
63
+ }
64
+
65
+ # Function to make API request and show results
66
+ test_export() {
67
+ local test_name="$1"
68
+ local request_body="$2"
69
+ local description="$3"
70
+
71
+ echo -e "${BLUE}Test: $test_name${NC}"
72
+ echo -e "${YELLOW}Description: $description${NC}"
73
+ echo "Request body: $request_body"
74
+ echo ""
75
+
76
+ # Make the API request
77
+ RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/export" \
78
+ -H "Content-Type: application/json" \
79
+ -H "Authorization: Bearer $TOKEN" \
80
+ -d "$request_body" 2>&1)
81
+
82
+ # Extract HTTP code and response body
83
+ HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
84
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
85
+
86
+ echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
87
+
88
+ if [ "$HTTP_CODE" = "200" ]; then
89
+ echo -e "${GREEN}✓ Request successful${NC}"
90
+ echo ""
91
+ echo -e "${BLUE}Response:${NC}"
92
+ echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
93
+ else
94
+ echo -e "${RED}✗ Request failed${NC}"
95
+ echo ""
96
+ echo -e "${RED}Response:${NC}"
97
+ echo "$RESPONSE_BODY"
98
+ fi
99
+
100
+ echo ""
101
+ echo "----------------------------------------"
102
+ echo ""
103
+ }
104
+
105
+ # Function to test import endpoint with file upload
106
+ test_import() {
107
+ local test_name="$1"
108
+ local file_path="$2"
109
+ local truncate_option="$3"
110
+ local description="$4"
111
+
112
+ echo -e "${BLUE}Test: $test_name${NC}"
113
+ echo -e "${YELLOW}Description: $description${NC}"
114
+ echo "File: $file_path"
115
+ echo "Truncate: $truncate_option"
116
+ echo ""
117
+
118
+ # Check if file exists
119
+ if [ ! -f "$file_path" ]; then
120
+ echo -e "${RED}✗ File not found: $file_path${NC}"
121
+ echo ""
122
+ echo "----------------------------------------"
123
+ echo ""
124
+ return 1
125
+ fi
126
+
127
+ # Make the API request with file upload
128
+ RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/import" \
129
+ -H "Authorization: Bearer $TOKEN" \
130
+ -F "file=@$file_path" \
131
+ -F "truncate=$truncate_option" 2>&1)
132
+
133
+ # Extract HTTP code and response body
134
+ HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
135
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
136
+
137
+ echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
138
+
139
+ if [ "$HTTP_CODE" = "200" ]; then
140
+ echo -e "${GREEN}✓ Request successful${NC}"
141
+ echo ""
142
+ echo -e "${BLUE}Response:${NC}"
143
+ echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
144
+ else
145
+ echo -e "${RED}✗ Request failed${NC}"
146
+ echo ""
147
+ echo -e "${RED}Response:${NC}"
148
+ echo "$RESPONSE_BODY"
149
+ fi
150
+
151
+ echo ""
152
+ echo "----------------------------------------"
153
+ echo ""
154
+ }
155
+
156
+ # ===========================================
157
+ # RAW SQL TESTS
158
+ # ===========================================
159
+
160
+ echo -e "${GREEN}=== RAW SQL TESTS ===${NC}"
161
+ echo ""
162
+
163
+ # Test 1: Check if posts table exists
164
+ test_rawsql \
165
+ "Check Posts Table Existence" \
166
+ '{"query": "SELECT tablename FROM pg_tables WHERE schemaname = '\''public'\'' AND tablename = '\''posts'\'';"}' \
167
+ "Verify that the posts table exists before creating index"
168
+
169
+ # Test 2: Check existing indexes on posts table
170
+ test_rawsql \
171
+ "Check Existing Indexes on Posts" \
172
+ '{"query": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '\''posts'\'';"}' \
173
+ "List all existing indexes on the posts table"
174
+
175
+ # Test 3: Create index on posts.title column
176
+ test_rawsql \
177
+ "Create Title Index on Posts" \
178
+ '{"query": "CREATE INDEX IF NOT EXISTS idx_posts_title ON posts(title);"}' \
179
+ "Create an index on the title column of the posts table for better query performance"
180
+
181
+ # Test 4: Verify the index was created
182
+ test_rawsql \
183
+ "Verify Title Index Creation" \
184
+ '{"query": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '\''posts'\'' AND indexname = '\''idx_posts_title'\'';"}' \
185
+ "Confirm that the title index was successfully created"
186
+
187
+ # Test 5: Test a simple SELECT query
188
+ test_rawsql \
189
+ "Simple Select Query" \
190
+ '{"query": "SELECT COUNT(*) as total_posts FROM posts;"}' \
191
+ "Count total number of posts in the table"
192
+
193
+ echo -e "${GREEN}=== EXPORT TESTS ===${NC}"
194
+ echo ""
195
+
196
+ # Test 6: Export users table in SQL format with data
197
+ test_export \
198
+ "Users Table - SQL with Data" \
199
+ '{"tables": ["users"], "format": "sql", "includeData": true}' \
200
+ "Export users table as SQL with both schema and data"
201
+
202
+ # Test 7: Export users table in SQL format without data (schema only)
203
+ test_export \
204
+ "Users Table - SQL Schema Only" \
205
+ '{"tables": ["users"], "format": "sql", "includeData": false}' \
206
+ "Export users table as SQL with schema only, no data"
207
+
208
+ # Test 8: Export users table in JSON format with data
209
+ test_export \
210
+ "Users Table - JSON with Data" \
211
+ '{"tables": ["users"], "format": "json", "includeData": true}' \
212
+ "Export users table as JSON with both schema and data"
213
+
214
+ # Test 9: Export users table in JSON format without data (schema only)
215
+ test_export \
216
+ "Users Table - JSON Schema Only" \
217
+ '{"tables": ["users"], "format": "json", "includeData": false}' \
218
+ "Export users table as JSON with schema only, no data"
219
+
220
+ # Test 10: Export all tables in SQL format (default behavior)
221
+ test_export \
222
+ "All Tables - SQL Format" \
223
+ '{"format": "sql"}' \
224
+ "Export all tables as SQL with default settings"
225
+
226
+ # Test 11: Test with invalid table name
227
+ test_export \
228
+ "Invalid Table Name" \
229
+ '{"tables": ["nonexistent_table"], "format": "sql"}' \
230
+ "Test error handling with non-existent table"
231
+
232
+ # Test 12: Test with invalid format
233
+ test_export \
234
+ "Invalid Format" \
235
+ '{"tables": ["users"], "format": "xml"}' \
236
+ "Test validation with invalid format"
237
+
238
+ # Test 12.5: Export posts table in SQL format with data
239
+ test_export \
240
+ "All Tables - SQL with Data" \
241
+ '{"format": "sql", "includeData": false}' \
242
+ "Export all tables as SQL with both schema and data"
243
+
244
+ echo -e "${GREEN}=== IMPORT TESTS ===${NC}"
245
+ echo ""
246
+
247
+ # Define the path to the SQL file
248
+ SQL_FILE_PATH="$(dirname "$0")/test-users.sql"
249
+
250
+ # Test 13: Import users.sql without truncate
251
+ test_import \
252
+ "Import Users SQL - No Truncate" \
253
+ "$SQL_FILE_PATH" \
254
+ "false" \
255
+ "Import users table structure from SQL file without truncating existing data"
256
+
257
+ # Test 14: Import users.sql with truncate
258
+ test_import \
259
+ "Import Users SQL - With Truncate" \
260
+ "$SQL_FILE_PATH" \
261
+ "true" \
262
+ "Import users table structure from SQL file with truncating existing data"
263
+
264
+ # Test 15: Test with non-existent file
265
+ test_import \
266
+ "Import Non-existent File" \
267
+ "$(dirname "$0")/nonexistent.sql" \
268
+ "false" \
269
+ "Test error handling with non-existent SQL file"
270
+
271
+ echo "========================================="
272
+ echo "Database Advance Tests Complete"
273
+ echo "========================================="
274
+ echo ""
275
+ echo -e "${GREEN}All tests have been executed.${NC}"
276
+ echo "Check the responses above to verify all functionality."
277
+ echo ""
278
+ echo "Key things to verify:"
279
+ echo ""
280
+ echo -e "${BLUE}Raw SQL Tests:${NC}"
281
+ echo "- Posts table existence check"
282
+ echo "- Index creation and verification"
283
+ echo "- SQL execution with proper responses"
284
+ echo ""
285
+ echo -e "${BLUE}Export Tests:${NC}"
286
+ echo "- SQL exports should contain CREATE TABLE statements"
287
+ echo "- When includeData=true, INSERT statements should be present"
288
+ echo "- When includeData=false, only schema should be exported"
289
+ echo "- JSON exports should have 'schema' and 'rows' properties"
290
+ echo "- Invalid requests should return appropriate error messages"
291
+ echo ""
292
+ echo -e "${BLUE}Import Tests:${NC}"
293
+ echo "- File uploads should be processed correctly"
294
+ echo "- SQL files should be executed and tables created"
295
+ echo "- Truncate option should control data preservation"
296
+ echo "- Error handling should work for missing files"
297
297
  echo "- Response should include import statistics"