@open-mercato/cli 0.6.6-develop.6431.1.g1037269810 → 0.6.6-develop.6451.1.5b071f47fc

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/cli",
3
- "version": "0.6.6-develop.6431.1.g1037269810",
3
+ "version": "0.6.6-develop.6451.1.5b071f47fc",
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.6431.1.g1037269810",
64
- "@open-mercato/shared": "0.6.6-develop.6431.1.g1037269810",
63
+ "@open-mercato/queue": "0.6.6-develop.6451.1.5b071f47fc",
64
+ "@open-mercato/shared": "0.6.6-develop.6451.1.5b071f47fc",
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.6431.1.g1037269810"
74
+ "@open-mercato/shared": "0.6.6-develop.6451.1.5b071f47fc"
75
75
  },
76
76
  "devDependencies": {
77
- "@open-mercato/shared": "0.6.6-develop.6431.1.g1037269810",
77
+ "@open-mercato/shared": "0.6.6-develop.6451.1.5b071f47fc",
78
78
  "@types/jest": "^30.0.0",
79
79
  "jest": "^30.4.2",
80
80
  "ts-jest": "^29.4.11"
@@ -27,8 +27,11 @@ import type { ChildProcess } from 'node:child_process'
27
27
  const CACHE_TTL_ENV_VAR = 'OM_INTEGRATION_BUILD_CACHE_TTL_SECONDS'
28
28
  const APP_READY_TIMEOUT_ENV_VAR = 'OM_INTEGRATION_APP_READY_TIMEOUT_SECONDS'
29
29
  const CHECKOUT_TEST_INJECTION_FLAG = 'NEXT_PUBLIC_OM_EXAMPLE_CHECKOUT_TEST_INJECTIONS_ENABLED'
30
+ const PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY = 'ATTACHMENTS_PARTITION_PRIVATE_ATTACHMENTS_ROOT'
30
31
  const resolver = createResolver()
31
32
  const projectRootDirectory = resolver.getRootDir()
33
+ const appDirectory = path.join(projectRootDirectory, 'apps', 'mercato')
34
+ const defaultPrivateAttachmentsRoot = path.join(appDirectory, 'storage', 'attachments', 'privateAttachments')
32
35
 
33
36
  const mockHealthyReadinessFetch = (
34
37
  overrides: {
@@ -169,6 +172,7 @@ describe('integration cache and options', () => {
169
172
  'postgres://integration:integration@127.0.0.1:5432/open_mercato',
170
173
  )
171
174
  expect(environment?.commandEnvironment.QUEUE_BASE_DIR).toBe('/tmp/open-mercato-queue')
175
+ expect(environment?.commandEnvironment[PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY]).toBe(defaultPrivateAttachmentsRoot)
172
176
  expect(environment?.commandEnvironment.PW_CAPTURE_SCREENSHOTS).toBe('1')
173
177
  expect(environment?.commandEnvironment.NEXT_PUBLIC_OM_EXAMPLE_CHECKOUT_TEST_INJECTIONS_ENABLED).toBeUndefined()
174
178
  } finally {
@@ -206,6 +210,43 @@ describe('integration cache and options', () => {
206
210
  }
207
211
  }, REUSE_ENV_TEST_TIMEOUT_MS)
208
212
 
213
+ it('reuses app-local private attachment storage when queue state points at an app root', async () => {
214
+ const baseUrl = 'http://127.0.0.1:5001'
215
+ const appRoot = await mkdtemp(path.join(os.tmpdir(), 'om-integration-app-root-'))
216
+ const queueBaseDir = path.join(appRoot, '.mercato', 'queue')
217
+ const fetchSpy = mockHealthyReadinessFetch()
218
+
219
+ try {
220
+ await mkdir(path.join(appRoot, 'src'), { recursive: true })
221
+ await writeFile(path.join(appRoot, 'package.json'), '{"name":"integration-test-app"}\n', 'utf8')
222
+ await writeFile(path.join(appRoot, 'src', 'modules.ts'), 'export const enabledModules = []\n', 'utf8')
223
+
224
+ await writeEphemeralEnvironmentState({
225
+ baseUrl,
226
+ port: 5001,
227
+ databaseUrl: 'postgres://integration:integration@127.0.0.1:5432/open_mercato',
228
+ queueBaseDir,
229
+ logPrefix: 'integration',
230
+ captureScreenshots: false,
231
+ })
232
+
233
+ const environment = await tryReuseExistingEnvironment({
234
+ verbose: false,
235
+ captureScreenshots: false,
236
+ logPrefix: 'integration',
237
+ forceRebuild: false,
238
+ })
239
+
240
+ expect(environment).not.toBeNull()
241
+ expect(environment?.commandEnvironment[PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY]).toBe(
242
+ path.join(appRoot, 'storage', 'attachments', 'privateAttachments'),
243
+ )
244
+ } finally {
245
+ fetchSpy.mockRestore()
246
+ await rm(appRoot, { recursive: true, force: true })
247
+ }
248
+ }, REUSE_ENV_TEST_TIMEOUT_MS)
249
+
209
250
  it('reuses an existing environment when /login returns a redirect status other than 302', async () => {
210
251
  const baseUrl = 'http://127.0.0.1:5001'
211
252
  const fetchSpy = mockHealthyReadinessFetch({
@@ -221,6 +221,32 @@ function collectExistingPaths(candidates: Array<string | null | undefined>): str
221
221
  return Array.from(collected)
222
222
  }
223
223
 
224
+ function isLikelyNextAppDirectory(candidate: string): boolean {
225
+ if (!existsSync(path.join(candidate, 'package.json'))) {
226
+ return false
227
+ }
228
+ return resolveFirstExistingPath(
229
+ path.join(candidate, 'next.config.ts'),
230
+ path.join(candidate, 'next.config.js'),
231
+ path.join(candidate, 'next.config.mjs'),
232
+ path.join(candidate, 'src', 'modules.ts'),
233
+ ) !== null
234
+ }
235
+
236
+ function resolveDefaultPrivateAttachmentsAppDirectory(): string {
237
+ const candidates = [
238
+ appDirectory,
239
+ path.join(projectRootDirectory, 'apps', 'mercato'),
240
+ path.join(projectRootDirectory, 'apps', 'app'),
241
+ ]
242
+ for (const candidate of candidates) {
243
+ if (isLikelyNextAppDirectory(candidate)) {
244
+ return candidate
245
+ }
246
+ }
247
+ return appDirectory
248
+ }
249
+
224
250
  function readPackageScripts(packageRoot: string): Record<string, string> {
225
251
  try {
226
252
  const raw = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8')) as {
@@ -246,6 +272,13 @@ const LEGACY_EPHEMERAL_ENV_FILE_PATH = path.join(projectRootDirectory, '.ai', 'q
246
272
  const EPHEMERAL_BUILD_CACHE_STATE_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'ephemeral-build-cache.json')
247
273
  const EPHEMERAL_CACHE_DB_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'ephemeral-cache.sqlite')
248
274
  const EPHEMERAL_QUEUE_BASE_DIR = path.join(appDirectory, '.mercato', 'queue')
275
+ const PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY = 'ATTACHMENTS_PARTITION_PRIVATE_ATTACHMENTS_ROOT'
276
+ const EPHEMERAL_PRIVATE_ATTACHMENTS_ROOT = path.join(
277
+ resolveDefaultPrivateAttachmentsAppDirectory(),
278
+ 'storage',
279
+ 'attachments',
280
+ 'privateAttachments',
281
+ )
249
282
  const PLAYWRIGHT_INTEGRATION_CONFIG_PATH = '.ai/qa/tests/playwright.config.ts'
250
283
  const PLAYWRIGHT_RESULTS_JSON_PATH = path.join(projectRootDirectory, '.ai', 'qa', 'test-results', 'results.json')
251
284
  const LEGACY_INTEGRATION_TEST_ROOT = path.join(projectRootDirectory, '.ai', 'qa', 'tests')
@@ -1677,6 +1710,7 @@ function buildReusableEnvironment(
1677
1710
  captureScreenshots: boolean,
1678
1711
  ): NodeJS.ProcessEnv {
1679
1712
  const enterpriseModulesFlag = process.env.OM_ENABLE_ENTERPRISE_MODULES ?? 'false'
1713
+ const privateAttachmentsRoot = resolvePrivateAttachmentsRootForQueueBaseDir(queueBaseDir)
1680
1714
  return buildEnvironment({
1681
1715
  DATABASE_URL: databaseUrl,
1682
1716
  BASE_URL: baseUrl,
@@ -1721,11 +1755,25 @@ function buildReusableEnvironment(
1721
1755
  OM_CLI_QUIET: '1',
1722
1756
  MERCATO_QUIET: '1',
1723
1757
  QUEUE_BASE_DIR: queueBaseDir,
1758
+ [PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY]:
1759
+ process.env[PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY] ?? privateAttachmentsRoot,
1724
1760
  NODE_NO_WARNINGS: '1',
1725
1761
  PW_CAPTURE_SCREENSHOTS: captureScreenshots ? '1' : '0',
1726
1762
  })
1727
1763
  }
1728
1764
 
1765
+ function resolvePrivateAttachmentsRootForQueueBaseDir(queueBaseDir: string): string {
1766
+ const resolvedQueueBaseDir = path.resolve(queueBaseDir)
1767
+ const queueParent = path.dirname(resolvedQueueBaseDir)
1768
+ if (path.basename(resolvedQueueBaseDir) === 'queue' && path.basename(queueParent) === '.mercato') {
1769
+ const queueAppDirectory = path.dirname(queueParent)
1770
+ if (isLikelyNextAppDirectory(queueAppDirectory)) {
1771
+ return path.join(queueAppDirectory, 'storage', 'attachments', 'privateAttachments')
1772
+ }
1773
+ }
1774
+ return EPHEMERAL_PRIVATE_ATTACHMENTS_ROOT
1775
+ }
1776
+
1729
1777
  export async function tryReuseExistingEnvironment(options: EphemeralRuntimeOptions): Promise<EphemeralEnvironmentHandle | null> {
1730
1778
  const state = await readEphemeralEnvironmentState()
1731
1779
  if (!state) {
@@ -3071,6 +3119,8 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
3071
3119
  OM_CLI_QUIET: '1',
3072
3120
  MERCATO_QUIET: '1',
3073
3121
  QUEUE_BASE_DIR: EPHEMERAL_QUEUE_BASE_DIR,
3122
+ [PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY]:
3123
+ process.env[PRIVATE_ATTACHMENTS_PARTITION_ENV_KEY] ?? EPHEMERAL_PRIVATE_ATTACHMENTS_ROOT,
3074
3124
  NODE_NO_WARNINGS: '1',
3075
3125
  PORT: String(applicationPort),
3076
3126
  PW_CAPTURE_SCREENSHOTS: options.captureScreenshots ? '1' : '0',