@open-mercato/cli 0.6.6-develop.6493.1.333455a884 → 0.6.6-develop.6505.1.6f6b83559f

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 (85) hide show
  1. package/.turbo/turbo-build.log +1 -2
  2. package/build.mjs +6 -29
  3. package/dist/agentic/guides/module-facts.json +53 -53
  4. package/dist/agentic/guides/modules/ai_assistant.md +1 -1
  5. package/dist/agentic/guides/modules/api_docs.md +1 -1
  6. package/dist/agentic/guides/modules/api_keys.md +1 -1
  7. package/dist/agentic/guides/modules/attachments.md +1 -1
  8. package/dist/agentic/guides/modules/audit_logs.md +1 -1
  9. package/dist/agentic/guides/modules/auth.md +1 -1
  10. package/dist/agentic/guides/modules/business_rules.md +1 -1
  11. package/dist/agentic/guides/modules/catalog.md +1 -1
  12. package/dist/agentic/guides/modules/channel_gmail.md +1 -1
  13. package/dist/agentic/guides/modules/channel_imap.md +1 -1
  14. package/dist/agentic/guides/modules/checkout.md +1 -1
  15. package/dist/agentic/guides/modules/communication_channels.md +1 -1
  16. package/dist/agentic/guides/modules/configs.md +1 -1
  17. package/dist/agentic/guides/modules/content.md +1 -1
  18. package/dist/agentic/guides/modules/currencies.md +1 -1
  19. package/dist/agentic/guides/modules/customer_accounts.md +1 -1
  20. package/dist/agentic/guides/modules/customers.md +1 -1
  21. package/dist/agentic/guides/modules/dashboards.md +1 -1
  22. package/dist/agentic/guides/modules/data_sync.md +1 -1
  23. package/dist/agentic/guides/modules/dictionaries.md +1 -1
  24. package/dist/agentic/guides/modules/directory.md +1 -1
  25. package/dist/agentic/guides/modules/entities.md +1 -1
  26. package/dist/agentic/guides/modules/events.md +1 -1
  27. package/dist/agentic/guides/modules/feature_toggles.md +1 -1
  28. package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
  29. package/dist/agentic/guides/modules/generators.md +1 -1
  30. package/dist/agentic/guides/modules/inbox_ops.md +1 -1
  31. package/dist/agentic/guides/modules/integrations.md +1 -1
  32. package/dist/agentic/guides/modules/messages.md +1 -1
  33. package/dist/agentic/guides/modules/notifications.md +1 -1
  34. package/dist/agentic/guides/modules/onboarding.md +1 -1
  35. package/dist/agentic/guides/modules/payment_gateways.md +1 -1
  36. package/dist/agentic/guides/modules/perspectives.md +1 -1
  37. package/dist/agentic/guides/modules/planner.md +1 -1
  38. package/dist/agentic/guides/modules/portal.md +1 -1
  39. package/dist/agentic/guides/modules/progress.md +1 -1
  40. package/dist/agentic/guides/modules/query_index.md +1 -1
  41. package/dist/agentic/guides/modules/record_locks.md +1 -1
  42. package/dist/agentic/guides/modules/resources.md +1 -1
  43. package/dist/agentic/guides/modules/sales.md +1 -1
  44. package/dist/agentic/guides/modules/scheduler.md +1 -1
  45. package/dist/agentic/guides/modules/search.md +1 -1
  46. package/dist/agentic/guides/modules/security.md +1 -1
  47. package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
  48. package/dist/agentic/guides/modules/sso.md +1 -1
  49. package/dist/agentic/guides/modules/staff.md +1 -1
  50. package/dist/agentic/guides/modules/storage_s3.md +1 -1
  51. package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
  52. package/dist/agentic/guides/modules/sync_excel.md +1 -1
  53. package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
  54. package/dist/agentic/guides/modules/translations.md +1 -1
  55. package/dist/agentic/guides/modules/webhooks.md +1 -1
  56. package/dist/agentic/guides/modules/workflows.md +1 -1
  57. package/dist/agentic/shared/AGENTS.md.template +3 -2
  58. package/dist/agentic/shared/ai/skills/om-prepare-test-env/SKILL.md +29 -3
  59. package/dist/lib/__integration__/TC-INT-008.spec.js +0 -7
  60. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  61. package/dist/lib/db/commands.js +2 -1
  62. package/dist/lib/db/commands.js.map +2 -2
  63. package/dist/lib/db/identifiers.js +7 -0
  64. package/dist/lib/db/identifiers.js.map +7 -0
  65. package/dist/lib/generators/module-facts.js +1 -13
  66. package/dist/lib/generators/module-facts.js.map +2 -2
  67. package/dist/mercato.js +2 -1
  68. package/dist/mercato.js.map +2 -2
  69. package/package.json +5 -5
  70. package/src/lib/__integration__/TC-INT-008.spec.ts +3 -10
  71. package/src/lib/db/__tests__/commands.test.ts +51 -0
  72. package/src/lib/db/commands.ts +2 -1
  73. package/src/lib/db/identifiers.ts +3 -0
  74. package/src/lib/generators/__tests__/example-public-route-safety.test.ts +16 -0
  75. package/src/lib/generators/module-facts.ts +2 -22
  76. package/src/mercato.ts +2 -1
  77. package/dist/agentic/guides/core.auth.md +0 -3
  78. package/dist/agentic/guides/core.catalog.md +0 -3
  79. package/dist/agentic/guides/core.currencies.md +0 -3
  80. package/dist/agentic/guides/core.customer_accounts.md +0 -3
  81. package/dist/agentic/guides/core.customers.md +0 -3
  82. package/dist/agentic/guides/core.data_sync.md +0 -3
  83. package/dist/agentic/guides/core.integrations.md +0 -3
  84. package/dist/agentic/guides/core.sales.md +0 -3
  85. package/dist/agentic/guides/core.workflows.md +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/cli",
