@absolutejs/absolute 0.19.0-beta.671 → 0.19.0-beta.673

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,46 @@ 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 RESERVED_TOP_LEVEL_KEYS, isObject = (value) => typeof value === "object" && value !== null, isCommandService = (service) => service.kind === "command" || Array.isArray(service.command), isServiceCandidate = (value) => isObject(value) && (typeof value.entry === "string" || Array.isArray(value.command)), isWorkspaceConfig = (config) => {
214
+ if (!isObject(config)) {
215
+ return false;
216
+ }
217
+ const entries = Object.entries(config);
218
+ if (entries.length === 0) {
219
+ return false;
220
+ }
221
+ if (entries.some(([key]) => RESERVED_TOP_LEVEL_KEYS.has(key))) {
222
+ return false;
223
+ }
224
+ return entries.every(([, value]) => isServiceCandidate(value));
225
+ }, getWorkspaceServices = (config) => {
226
+ if (!isWorkspaceConfig(config)) {
227
+ throw new Error("absolute.config.ts is not a multi-service config. Define top-level named services with `entry` or `command` before using `absolute workspace dev`.");
228
+ }
229
+ return config;
230
+ }, projectServiceConfig = (config, serviceName) => {
231
+ const services = getWorkspaceServices(config);
232
+ const service = services[serviceName];
233
+ if (!service) {
234
+ throw new Error(`Config file does not define service "${serviceName}".`);
235
+ }
236
+ if (isCommandService(service)) {
237
+ throw new Error(`Service "${serviceName}" is a command service and cannot be loaded as an AbsoluteJS app config.`);
238
+ }
239
+ const {
240
+ command: _command,
241
+ config: _config,
242
+ cwd: _cwd,
243
+ dependsOn: _dependsOn,
244
+ env: _env,
245
+ healthcheck: _healthcheck,
246
+ kind: _kind,
247
+ port: _port,
248
+ visibility: _visibility,
249
+ ...serviceConfig
250
+ } = service;
251
+ return serviceConfig;
252
+ }, loadRawConfig = async (configPath2) => {
214
253
  const resolved = resolve(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
215
254
  const mod = await import(resolved);
216
255
  const config = mod.default ?? mod.config;
@@ -218,9 +257,54 @@ var loadConfig = async (configPath2) => {
218
257
  throw new Error(`Config file "${resolved}" does not export a valid configuration.
219
258
  Expected: export default defineConfig({ ... })`);
220
259
  }
260
+ if (!isObject(config)) {
261
+ throw new Error(`Config file "${resolved}" must export an object configuration.`);
262
+ }
263
+ return config;
264
+ }, loadConfig = async (configPath2) => {
265
+ const config = await loadRawConfig(configPath2);
266
+ const serviceName = process.env.ABSOLUTE_WORKSPACE_SERVICE_NAME;
267
+ if (typeof serviceName === "string" && serviceName.length > 0) {
268
+ return projectServiceConfig(config, serviceName);
269
+ }
270
+ if (isWorkspaceConfig(config)) {
271
+ throw new Error("absolute.config.ts defines multiple services. Use `absolute workspace dev` or set ABSOLUTE_WORKSPACE_SERVICE_NAME before loading a specific service config.");
272
+ }
221
273
  return config;
222
274
  };
223
- var init_loadConfig = () => {};
275
+ var init_loadConfig = __esm(() => {
276
+ RESERVED_TOP_LEVEL_KEYS = new Set([
277
+ "assetsDirectory",
278
+ "astroDirectory",
279
+ "buildDirectory",
280
+ "command",
281
+ "config",
282
+ "cwd",
283
+ "dependsOn",
284
+ "dev",
285
+ "entry",
286
+ "env",
287
+ "healthcheck",
288
+ "htmlDirectory",
289
+ "htmxDirectory",
290
+ "images",
291
+ "incrementalFiles",
292
+ "islands",
293
+ "kind",
294
+ "mode",
295
+ "options",
296
+ "port",
297
+ "publicDirectory",
298
+ "reactDirectory",
299
+ "sitemap",
300
+ "static",
301
+ "stylesConfig",
302
+ "svelteDirectory",
303
+ "tailwind",
304
+ "visibility",
305
+ "vueDirectory"
306
+ ]);
307
+ });
224
308
 
225
309
  // src/cli/utils.ts
226
310
  var {$ } = globalThis.Bun;
@@ -1041,7 +1125,13 @@ __export(exports_typecheck, {
1041
1125
  import { resolve as resolve8, join as join7 } from "path";
1042
1126
  import { existsSync as existsSync10 } from "fs";
1043
1127
  import { mkdir as mkdir2, writeFile } from "fs/promises";
1044
- var run = async (name, command) => {
1128
+ var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), getTypecheckTargets = async (configPath2) => {
1129
+ const rawConfig = await loadRawConfig(configPath2);
1130
+ if (!isWorkspaceConfig(rawConfig)) {
1131
+ return [await loadConfig(configPath2)];
1132
+ }
1133
+ return Object.values(getWorkspaceServices(rawConfig)).filter((service) => !isCommandService3(service));
1134
+ }, run = async (name, command) => {
1045
1135
  const proc = Bun.spawn(command, {
1046
1136
  stderr: "pipe",
1047
1137
  stdout: "pipe"
@@ -1191,19 +1281,25 @@ Found ${errorCount} error${suffix}.`;
1191
1281
  "--color"
1192
1282
  ]);
1193
1283
  }, typecheck = async (configPath2) => {
1194
- const config = await loadConfig(configPath2);
1195
- const hasAngular = Boolean(config.angularDirectory);
1196
- const hasSvelte = Boolean(config.svelteDirectory);
1197
- const hasVue = Boolean(config.vueDirectory);
1284
+ const targets = await getTypecheckTargets(configPath2);
1285
+ const hasAngular = targets.some((config) => Boolean(config.angularDirectory));
1286
+ const hasSvelte = targets.some((config) => Boolean(config.svelteDirectory));
1287
+ const hasVue = targets.some((config) => Boolean(config.vueDirectory));
1288
+ const svelteDirs = [...new Set(targets.map((config) => config.svelteDirectory).filter((dir) => typeof dir === "string" && dir.length > 0))];
1289
+ const angularDirs = [...new Set(targets.map((config) => config.angularDirectory).filter((dir) => typeof dir === "string" && dir.length > 0))];
1198
1290
  const cacheDir = ".absolutejs";
1199
1291
  await mkdir2(cacheDir, { recursive: true });
1200
1292
  const checks = [];
1201
1293
  checks.push(hasVue ? buildVueTscCheck(cacheDir) : buildTscCheck(cacheDir));
1202
1294
  if (hasSvelte) {
1203
- checks.push(buildSvelteCheck(cacheDir, config.svelteDirectory ?? ""));
1295
+ for (const svelteDir of svelteDirs) {
1296
+ checks.push(buildSvelteCheck(cacheDir, svelteDir));
1297
+ }
1204
1298
  }
1205
1299
  if (hasAngular) {
1206
- checks.push(buildAngularCheck(cacheDir, config.angularDirectory ?? ""));
1300
+ for (const angularDir of angularDirs) {
1301
+ checks.push(buildAngularCheck(cacheDir, angularDir));
1302
+ }
1207
1303
  }
1208
1304
  const results = await Promise.all(checks);
1209
1305
  const failed = results.filter((res) => res.exitCode !== 0);
@@ -2948,6 +3044,8 @@ var resolvePackageVersion2 = () => {
2948
3044
  }
2949
3045
  return process.env.ABSOLUTE_VERSION || "unknown";
2950
3046
  };
3047
+ var isCommandService2 = (service) => service.kind === "command" || Array.isArray(service.command);
3048
+ var isAbsoluteService = (service) => !isCommandService2(service);
2951
3049
  var getVisibility = (service) => service.visibility ?? "public";
2952
3050
  var getServiceUrl = (service) => {
2953
3051
  if (!service.port) {
@@ -2959,17 +3057,11 @@ var getHealthcheckUrl = (service) => {
2959
3057
  if (service.healthcheck) {
2960
3058
  return service.healthcheck;
2961
3059
  }
2962
- if (service.kind === "absolute" && service.port) {
3060
+ if (isAbsoluteService(service) && service.port) {
2963
3061
  return `http://127.0.0.1:${service.port}/hmr-status`;
2964
3062
  }
2965
3063
  return;
2966
3064
  };
2967
- var ensureWorkspaceConfig = (config) => {
2968
- if (!config.workspace?.services || Object.keys(config.workspace.services).length === 0) {
2969
- throw new Error("absolute.config.ts is missing workspace.services. Add a workspace section before using `absolute workspace dev`.");
2970
- }
2971
- return config.workspace;
2972
- };
2973
3065
  var resolveHealthcheck = (healthcheck) => {
2974
3066
  if (!healthcheck) {
2975
3067
  return null;
@@ -3013,16 +3105,16 @@ var topologicallySortServices = (services) => {
3013
3105
  return;
3014
3106
  }
3015
3107
  if (visiting.has(name)) {
3016
- throw new Error(`workspace.services has a dependency cycle involving "${name}"`);
3108
+ throw new Error(`services has a dependency cycle involving "${name}"`);
3017
3109
  }
3018
3110
  const service = services[name];
3019
3111
  if (!service) {
3020
- throw new Error(`workspace.services references unknown service "${name}"`);
3112
+ throw new Error(`services references unknown service "${name}"`);
3021
3113
  }
3022
3114
  visiting.add(name);
3023
3115
  for (const dependency of service.dependsOn ?? []) {
3024
3116
  if (!services[dependency]) {
3025
- throw new Error(`workspace.services.${name} depends on missing service "${dependency}"`);
3117
+ throw new Error(`services.${name} depends on missing service "${dependency}"`);
3026
3118
  }
3027
3119
  visit(dependency);
3028
3120
  }
@@ -3083,7 +3175,7 @@ var resolveService = (name, service, options) => {
3083
3175
  if (service.port && !envVars.PORT) {
3084
3176
  envVars.PORT = String(service.port);
3085
3177
  }
3086
- if (service.kind === "absolute") {
3178
+ if (isAbsoluteService(service)) {
3087
3179
  const configPath2 = service.config ? resolve6(cwd, service.config) : options.configPath ? resolve6(options.configPath) : process.env.ABSOLUTE_CONFIG ? resolve6(process.env.ABSOLUTE_CONFIG) : undefined;
3088
3180
  if (configPath2) {
3089
3181
  envVars.ABSOLUTE_CONFIG = configPath2;
@@ -3117,9 +3209,9 @@ var workspace = async (subcommand, options) => {
3117
3209
  if (subcommand !== "dev") {
3118
3210
  throw new Error(subcommand ? `Unknown workspace command: ${subcommand}` : "No workspace subcommand specified. Use `absolute workspace dev`.");
3119
3211
  }
3120
- const config = await loadConfig(options.configPath);
3121
- const workspaceConfig = ensureWorkspaceConfig(config);
3122
- const orderedNames = topologicallySortServices(workspaceConfig.services);
3212
+ const config = await loadRawConfig(options.configPath);
3213
+ const services = getWorkspaceServices(config);
3214
+ const orderedNames = topologicallySortServices(services);
3123
3215
  const running = [];
3124
3216
  const serviceBootStartedAt = new Map;
3125
3217
  let shuttingDown = false;
@@ -3140,7 +3232,7 @@ var workspace = async (subcommand, options) => {
3140
3232
  shell: (command) => runShellCommand2(command)
3141
3233
  },
3142
3234
  services: orderedNames.map((name) => {
3143
- const service = workspaceConfig.services[name];
3235
+ const service = services[name];
3144
3236
  return {
3145
3237
  name,
3146
3238
  port: service?.port,
@@ -3187,9 +3279,9 @@ var workspace = async (subcommand, options) => {
3187
3279
  const startServices = async () => {
3188
3280
  tui.setReadyDuration(null);
3189
3281
  for (const name of orderedNames) {
3190
- const service = workspaceConfig.services[name];
3282
+ const service = services[name];
3191
3283
  if (!service) {
3192
- throw new Error(`workspace.services is missing "${name}"`);
3284
+ throw new Error(`services is missing "${name}"`);
3193
3285
  }
3194
3286
  const resolved = resolveService(name, service, options);
3195
3287
  const port = (resolved.service.port ?? Number(resolved.env.PORT ?? "")) || DEFAULT_PORT;
@@ -3198,7 +3290,7 @@ var workspace = async (subcommand, options) => {
3198
3290
  tui.addLog("workspace", message, "warn");
3199
3291
  });
3200
3292
  }
3201
- if (resolved.service.kind === "absolute" && resolved.configPath && !existsSync8(resolved.configPath)) {
3293
+ if (isAbsoluteService(resolved.service) && resolved.configPath && !existsSync8(resolved.configPath)) {
3202
3294
  throw new Error(`${name} references missing config "${resolved.configPath}"`);
3203
3295
  }
3204
3296
  serviceBootStartedAt.set(name, performance.now());
@@ -3288,7 +3380,7 @@ var workspace = async (subcommand, options) => {
3288
3380
  tui.addLog("workspace", `Shell command failed with exit code ${exitCode}: ${command}`, "error");
3289
3381
  };
3290
3382
  const openInBrowser = async () => {
3291
- const publicService = orderedNames.map((name) => workspaceConfig.services[name]).find((service) => service && getVisibility(service) === "public");
3383
+ const publicService = orderedNames.map((name) => services[name]).find((service) => service && getVisibility(service) === "public");
3292
3384
  const url = publicService ? getServiceUrl(publicService) : null;
3293
3385
  if (!url) {
3294
3386
  tui.addLog("workspace", "No public service to open.", "warn");
package/dist/index.js CHANGED
@@ -181925,7 +181925,83 @@ import { Elysia as Elysia5 } from "elysia";
181925
181925
 
181926
181926
  // src/utils/loadConfig.ts
181927
181927
  import { resolve as resolve6 } from "path";
181928
- var loadConfig = async (configPath) => {
181928
+ var RESERVED_TOP_LEVEL_KEYS = new Set([
181929
+ "assetsDirectory",
181930
+ "astroDirectory",
181931
+ "buildDirectory",
181932
+ "command",
181933
+ "config",
181934
+ "cwd",
181935
+ "dependsOn",
181936
+ "dev",
181937
+ "entry",
181938
+ "env",
181939
+ "healthcheck",
181940
+ "htmlDirectory",
181941
+ "htmxDirectory",
181942
+ "images",
181943
+ "incrementalFiles",
181944
+ "islands",
181945
+ "kind",
181946
+ "mode",
181947
+ "options",
181948
+ "port",
181949
+ "publicDirectory",
181950
+ "reactDirectory",
181951
+ "sitemap",
181952
+ "static",
181953
+ "stylesConfig",
181954
+ "svelteDirectory",
181955
+ "tailwind",
181956
+ "visibility",
181957
+ "vueDirectory"
181958
+ ]);
181959
+ var isObject = (value) => typeof value === "object" && value !== null;
181960
+ var isCommandService = (service) => service.kind === "command" || Array.isArray(service.command);
181961
+ var isServiceCandidate = (value) => isObject(value) && (typeof value.entry === "string" || Array.isArray(value.command));
181962
+ var isWorkspaceConfig = (config) => {
181963
+ if (!isObject(config)) {
181964
+ return false;
181965
+ }
181966
+ const entries = Object.entries(config);
181967
+ if (entries.length === 0) {
181968
+ return false;
181969
+ }
181970
+ if (entries.some(([key]) => RESERVED_TOP_LEVEL_KEYS.has(key))) {
181971
+ return false;
181972
+ }
181973
+ return entries.every(([, value]) => isServiceCandidate(value));
181974
+ };
181975
+ var getWorkspaceServices = (config) => {
181976
+ if (!isWorkspaceConfig(config)) {
181977
+ throw new Error("absolute.config.ts is not a multi-service config. Define top-level named services with `entry` or `command` before using `absolute workspace dev`.");
181978
+ }
181979
+ return config;
181980
+ };
181981
+ var projectServiceConfig = (config, serviceName) => {
181982
+ const services = getWorkspaceServices(config);
181983
+ const service = services[serviceName];
181984
+ if (!service) {
181985
+ throw new Error(`Config file does not define service "${serviceName}".`);
181986
+ }
181987
+ if (isCommandService(service)) {
181988
+ throw new Error(`Service "${serviceName}" is a command service and cannot be loaded as an AbsoluteJS app config.`);
181989
+ }
181990
+ const {
181991
+ command: _command,
181992
+ config: _config,
181993
+ cwd: _cwd,
181994
+ dependsOn: _dependsOn,
181995
+ env: _env,
181996
+ healthcheck: _healthcheck,
181997
+ kind: _kind,
181998
+ port: _port,
181999
+ visibility: _visibility,
182000
+ ...serviceConfig
182001
+ } = service;
182002
+ return serviceConfig;
182003
+ };
182004
+ var loadRawConfig = async (configPath) => {
181929
182005
  const resolved = resolve6(configPath ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
181930
182006
  const mod = await import(resolved);
181931
182007
  const config = mod.default ?? mod.config;
@@ -181933,6 +182009,20 @@ var loadConfig = async (configPath) => {
181933
182009
  throw new Error(`Config file "${resolved}" does not export a valid configuration.
181934
182010
  Expected: export default defineConfig({ ... })`);
181935
182011
  }
182012
+ if (!isObject(config)) {
182013
+ throw new Error(`Config file "${resolved}" must export an object configuration.`);
182014
+ }
182015
+ return config;
182016
+ };
182017
+ var loadConfig = async (configPath) => {
182018
+ const config = await loadRawConfig(configPath);
182019
+ const serviceName = process.env.ABSOLUTE_WORKSPACE_SERVICE_NAME;
182020
+ if (typeof serviceName === "string" && serviceName.length > 0) {
182021
+ return projectServiceConfig(config, serviceName);
182022
+ }
182023
+ if (isWorkspaceConfig(config)) {
182024
+ throw new Error("absolute.config.ts defines multiple services. Use `absolute workspace dev` or set ABSOLUTE_WORKSPACE_SERVICE_NAME before loading a specific service config.");
182025
+ }
181936
182026
  return config;
181937
182027
  };
181938
182028
 
@@ -182741,8 +182831,8 @@ var TypeSystemPolicy;
182741
182831
  }
182742
182832
  TypeSystemPolicy2.IsExactOptionalProperty = IsExactOptionalProperty;
182743
182833
  function IsObjectLike(value) {
182744
- const isObject = IsObject2(value);
182745
- return TypeSystemPolicy2.AllowArrayObject ? isObject : isObject && !IsArray2(value);
182834
+ const isObject2 = IsObject2(value);
182835
+ return TypeSystemPolicy2.AllowArrayObject ? isObject2 : isObject2 && !IsArray2(value);
182746
182836
  }
182747
182837
  TypeSystemPolicy2.IsObjectLike = IsObjectLike;
182748
182838
  function IsRecordLike(value) {
@@ -188808,5 +188898,5 @@ export {
188808
188898
  ANGULAR_INIT_TIMEOUT_MS
188809
188899
  };
188810
188900
 
188811
- //# debugId=2F8EDE59772BBE0764756E2164756E21
188901
+ //# debugId=98967D2F4839D93264756E2164756E21
188812
188902
  //# sourceMappingURL=index.js.map