@geekmidas/cli 10.0.0-alpha.22 → 10.0.0-alpha.24

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/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { A as stripPublicPrefix, C as InvalidStages, D as stageProblems, E as de
6
6
  import { C as providerOf, S as eventsBackendFor, _ as COMPOSE_PATH, a as loadEnvFiles, b as resourceName, c as resolveServicePorts, d as backendsOf, f as constructGlobs, h as usesConstructs, i as isPortAvailable, l as rewriteUrlsWithPorts, m as reconcileWorkspace, n as createEntryWrapper, o as loadSecretsForApp, p as derivedContainers, r as findAvailablePort, s as prepareEntryCredentials, t as createCredentialsPreload, u as startWorkspaceServices, v as LOCAL_CA_PATH, w as storageBackendFor, x as cacheBackendFor, y as applyPostgres } from "./credentials-D9TKJJZc.mjs";
7
7
  import { a as generateServiceCredentials, i as generateSecurePassword, n as generateConnectionUrls, o as rotateServicePassword, t as createStageSecrets } from "./generator-LfZU7NlU.mjs";
8
8
  import { c as getKeyPath, i as setCustomSecret, n as readStageSecrets, o as toEmbeddableSecrets, r as secretsExist, s as writeStageSecrets, t as maskPassword } from "./storage-TP0x118M.mjs";
9
- import { a as openapiCommand, c as EndpointGenerator, l as runtimeFor, n as generateOpenApi, o as resolveOpenApiConfig, r as generateOpenApiFrom, s as OpenApiTsGenerator, t as OPENAPI_OUTPUT_PATH$1 } from "./openapi-B5PSuLym.mjs";
9
+ import { a as openapiCommand, c as EndpointGenerator, l as runtimeFor, n as generateOpenApi, o as resolveOpenApiConfig, r as generateOpenApiFrom, s as OpenApiTsGenerator, t as OPENAPI_OUTPUT_PATH$1 } from "./openapi-Co2Tv7zh.mjs";
10
10
  import { i as withRoutes, r as withCompute } from "./emit-Bzq7JsMP.mjs";
11
11
  import { i as writeDockerEnvFromSecrets, r as generateFullstackCustomSecrets } from "./reconcile-gb1lz1Dk.mjs";
12
12
  import { a as isRemoteStore, n as pullStageSecrets, r as pushStageSecrets, t as NoStoredSecrets } from "./transfer-Bk5YlRyB.mjs";
@@ -39,7 +39,7 @@ import prompts from "prompts";
39
39
  import { EnvironmentParser } from "@geekmidas/envkit";
40
40
  import { serviceContext } from "@geekmidas/services";
41
41
  //#region package.json
42
- var version = "10.0.0-alpha.22";
42
+ var version = "10.0.0-alpha.24";
43
43
  //#endregion
44
44
  //#region src/auth/credentials.ts
45
45
  /**
@@ -324,6 +324,76 @@ function maskToken(token) {
324
324
  return `${token.slice(0, 4)}...${token.slice(-4)}`;
325
325
  }
326
326
  //#endregion
327
+ //#region src/build/owners.ts
328
+ /**
329
+ * What a generated entry imports its runtime from, read off the discovered
330
+ * constructs: the surface it serves, every construct a runnable can be built
331
+ * from, and the database Studio browses.
332
+ *
333
+ * `gkm build` and `gkm dev` both write entries that import the surface for its
334
+ * logger and environment parser, so both ask here. A dev server that skipped it
335
+ * had nothing to import them from.
336
+ */
337
+ function ownersContext(options) {
338
+ const { declared, sources, workspaceRoot, appRoot, studio } = options;
339
+ const surfaces = restApis(declared);
340
+ const primary = servedSurface(declared, workspaceRoot, appRoot) ?? surfaces.find((d) => d.endpoints.length === 0) ?? surfaces[0];
341
+ const browsable = Object.entries(declared).find(([, d]) => d.kind === "database");
342
+ const browsableSource = browsable ? sources[browsable[0]] : void 0;
343
+ const owners = {};
344
+ for (const [id, declaration] of Object.entries(declared)) {
345
+ if (declaration.kind !== "rest-api" && declaration.kind !== "worker") continue;
346
+ const source = sources[id];
347
+ if (!source) continue;
348
+ owners[id] = {
349
+ specifier: source.file,
350
+ exportName: source.exportName
351
+ };
352
+ }
353
+ const primarySource = primary ? sources[primary.id] : void 0;
354
+ return {
355
+ owners,
356
+ ...primary ? { surface: {
357
+ id: primary.id,
358
+ trustedOriginsKey: provideKey(primary.id, "trustedOrigins"),
359
+ ...primary.cors ? { cors: primary.cors } : {},
360
+ ...primarySource ? { module: {
361
+ specifier: primarySource.file,
362
+ exportName: primarySource.exportName
363
+ } } : {}
364
+ } } : {},
365
+ studio: studio && browsableSource ? {
366
+ ...studio,
367
+ database: {
368
+ specifier: browsableSource.file,
369
+ exportName: browsableSource.exportName
370
+ }
371
+ } : studio
372
+ };
373
+ }
374
+ /**
375
+ * The endpoints one surface serves.
376
+ *
377
+ * One glob finds every surface's endpoints, wherever their files live. A build
378
+ * keeps the ones built from the surface it serves; one built from no surface at
379
+ * all has nowhere else to go.
380
+ */
381
+ function servedBy(endpoints, surface) {
382
+ if (!surface) return endpoints;
383
+ return endpoints.filter(({ construct }) => !construct.surface || construct.surface.id === surface.id);
384
+ }
385
+ function restApis(declared) {
386
+ return Object.values(declared).filter((d) => d.kind === "rest-api");
387
+ }
388
+ /**
389
+ * The surface whose declared `path` is the directory being built — asked of
390
+ * every surface, because a workspace has several and each app's build serves
391
+ * exactly one.
392
+ */
393
+ function servedSurface(declared, workspaceRoot, appRoot) {
394
+ return restApis(declared).find((d) => resolve(workspaceRoot, d.path) === resolve(appRoot));
395
+ }
396
+ //#endregion
327
397
  //#region src/build/providerResolver.ts
328
398
  /**
329
399
  * Resolves provider configuration from the new simplified system
@@ -1360,12 +1430,13 @@ async function devCommand(options) {
1360
1430
  if (hooks) logger$11.log(`🪝 Server hooks enabled from ${config.hooks?.server}`);
1361
1431
  const enableOpenApi = resolveOpenApiConfig(config).enabled || resolved.enableOpenApi;
1362
1432
  if (enableOpenApi) logger$11.log(`📄 OpenAPI output: ${OPENAPI_OUTPUT_PATH$1}`);
1433
+ const workspaceRoot = workspace?.root ?? secretsRoot;
1363
1434
  const buildContext = {
1364
1435
  telescope,
1365
1436
  studio,
1366
1437
  hooks
1367
1438
  };
1368
- await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot);
1439
+ await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot, workspaceRoot);
1369
1440
  if (enableOpenApi) await generateOpenApiFrom(config.constructs, { openapi: config.openapi });
1370
1441
  const runtime = config.runtime ?? "node";
1371
1442
  let secretsJsonPath;
@@ -1430,7 +1501,7 @@ async function devCommand(options) {
1430
1501
  rebuildTimeout = setTimeout(async () => {
1431
1502
  try {
1432
1503
  logger$11.log("🔄 Rebuilding...");
1433
- await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot, true);
1504
+ await buildServer(config, buildContext, resolved.providers[0], enableOpenApi, appRoot, workspaceRoot, true);
1434
1505
  if (enableOpenApi) await generateOpenApiFrom(config.constructs, {
1435
1506
  openapi: config.openapi,
1436
1507
  silent: true,
@@ -1816,24 +1887,34 @@ async function workspaceDevCommand(workspace, options) {
1816
1887
  * guarded rather than unconditional: a project with no `constructs` glob has
1817
1888
  * not adopted the model, and there is nothing to import.
1818
1889
  */
1819
- async function declaredConstructs(config, appRoot) {
1890
+ async function declaredConstructs(config, appRoot, sources) {
1820
1891
  const patterns = typeof config?.constructs === "string" || Array.isArray(config?.constructs) ? config.constructs : void 0;
1821
1892
  if (!patterns) return {};
1822
1893
  try {
1823
1894
  return await discover({
1824
1895
  patterns: (Array.isArray(patterns) ? patterns : [patterns]).map((p) => isAbsolute(p) ? p : join(appRoot, p)),
1825
- cwd: appRoot
1896
+ cwd: appRoot,
1897
+ sources
1826
1898
  });
1827
1899
  } catch {
1828
1900
  return {};
1829
1901
  }
1830
1902
  }
1831
- async function buildServer(config, context, provider, enableOpenApi, appRoot = process.cwd(), bustCache = false) {
1903
+ async function buildServer(config, context, provider, enableOpenApi, appRoot, workspaceRoot, bustCache = false) {
1904
+ const sources = {};
1905
+ const declared = await declaredConstructs(config, appRoot, sources);
1832
1906
  context = {
1833
1907
  ...context,
1908
+ ...ownersContext({
1909
+ declared,
1910
+ sources,
1911
+ workspaceRoot,
1912
+ appRoot,
1913
+ studio: context.studio
1914
+ }),
1834
1915
  storageDrivers: driversFor({
1835
1916
  appRoot,
1836
- cache: cacheBackendsIn(await declaredConstructs(config, appRoot), cacheBackendFor(providerOf(config ?? {})))
1917
+ cache: cacheBackendsIn(declared, cacheBackendFor(providerOf(config ?? {})))
1837
1918
  })
1838
1919
  };
1839
1920
  const endpointGenerator = new EndpointGenerator();
@@ -1842,7 +1923,7 @@ async function buildServer(config, context, provider, enableOpenApi, appRoot = p
1842
1923
  const subscriberGenerator = new SubscriberGenerator();
1843
1924
  const queueGenerator = new QueueGenerator();
1844
1925
  const topicGenerator = new TopicGenerator();
1845
- const [allEndpoints, allFunctions, allCrons, allSubscribers, allQueues, allTopics] = await Promise.all([
1926
+ const [loadedEndpoints, allFunctions, allCrons, allSubscribers, allQueues, allTopics] = await Promise.all([
1846
1927
  endpointGenerator.load(config.constructs, appRoot, bustCache),
1847
1928
  config.functions ? functionGenerator.load(config.functions, appRoot, bustCache) : [],
1848
1929
  config.crons ? cronGenerator.load(config.crons, appRoot, bustCache) : [],
@@ -1850,6 +1931,7 @@ async function buildServer(config, context, provider, enableOpenApi, appRoot = p
1850
1931
  config.queues ? queueGenerator.load(config.queues, appRoot, bustCache) : [],
1851
1932
  config.topics ? topicGenerator.load(config.topics, appRoot, bustCache) : []
1852
1933
  ]);
1934
+ const allEndpoints = servedBy(loadedEndpoints, context.surface);
1853
1935
  const outputDir = join(appRoot, ".gkm", provider);
1854
1936
  await mkdir(outputDir, { recursive: true });
1855
1937
  await Promise.all([
@@ -2481,41 +2563,16 @@ async function buildCommand(options) {
2481
2563
  cwd: process.cwd(),
2482
2564
  sources: constructSources
2483
2565
  }) : {};
2484
- const surfaces = Object.values(declared).filter((d) => d.kind === "rest-api");
2485
- const workspaceRoot = loadedConfig.workspace.root;
2486
- const served = surfaces.find((d) => resolve(workspaceRoot, d.path) === resolve(process.cwd()));
2487
- const primary = served ?? surfaces.find((d) => d.endpoints.length === 0) ?? surfaces[0];
2488
- const browsable = Object.entries(declared).find(([, d]) => d.kind === "database");
2489
- const browsableSource = browsable ? constructSources[browsable[0]] : void 0;
2490
- const owners = {};
2491
- for (const [id, declaration] of Object.entries(declared)) {
2492
- if (declaration.kind !== "rest-api" && declaration.kind !== "worker") continue;
2493
- const source = constructSources[id];
2494
- if (!source) continue;
2495
- owners[id] = {
2496
- specifier: source.file,
2497
- exportName: source.exportName
2498
- };
2499
- }
2566
+ const derived = ownersContext({
2567
+ declared,
2568
+ sources: constructSources,
2569
+ workspaceRoot: loadedConfig.workspace.root,
2570
+ appRoot: process.cwd(),
2571
+ studio
2572
+ });
2500
2573
  const buildContext = {
2501
- owners,
2502
- ...primary ? { surface: {
2503
- id: primary.id,
2504
- trustedOriginsKey: provideKey(primary.id, "trustedOrigins"),
2505
- ...primary.cors ? { cors: primary.cors } : {},
2506
- ...constructSources[primary.id] ? { module: {
2507
- specifier: constructSources[primary.id].file,
2508
- exportName: constructSources[primary.id].exportName
2509
- } } : {}
2510
- } } : {},
2574
+ ...derived,
2511
2575
  telescope,
2512
- studio: studio && browsableSource ? {
2513
- ...studio,
2514
- database: {
2515
- specifier: browsableSource.file,
2516
- exportName: browsableSource.exportName
2517
- }
2518
- } : studio,
2519
2576
  hooks,
2520
2577
  production,
2521
2578
  constructGlobs,
@@ -2542,7 +2599,7 @@ async function buildCommand(options) {
2542
2599
  queueGenerator.load(code),
2543
2600
  topicGenerator.load(code)
2544
2601
  ]);
2545
- const allEndpoints = primary ? loadedEndpoints.filter(({ construct }) => !construct.surface || construct.surface.id === primary.id) : loadedEndpoints;
2602
+ const allEndpoints = servedBy(loadedEndpoints, derived.surface);
2546
2603
  logger$9.log(`Found ${allEndpoints.length} endpoints`);
2547
2604
  logger$9.log(`Found ${allFunctions.length} functions`);
2548
2605
  logger$9.log(`Found ${allCrons.length} crons`);
@@ -2550,6 +2607,7 @@ async function buildCommand(options) {
2550
2607
  logger$9.log(`Found ${allQueues.length} queues`);
2551
2608
  logger$9.log(`Found ${allTopics.length} topics`);
2552
2609
  if (allEndpoints.length === 0 && allFunctions.length === 0 && allCrons.length === 0 && allSubscribers.length === 0 && allQueues.length === 0 && allTopics.length === 0) {
2610
+ const served = servedSurface(declared, loadedConfig.workspace.root, process.cwd());
2553
2611
  const selfServing = served && served.endpoints.length > 0 && constructSources[served.id] !== void 0 ? [served.id, served] : void 0;
2554
2612
  if (selfServing) {
2555
2613
  const [id] = selfServing;
@@ -8409,26 +8467,26 @@ function loadPackageJson() {
8409
8467
  * Run: pnpm --filter @geekmidas/cli sync-versions
8410
8468
  */
8411
8469
  const GEEKMIDAS_VERSIONS = {
8412
- "@geekmidas/audit": "~10.0.0-alpha.22",
8413
- "@geekmidas/auth": "~10.0.0-alpha.22",
8414
- "@geekmidas/cache": "~10.0.0-alpha.22",
8415
- "@geekmidas/client": "~10.0.0-alpha.22",
8416
- "@geekmidas/cloud": "~10.0.0-alpha.22",
8417
- "@geekmidas/constructs": "~10.0.0-alpha.22",
8418
- "@geekmidas/db": "~10.0.0-alpha.22",
8419
- "@geekmidas/emailkit": "~10.0.0-alpha.22",
8420
- "@geekmidas/envkit": "~10.0.0-alpha.22",
8421
- "@geekmidas/errors": "~10.0.0-alpha.22",
8422
- "@geekmidas/events": "~10.0.0-alpha.22",
8423
- "@geekmidas/logger": "~10.0.0-alpha.22",
8424
- "@geekmidas/manifest": "~10.0.0-alpha.22",
8425
- "@geekmidas/rate-limit": "~10.0.0-alpha.22",
8426
- "@geekmidas/schema": "~10.0.0-alpha.22",
8427
- "@geekmidas/services": "~10.0.0-alpha.22",
8428
- "@geekmidas/storage": "~10.0.0-alpha.22",
8429
- "@geekmidas/studio": "~10.0.0-alpha.22",
8430
- "@geekmidas/telescope": "~10.0.0-alpha.22",
8431
- "@geekmidas/testkit": "~10.0.0-alpha.22",
8470
+ "@geekmidas/audit": "~10.0.0-alpha.24",
8471
+ "@geekmidas/auth": "~10.0.0-alpha.24",
8472
+ "@geekmidas/cache": "~10.0.0-alpha.24",
8473
+ "@geekmidas/client": "~10.0.0-alpha.24",
8474
+ "@geekmidas/cloud": "~10.0.0-alpha.24",
8475
+ "@geekmidas/constructs": "~10.0.0-alpha.24",
8476
+ "@geekmidas/db": "~10.0.0-alpha.24",
8477
+ "@geekmidas/emailkit": "~10.0.0-alpha.24",
8478
+ "@geekmidas/envkit": "~10.0.0-alpha.24",
8479
+ "@geekmidas/errors": "~10.0.0-alpha.24",
8480
+ "@geekmidas/events": "~10.0.0-alpha.24",
8481
+ "@geekmidas/logger": "~10.0.0-alpha.24",
8482
+ "@geekmidas/manifest": "~10.0.0-alpha.24",
8483
+ "@geekmidas/rate-limit": "~10.0.0-alpha.24",
8484
+ "@geekmidas/schema": "~10.0.0-alpha.24",
8485
+ "@geekmidas/services": "~10.0.0-alpha.24",
8486
+ "@geekmidas/storage": "~10.0.0-alpha.24",
8487
+ "@geekmidas/studio": "~10.0.0-alpha.24",
8488
+ "@geekmidas/telescope": "~10.0.0-alpha.24",
8489
+ "@geekmidas/testkit": "~10.0.0-alpha.24",
8432
8490
  "@geekmidas/cli": `~${loadPackageJson().version}`
8433
8491
  };
8434
8492
  //#endregion
@@ -15232,8 +15290,10 @@ async function writeTestHarness(options) {
15232
15290
  cache: cacheBackendsIn(declared, options.cacheBackend)
15233
15291
  });
15234
15292
  const database = await databaseSource(declared, sources, endpoints.map(({ construct }) => construct));
15293
+ const files = [.../* @__PURE__ */ new Set([...Object.values(manifest.constructs).map(({ source }) => source.file), ...manifest.endpoints.map(({ source }) => source.file)])];
15235
15294
  const harnessFor = (dir) => harnessModule({
15236
15295
  dir,
15296
+ files,
15237
15297
  database,
15238
15298
  surfaces: surfaces.map((id, index) => ({
15239
15299
  id,
@@ -15306,7 +15366,7 @@ function specifierFrom(dir, file) {
15306
15366
  return path.startsWith(".") ? path : `./${path}`;
15307
15367
  }
15308
15368
  function harnessModule(options) {
15309
- const { surfaces, auths, drivers, database, dir } = options;
15369
+ const { surfaces, auths, drivers, database, dir, files } = options;
15310
15370
  const plugins = [...new Set(auths.flatMap(({ plugins }) => plugins))].sort();
15311
15371
  const imports = [
15312
15372
  `import {${database ? " type DatabaseOf," : ""} featureTest, loadTestManifest } from '@geekmidas/constructs/testing';`,
@@ -15315,7 +15375,8 @@ function harnessModule(options) {
15315
15375
  ...surfaces.map(({ id }) => `import { createApi as create${id} } from './clients/${kebabCase(id)}.js';`),
15316
15376
  ...auths.length ? [`import { createAuthClient } from 'better-auth/client';`] : [],
15317
15377
  ...plugins.length ? [`import { ${plugins.join(", ")} } from 'better-auth/client/plugins';`] : [],
15318
- ...drivers.imports ? [drivers.imports] : []
15378
+ ...drivers.imports ? [drivers.imports] : [],
15379
+ ...files.map((file, index) => `import * as __module${index} from '${specifierFrom(dir, file)}';`)
15319
15380
  ];
15320
15381
  const url = (id) => `manifest.env[${JSON.stringify(provideKey(id, "url"))}]!`;
15321
15382
  const members = [...surfaces.map(({ id, secured }) => ` /** \`${id}\`, at ${provideKey(id, "url")}. */
@@ -15341,8 +15402,13 @@ export class Browser extends TestBrowser {
15341
15402
  ${members.join("\n\n")}
15342
15403
  }
15343
15404
 
15405
+ /** The app's modules, by the path the manifest records for each. */
15406
+ const modules = {
15407
+ ${files.map((file, index) => `\t${JSON.stringify(file)}: __module${index},`).join("\n")}
15408
+ };
15409
+
15344
15410
  /** \`it\`, for a test that drives the app the way it runs deployed. */
15345
- export const it = featureTest${database ? "<Browser, DatabaseOf<typeof __database>>" : ""}({ manifest, browser: Browser });
15411
+ export const it = featureTest${database ? "<Browser, DatabaseOf<typeof __database>>" : ""}({ manifest, modules, browser: Browser });
15346
15412
  `;
15347
15413
  }
15348
15414
  //#endregion