3
- "version": "0.6.6-develop.6493.1.333455a884",
3
+ "version": "0.6.6-develop.6505.1.6f6b83559f",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,8 +60,8 @@
60
60
  "@mikro-orm/decorators": "^7.1.5",
61
61
  "@mikro-orm/migrations": "^7.1.5",
62
62
  "@mikro-orm/postgresql": "^7.1.5",
63
- "@open-mercato/queue": "0.6.6-develop.6493.1.333455a884",
64
- "@open-mercato/shared": "0.6.6-develop.6493.1.333455a884",
63
+ "@open-mercato/queue": "0.6.6-develop.6505.1.6f6b83559f",
64
+ "@open-mercato/shared": "0.6.6-develop.6505.1.6f6b83559f",
65
65
  "cross-spawn": "^7.0.6",
66
66
  "pg": "8.22.0",
67
67
  "semver": "^7.8.5",
@@ -71,10 +71,10 @@
71
71
  "typescript": "^6.0.3"
72
72
  },
73
73
  "peerDependencies": {
74
- "@open-mercato/shared": "0.6.6-develop.6493.1.333455a884"
74
+ "@open-mercato/shared": "0.6.6-develop.6505.1.6f6b83559f"
75
75
  },
76
76
  "devDependencies": {
77
- "@open-mercato/shared": "0.6.6-develop.6493.1.333455a884",
77
+ "@open-mercato/shared": "0.6.6-develop.6505.1.6f6b83559f",
78
78
  "@types/jest": "^30.0.0",
79
79
  "jest": "^30.4.2",
80
80
  "ts-jest": "^29.4.11"
@@ -4,7 +4,6 @@ import fs from 'node:fs'
4
4
  import os from 'node:os'
5
5
  import path from 'node:path'
6
6
  import { fileURLToPath } from 'node:url'
7
- import { MODULE_FACTS_ALLOWLIST } from '../generators/module-facts'
8
7
 
9
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
10
9
  const repoRoot = path.resolve(__dirname, '..', '..', '..', '..', '..')
@@ -213,19 +212,13 @@ function expectedGuideOutputNames(): string[] {
213
212
  }
214
213
 
215
214
  // Generated fact-sheet artifacts (spec 2026-06-27-ts-morph-module-fact-sheets):
216
- // the module-facts.json sidecar is copied as-is, fact-sheets are filtered to the
217
- // fixture's enabled modules, and every allowlisted module whose hand-written
218
- // core.<module>.md guide no longer exists gets a legacy redirect stub.
215
+ // the module-facts.json sidecar is copied as-is and fact-sheets are filtered to the
216
+ // fixture's enabled modules. The legacy core.<module>.md redirect stubs are no longer
217
+ // emitted (#3754).
219
218
  collected.add('module-facts.json')
220
219
  for (const moduleId of FIXTURE_ENABLED_MODULES) {
221
220
  collected.add(normalizePath(path.join('modules', `${moduleId}.md`)))
222
221
  }
223
- for (const moduleId of MODULE_FACTS_ALLOWLIST) {
224
- const legacyGuideSource = path.join(packagesRoot, 'core', 'src', 'modules', moduleId, 'agentic', 'standalone-guide.md')
225
- if (!fs.existsSync(legacyGuideSource)) {
226
- collected.add(`core.${moduleId}.md`)
227
- }
228
- }
229
222
 
230
223
  return Array.from(collected).sort()
231
224
  }
@@ -228,6 +228,57 @@ describe('db commands', () => {
228
228
  mockConsoleError.mockRestore()
229
229
  mockExit.mockRestore()
230
230
  })
