@absolutejs/absolute 0.19.0-beta.670 → 0.19.0-beta.672

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/cli/index.js CHANGED
@@ -210,7 +210,34 @@ var init_telemetryEvent = __esm(() => {
210
210
 
211
211
  // src/utils/loadConfig.ts
212
212
  import { resolve } from "path";
213
- var loadConfig = async (configPath2) => {
213
+ var isObject = (value) => typeof value === "object" && value !== null, isCommandService = (service) => service.kind === "command" || Array.isArray(service.command), projectServiceConfig = (config, serviceName) => {
214
+ const service = config.services?.[serviceName];
215
+ if (!service) {
216
+ throw new Error(`Config file does not define services.${serviceName}.`);
217
+ }
218
+ if (isCommandService(service)) {
219
+ throw new Error(`services.${serviceName} is a command service and cannot be loaded as an AbsoluteJS app config.`);
220
+ }
221
+ const {
222
+ command: _command,
223
+ config: _config,
224
+ cwd: _cwd,
225
+ dependsOn: _dependsOn,
226
+ entry: _entry,
227
+ env: _env,
228
+ healthcheck: _healthcheck,
229
+ kind: _kind,
230
+ port: _port,
231
+ services: _nestedServices,
232
+ visibility: _visibility,
233
+ ...serviceConfig
234
+ } = service;
235
+ const { services: _services, ...sharedConfig } = config;
236
+ return {
237
+ ...sharedConfig,
238
+ ...serviceConfig
239
+ };
240
+ }, loadConfig = async (configPath2) => {
214
241
  const resolved = resolve(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
215
242
  const mod = await import(resolved);
216
243
  const config = mod.default ?? mod.config;
@@ -218,6 +245,13 @@ var loadConfig = async (configPath2) => {
218
245
  throw new Error(`Config file "${resolved}" does not export a valid configuration.
219
246
  Expected: export default defineConfig({ ... })`);
220
247
  }
248
+ if (!isObject(config)) {
249
+ throw new Error(`Config file "${resolved}" must export an object configuration.`);
250
+ }
251
+ const serviceName = process.env.ABSOLUTE_WORKSPACE_SERVICE_NAME;
252
+ if (typeof serviceName === "string" && serviceName.length > 0) {
253
+ return projectServiceConfig(config, serviceName);
254
+ }
221
255
  return config;
222
256
  };
223
257
  var init_loadConfig = () => {};
@@ -2384,6 +2418,7 @@ var start = async (serverEntry, outdir, configPath2) => {
2384
2418
  // src/cli/scripts/workspace.ts
2385
2419
  init_constants();
2386
2420
  init_loadConfig();
2421
+ init_getDurationString();
2387
2422
  import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
2388
2423
  import { resolve as resolve6 } from "path";
2389
2424
 
@@ -2664,8 +2699,8 @@ var createWorkspaceTui = ({
2664
2699
  const statusWidth = 10;
2665
2700
  const rows = [];
2666
2701
  rows.push(padLine(title, width));
2667
- rows.push(padLine(`${colors.bold}Services${colors.reset}`, width));
2668
2702
  rows.push(divider);
2703
+ rows.push(padLine(`${colors.bold}Services${colors.reset}`, width));
2669
2704
  for (const service of servicesSnapshot) {
2670
2705
  const stateColor = getStatusColor(service.status);
2671
2706
  const detail = service.detail ? ` \xB7 ${service.detail}` : "";
@@ -2947,6 +2982,8 @@ var resolvePackageVersion2 = () => {
2947
2982
  }
2948
2983
  return process.env.ABSOLUTE_VERSION || "unknown";
2949
2984
  };
2985
+ var isCommandService2 = (service) => service.kind === "command" || Array.isArray(service.command);
2986
+ var isAbsoluteService = (service) => !isCommandService2(service);
2950
2987
  var getVisibility = (service) => service.visibility ?? "public";
2951
2988
  var getServiceUrl = (service) => {
2952
2989
  if (!service.port) {
@@ -2958,16 +2995,16 @@ var getHealthcheckUrl = (service) => {
2958
2995
  if (service.healthcheck) {
2959
2996
  return service.healthcheck;
2960
2997
  }
2961
- if (service.kind === "absolute" && service.port) {
2998
+ if (isAbsoluteService(service) && service.port) {
2962
2999
  return `http://127.0.0.1:${service.port}/hmr-status`;
2963
3000
  }
2964
3001
  return;
2965
3002
  };
2966
- var ensureWorkspaceConfig = (config) => {
2967
- if (!config.workspace?.services || Object.keys(config.workspace.services).length === 0) {
2968
- throw new Error("absolute.config.ts is missing workspace.services. Add a workspace section before using `absolute workspace dev`.");
3003
+ var ensureServicesConfig = (config) => {
3004
+ if (!config.services || Object.keys(config.services).length === 0) {
3005
+ throw new Error("absolute.config.ts is missing services. Add a services section before using `absolute workspace dev`.");
2969
3006
  }
2970
- return config.workspace;
3007
+ return config.services;
2971
3008
  };
2972
3009
  var resolveHealthcheck = (healthcheck) => {
2973
3010
  if (!healthcheck) {
@@ -3012,16 +3049,16 @@ var topologicallySortServices = (services) => {
3012
3049
  return;
3013
3050
  }
3014
3051
  if (visiting.has(name)) {
3015
- throw new Error(`workspace.services has a dependency cycle involving "${name}"`);
3052
+ throw new Error(`services has a dependency cycle involving "${name}"`);
3016
3053
  }
3017
3054
  const service = services[name];
3018
3055
  if (!service) {
3019
- throw new Error(`workspace.services references unknown service "${name}"`);
3056
+ throw new Error(`services references unknown service "${name}"`);
3020
3057
  }
3021
3058
  visiting.add(name);
3022
3059
  for (const dependency of service.dependsOn ?? []) {
3023
3060
  if (!services[dependency]) {
3024
- throw new Error(`workspace.services.${name} depends on missing service "${dependency}"`);
3061
+ throw new Error(`services.${name} depends on missing service "${dependency}"`);
3025
3062
  }
3026
3063
  visit(dependency);
3027
3064
  }
@@ -3082,7 +3119,7 @@ var resolveService = (name, service, options) => {
3082
3119
  if (service.port && !envVars.PORT) {
3083
3120
  envVars.PORT = String(service.port);
3084
3121
  }
3085
- if (service.kind === "absolute") {
3122
+ if (isAbsoluteService(service)) {
3086
3123
  const configPath2 = service.config ? resolve6(cwd, service.config) : options.configPath ? resolve6(options.configPath) : process.env.ABSOLUTE_CONFIG ? resolve6(process.env.ABSOLUTE_CONFIG) : undefined;
3087
3124
  if (configPath2) {
3088
3125
  envVars.ABSOLUTE_CONFIG = configPath2;
@@ -3117,9 +3154,10 @@ var workspace = async (subcommand, options) => {
3117
3154
  throw new Error(subcommand ? `Unknown workspace command: ${subcommand}` : "No workspace subcommand specified. Use `absolute workspace dev`.");
3118
3155
  }
3119
3156
  const config = await loadConfig(options.configPath);
3120
- const workspaceConfig = ensureWorkspaceConfig(config);
3121
- const orderedNames = topologicallySortServices(workspaceConfig.services);
3157
+ const services = ensureServicesConfig(config);
3158
+ const orderedNames = topologicallySortServices(services);
3122
3159
  const running = [];
3160
+ const serviceBootStartedAt = new Map;
3123
3161
  let shuttingDown = false;
3124
3162
  let restarting = false;
3125
3163
  let paused = false;
@@ -3138,7 +3176,7 @@ var workspace = async (subcommand, options) => {
3138
3176
  shell: (command) => runShellCommand2(command)
3139
3177
  },
3140
3178
  services: orderedNames.map((name) => {
3141
- const service = workspaceConfig.services[name];
3179
+ const service = services[name];
3142
3180
  return {
3143
3181
  name,
3144
3182
  port: service?.port,
@@ -3185,9 +3223,9 @@ var workspace = async (subcommand, options) => {
3185
3223
  const startServices = async () => {
3186
3224
  tui.setReadyDuration(null);
3187
3225
  for (const name of orderedNames) {
3188
- const service = workspaceConfig.services[name];
3226
+ const service = services[name];
3189
3227
  if (!service) {
3190
- throw new Error(`workspace.services is missing "${name}"`);
3228
+ throw new Error(`services is missing "${name}"`);
3191
3229
  }
3192
3230
  const resolved = resolveService(name, service, options);
3193
3231
  const port = (resolved.service.port ?? Number(resolved.env.PORT ?? "")) || DEFAULT_PORT;
@@ -3196,9 +3234,10 @@ var workspace = async (subcommand, options) => {
3196
3234
  tui.addLog("workspace", message, "warn");
3197
3235
  });
3198
3236
  }
3199
- if (resolved.service.kind === "absolute" && resolved.configPath && !existsSync8(resolved.configPath)) {
3237
+ if (isAbsoluteService(resolved.service) && resolved.configPath && !existsSync8(resolved.configPath)) {
3200
3238
  throw new Error(`${name} references missing config "${resolved.configPath}"`);
3201
3239
  }
3240
+ serviceBootStartedAt.set(name, performance.now());
3202
3241
  tui.setServiceStatus(name, restarting ? "restarting" : "starting");
3203
3242
  const processHandle = Bun.spawn(resolved.command, {
3204
3243
  cwd: resolved.cwd,
@@ -3226,7 +3265,9 @@ var workspace = async (subcommand, options) => {
3226
3265
  shutdown(exitCode || 1);
3227
3266
  });
3228
3267
  await waitForHealthcheck(getHealthcheckUrl(resolved.service));
3229
- tui.setServiceStatus(name, "ready");
3268
+ const startedAt = serviceBootStartedAt.get(name);
3269
+ const readyDuration = typeof startedAt === "number" ? `ready in ${getDurationString(performance.now() - startedAt)}` : undefined;
3270
+ tui.setServiceStatus(name, "ready", readyDuration);
3230
3271
  }
3231
3272
  };
3232
3273
  const restartWorkspace = async () => {
@@ -3283,7 +3324,7 @@ var workspace = async (subcommand, options) => {
3283
3324
  tui.addLog("workspace", `Shell command failed with exit code ${exitCode}: ${command}`, "error");
3284
3325
  };
3285
3326
  const openInBrowser = async () => {
3286
- const publicService = orderedNames.map((name) => workspaceConfig.services[name]).find((service) => service && getVisibility(service) === "public");
3327
+ const publicService = orderedNames.map((name) => services[name]).find((service) => service && getVisibility(service) === "public");
3287
3328
  const url = publicService ? getServiceUrl(publicService) : null;
3288
3329
  if (!url) {
3289
3330
  tui.addLog("workspace", "No public service to open.", "warn");
package/dist/index.js CHANGED
@@ -181925,6 +181925,36 @@ import { Elysia as Elysia5 } from "elysia";
181925
181925
 
181926
181926
  // src/utils/loadConfig.ts
181927
181927
  import { resolve as resolve6 } from "path";
181928
+ var isObject = (value) => typeof value === "object" && value !== null;
181929
+ var isCommandService = (service) => service.kind === "command" || Array.isArray(service.command);
181930
+ var projectServiceConfig = (config, serviceName) => {
181931
+ const service = config.services?.[serviceName];
181932
+ if (!service) {
181933
+ throw new Error(`Config file does not define services.${serviceName}.`);
181934
+ }
181935
+ if (isCommandService(service)) {
181936
+ throw new Error(`services.${serviceName} is a command service and cannot be loaded as an AbsoluteJS app config.`);
181937
+ }
181938
+ const {
181939
+ command: _command,
181940
+ config: _config,
181941
+ cwd: _cwd,
181942
+ dependsOn: _dependsOn,
181943
+ entry: _entry,
181944
+ env: _env,
181945
+ healthcheck: _healthcheck,
181946
+ kind: _kind,
181947
+ port: _port,
181948
+ services: _nestedServices,
181949
+ visibility: _visibility,
181950
+ ...serviceConfig
181951
+ } = service;
181952
+ const { services: _services, ...sharedConfig } = config;
181953
+ return {
181954
+ ...sharedConfig,
181955
+ ...serviceConfig
181956
+ };
181957
+ };
181928
181958
  var loadConfig = async (configPath) => {
181929
181959
  const resolved = resolve6(configPath ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
181930
181960
  const mod = await import(resolved);
@@ -181933,6 +181963,13 @@ var loadConfig = async (configPath) => {
181933
181963
  throw new Error(`Config file "${resolved}" does not export a valid configuration.
181934
181964
  Expected: export default defineConfig({ ... })`);
181935
181965
  }
181966
+ if (!isObject(config)) {
181967
+ throw new Error(`Config file "${resolved}" must export an object configuration.`);
181968
+ }
181969
+ const serviceName = process.env.ABSOLUTE_WORKSPACE_SERVICE_NAME;
181970
+ if (typeof serviceName === "string" && serviceName.length > 0) {
181971
+ return projectServiceConfig(config, serviceName);
181972
+ }
181936
181973
  return config;
181937
181974
  };
181938
181975
 
@@ -182741,8 +182778,8 @@ var TypeSystemPolicy;
182741
182778
  }
182742
182779
  TypeSystemPolicy2.IsExactOptionalProperty = IsExactOptionalProperty;
182743
182780
  function IsObjectLike(value) {
182744
- const isObject = IsObject2(value);
182745
- return TypeSystemPolicy2.AllowArrayObject ? isObject : isObject && !IsArray2(value);
182781
+ const isObject2 = IsObject2(value);
182782
+ return TypeSystemPolicy2.AllowArrayObject ? isObject2 : isObject2 && !IsArray2(value);
182746
182783
  }
182747
182784
  TypeSystemPolicy2.IsObjectLike = IsObjectLike;
182748
182785
  function IsRecordLike(value) {
@@ -188808,5 +188845,5 @@ export {
188808
188845
  ANGULAR_INIT_TIMEOUT_MS
188809
188846
  };
188810
188847
 
188811
- //# debugId=2F8EDE59772BBE0764756E2164756E21
188848
+ //# debugId=4B9F0A17F5EB81CB64756E2164756E21
188812
188849
  //# sourceMappingURL=index.js.map