@orieljs/framework 0.1.0-alpha.8 → 0.1.0-alpha.9

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.d.ts CHANGED
@@ -130,7 +130,7 @@ declare class ApplicationBuilder {
130
130
  type LifecycleCallback = (app: Application$2) => void | Promise<void>;
131
131
  declare class Application$1 extends Container implements Application$2 {
132
132
  private readonly base;
133
- readonly version = "0.1.0-alpha.8";
133
+ readonly version = "0.1.0-alpha.9";
134
134
  private readonly providers;
135
135
  private readonly bootingCallbacks;
136
136
  private readonly bootedCallbacks;
@@ -5752,6 +5752,8 @@ declare class ValidatorImpl<R extends Rules = Rules> implements Validator$1<R> {
5752
5752
  declare class ValidationFactoryImpl implements ValidationFactory {
5753
5753
  private readonly extended;
5754
5754
  make<const R extends Rules>(data: Record<string, unknown>, rules: R, messages?: Record<string, string>, attributes?: Record<string, string>): ValidatorImpl<R>;
5755
+ /** Every rule this factory knows, built-in and extend()ed, sorted (for editors: `oriel ide:info`). */
5756
+ ruleNames(): string[];
5755
5757
  extend(name: string, callback: RuleCallback, message?: string): void;
5756
5758
  }
5757
5759
 
package/dist/index.js CHANGED
@@ -95,11 +95,13 @@ import {
95
95
  back,
96
96
  bunRuntime,
97
97
  clientAddress,
98
+ componentFiles,
98
99
  componentName,
99
100
  contentDisposition,
100
101
  currentRequest,
101
102
  currentVite,
102
103
  debugPage,
104
+ describeComponent,
103
105
  detectRuntime,
104
106
  env,
105
107
  escapeHtml,
@@ -141,7 +143,7 @@ import {
141
143
  vite,
142
144
  viteReactRefresh,
143
145
  writeResponse
144
- } from "./chunk-SPQUX3C7.js";
146
+ } from "./chunk-YAB54Y5I.js";
145
147
  import {
146
148
  Arr,
147
149
  BindingResolutionError,
@@ -3452,16 +3454,16 @@ var AboutCommand = class extends Command {
3452
3454
  const app2 = inject(Application);
3453
3455
  const container = currentContainer();
3454
3456
  const config2 = container?.bound(ConfigRepository) ? container.make(ConfigRepository) : void 0;
3455
- const read = (key, fallback) => config2 ? config2.get(key, fallback) : fallback;
3457
+ const read2 = (key, fallback) => config2 ? config2.get(key, fallback) : fallback;
3456
3458
  this.table(
3457
3459
  ["Property", "Value"],
3458
3460
  [
3459
- ["Application Name", String(read("app.name", "Oriel"))],
3461
+ ["Application Name", String(read2("app.name", "Oriel"))],
3460
3462
  ["Oriel Version", app2.version],
3461
3463
  ["Node Version", process.version],
3462
3464
  ["Environment", app2.environment()],
3463
- ["Debug Mode", String(read("app.debug", false))],
3464
- ["URL", String(read("app.url", "(none)"))]
3465
+ ["Debug Mode", String(read2("app.debug", false))],
3466
+ ["URL", String(read2("app.url", "(none)"))]
3465
3467
  ]
3466
3468
  );
3467
3469
  return 0;
@@ -3526,13 +3528,13 @@ function applyOption(options, def, inline, next) {
3526
3528
  }
3527
3529
  return takesNext ? 1 : 0;
3528
3530
  }
3529
- function applyShortcutToken(options, token2, next, shortcuts, byName) {
3531
+ function applyShortcutToken(options, token2, next, shortcuts, byName2) {
3530
3532
  let pos = 1;
3531
3533
  while (pos < token2.length) {
3532
3534
  const shortcutChar = token2[pos];
3533
3535
  const name = shortcuts.get(shortcutChar);
3534
3536
  if (!name) throw new InvalidSignatureError(`The "-${shortcutChar}" option does not exist.`);
3535
- const def = byName.get(name);
3537
+ const def = byName2.get(name);
3536
3538
  if (def.mode === "flag") {
3537
3539
  options[def.name] = true;
3538
3540
  pos++;
@@ -3546,7 +3548,7 @@ function applyShortcutToken(options, token2, next, shortcuts, byName) {
3546
3548
  }
3547
3549
  function parseArgv(argv, signature) {
3548
3550
  const shortcuts = new Map(signature.options.filter((o) => o.shortcut).map((o) => [o.shortcut, o.name]));
3549
- const byName = new Map(signature.options.map((o) => [o.name, o]));
3551
+ const byName2 = new Map(signature.options.map((o) => [o.name, o]));
3550
3552
  const options = {};
3551
3553
  const positionals = [];
3552
3554
  for (let i = 0; i < argv.length; i++) {
@@ -3559,11 +3561,11 @@ function parseArgv(argv, signature) {
3559
3561
  const eq = token2.indexOf("=");
3560
3562
  const name = eq === -1 ? token2.slice(2) : token2.slice(2, eq);
3561
3563
  const inline = eq === -1 ? void 0 : token2.slice(eq + 1);
3562
- const def = byName.get(name);
3564
+ const def = byName2.get(name);
3563
3565
  if (!def) throw new InvalidSignatureError(`The "--${name}" option does not exist.`);
3564
3566
  i += applyOption(options, def, inline, argv[i + 1]);
3565
3567
  } else if (token2.length > 1 && token2.startsWith("-")) {
3566
- i += applyShortcutToken(options, token2, argv[i + 1], shortcuts, byName);
3568
+ i += applyShortcutToken(options, token2, argv[i + 1], shortcuts, byName2);
3567
3569
  } else {
3568
3570
  positionals.push(token2);
3569
3571
  }
@@ -3662,17 +3664,17 @@ var ListCommand = class extends Command {
3662
3664
  const namespace = this.argument("namespace");
3663
3665
  const names = Object.keys(all).filter((name) => namespace === void 0 || name === namespace || name.startsWith(`${namespace}:`)).sort();
3664
3666
  const width = Math.max(0, ...names.map((name) => name.length));
3665
- const describe = (name) => ` ${name.padEnd(width)} ${all[name].description}`;
3667
+ const describe2 = (name) => ` ${name.padEnd(width)} ${all[name].description}`;
3666
3668
  this.line("Available commands:");
3667
3669
  const unnamespaced = names.filter((name) => !name.includes(":"));
3668
3670
  const namespaced = names.filter((name) => name.includes(":"));
3669
- for (const name of unnamespaced) this.line(describe(name));
3671
+ for (const name of unnamespaced) this.line(describe2(name));
3670
3672
  let currentGroup;
3671
3673
  for (const name of namespaced) {
3672
3674
  const group = name.slice(0, name.indexOf(":"));
3673
3675
  if (group !== currentGroup) this.line(` ${group}`);
3674
3676
  currentGroup = group;
3675
- this.line(describe(name));
3677
+ this.line(describe2(name));
3676
3678
  }
3677
3679
  return 0;
3678
3680
  }
@@ -9737,10 +9739,10 @@ function isEquivalent(cast, current, original, model, key, className) {
9737
9739
  if (typeof cast === "string" && ["float", "double", "real"].includes(cast)) {
9738
9740
  return Math.abs(Number(current) - Number(original)) < Number.EPSILON * 4;
9739
9741
  }
9740
- const read = (value2) => castGet(model, key, cast, value2, {}, className);
9742
+ const read2 = (value2) => castGet(model, key, cast, value2, {}, className);
9741
9743
  if (typeof cast === "string" && (JSON_CASTS.has(cast) || PRIMITIVE_CASTS.has(cast) || cast.startsWith("decimal:"))) {
9742
- const a = read(current);
9743
- const b = read(original);
9744
+ const a = read2(current);
9745
+ const b = read2(original);
9744
9746
  return isDeepStrictEqual(a instanceof Collection ? a.all() : a, b instanceof Collection ? b.all() : b);
9745
9747
  }
9746
9748
  if (isEnum(cast)) return String(current) === String(original);
@@ -13880,24 +13882,24 @@ var UNIQUE2 = /* @__PURE__ */ Symbol.for("oriel:bus.unique");
13880
13882
  function uniqueSpecOf(cls, instance, name, data) {
13881
13883
  const statics = cls;
13882
13884
  const members = instance;
13883
- const read = (key) => {
13885
+ const read2 = (key) => {
13884
13886
  if (members[key] !== void 0) return { value: members[key], on: instance };
13885
13887
  if (statics[key] !== void 0) return { value: statics[key], on: cls };
13886
13888
  return void 0;
13887
13889
  };
13888
13890
  const resolve4 = (key) => {
13889
- const found = read(key);
13891
+ const found = read2(key);
13890
13892
  if (found === void 0) return void 0;
13891
13893
  return typeof found.value === "function" ? found.value.apply(found.on, data) : found.value;
13892
13894
  };
13893
- const declared = typeof read("uniqueId")?.value === "function" || read("uniqueFor") !== void 0 || read("uniqueUntilProcessing")?.value === true || typeof read("uniqueVia")?.value === "function";
13895
+ const declared = typeof read2("uniqueId")?.value === "function" || read2("uniqueFor") !== void 0 || read2("uniqueUntilProcessing")?.value === true || typeof read2("uniqueVia")?.value === "function";
13894
13896
  if (!declared) return void 0;
13895
- const id = typeof read("uniqueId")?.value === "function" ? resolve4("uniqueId") : void 0;
13897
+ const id = typeof read2("uniqueId")?.value === "function" ? resolve4("uniqueId") : void 0;
13896
13898
  const spec = { name, id: id === void 0 || id === null ? "" : String(id) };
13897
13899
  const uniqueFor = resolve4("uniqueFor");
13898
13900
  if (typeof uniqueFor === "number") spec.for = uniqueFor;
13899
- if (read("uniqueUntilProcessing")?.value === true) spec.untilProcessing = true;
13900
- const via = typeof read("uniqueVia")?.value === "function" ? resolve4("uniqueVia") : void 0;
13901
+ if (read2("uniqueUntilProcessing")?.value === true) spec.untilProcessing = true;
13902
+ const via = typeof read2("uniqueVia")?.value === "function" ? resolve4("uniqueVia") : void 0;
13901
13903
  if (typeof via === "string") spec.via = via;
13902
13904
  return spec;
13903
13905
  }
@@ -14970,14 +14972,14 @@ var HashingServiceProvider = class extends ServiceProvider {
14970
14972
  };
14971
14973
 
14972
14974
  // ../Inertia/dist/index.js
14973
- import { existsSync as existsSync7 } from "fs";
14974
- import { join as join11 } from "path";
14975
+ import { existsSync as existsSync7, readdirSync as readdirSync5 } from "fs";
14976
+ import { join as join11, relative as relative5, sep as sep4 } from "path";
14975
14977
  import { createHash as createHash7 } from "crypto";
14976
14978
  import { existsSync as existsSync23, readFileSync } from "fs";
14977
14979
  import { spawn as spawn2 } from "child_process";
14978
14980
  import { existsSync as existsSync33 } from "fs";
14979
14981
  import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
14980
- import { dirname as dirname5, isAbsolute as isAbsolute2, join as join24, relative as relative5 } from "path";
14982
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join24, relative as relative22 } from "path";
14981
14983
  import { existsSync as existsSync43, readFileSync as readFileSync2 } from "fs";
14982
14984
  var Header = {
14983
14985
  INERTIA: "X-Inertia",
@@ -15632,6 +15634,22 @@ var Response2 = class {
15632
15634
  return scope?.bound(ConfigRepository) ? scope.make(ConfigRepository).get(key, fallback) : fallback;
15633
15635
  }
15634
15636
  };
15637
+ function pageNames(paths, extensions) {
15638
+ const byLength = [...extensions].sort((a, b) => b.length - a.length);
15639
+ const pages = /* @__PURE__ */ new Map();
15640
+ for (const path of paths) {
15641
+ if (!existsSync7(path)) continue;
15642
+ for (const entry of readdirSync5(path, { recursive: true, withFileTypes: true })) {
15643
+ if (!entry.isFile()) continue;
15644
+ const file = join11(entry.parentPath, entry.name);
15645
+ const extension = byLength.find((candidate) => entry.name.endsWith(`.${candidate}`));
15646
+ if (extension === void 0) continue;
15647
+ const name = relative5(path, file).slice(0, -(extension.length + 1)).split(sep4).join("/");
15648
+ if (!pages.has(name)) pages.set(name, file);
15649
+ }
15650
+ }
15651
+ return [...pages].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, file]) => ({ name, file }));
15652
+ }
15635
15653
  function pageExists(component, paths, extensions) {
15636
15654
  return paths.some((path) => extensions.some((extension) => existsSync7(join11(path, `${component}.${extension}`))));
15637
15655
  }
@@ -16149,7 +16167,7 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
16149
16167
  await writeFile6(output, renderRoutesModule(table));
16150
16168
  await mkdir5(dirname5(server), { recursive: true });
16151
16169
  await writeFile6(server, renderServerRouteTypes(routeTable(app2.make(Router).getRoutes())));
16152
- this.info(`Route types for ${Object.keys(table).length} named routes written to ${relative5(app2.basePath(), output)}.`);
16170
+ this.info(`Route types for ${Object.keys(table).length} named routes written to ${relative22(app2.basePath(), output)}.`);
16153
16171
  return 0;
16154
16172
  }
16155
16173
  ).purpose("Generate the route table and route name types for the frontend");
@@ -16162,7 +16180,7 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
16162
16180
  const output = absolute(optionText(this.option("output")) ?? config2("inertia.types.pages", "resources/js/oriel/pages.d.ts"));
16163
16181
  const result = await module.generatePageTypes({ root: app2.basePath(), output });
16164
16182
  for (const warning of result.warnings) this.warn(warning);
16165
- this.info(`Page types for ${result.pages} pages written to ${relative5(app2.basePath(), result.output)}.`);
16183
+ this.info(`Page types for ${result.pages} pages written to ${relative22(app2.basePath(), result.output)}.`);
16166
16184
  return 0;
16167
16185
  }).purpose("Generate TypeScript types for the Inertia page props");
16168
16186
  kernel.command("inertia:middleware {name=HandleInertiaRequests : The middleware class name} {--force : Overwrite an existing file}", async function() {
@@ -16173,12 +16191,12 @@ function registerInertiaCommands(kernel, app2, gateway, options = {}) {
16173
16191
  }
16174
16192
  const file = app2.appPath(join24("Http", "Middleware", `${name}.ts`));
16175
16193
  if (existsSync33(file) && this.option("force") !== true) {
16176
- this.error(`Middleware [${relative5(app2.basePath(), file)}] already exists.`);
16194
+ this.error(`Middleware [${relative22(app2.basePath(), file)}] already exists.`);
16177
16195
  return 1;
16178
16196
  }
16179
16197
  await mkdir5(dirname5(file), { recursive: true });
16180
16198
  await writeFile6(file, MIDDLEWARE_STUB2.replace("{{ class }}", () => name));
16181
- this.info(`Middleware [${relative5(app2.basePath(), file)}] created successfully.`);
16199
+ this.info(`Middleware [${relative22(app2.basePath(), file)}] created successfully.`);
16182
16200
  return 0;
16183
16201
  }).purpose("Create a new Inertia middleware");
16184
16202
  kernel.command("inertia:start-ssr {--runtime= : The runtime that runs the SSR bundle (node or bun)}", async function() {
@@ -16377,7 +16395,7 @@ var InertiaServiceProvider = class extends ServiceProvider {
16377
16395
 
16378
16396
  // ../Log/dist/index.js
16379
16397
  import pino2 from "pino";
16380
- import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync2, readdirSync as readdirSync5, rmSync } from "fs";
16398
+ import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync2, readdirSync as readdirSync6, rmSync } from "fs";
16381
16399
  import { basename as basename2, dirname as dirname6, extname as extname3, join as join12 } from "path";
16382
16400
  import { Writable } from "stream";
16383
16401
  import "pino";
@@ -16572,7 +16590,7 @@ var DailyRotatingStream = class extends Writable {
16572
16590
  const prefix = `${this.stem}-`;
16573
16591
  const now5 = this.now();
16574
16592
  const cutoff = new Date(now5.getFullYear(), now5.getMonth(), now5.getDate() - (this.days - 1)).getTime();
16575
- for (const file of readdirSync5(this.dir)) {
16593
+ for (const file of readdirSync6(this.dir)) {
16576
16594
  if (!file.startsWith(prefix) || !file.endsWith(".log")) continue;
16577
16595
  const match = DATE_PATTERN.exec(file.slice(prefix.length, -".log".length));
16578
16596
  if (!match) continue;
@@ -18149,7 +18167,7 @@ import { randomUUID as randomUUID32 } from "crypto";
18149
18167
  import { setTimeout as sleep4 } from "timers/promises";
18150
18168
  import { spawn as spawnProcess } from "child_process";
18151
18169
  import { setTimeout as sleep22 } from "timers/promises";
18152
- import { existsSync as existsSync8, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
18170
+ import { existsSync as existsSync8, readdirSync as readdirSync7, statSync as statSync3 } from "fs";
18153
18171
  import { join as join13 } from "path";
18154
18172
  import { pathToFileURL as pathToFileURL6 } from "url";
18155
18173
  var QueueError = class extends Error {
@@ -19943,7 +19961,7 @@ var Listener = class _Listener {
19943
19961
  var EXTENSIONS2 = [".ts", ".js", ".mts", ".mjs"];
19944
19962
  function files2(directory) {
19945
19963
  const found = [];
19946
- for (const entry of readdirSync6(directory).sort()) {
19964
+ for (const entry of readdirSync7(directory).sort()) {
19947
19965
  const path = join13(directory, entry);
19948
19966
  if (statSync3(path).isDirectory()) found.push(...files2(path));
19949
19967
  else if (EXTENSIONS2.some((extension) => entry.endsWith(extension)) && !entry.endsWith(".d.ts")) found.push(path);
@@ -22702,7 +22720,7 @@ function parse(format2, value2) {
22702
22720
  };
22703
22721
  for (let i = 0; i < format2.length; i++) {
22704
22722
  const char = format2[i];
22705
- let read = 0;
22723
+ let read2 = 0;
22706
22724
  switch (char) {
22707
22725
  case "!":
22708
22726
  case "|":
@@ -22714,12 +22732,12 @@ function parse(format2, value2) {
22714
22732
  continue;
22715
22733
  case "d":
22716
22734
  case "j":
22717
- read = digits(1, 2);
22718
- if (read !== void 0) fields.day = read;
22735
+ read2 = digits(1, 2);
22736
+ if (read2 !== void 0) fields.day = read2;
22719
22737
  break;
22720
22738
  case "D":
22721
22739
  case "l":
22722
- read = word(DAYS, true);
22740
+ read2 = word(DAYS, true);
22723
22741
  break;
22724
22742
  case "S":
22725
22743
  if (!/^(st|nd|rd|th)/i.test(value2.slice(position))) return void 0;
@@ -22727,21 +22745,21 @@ function parse(format2, value2) {
22727
22745
  break;
22728
22746
  case "F":
22729
22747
  case "M":
22730
- read = word(MONTHS, true);
22731
- if (read !== void 0) fields.month = read + 1;
22748
+ read2 = word(MONTHS, true);
22749
+ if (read2 !== void 0) fields.month = read2 + 1;
22732
22750
  break;
22733
22751
  case "m":
22734
22752
  case "n":
22735
- read = digits(1, 2);
22736
- if (read !== void 0) fields.month = read;
22753
+ read2 = digits(1, 2);
22754
+ if (read2 !== void 0) fields.month = read2;
22737
22755
  break;
22738
22756
  case "Y":
22739
- read = digits(1, 4);
22740
- if (read !== void 0) fields.year = read;
22757
+ read2 = digits(1, 4);
22758
+ if (read2 !== void 0) fields.year = read2;
22741
22759
  break;
22742
22760
  case "y":
22743
- read = digits(2, 2);
22744
- if (read !== void 0) fields.year = read + (read < 70 ? 2e3 : 1900);
22761
+ read2 = digits(2, 2);
22762
+ if (read2 !== void 0) fields.year = read2 + (read2 < 70 ? 2e3 : 1900);
22745
22763
  break;
22746
22764
  case "a":
22747
22765
  case "A": {
@@ -22753,49 +22771,49 @@ function parse(format2, value2) {
22753
22771
  }
22754
22772
  case "g":
22755
22773
  case "h":
22756
- read = digits(1, 2);
22757
- if (read !== void 0 && (read < 1 || read > 12)) return void 0;
22758
- if (read !== void 0) fields.hour = read;
22774
+ read2 = digits(1, 2);
22775
+ if (read2 !== void 0 && (read2 < 1 || read2 > 12)) return void 0;
22776
+ if (read2 !== void 0) fields.hour = read2;
22759
22777
  twelveHour = true;
22760
22778
  break;
22761
22779
  case "G":
22762
22780
  case "H":
22763
- read = digits(1, 2);
22764
- if (read !== void 0) fields.hour = read;
22781
+ read2 = digits(1, 2);
22782
+ if (read2 !== void 0) fields.hour = read2;
22765
22783
  break;
22766
22784
  case "i":
22767
- read = digits(2, 2);
22768
- if (read !== void 0) fields.minute = read;
22785
+ read2 = digits(2, 2);
22786
+ if (read2 !== void 0) fields.minute = read2;
22769
22787
  break;
22770
22788
  case "s":
22771
- read = digits(2, 2);
22772
- if (read !== void 0) fields.second = read;
22789
+ read2 = digits(2, 2);
22790
+ if (read2 !== void 0) fields.second = read2;
22773
22791
  break;
22774
22792
  case "v":
22775
- read = digits(3, 3);
22776
- if (read !== void 0) fields.micro = read * 1e3;
22793
+ read2 = digits(3, 3);
22794
+ if (read2 !== void 0) fields.micro = read2 * 1e3;
22777
22795
  break;
22778
22796
  case "u": {
22779
22797
  const match = /^\d{1,6}/.exec(value2.slice(position));
22780
- read = match ? Number(match[0].padEnd(6, "0")) : void 0;
22798
+ read2 = match ? Number(match[0].padEnd(6, "0")) : void 0;
22781
22799
  if (match) position += match[0].length;
22782
- if (read !== void 0) fields.micro = read;
22800
+ if (read2 !== void 0) fields.micro = read2;
22783
22801
  break;
22784
22802
  }
22785
22803
  case "O":
22786
- read = fields.offset = offset("none");
22804
+ read2 = fields.offset = offset("none");
22787
22805
  break;
22788
22806
  case "P":
22789
- read = fields.offset = offset("required");
22807
+ read2 = fields.offset = offset("required");
22790
22808
  break;
22791
22809
  case "p":
22792
- read = fields.offset = offset("z");
22810
+ read2 = fields.offset = offset("z");
22793
22811
  break;
22794
22812
  case "U": {
22795
22813
  const match = /^-?\d+/.exec(value2.slice(position));
22796
- read = match ? Number(match[0]) : void 0;
22814
+ read2 = match ? Number(match[0]) : void 0;
22797
22815
  if (match) position += match[0].length;
22798
- fields.unix = read;
22816
+ fields.unix = read2;
22799
22817
  break;
22800
22818
  }
22801
22819
  default:
@@ -22803,7 +22821,7 @@ function parse(format2, value2) {
22803
22821
  position++;
22804
22822
  continue;
22805
22823
  }
22806
- if (read === void 0) return void 0;
22824
+ if (read2 === void 0) return void 0;
22807
22825
  }
22808
22826
  if (position !== value2.length) return void 0;
22809
22827
  if (twelveHour && meridiem !== void 0) fields.hour = fields.hour % 12 + (meridiem === "pm" ? 12 : 0);
@@ -23008,8 +23026,8 @@ function resolveDateParam(ctx, rule, param, format2) {
23008
23026
  const parsed = readDate(fieldValue, ctx.getRule?.(param, "date_format")?.[0] ?? format2);
23009
23027
  if (!Number.isNaN(parsed)) return parsed;
23010
23028
  }
23011
- const relative6 = relativeDate(param);
23012
- if (relative6 !== void 0) return relative6;
23029
+ const relative8 = relativeDate(param);
23030
+ if (relative8 !== void 0) return relative8;
23013
23031
  const literal = readDate(param, format2);
23014
23032
  if (!Number.isNaN(literal)) return literal;
23015
23033
  if (FIELD_REFERENCE_RE.test(param)) return null;
@@ -24572,6 +24590,10 @@ var ValidationFactoryImpl = class {
24572
24590
  make(data, rules, messages = {}, attributes = {}) {
24573
24591
  return new ValidatorImpl(data, rules, messages, attributes, { ...builtinRules, ...this.extended });
24574
24592
  }
24593
+ /** Every rule this factory knows, built-in and extend()ed, sorted (for editors: `oriel ide:info`). */
24594
+ ruleNames() {
24595
+ return [.../* @__PURE__ */ new Set([...Object.keys(builtinRules), ...Object.keys(this.extended)])].sort();
24596
+ }
24575
24597
  extend(name, callback, message) {
24576
24598
  this.extended[name] = {
24577
24599
  validate: (ctx) => callback(ctx.attribute, ctx.value, ctx.parameters, ctx.data),
@@ -24588,6 +24610,139 @@ var ValidationServiceProvider = class extends ServiceProvider {
24588
24610
  }
24589
24611
  };
24590
24612
 
24613
+ // ide/IdeInfoCommand.ts
24614
+ import { existsSync as existsSync10, readdirSync as readdirSync9, readFileSync as readFileSync3 } from "fs";
24615
+ import { join as join16, relative as relative7, sep as sep6 } from "path";
24616
+
24617
+ // ide/sections.ts
24618
+ import { existsSync as existsSync9, readdirSync as readdirSync8 } from "fs";
24619
+ import { join as join15, relative as relative6, sep as sep5 } from "path";
24620
+ import { parse as parse2 } from "dotenv";
24621
+ var SECRET = /key|secret|password|token|credential|salt|private/i;
24622
+ var CREDENTIALS = /^[a-z][a-z0-9+.-]*:\/\/[^/?#\s]*@/i;
24623
+ var byName = (a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
24624
+ var posix2 = (path) => path.split(sep5).join("/");
24625
+ function commandSection(all) {
24626
+ return Object.entries(all).map(([name, command]) => {
24627
+ const signature = parseSignature(command.signature);
24628
+ return { name, description: command.description, arguments: signature.arguments, options: signature.options };
24629
+ }).sort(byName);
24630
+ }
24631
+ function configSection(all, configFiles) {
24632
+ const entries = [];
24633
+ const walk = (value2, path) => {
24634
+ const isPlain = typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && [Object.prototype, null].includes(Object.getPrototypeOf(value2));
24635
+ if (isPlain && path.length > 0 && Object.keys(value2).length === 0) return void entries.push(entry(path, "object"));
24636
+ if (isPlain) {
24637
+ for (const [key, child] of Object.entries(value2)) walk(child, [...path, key]);
24638
+ return;
24639
+ }
24640
+ const type = value2 === null ? "null" : Array.isArray(value2) ? "array" : typeof value2 === "function" ? "function" : typeof value2 === "object" ? "object" : typeof value2;
24641
+ const shown = ["string", "number", "boolean", "null"].includes(type) && !path.some((segment) => SECRET.test(segment)) && !(typeof value2 === "string" && CREDENTIALS.test(value2));
24642
+ entries.push({ ...entry(path, type), ...shown ? { value: value2 } : {} });
24643
+ };
24644
+ const entry = (path, type) => {
24645
+ const file = `config/${path[0]}.ts`;
24646
+ return { key: path.join("."), type, file: configFiles.includes(file) ? file : null };
24647
+ };
24648
+ walk(all, []);
24649
+ return entries.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
24650
+ }
24651
+ function envSection(env3, example) {
24652
+ const set = env3 === null ? {} : parse2(env3);
24653
+ const documented = example === null ? {} : parse2(example);
24654
+ const names = [.../* @__PURE__ */ new Set([...Object.keys(set), ...Object.keys(documented)])].sort();
24655
+ return names.map((name) => ({ name, inEnv: name in set, inExample: name in documented, example: name in documented ? documented[name] : null }));
24656
+ }
24657
+ function viewSection(paths, hints, extensions, basePath) {
24658
+ const views = /* @__PURE__ */ new Map();
24659
+ const collect2 = (root, prefix) => {
24660
+ if (!existsSync9(root)) return;
24661
+ for (const item of readdirSync8(root, { recursive: true, withFileTypes: true })) {
24662
+ if (!item.isFile()) continue;
24663
+ const extension = extensions.find((candidate) => item.name.endsWith(`.${candidate}`));
24664
+ if (extension === void 0) continue;
24665
+ const file = join15(item.parentPath, item.name);
24666
+ const name = prefix + posix2(relative6(root, file)).slice(0, -(extension.length + 1)).split("/").join(".");
24667
+ if (!views.has(name)) views.set(name, posix2(relative6(basePath, file)));
24668
+ }
24669
+ };
24670
+ for (const path of paths) collect2(path, "");
24671
+ for (const [namespace, roots] of Object.entries(hints)) for (const root of roots) collect2(root, `${namespace}::`);
24672
+ return [...views].map(([name, file]) => ({ name, file })).sort(byName);
24673
+ }
24674
+
24675
+ // ide/IdeInfoCommand.ts
24676
+ var posix3 = (path) => path.split(sep6).join("/");
24677
+ var read = (file) => existsSync10(file) ? readFileSync3(file, "utf8") : null;
24678
+ var IdeInfoCommand = class extends Command {
24679
+ signature = "ide:info {--pretty : Indent the JSON}";
24680
+ description = "Describe the application for editors, as JSON";
24681
+ handle() {
24682
+ const methods = ["log", "info", "debug"];
24683
+ const saved = methods.map((method) => console[method]);
24684
+ for (const method of methods) console[method] = (...args) => console.error(...args);
24685
+ let info;
24686
+ try {
24687
+ info = describe(inject(Application), currentContainer());
24688
+ } finally {
24689
+ methods.forEach((method, i) => console[method] = saved[i]);
24690
+ }
24691
+ this.line(this.option("pretty") ? JSON.stringify(info, null, 2) : JSON.stringify(info));
24692
+ return 0;
24693
+ }
24694
+ };
24695
+ function describeSafely(name, cls) {
24696
+ try {
24697
+ return describeComponent(cls);
24698
+ } catch (error) {
24699
+ console.error(`ide:info: the Live component [${name}] couldn't be built to read its actions: ${error instanceof Error ? error.message : String(error)}`);
24700
+ return { actions: [], properties: [] };
24701
+ }
24702
+ }
24703
+ function describe(app2, container) {
24704
+ const optional = (token2) => container.bound(token2) ? container.make(token2) : void 0;
24705
+ const basePath = app2.basePath();
24706
+ const config2 = optional(ConfigRepository);
24707
+ const get = (key, fallback) => config2 ? config2.get(key, fallback) : fallback;
24708
+ const relativeTo = (file) => posix3(relative7(basePath, file));
24709
+ const configDirectory = app2.configPath();
24710
+ const configFiles = existsSync10(configDirectory) ? readdirSync9(configDirectory).filter((file) => /\.(ts|js|mjs)$/.test(file)).map((file) => relativeTo(join16(configDirectory, file))) : [];
24711
+ const factory = optional(ViewFactory);
24712
+ const finder = factory instanceof Factory ? factory.getFinder() : void 0;
24713
+ const registry2 = optional(ClassRegistry);
24714
+ const classPath = get("live.class_path", app2.appPath("Live"));
24715
+ const live2 = registry2 ? componentFiles(classPath).flatMap((file) => {
24716
+ const name = componentName(file);
24717
+ if (!registry2.has(name)) return [];
24718
+ const cls = registry2.resolve(name);
24719
+ if (typeof cls !== "function" || !(cls.prototype instanceof Component)) return [];
24720
+ return [{ name, file: relativeTo(join16(classPath, file)), ...describeSafely(name, cls) }];
24721
+ }) : [];
24722
+ const validation = optional(ValidationFactory);
24723
+ const pagePaths = get("inertia.pages.paths", []);
24724
+ const inertia2 = pagePaths.some((path) => existsSync10(path)) ? { pages: pageNames(pagePaths, get("inertia.pages.extensions", [])).map((page) => ({ name: page.name, file: relativeTo(page.file) })) } : null;
24725
+ return {
24726
+ schema: 1,
24727
+ oriel: { version: app2.version, runtime: process.versions.bun ? "bun" : "node", runtimeVersion: process.versions.bun ?? process.versions.node, environment: app2.environment(), basePath },
24728
+ commands: commandSection(inject(ConsoleKernel).all()),
24729
+ routes: container.bound(Router) ? routeListRows(container.make(Router).getRoutes()) : [],
24730
+ config: config2 ? configSection(config2.all(), configFiles) : [],
24731
+ env: envSection(read(join16(basePath, ".env")), read(join16(basePath, ".env.example"))),
24732
+ views: finder ? viewSection(finder.getPaths(), finder.getHints(), FileViewFinder.defaultExtensions, basePath) : [],
24733
+ live: live2,
24734
+ rules: typeof validation?.ruleNames === "function" ? validation.ruleNames() : Object.keys(builtinRules).sort(),
24735
+ inertia: inertia2
24736
+ };
24737
+ }
24738
+
24739
+ // ide/IdeServiceProvider.ts
24740
+ var IdeServiceProvider = class extends ServiceProvider {
24741
+ boot() {
24742
+ this.app.make(ConsoleKernel).register(IdeInfoCommand);
24743
+ }
24744
+ };
24745
+
24591
24746
  // providers.ts
24592
24747
  function defaultProviders() {
24593
24748
  return [
@@ -24612,7 +24767,8 @@ function defaultProviders() {
24612
24767
  LiveServiceProvider,
24613
24768
  RoutingServiceProvider,
24614
24769
  HttpServiceProvider,
24615
- ConsoleServiceProvider
24770
+ ConsoleServiceProvider,
24771
+ IdeServiceProvider
24616
24772
  ];
24617
24773
  }
24618
24774