231
+
232
+ it('quotes discovered table names as single PostgreSQL identifiers', async () => {
233
+ const dangerousTableName = 'orders"; SELECT pg_sleep(10); --'
234
+ const migrationQuery = jest.fn().mockResolvedValue({ rows: [] })
235
+ const discoveredTableQuery = jest.fn().mockImplementation(async (sql: string) => {
236
+ if (sql.includes('FROM pg_tables')) {
237
+ return { rows: [{ tablename: dangerousTableName }] }
238
+ }
239
+ return { rows: [] }
240
+ })
241
+
242
+ const Client = jest
243
+ .fn()
244
+ .mockImplementationOnce(() => ({
245
+ connect: jest.fn().mockResolvedValue(undefined),
246
+ query: migrationQuery,
247
+ end: jest.fn().mockResolvedValue(undefined),
248
+ }))
249
+ .mockImplementationOnce(() => ({
250
+ connect: jest.fn().mockResolvedValue(undefined),
251
+ query: discoveredTableQuery,
252
+ end: jest.fn().mockResolvedValue(undefined),
253
+ }))
254
+ jest.doMock('pg', () => ({ Client }))
255
+
256
+ const originalDatabaseUrl = process.env.DATABASE_URL
257
+ process.env.DATABASE_URL = 'postgres://postgres:secret@127.0.0.1:5432/open_mercato'
258
+ const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation()
259
+ const resolver = {
260
+ loadEnabledModules: () => [],
261
+ getOutputDir: () => '/definitely/missing/generated',
262
+ getRootDir: () => '/definitely/missing',
263
+ getModulePaths: () => ({ appBase: '', pkgBase: '' }),
264
+ } as any
265
+
266
+ try {
267
+ await dbGreenfield(resolver, { yes: true })
268
+ } finally {
269
+ if (originalDatabaseUrl === undefined) {
270
+ delete process.env.DATABASE_URL
271
+ } else {
272
+ process.env.DATABASE_URL = originalDatabaseUrl
273
+ }
274
+ consoleLogSpy.mockRestore()
275
+ jest.dontMock('pg')
276
+ }
277
+
278
+ expect(discoveredTableQuery).toHaveBeenCalledWith(
279
+ 'DROP TABLE IF EXISTS "orders""; SELECT pg_sleep(10); --" CASCADE',
280
+ )
281
+ })
231
282
  })
232
283
 
