@dooer/dooer-test-env 1.0.1 → 1.0.3

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/lib/account.js CHANGED
@@ -78,10 +78,12 @@ async function createAccount({ local, name, ownerUserId, execute = false } = {})
78
78
 
79
79
  await client.query('BEGIN')
80
80
  await client.query(
81
+ // Populate a placeholder address: some org endpoints serialize organization.address as a required
82
+ // OBJECT and return null (schema violation, seen in sumify) when all address columns are empty.
81
83
  `INSERT INTO service_accounts.companies
82
84
  (companies_pk, fk_countries_pk, fk_company_types_pk, company_name, short_name, organization_number,
83
- api_uuid, language, "timeZone", currency, inserted_at, updated_at)
84
- VALUES ($1,'SE','AB',$2,$3,$4,$5,'sv','Europe/Stockholm','SEK',now(),now())`,
85
+ api_uuid, language, "timeZone", currency, address, postal_code, city, inserted_at, updated_at)
86
+ VALUES ($1,'SE','AB',$2,$3,$4,$5,'sv','Europe/Stockholm','SEK','Testgatan 1','11111','Stockholm',now(),now())`,
85
87
  [orgId, name, shortName, orgNumber(), uuid()]
86
88
  )
87
89
  await client.query(
@@ -275,9 +275,44 @@ function frontendPort(name, index) {
275
275
  return name === 'frontend-hq' ? HQ_HOST_PORT : 8081 + index
276
276
  }
277
277
 
278
+ // {frontend name → published host port}, deterministic over the sorted frontend list.
279
+ function frontendPortMap(frontends) {
280
+ const map = {}
281
+ ;(frontends || []).forEach((fe, i) => {
282
+ map[fe.name] = frontendPort(fe.name, i)
283
+ })
284
+ return map
285
+ }
286
+
287
+ // Cross-frontend base-URL env vars → the frontend that serves them. These are browser-facing links (e.g. HQ's
288
+ // "open frontend-sumify-neue" button), so each must point at that frontend's OWN localhost port — NOT the
289
+ // current app's port. Keyed by env-var NAME (robust: DOOER_XRAYS_BASE_URL's staging value is xray.s-e032.com
290
+ // while the route host is xrays.s-e032.com, so hostname matching would miss it).
291
+ const FRONTEND_URL_ENV = {
292
+ DOOER_PUBLIC_FRONTEND_BASE_URL: 'frontend-sumify-neue', // go.dooer.com
293
+ DOOER_SUMIFY_HOST: 'frontend-sumify-neue',
294
+ DOOER_PUBLIC_WEBSITE_BASE_URL: 'frontend-website',
295
+ DOOER_TASKS_BASE_URL: 'frontend-tasks',
296
+ DOOER_XRAYS_BASE_URL: 'frontend-xrays',
297
+ DOOER_BACKOFFICE_BASE_URL: 'frontend-back-office-neue',
298
+ DOOER_AI_DATA_STUDIO_BASE_URL: 'frontend-ai-data-studio',
299
+ }
300
+
301
+ // Repoint every browser-facing URL in `env` at the local ports: the GraphQL facade → gateway, and each
302
+ // cross-frontend base URL → its frontend's own host port. Only rewrites keys already present (from the
303
+ // manifest) whose target frontend has a known port. Applied to services AND frontends.
304
+ function rewriteBrowserUrls(env, portMap) {
305
+ if ('DOOER_PUBLIC_FACADE_HOST' in env) env.DOOER_PUBLIC_FACADE_HOST = `http://localhost:${GATEWAY_HOST_PORT}`
306
+ for (const [key, frontendName] of Object.entries(FRONTEND_URL_ENV)) {
307
+ if (key in env && portMap[frontendName]) env[key] = `http://localhost:${portMap[frontendName]}`
308
+ }
309
+ return env
310
+ }
311
+
278
312
  // Turn the parsed manifests into the compose object.
279
313
  function buildCompose(services, frontends, { profile } = {}) {
280
314
  const wantedSvc = profile ? services.filter((s) => profilesFor(s.name).includes(profile)) : services
315
+ const portMap = frontendPortMap(frontends)
281
316
 
282
317
  const composeServices = infraServices()
283
318
  wantedSvc.forEach((svc) => {
@@ -289,7 +324,7 @@ function buildCompose(services, frontends, { profile } = {}) {
289
324
  // Fall back to ./CMD-OPF.sh when a manifest sets none, so we never hit the image default ./CMD.sh
290
325
  // (Consul path) which hangs on consul-template.
291
326
  command: svc.command || ['./CMD-OPF.sh'],
292
- environment: { ...buildServiceEnv(svc), ...(SERVICE_ENV_OVERRIDES[svc.name] || {}) },
327
+ environment: rewriteBrowserUrls({ ...buildServiceEnv(svc), ...(SERVICE_ENV_OVERRIDES[svc.name] || {}) }, portMap),
293
328
  // publish the GraphQL gateway on the host so the frontends' browsers can reach it at localhost
294
329
  ...(svc.name === 'service-graphql' ? { ports: [`${GATEWAY_HOST_PORT}:3000`] } : {}),
295
330
  depends_on: ['postgres', 'redis', 'discovery-router'],
@@ -301,16 +336,19 @@ function buildCompose(services, frontends, { profile } = {}) {
301
336
  // frontends: served (SSR/static) on :3000, published to a host port. The BROWSER loads them from
302
337
  // localhost and calls the GraphQL facade — repointed to the local gateway. Cross-frontend base URLs are
303
338
  // repointed to each frontend's own localhost port where we run it (others stay as-is).
304
- ;(frontends || []).forEach((fe, i) => {
305
- const hostPort = frontendPort(fe.name, i)
339
+ ;(frontends || []).forEach((fe) => {
340
+ const hostPort = portMap[fe.name]
306
341
  const env = buildServiceEnv(fe)
307
- env.DOOER_PUBLIC_FACADE_HOST = `http://localhost:${GATEWAY_HOST_PORT}`
308
342
  // dooer-frontend's config validation rejects an EMPTY sentryEndpoint for the `local` environment
309
343
  // ("No value specified for [sentryEndpoint] ... (ENV: 'DOOER_SENTRY_ENDPOINT')"), even though staging
310
344
  // ships it as "". We don't use Sentry (Jimmy 2026-09-01) — inject a well-formed but inert DSN so the
311
345
  // client SDK initialises and any error POST just fails silently against the loopback host.
312
346
  env.DOOER_SENTRY_ENDPOINT = 'https://local@localhost/0'
313
- if (env.DOOER_PUBLIC_FRONTEND_BASE_URL) env.DOOER_PUBLIC_FRONTEND_BASE_URL = `http://localhost:${hostPort}`
347
+ // Repoint the facade + every cross-frontend link at the right local ports. Each base URL points at the
348
+ // frontend that SERVES it (e.g. DOOER_PUBLIC_FRONTEND_BASE_URL → frontend-sumify-neue's port), never at
349
+ // this app's own port — that was the bug that sent HQ's "open go.dooer.com" button to localhost:8080.
350
+ if (!('DOOER_PUBLIC_FACADE_HOST' in env)) env.DOOER_PUBLIC_FACADE_HOST = `http://localhost:${GATEWAY_HOST_PORT}`
351
+ rewriteBrowserUrls(env, portMap)
314
352
  composeServices[fe.name] = {
315
353
  image: fe.image,
316
354
  platform: 'linux/amd64',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dooer/dooer-test-env",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Run the whole Dooer backend locally (staging DB minus customers), copy/purge customers between environments, and shred — one CLI.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": "Dooer/cli-dooer-test-env",