@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.
- package/.turbo/turbo-build.log +1 -2
- package/build.mjs +6 -29
- package/dist/agentic/guides/module-facts.json +53 -53
- package/dist/agentic/guides/modules/ai_assistant.md +1 -1
- package/dist/agentic/guides/modules/api_docs.md +1 -1
- package/dist/agentic/guides/modules/api_keys.md +1 -1
- package/dist/agentic/guides/modules/attachments.md +1 -1
- package/dist/agentic/guides/modules/audit_logs.md +1 -1
- package/dist/agentic/guides/modules/auth.md +1 -1
- package/dist/agentic/guides/modules/business_rules.md +1 -1
- package/dist/agentic/guides/modules/catalog.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail.md +1 -1
- package/dist/agentic/guides/modules/channel_imap.md +1 -1
- package/dist/agentic/guides/modules/checkout.md +1 -1
- package/dist/agentic/guides/modules/communication_channels.md +1 -1
- package/dist/agentic/guides/modules/configs.md +1 -1
- package/dist/agentic/guides/modules/content.md +1 -1
- package/dist/agentic/guides/modules/currencies.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts.md +1 -1
- package/dist/agentic/guides/modules/customers.md +1 -1
- package/dist/agentic/guides/modules/dashboards.md +1 -1
- package/dist/agentic/guides/modules/data_sync.md +1 -1
- package/dist/agentic/guides/modules/dictionaries.md +1 -1
- package/dist/agentic/guides/modules/directory.md +1 -1
- package/dist/agentic/guides/modules/entities.md +1 -1
- package/dist/agentic/guides/modules/events.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
- package/dist/agentic/guides/modules/generators.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops.md +1 -1
- package/dist/agentic/guides/modules/integrations.md +1 -1
- package/dist/agentic/guides/modules/messages.md +1 -1
- package/dist/agentic/guides/modules/notifications.md +1 -1
- package/dist/agentic/guides/modules/onboarding.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways.md +1 -1
- package/dist/agentic/guides/modules/perspectives.md +1 -1
- package/dist/agentic/guides/modules/planner.md +1 -1
- package/dist/agentic/guides/modules/portal.md +1 -1
- package/dist/agentic/guides/modules/progress.md +1 -1
- package/dist/agentic/guides/modules/query_index.md +1 -1
- package/dist/agentic/guides/modules/record_locks.md +1 -1
- package/dist/agentic/guides/modules/resources.md +1 -1
- package/dist/agentic/guides/modules/sales.md +1 -1
- package/dist/agentic/guides/modules/scheduler.md +1 -1
- package/dist/agentic/guides/modules/search.md +1 -1
- package/dist/agentic/guides/modules/security.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
- package/dist/agentic/guides/modules/sso.md +1 -1
- package/dist/agentic/guides/modules/staff.md +1 -1
- package/dist/agentic/guides/modules/storage_s3.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
- package/dist/agentic/guides/modules/sync_excel.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
- package/dist/agentic/guides/modules/translations.md +1 -1
- package/dist/agentic/guides/modules/webhooks.md +1 -1
- package/dist/agentic/guides/modules/workflows.md +1 -1
- package/dist/agentic/shared/AGENTS.md.template +3 -2
- package/dist/agentic/shared/ai/skills/om-prepare-test-env/SKILL.md +29 -3
- package/dist/lib/__integration__/TC-INT-008.spec.js +0 -7
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/db/commands.js +2 -1
- package/dist/lib/db/commands.js.map +2 -2
- package/dist/lib/db/identifiers.js +7 -0
- package/dist/lib/db/identifiers.js.map +7 -0
- package/dist/lib/generators/module-facts.js +1 -13
- package/dist/lib/generators/module-facts.js.map +2 -2
- package/dist/mercato.js +2 -1
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/lib/__integration__/TC-INT-008.spec.ts +3 -10
- package/src/lib/db/__tests__/commands.test.ts +51 -0
- package/src/lib/db/commands.ts +2 -1
- package/src/lib/db/identifiers.ts +3 -0
- package/src/lib/generators/__tests__/example-public-route-safety.test.ts +16 -0
- package/src/lib/generators/module-facts.ts +2 -22
- package/src/mercato.ts +2 -1
- package/dist/agentic/guides/core.auth.md +0 -3
- package/dist/agentic/guides/core.catalog.md +0 -3
- package/dist/agentic/guides/core.currencies.md +0 -3
- package/dist/agentic/guides/core.customer_accounts.md +0 -3
- package/dist/agentic/guides/core.customers.md +0 -3
- package/dist/agentic/guides/core.data_sync.md +0 -3
- package/dist/agentic/guides/core.integrations.md +0 -3
- package/dist/agentic/guides/core.sales.md +0 -3
- 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.
|
|
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.
|
|
64
|
-
"@open-mercato/shared": "0.6.6-develop.
|
|
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.
|
|
74
|
+
"@open-mercato/shared": "0.6.6-develop.6505.1.6f6b83559f"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@open-mercato/shared": "0.6.6-develop.
|
|
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
|
|
217
|
-
// fixture's enabled modules
|
|
218
|
-
//
|
|
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', () => {
|
package/src/lib/db/commands.ts
CHANGED
|
@@ -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
|
|
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,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
|
|
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 ??
|
|
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
|
|
917
|
+
await client.query(`DROP TABLE IF EXISTS ${quotePostgresIdentifier(t)} CASCADE`)
|
|
917
918
|
dropped += 1
|
|
918
919
|
}
|
|
919
920
|
await client.query('COMMIT')
|