233
284
  describe('integration with sanitization', () => {
@@ -8,6 +8,7 @@ import { Migrator } from '@mikro-orm/migrations'
8
8
  import { PostgreSqlDriver } from '@mikro-orm/postgresql'
9
9
  import { getSslConfig } from '@open-mercato/shared/lib/db/ssl'
10
10
  import type { PackageResolver, ModuleEntry } from '../resolver'
11
+ import { quotePostgresIdentifier } from './identifiers'
11
12
 
12
13
  const QUIET_MODE = process.env.OM_CLI_QUIET === '1' || process.env.MERCATO_QUIET === '1'
13
14
  const PROGRESS_EMOJI = ''
@@ -528,7 +529,7 @@ export async function dbGreenfield(resolver: PackageResolver, options: Greenfiel
528
529
  try {
529
530
  await client.query("SET session_replication_role = 'replica'")
530
531
  for (const t of tables) {
531
- await client.query(`DROP TABLE IF EXISTS "${t}" CASCADE`)
532
+ await client.query(`DROP TABLE IF EXISTS ${quotePostgresIdentifier(t)} CASCADE`)
532
533
  }
533
534
  await client.query("SET session_replication_role = 'origin'")
534
535
  await client.query('COMMIT')
@@ -0,0 +1,3 @@
1
+ export function quotePostgresIdentifier(identifier: string): string {
2
+ return `"${identifier.replace(/"/g, '""')}"`
3
+ }
@@ -0,0 +1,16 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+
4
+ const repoRoot = join(__dirname, '..', '..', '..', '..', '..', '..')
5
+ const probeRoutes = [
6
+ 'apps/mercato/src/modules/example/api/override-probe/route.ts',
7
+ 'packages/create-app/template/src/modules/example/api/override-probe/route.ts',
8
+ ]
9
+
10
+ describe('example public route safety guidance (#3864)', () => {
11
+ it.each(probeRoutes)('%s warns against copying unauthenticated metadata to data-bearing routes', (route) => {
12
+ const source = readFileSync(join(repoRoot, route), 'utf8')
13
+
14
+ expect(source).toContain('Test-only public probe: do not copy `requireAuth: false` to data-bearing routes.')
15
+ })
16
+ })
@@ -75,26 +75,6 @@ export interface ModuleFactSource {
75
75
  from?: string
76
76
  }
77
77
 
78
- /**
79
- * @deprecated Superseded by auto-discovery (`discoverPackageModuleSources` in
80
- * `module-facts-discovery.ts`). Retained as a stable export for one minor; no
81
- * longer gates which modules receive fact-sheets.
82
- */
83
- export const MODULE_FACTS_ALLOWLIST = [
84
- 'auth',
85
- 'catalog',
86
- 'currencies',
87
- 'customer_accounts',
88
- 'customers',
89
- 'data_sync',
90
- 'integrations',
91
- 'sales',
92
- 'workflows',
93
- ] as const
94
-
95
- /** @deprecated See {@link MODULE_FACTS_ALLOWLIST}. */
96
- export type ModuleFactsModuleId = (typeof MODULE_FACTS_ALLOWLIST)[number]
97
-
98
78
  function readSourceFile(filePath: string): ts.SourceFile | null {
99
79
  if (!fs.existsSync(filePath)) return null
100
80
  const source = fs.readFileSync(filePath, 'utf8')
@@ -959,7 +939,7 @@ export interface ExtractAllModuleFactsOptions {
959
939
  registryPath?: string | null
960
940
  registrySource?: string | null
961
941
  coreVersion?: string | null
962
- /** @deprecated Legacy allowlist iteration; only consulted when `sources` is absent. */
942
+ /** @deprecated Legacy explicit module-id list; only consulted when `sources` is absent. */
963
943
  moduleIds?: readonly string[]
964
944
  }
965
945
 
@@ -973,7 +953,7 @@ export function extractAllModuleFacts(options: ExtractAllModuleFactsOptions): Ex
973
953
  const sources: ModuleFactSource[] = options.sources
974
954
  ? [...options.sources]
975
955
  : (options.coreSrcRoot
976
- ? (options.moduleIds ?? MODULE_FACTS_ALLOWLIST).map((moduleId) => ({
956
+ ? (options.moduleIds ?? []).map((moduleId) => ({
977
957
  moduleId,
978
958
  moduleRoot: path.join(options.coreSrcRoot as string, moduleId),
979
959
  }))
package/src/mercato.ts CHANGED
@@ -42,6 +42,7 @@ import { resolveNextBuildIdCandidate } from './lib/next-build-id'
42
42
  import { acquireServerStartLock } from './lib/server-start-lock'
43
43
  import { assertSingleInstanceStrategies } from './lib/single-instance-strategy-guard'
44
44
  import { createDevEnvReloader, watchDevEnvFiles } from './lib/dev-env-reload'
45
+ import { quotePostgresIdentifier } from './lib/db/identifiers'
45
46
  // Lazy-imported to avoid pulling in `testcontainers` (devDependency) at startup
46
47
  const lazyIntegration = () => import('./lib/testing/integration')
47
48
  import type { ChildProcess } from 'node:child_process'
@@ -913,7 +914,7 @@ export async function run(argv = process.argv) {
913
914
  await client.query('BEGIN')
914
915
  try {
915
916
  for (const t of dropTargets) {
916
- await client.query(`DROP TABLE IF EXISTS "${t}" CASCADE`)
917
+ await client.query(`DROP TABLE IF EXISTS ${quotePostgresIdentifier(t)} CASCADE`)
917
918
  dropped += 1
918
919
  }
919
920
  await client.query('COMMIT')
@@ -1,3 +0,0 @@
1
- # core.auth — moved
2
-
3
- > This guide has moved. See [`modules/auth.md`](modules/auth.md) for the generated `auth` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.catalog — moved
2
-
3
- > This guide has moved. See [`modules/catalog.md`](modules/catalog.md) for the generated `catalog` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.currencies — moved
2
-
3
- > This guide has moved. See [`modules/currencies.md`](modules/currencies.md) for the generated `currencies` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.customer_accounts — moved
2
-
3
- > This guide has moved. See [`modules/customer_accounts.md`](modules/customer_accounts.md) for the generated `customer_accounts` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.customers — moved
2
-
3
- > This guide has moved. See [`modules/customers.md`](modules/customers.md) for the generated `customers` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.data_sync — moved
2
-
3
- > This guide has moved. See [`modules/data_sync.md`](modules/data_sync.md) for the generated `data_sync` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.integrations — moved
2
-
3
- > This guide has moved. See [`modules/integrations.md`](modules/integrations.md) for the generated `integrations` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.sales — moved
2
-
3
- > This guide has moved. See [`modules/sales.md`](modules/sales.md) for the generated `sales` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.
@@ -1,3 +0,0 @@
1
- # core.workflows — moved
2
-
3
- > This guide has moved. See [`modules/workflows.md`](modules/workflows.md) for the generated `workflows` fact-sheet, and [`module-system.md`](module-system.md) for conceptual module guidance.