@gtkx/config 1.0.0-rc.4 → 1.1.0

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.
Files changed (46) hide show
  1. package/README.md +5 -5
  2. package/dist/config-error.d.ts +2 -1
  3. package/dist/config-error.d.ts.map +1 -1
  4. package/dist/config-error.js +16 -4
  5. package/dist/config-error.js.map +1 -1
  6. package/dist/config.d.ts +239 -5
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +6 -33
  9. package/dist/config.js.map +1 -1
  10. package/dist/deploy.d.ts +237 -0
  11. package/dist/deploy.d.ts.map +1 -0
  12. package/dist/deploy.js +232 -0
  13. package/dist/deploy.js.map +1 -0
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/internal.d.ts +2 -2
  18. package/dist/internal.d.ts.map +1 -1
  19. package/dist/internal.js +1 -1
  20. package/dist/internal.js.map +1 -1
  21. package/dist/loader.d.ts +6 -3
  22. package/dist/loader.d.ts.map +1 -1
  23. package/dist/loader.js +10 -8
  24. package/dist/loader.js.map +1 -1
  25. package/dist/schema-text.d.ts +10 -0
  26. package/dist/schema-text.d.ts.map +1 -0
  27. package/dist/schema-text.js +19 -0
  28. package/dist/schema-text.js.map +1 -0
  29. package/dist/user-event-signals.d.ts +1 -2
  30. package/dist/user-event-signals.d.ts.map +1 -1
  31. package/dist/user-event-signals.js +1 -7
  32. package/dist/user-event-signals.js.map +1 -1
  33. package/dist/vite-plugin.d.ts +8 -1
  34. package/dist/vite-plugin.d.ts.map +1 -1
  35. package/dist/vite-plugin.js +5 -1
  36. package/dist/vite-plugin.js.map +1 -1
  37. package/package.json +13 -3
  38. package/src/config-error.ts +23 -4
  39. package/src/config.ts +6 -36
  40. package/src/deploy.ts +260 -0
  41. package/src/index.ts +1 -1
  42. package/src/internal.ts +2 -1
  43. package/src/loader.ts +16 -9
  44. package/src/schema-text.ts +38 -0
  45. package/src/user-event-signals.ts +1 -7
  46. package/src/vite-plugin.ts +11 -2
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAe,YAAY,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC1F,cAAc;AACd,OAAO,EAAqB,UAAU,EAAE,MAAM,aAAa,CAAC","sourcesContent":["/** @public */\nexport { type Config, defineConfig, mergeConfig, type ResolvedConfig } from \"./config.ts\";\n/** @public */\nexport { type LoadedConfig, loadConfig } from \"./loader.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAe,YAAY,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAC1F,cAAc;AACd,OAAO,EAAwC,UAAU,EAAE,MAAM,aAAa,CAAC","sourcesContent":["/** @public */\nexport { type Config, defineConfig, mergeConfig, type ResolvedConfig } from \"./config.ts\";\n/** @public */\nexport { type ConfigLoader, type LoadedConfig, loadConfig } from \"./loader.ts\";\n"]}
@@ -1,4 +1,4 @@
1
1
  export type { ResolvedReactCompilerOptions } from "./config.ts";
2
- export { isValidApplicationId, resolveElementComponents, resolveElementProps, resolveLazyElements, resolveOmittedProps, } from "./config.ts";
3
- export { type ConfigLoader, createConfigLoader } from "./loader.ts";
2
+ export { APPLICATION_ID_MAX_LENGTH, isValidApplicationId, resolveElementComponents, resolveElementProps, resolveLazyElements, resolveOmittedProps, } from "./config.ts";
3
+ export { createConfigLoader } from "./loader.ts";
4
4
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACH,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EACH,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
package/dist/internal.js CHANGED
@@ -1,3 +1,3 @@
1
- export { isValidApplicationId, resolveElementComponents, resolveElementProps, resolveLazyElements, resolveOmittedProps, } from "./config.js";
1
+ export { APPLICATION_ID_MAX_LENGTH, isValidApplicationId, resolveElementComponents, resolveElementProps, resolveLazyElements, resolveOmittedProps, } from "./config.js";
2
2
  export { createConfigLoader } from "./loader.js";
3
3
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AACA,OAAO,EACH,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAqB,kBAAkB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export type { ResolvedReactCompilerOptions } from \"./config.ts\";\nexport {\n isValidApplicationId,\n resolveElementComponents,\n resolveElementProps,\n resolveLazyElements,\n resolveOmittedProps,\n} from \"./config.ts\";\nexport { type ConfigLoader, createConfigLoader } from \"./loader.ts\";\n"]}
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AACA,OAAO,EACH,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export type { ResolvedReactCompilerOptions } from \"./config.ts\";\nexport {\n APPLICATION_ID_MAX_LENGTH,\n isValidApplicationId,\n resolveElementComponents,\n resolveElementProps,\n resolveLazyElements,\n resolveOmittedProps,\n} from \"./config.ts\";\nexport { createConfigLoader } from \"./loader.ts\";\n"]}
package/dist/loader.d.ts CHANGED
@@ -16,17 +16,20 @@ type LoadConfigOptions = {
16
16
  */
17
17
  mode?: string | undefined;
18
18
  };
19
+ /** Reads a project's configuration once per directory, caching what it loads and what it resolves. */
19
20
  type ConfigLoader = {
21
+ /** Loads the configuration file the given directory resolves to, as {@link loadConfig} does. */
20
22
  load: (cwd: string) => Promise<LoadedConfig>;
23
+ /** Loads the configuration for the given directory and reduces it to what the build and the app need. */
21
24
  resolve: (cwd: string) => Promise<ResolvedConfig>;
22
25
  };
23
26
  /**
24
27
  * Loads and validates the `gtkx.config.ts` file for a project.
25
- * @param cwd Directory the configuration file is looked up in.
28
+ * @param cwd Directory the configuration file is looked up in; parent directories are not searched.
26
29
  * @param options Loading options, such as the environment mode whose overrides are applied.
27
- * @throws When the configuration fails validation, or when no configuration file is found.
30
+ * @throws When that directory holds no configuration file, or when the configuration fails validation.
28
31
  */
29
32
  declare const loadConfig: (cwd: string, options?: LoadConfigOptions) => Promise<LoadedConfig>;
30
33
  declare const createConfigLoader: (options?: LoadConfigOptions) => ConfigLoader;
31
- export { loadConfig, createConfigLoader, type LoadedConfig, type LoadConfigOptions, type ConfigLoader };
34
+ export { loadConfig, createConfigLoader, type LoadedConfig, type ConfigLoader };
32
35
  //# sourceMappingURL=loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAiB,KAAK,cAAc,EAAkB,MAAM,aAAa,CAAC;AAE9F,2DAA2D;AAC3D,KAAK,YAAY,GAAG;IAChB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,+FAA+F;AAC/F,KAAK,iBAAiB,GAAG;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,KAAK,YAAY,GAAG;IAChB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACrD,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAU,KAAK,MAAM,EAAE,UAAS,iBAAsB,KAAG,OAAO,CAAC,YAAY,CAwB5F,CAAC;AAEF,QAAA,MAAM,kBAAkB,GAAI,UAAS,iBAAsB,KAAG,YAiB7D,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,MAAM,EAAiB,KAAK,cAAc,EAAkB,MAAM,aAAa,CAAC;AAE9F,2DAA2D;AAC3D,KAAK,YAAY,GAAG;IAChB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,+FAA+F;AAC/F,KAAK,iBAAiB,GAAG;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,sGAAsG;AACtG,KAAK,YAAY,GAAG;IAChB,gGAAgG;IAChG,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,yGAAyG;IACzG,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACrD,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,UAAU,GAAU,KAAK,MAAM,EAAE,UAAS,iBAAsB,KAAG,OAAO,CAAC,YAAY,CA2B5F,CAAC;AAEF,QAAA,MAAM,kBAAkB,GAAI,UAAS,iBAAsB,KAAG,YAiB7D,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,CAAC"}
package/dist/loader.js CHANGED
@@ -2,33 +2,35 @@ import { getOrInsert } from "@gtkx/utils";
2
2
  import { loadConfig as loadConfigFile } from "c12";
3
3
  import { existsSync } from "node:fs";
4
4
  import { resolve } from "node:path";
5
+ import { missingConfigFileError } from "./config-error.js";
5
6
  import { resolveConfig, validateConfig } from "./config.js";
6
7
  /**
7
8
  * Loads and validates the `gtkx.config.ts` file for a project.
8
- * @param cwd Directory the configuration file is looked up in.
9
+ * @param cwd Directory the configuration file is looked up in; parent directories are not searched.
9
10
  * @param options Loading options, such as the environment mode whose overrides are applied.
10
- * @throws When the configuration fails validation, or when no configuration file is found.
11
+ * @throws When that directory holds no configuration file, or when the configuration fails validation.
11
12
  */
12
13
  const loadConfig = async (cwd, options = {}) => {
14
+ const searched = resolve(cwd);
13
15
  const result = await loadConfigFile({
14
16
  name: "gtkx",
15
- cwd,
17
+ cwd: searched,
16
18
  rcFile: false,
17
19
  globalRc: false,
18
20
  packageJson: false,
19
21
  context: { mode: options.mode },
20
22
  ...((options.mode !== undefined) && { envName: options.mode }),
21
23
  });
22
- const config = result.config;
23
24
  const configFile = result.configFile;
24
- validateConfig(config);
25
- if (configFile === undefined || !existsSync(resolve(cwd, configFile))) {
26
- throw new Error(`gtkx.config.ts: no configuration file was found from ${cwd}`);
25
+ if (configFile === undefined || !existsSync(resolve(searched, configFile))) {
26
+ throw missingConfigFileError(searched);
27
27
  }
28
+ const config = result.config;
29
+ validateConfig(config);
28
30
  return {
29
31
  config,
30
32
  configFile,
31
- root: result.cwd ?? cwd,
33
+ root: result.cwd ?? searched,
32
34
  };
33
35
  };
34
36
  const createConfigLoader = (options = {}) => {
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,KAAK,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAe,aAAa,EAAuB,cAAc,EAAE,MAAM,aAAa,CAAC;AA0B9F;;;;;GAKG;AACH,MAAM,UAAU,GAAG,KAAK,EAAE,GAAW,EAAE,UAA6B,EAAE,EAAyB,EAAE;IAC7F,MAAM,MAAM,GAAG,MAAM,cAAc,CAAS;QACxC,IAAI,EAAE,MAAM;QACZ,GAAG;QACH,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;QAC/B,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;KACjE,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,wDAAwD,GAAG,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,OAAO;QACH,MAAM;QACN,UAAU;QACV,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG;KAC1B,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,UAA6B,EAAE,EAAgB,EAAE;IACzE,MAAM,MAAM,GAAuC,IAAI,GAAG,EAAE,CAAC;IAC7D,MAAM,QAAQ,GAAyC,IAAI,GAAG,EAAE,CAAC;IAEjE,MAAM,IAAI,GAAG,CAAC,GAAW,EAAyB,EAAE,CAChD,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAE3E,MAAM,SAAS,GAAG,KAAK,EAAE,IAAY,EAA2B,EAAE;QAC9D,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAEtD,OAAO,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,OAAO;QACH,IAAI;QACJ,OAAO,EAAE,CAAC,GAAW,EAA2B,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC;KACpG,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAgE,CAAC","sourcesContent":["import { getOrInsert } from \"@gtkx/utils\";\nimport { loadConfig as loadConfigFile } from \"c12\";\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { type Config, resolveConfig, type ResolvedConfig, validateConfig } from \"./config.ts\";\n\n/** Result of loading a project's `gtkx.config.ts` file. */\ntype LoadedConfig = {\n /** The parsed and validated configuration. */\n config: Config;\n /** Absolute path of the configuration file that was loaded. */\n configFile: string;\n /** Absolute path of the project root the configuration was resolved against. */\n root: string;\n};\n\n/** How a configuration file is read, shared by {@link loadConfig} and `createConfigLoader`. */\ntype LoadConfigOptions = {\n /**\n * Environment name such as `development`: the config's matching `$<mode>` block is layered over the\n * top-level values, and the name is passed to a config authored as a function.\n */\n mode?: string | undefined;\n};\n\ntype ConfigLoader = {\n load: (cwd: string) => Promise<LoadedConfig>;\n resolve: (cwd: string) => Promise<ResolvedConfig>;\n};\n\n/**\n * Loads and validates the `gtkx.config.ts` file for a project.\n * @param cwd Directory the configuration file is looked up in.\n * @param options Loading options, such as the environment mode whose overrides are applied.\n * @throws When the configuration fails validation, or when no configuration file is found.\n */\nconst loadConfig = async (cwd: string, options: LoadConfigOptions = {}): Promise<LoadedConfig> => {\n const result = await loadConfigFile<Config>({\n name: \"gtkx\",\n cwd,\n rcFile: false,\n globalRc: false,\n packageJson: false,\n context: { mode: options.mode },\n ...((options.mode !== undefined) && { envName: options.mode }),\n });\n\n const config = result.config;\n const configFile = result.configFile;\n validateConfig(config);\n\n if (configFile === undefined || !existsSync(resolve(cwd, configFile))) {\n throw new Error(`gtkx.config.ts: no configuration file was found from ${cwd}`);\n }\n\n return {\n config,\n configFile,\n root: result.cwd ?? cwd,\n };\n};\n\nconst createConfigLoader = (options: LoadConfigOptions = {}): ConfigLoader => {\n const loaded: Map<string, Promise<LoadedConfig>> = new Map();\n const resolved: Map<string, Promise<ResolvedConfig>> = new Map();\n\n const load = (cwd: string): Promise<LoadedConfig> =>\n getOrInsert(loaded, resolve(cwd), (root) => loadConfig(root, options));\n\n const resolveAt = async (root: string): Promise<ResolvedConfig> => {\n const { config, root: configRoot } = await load(root);\n\n return resolveConfig(config, configRoot);\n };\n\n return {\n load,\n resolve: (cwd: string): Promise<ResolvedConfig> => getOrInsert(resolved, resolve(cwd), resolveAt),\n };\n};\n\nexport { loadConfig, createConfigLoader, type LoadedConfig, type LoadConfigOptions, type ConfigLoader };\n"]}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,KAAK,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAe,aAAa,EAAuB,cAAc,EAAE,MAAM,aAAa,CAAC;AA6B9F;;;;;GAKG;AACH,MAAM,UAAU,GAAG,KAAK,EAAE,GAAW,EAAE,UAA6B,EAAE,EAAyB,EAAE;IAC7F,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE9B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAS;QACxC,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,QAAQ;QACb,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;QAC/B,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;KACjE,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAErC,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO;QACH,MAAM;QACN,UAAU;QACV,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,QAAQ;KAC/B,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,UAA6B,EAAE,EAAgB,EAAE;IACzE,MAAM,MAAM,GAAuC,IAAI,GAAG,EAAE,CAAC;IAC7D,MAAM,QAAQ,GAAyC,IAAI,GAAG,EAAE,CAAC;IAEjE,MAAM,IAAI,GAAG,CAAC,GAAW,EAAyB,EAAE,CAChD,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAE3E,MAAM,SAAS,GAAG,KAAK,EAAE,IAAY,EAA2B,EAAE;QAC9D,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAEtD,OAAO,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,OAAO;QACH,IAAI;QACJ,OAAO,EAAE,CAAC,GAAW,EAA2B,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC;KACpG,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAwC,CAAC","sourcesContent":["import { getOrInsert } from \"@gtkx/utils\";\nimport { loadConfig as loadConfigFile } from \"c12\";\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { missingConfigFileError } from \"./config-error.ts\";\nimport { type Config, resolveConfig, type ResolvedConfig, validateConfig } from \"./config.ts\";\n\n/** Result of loading a project's `gtkx.config.ts` file. */\ntype LoadedConfig = {\n /** The parsed and validated configuration. */\n config: Config;\n /** Absolute path of the configuration file that was loaded. */\n configFile: string;\n /** Absolute path of the project root the configuration was resolved against. */\n root: string;\n};\n\n/** How a configuration file is read, shared by {@link loadConfig} and `createConfigLoader`. */\ntype LoadConfigOptions = {\n /**\n * Environment name such as `development`: the config's matching `$<mode>` block is layered over the\n * top-level values, and the name is passed to a config authored as a function.\n */\n mode?: string | undefined;\n};\n\n/** Reads a project's configuration once per directory, caching what it loads and what it resolves. */\ntype ConfigLoader = {\n /** Loads the configuration file the given directory resolves to, as {@link loadConfig} does. */\n load: (cwd: string) => Promise<LoadedConfig>;\n /** Loads the configuration for the given directory and reduces it to what the build and the app need. */\n resolve: (cwd: string) => Promise<ResolvedConfig>;\n};\n\n/**\n * Loads and validates the `gtkx.config.ts` file for a project.\n * @param cwd Directory the configuration file is looked up in; parent directories are not searched.\n * @param options Loading options, such as the environment mode whose overrides are applied.\n * @throws When that directory holds no configuration file, or when the configuration fails validation.\n */\nconst loadConfig = async (cwd: string, options: LoadConfigOptions = {}): Promise<LoadedConfig> => {\n const searched = resolve(cwd);\n\n const result = await loadConfigFile<Config>({\n name: \"gtkx\",\n cwd: searched,\n rcFile: false,\n globalRc: false,\n packageJson: false,\n context: { mode: options.mode },\n ...((options.mode !== undefined) && { envName: options.mode }),\n });\n\n const configFile = result.configFile;\n\n if (configFile === undefined || !existsSync(resolve(searched, configFile))) {\n throw missingConfigFileError(searched);\n }\n\n const config = result.config;\n validateConfig(config);\n\n return {\n config,\n configFile,\n root: result.cwd ?? searched,\n };\n};\n\nconst createConfigLoader = (options: LoadConfigOptions = {}): ConfigLoader => {\n const loaded: Map<string, Promise<LoadedConfig>> = new Map();\n const resolved: Map<string, Promise<ResolvedConfig>> = new Map();\n\n const load = (cwd: string): Promise<LoadedConfig> =>\n getOrInsert(loaded, resolve(cwd), (root) => loadConfig(root, options));\n\n const resolveAt = async (root: string): Promise<ResolvedConfig> => {\n const { config, root: configRoot } = await load(root);\n\n return resolveConfig(config, configRoot);\n };\n\n return {\n load,\n resolve: (cwd: string): Promise<ResolvedConfig> => getOrInsert(resolved, resolve(cwd), resolveAt),\n };\n};\n\nexport { loadConfig, createConfigLoader, type LoadedConfig, type ConfigLoader };\n"]}
@@ -0,0 +1,10 @@
1
+ import { z } from "zod";
2
+ declare const text: (message: string) => z.ZodString;
3
+ declare const textList: (itemNoun: string, listMessage: string) => z.ZodArray<z.ZodString>;
4
+ declare const url: (message: string) => z.ZodURL;
5
+ declare const flag: (message: string) => z.ZodBoolean;
6
+ declare const textRecord: (valueMessage: string, recordMessage: string) => z.ZodRecord<z.ZodString, z.ZodString>;
7
+ declare const fileExtension: (message: string) => z.ZodString;
8
+ declare const relativePathRecord: (keyMessage: string, valueMessage: string, recordMessage: string) => z.ZodRecord<z.ZodString, z.ZodString>;
9
+ export { fileExtension, flag, relativePathRecord, text, textList, textRecord, url };
10
+ //# sourceMappingURL=schema-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-text.d.ts","sourceRoot":"","sources":["../src/schema-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,QAAA,MAAM,IAAI,GAAI,SAAS,MAAM,KAAG,CAAC,CAAC,SAAoE,CAAC;AAEvG,QAAA,MAAM,QAAQ,GAAI,UAAU,MAAM,EAAE,aAAa,MAAM,KAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CACJ,CAAC;AAE7E,QAAA,MAAM,GAAG,GAAI,SAAS,MAAM,KAAG,CAAC,CAAC,MAAmC,CAAC;AACrE,QAAA,MAAM,IAAI,GAAI,SAAS,MAAM,KAAG,CAAC,CAAC,UAA2C,CAAC;AAE9E,QAAA,MAAM,UAAU,GAAI,cAAc,MAAM,EAAE,eAAe,MAAM,KAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAChC,CAAC;AAEvE,QAAA,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,CAAC,CAAC,SACuD,CAAC;AAKnG,QAAA,MAAM,kBAAkB,GACpB,YAAY,MAAM,EAClB,cAAc,MAAM,EACpB,eAAe,MAAM,KACtB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAC6C,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ const FILE_EXTENSION = /^[^\s./\\*?[\]]+(?:\.[^\s./\\*?[\]]+)*$/;
3
+ const SEGMENT_SEPARATOR = /[/\\]/;
4
+ const isRelativePath = (value) => {
5
+ if (value.length === 0 || value.startsWith("/") || value.includes("\\")) {
6
+ return false;
7
+ }
8
+ return value.split(SEGMENT_SEPARATOR).every((part) => part !== "" && part !== "..");
9
+ };
10
+ const text = (message) => z.string({ error: message }).min(1, { error: message });
11
+ const textList = (itemNoun, listMessage) => z.array(text(`must be a non-empty ${itemNoun}`), { error: listMessage });
12
+ const url = (message) => z.url({ error: message });
13
+ const flag = (message) => z.boolean({ error: message });
14
+ const textRecord = (valueMessage, recordMessage) => z.record(z.string(), text(valueMessage), { error: recordMessage });
15
+ const fileExtension = (message) => z.string({ error: message }).refine((value) => FILE_EXTENSION.test(value), { error: message });
16
+ const relativePath = (message) => z.string({ error: message }).refine((value) => isRelativePath(value), { error: message });
17
+ const relativePathRecord = (keyMessage, valueMessage, recordMessage) => z.record(relativePath(keyMessage), text(valueMessage), { error: recordMessage });
18
+ export { fileExtension, flag, relativePathRecord, text, textList, textRecord, url };
19
+ //# sourceMappingURL=schema-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-text.js","sourceRoot":"","sources":["../src/schema-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,cAAc,GAAG,yCAAyC,CAAC;AACjE,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAElC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAW,EAAE;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;AACxF,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,CAAC,OAAe,EAAe,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAEvG,MAAM,QAAQ,GAAG,CAAC,QAAgB,EAAE,WAAmB,EAA2B,EAAE,CAChF,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,QAAQ,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;AAE7E,MAAM,GAAG,GAAG,CAAC,OAAe,EAAY,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AACrE,MAAM,IAAI,GAAG,CAAC,OAAe,EAAgB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9E,MAAM,UAAU,GAAG,CAAC,YAAoB,EAAE,aAAqB,EAAyC,EAAE,CACtG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;AAEvE,MAAM,aAAa,GAAG,CAAC,OAAe,EAAe,EAAE,CACnD,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAEnG,MAAM,YAAY,GAAG,CAAC,OAAe,EAAe,EAAE,CAClD,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9F,MAAM,kBAAkB,GAAG,CACvB,UAAkB,EAClB,YAAoB,EACpB,aAAqB,EACgB,EAAE,CACvC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC","sourcesContent":["import { z } from \"zod\";\n\nconst FILE_EXTENSION = /^[^\\s./\\\\*?[\\]]+(?:\\.[^\\s./\\\\*?[\\]]+)*$/;\nconst SEGMENT_SEPARATOR = /[/\\\\]/;\n\nconst isRelativePath = (value: string): boolean => {\n if (value.length === 0 || value.startsWith(\"/\") || value.includes(\"\\\\\")) {\n return false;\n }\n\n return value.split(SEGMENT_SEPARATOR).every((part) => part !== \"\" && part !== \"..\");\n};\n\nconst text = (message: string): z.ZodString => z.string({ error: message }).min(1, { error: message });\n\nconst textList = (itemNoun: string, listMessage: string): z.ZodArray<z.ZodString> =>\n z.array(text(`must be a non-empty ${itemNoun}`), { error: listMessage });\n\nconst url = (message: string): z.ZodURL => z.url({ error: message });\nconst flag = (message: string): z.ZodBoolean => z.boolean({ error: message });\n\nconst textRecord = (valueMessage: string, recordMessage: string): z.ZodRecord<z.ZodString, z.ZodString> =>\n z.record(z.string(), text(valueMessage), { error: recordMessage });\n\nconst fileExtension = (message: string): z.ZodString =>\n z.string({ error: message }).refine((value) => FILE_EXTENSION.test(value), { error: message });\n\nconst relativePath = (message: string): z.ZodString =>\n z.string({ error: message }).refine((value) => isRelativePath(value), { error: message });\n\nconst relativePathRecord = (\n keyMessage: string,\n valueMessage: string,\n recordMessage: string,\n): z.ZodRecord<z.ZodString, z.ZodString> =>\n z.record(relativePath(keyMessage), text(valueMessage), { error: recordMessage });\n\nexport { fileExtension, flag, relativePathRecord, text, textList, textRecord, url };\n"]}
@@ -1,4 +1,3 @@
1
- declare const DEFAULT_USER_EVENT_SIGNALS: Record<string, string[]>;
2
1
  declare const resolveUserEventSignals: (overrides: Record<string, string[]> | undefined) => Record<string, string[]>;
3
- export { DEFAULT_USER_EVENT_SIGNALS, resolveUserEventSignals };
2
+ export { resolveUserEventSignals };
4
3
  //# sourceMappingURL=user-event-signals.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-event-signals.d.ts","sourceRoot":"","sources":["../src/user-event-signals.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA2CxD,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAI,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CASzG,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"user-event-signals.d.ts","sourceRoot":"","sources":["../src/user-event-signals.ts"],"names":[],"mappings":"AAuCA,QAAA,MAAM,uBAAuB,GAAI,WAAW,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CASzG,CAAC;AAEF,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
@@ -6,15 +6,11 @@ const DEFAULT_USER_EVENT_SIGNALS = {
6
6
  AdwTabView: ["close-page", "page-attached", "page-detached", "page-reordered"],
7
7
  GObject: ["notify"],
8
8
  GtkAdjustment: ["changed", "value-changed"],
9
- GtkAppChooserButton: ["changed"],
10
- GtkAppChooserWidget: ["application-selected"],
11
9
  GtkCalendar: ["day-selected"],
12
10
  GtkCheckButton: ["toggled"],
13
- GtkComboBox: ["changed"],
14
11
  GtkEditable: ["changed", "delete-text", "insert-text"],
15
12
  GtkEntryBuffer: ["deleted-text", "inserted-text"],
16
13
  GtkFlowBox: ["selected-children-changed"],
17
- GtkIconView: ["selection-changed"],
18
14
  GtkListBox: ["row-selected", "selected-rows-changed"],
19
15
  GtkNotebook: ["page-added", "page-removed", "page-reordered", "switch-page"],
20
16
  GtkPopover: ["closed"],
@@ -38,8 +34,6 @@ const DEFAULT_USER_EVENT_SIGNALS = {
38
34
  "remove-tag",
39
35
  ],
40
36
  GtkToggleButton: ["toggled"],
41
- GtkTreeSelection: ["changed"],
42
- GtkTreeView: ["columns-changed", "cursor-changed", "row-collapsed", "row-expanded"],
43
37
  GtkWidget: ["state-flags-changed"],
44
38
  };
45
39
  const resolveUserEventSignals = (overrides) => {
@@ -50,5 +44,5 @@ const resolveUserEventSignals = (overrides) => {
50
44
  }
51
45
  return resolved;
52
46
  };
53
- export { DEFAULT_USER_EVENT_SIGNALS, resolveUserEventSignals };
47
+ export { resolveUserEventSignals };
54
48
  //# sourceMappingURL=user-event-signals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-event-signals.js","sourceRoot":"","sources":["../src/user-event-signals.ts"],"names":[],"mappings":"AAAA,MAAM,0BAA0B,GAA6B;IACzD,cAAc,EAAE,CAAC,UAAU,CAAC;IAC5B,WAAW,EAAE,CAAC,cAAc,CAAC;IAC7B,SAAS,EAAE,CAAC,QAAQ,CAAC;IACrB,iBAAiB,EAAE,CAAC,QAAQ,CAAC;IAC7B,UAAU,EAAE,CAAC,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,CAAC;IAC9E,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,aAAa,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;IAC3C,mBAAmB,EAAE,CAAC,SAAS,CAAC;IAChC,mBAAmB,EAAE,CAAC,sBAAsB,CAAC;IAC7C,WAAW,EAAE,CAAC,cAAc,CAAC;IAC7B,cAAc,EAAE,CAAC,SAAS,CAAC;IAC3B,WAAW,EAAE,CAAC,SAAS,CAAC;IACxB,WAAW,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC;IACtD,cAAc,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;IACjD,UAAU,EAAE,CAAC,2BAA2B,CAAC;IACzC,WAAW,EAAE,CAAC,mBAAmB,CAAC;IAClC,UAAU,EAAE,CAAC,cAAc,EAAE,uBAAuB,CAAC;IACrD,WAAW,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAC5E,UAAU,EAAE,CAAC,QAAQ,CAAC;IACtB,QAAQ,EAAE,CAAC,eAAe,CAAC;IAC3B,cAAc,EAAE,CAAC,eAAe,CAAC;IACjC,iBAAiB,EAAE,CAAC,cAAc,CAAC;IACnC,cAAc,EAAE,CAAC,gBAAgB,CAAC;IAClC,iBAAiB,EAAE,CAAC,mBAAmB,CAAC;IACxC,aAAa,EAAE,CAAC,eAAe,CAAC;IAChC,SAAS,EAAE,CAAC,WAAW,CAAC;IACxB,aAAa,EAAE;QACX,WAAW;QACX,SAAS;QACT,cAAc;QACd,qBAAqB;QACrB,kBAAkB;QAClB,aAAa;QACb,cAAc;QACd,UAAU;QACV,kBAAkB;QAClB,YAAY;KACf;IACD,eAAe,EAAE,CAAC,SAAS,CAAC;IAC5B,gBAAgB,EAAE,CAAC,SAAS,CAAC;IAC7B,WAAW,EAAE,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,CAAC;IACnF,SAAS,EAAE,CAAC,qBAAqB,CAAC;CACrC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,SAA+C,EAA4B,EAAE;IAC1G,MAAM,QAAQ,GAA6B,EAAE,GAAG,0BAA0B,EAAE,CAAC;IAC7E,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAExD,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,eAAe,EAAE,CAAC;QAChD,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,CAAC","sourcesContent":["const DEFAULT_USER_EVENT_SIGNALS: Record<string, string[]> = {\n AdwAlertDialog: [\"response\"],\n AdwCarousel: [\"page-changed\"],\n AdwDialog: [\"closed\"],\n AdwNavigationView: [\"pushed\"],\n AdwTabView: [\"close-page\", \"page-attached\", \"page-detached\", \"page-reordered\"],\n GObject: [\"notify\"],\n GtkAdjustment: [\"changed\", \"value-changed\"],\n GtkAppChooserButton: [\"changed\"],\n GtkAppChooserWidget: [\"application-selected\"],\n GtkCalendar: [\"day-selected\"],\n GtkCheckButton: [\"toggled\"],\n GtkComboBox: [\"changed\"],\n GtkEditable: [\"changed\", \"delete-text\", \"insert-text\"],\n GtkEntryBuffer: [\"deleted-text\", \"inserted-text\"],\n GtkFlowBox: [\"selected-children-changed\"],\n GtkIconView: [\"selection-changed\"],\n GtkListBox: [\"row-selected\", \"selected-rows-changed\"],\n GtkNotebook: [\"page-added\", \"page-removed\", \"page-reordered\", \"switch-page\"],\n GtkPopover: [\"closed\"],\n GtkRange: [\"value-changed\"],\n GtkScaleButton: [\"value-changed\"],\n GtkScrolledWindow: [\"edge-reached\"],\n GtkSearchEntry: [\"search-changed\"],\n GtkSelectionModel: [\"selection-changed\"],\n GtkSpinButton: [\"value-changed\"],\n GtkSwitch: [\"state-set\"],\n GtkTextBuffer: [\n \"apply-tag\",\n \"changed\",\n \"delete-range\",\n \"insert-child-anchor\",\n \"insert-paintable\",\n \"insert-text\",\n \"mark-deleted\",\n \"mark-set\",\n \"modified-changed\",\n \"remove-tag\",\n ],\n GtkToggleButton: [\"toggled\"],\n GtkTreeSelection: [\"changed\"],\n GtkTreeView: [\"columns-changed\", \"cursor-changed\", \"row-collapsed\", \"row-expanded\"],\n GtkWidget: [\"state-flags-changed\"],\n};\n\nconst resolveUserEventSignals = (overrides: Record<string, string[]> | undefined): Record<string, string[]> => {\n const resolved: Record<string, string[]> = { ...DEFAULT_USER_EVENT_SIGNALS };\n const overrideEntries = Object.entries(overrides ?? {});\n\n for (const [typeName, signals] of overrideEntries) {\n resolved[typeName] = [...new Set([...(resolved[typeName] ?? []), ...signals])];\n }\n\n return resolved;\n};\n\nexport { DEFAULT_USER_EVENT_SIGNALS, resolveUserEventSignals };\n"]}
1
+ {"version":3,"file":"user-event-signals.js","sourceRoot":"","sources":["../src/user-event-signals.ts"],"names":[],"mappings":"AAAA,MAAM,0BAA0B,GAA6B;IACzD,cAAc,EAAE,CAAC,UAAU,CAAC;IAC5B,WAAW,EAAE,CAAC,cAAc,CAAC;IAC7B,SAAS,EAAE,CAAC,QAAQ,CAAC;IACrB,iBAAiB,EAAE,CAAC,QAAQ,CAAC;IAC7B,UAAU,EAAE,CAAC,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,CAAC;IAC9E,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,aAAa,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;IAC3C,WAAW,EAAE,CAAC,cAAc,CAAC;IAC7B,cAAc,EAAE,CAAC,SAAS,CAAC;IAC3B,WAAW,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC;IACtD,cAAc,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;IACjD,UAAU,EAAE,CAAC,2BAA2B,CAAC;IACzC,UAAU,EAAE,CAAC,cAAc,EAAE,uBAAuB,CAAC;IACrD,WAAW,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAC5E,UAAU,EAAE,CAAC,QAAQ,CAAC;IACtB,QAAQ,EAAE,CAAC,eAAe,CAAC;IAC3B,cAAc,EAAE,CAAC,eAAe,CAAC;IACjC,iBAAiB,EAAE,CAAC,cAAc,CAAC;IACnC,cAAc,EAAE,CAAC,gBAAgB,CAAC;IAClC,iBAAiB,EAAE,CAAC,mBAAmB,CAAC;IACxC,aAAa,EAAE,CAAC,eAAe,CAAC;IAChC,SAAS,EAAE,CAAC,WAAW,CAAC;IACxB,aAAa,EAAE;QACX,WAAW;QACX,SAAS;QACT,cAAc;QACd,qBAAqB;QACrB,kBAAkB;QAClB,aAAa;QACb,cAAc;QACd,UAAU;QACV,kBAAkB;QAClB,YAAY;KACf;IACD,eAAe,EAAE,CAAC,SAAS,CAAC;IAC5B,SAAS,EAAE,CAAC,qBAAqB,CAAC;CACrC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAAC,SAA+C,EAA4B,EAAE;IAC1G,MAAM,QAAQ,GAA6B,EAAE,GAAG,0BAA0B,EAAE,CAAC;IAC7E,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAExD,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,eAAe,EAAE,CAAC;QAChD,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAC;AAEF,OAAO,EAAE,uBAAuB,EAAE,CAAC","sourcesContent":["const DEFAULT_USER_EVENT_SIGNALS: Record<string, string[]> = {\n AdwAlertDialog: [\"response\"],\n AdwCarousel: [\"page-changed\"],\n AdwDialog: [\"closed\"],\n AdwNavigationView: [\"pushed\"],\n AdwTabView: [\"close-page\", \"page-attached\", \"page-detached\", \"page-reordered\"],\n GObject: [\"notify\"],\n GtkAdjustment: [\"changed\", \"value-changed\"],\n GtkCalendar: [\"day-selected\"],\n GtkCheckButton: [\"toggled\"],\n GtkEditable: [\"changed\", \"delete-text\", \"insert-text\"],\n GtkEntryBuffer: [\"deleted-text\", \"inserted-text\"],\n GtkFlowBox: [\"selected-children-changed\"],\n GtkListBox: [\"row-selected\", \"selected-rows-changed\"],\n GtkNotebook: [\"page-added\", \"page-removed\", \"page-reordered\", \"switch-page\"],\n GtkPopover: [\"closed\"],\n GtkRange: [\"value-changed\"],\n GtkScaleButton: [\"value-changed\"],\n GtkScrolledWindow: [\"edge-reached\"],\n GtkSearchEntry: [\"search-changed\"],\n GtkSelectionModel: [\"selection-changed\"],\n GtkSpinButton: [\"value-changed\"],\n GtkSwitch: [\"state-set\"],\n GtkTextBuffer: [\n \"apply-tag\",\n \"changed\",\n \"delete-range\",\n \"insert-child-anchor\",\n \"insert-paintable\",\n \"insert-text\",\n \"mark-deleted\",\n \"mark-set\",\n \"modified-changed\",\n \"remove-tag\",\n ],\n GtkToggleButton: [\"toggled\"],\n GtkWidget: [\"state-flags-changed\"],\n};\n\nconst resolveUserEventSignals = (overrides: Record<string, string[]> | undefined): Record<string, string[]> => {\n const resolved: Record<string, string[]> = { ...DEFAULT_USER_EVENT_SIGNALS };\n const overrideEntries = Object.entries(overrides ?? {});\n\n for (const [typeName, signals] of overrideEntries) {\n resolved[typeName] = [...new Set([...(resolved[typeName] ?? []), ...signals])];\n }\n\n return resolved;\n};\n\nexport { resolveUserEventSignals };\n"]}
@@ -1,9 +1,16 @@
1
1
  import type { Plugin, UserConfig } from "vite";
2
2
  import { type ConfigLoader } from "./loader.ts";
3
+ /**
4
+ * Creates a Vite plugin serving `virtual:gtkx-config`, the module carrying the project's resolved
5
+ * `gtkx.config.ts`.
6
+ */
3
7
  declare const createConfigPlugin: (options: {
8
+ /** Name the plugin is registered under in Vite. */
4
9
  name: string;
10
+ /** Loader the configuration is resolved through, defaulting to a fresh caching loader. */
5
11
  loadConfig?: ConfigLoader;
6
- config?: () => Omit<UserConfig, "plugins">;
12
+ /** Extra Vite configuration contributed from the plugin's `config` hook, given the user's own configuration. */
13
+ config?: (config: UserConfig) => Omit<UserConfig, "plugins">;
7
14
  }) => Plugin;
8
15
  export default createConfigPlugin;
9
16
  //# sourceMappingURL=vite-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAsBpE,QAAA,MAAM,kBAAkB,GAAI,SAAS;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;CAC9C,KAAG,MAcH,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAwBpE;;;GAGG;AACH,QAAA,MAAM,kBAAkB,GAAI,SAAS;IACjC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,gHAAgH;IAChH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;CAChE,KAAG,MAcH,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -7,6 +7,10 @@ const loadVirtualModule = async (id, loadConfig, state) => {
7
7
  }
8
8
  return renderConfigModule(await loadConfig.resolve(state.root ?? process.cwd()));
9
9
  };
10
+ /**
11
+ * Creates a Vite plugin serving `virtual:gtkx-config`, the module carrying the project's resolved
12
+ * `gtkx.config.ts`.
13
+ */
10
14
  const createConfigPlugin = (options) => {
11
15
  const loadConfig = options.loadConfig ?? createConfigLoader();
12
16
  const state = { root: undefined };
@@ -14,7 +18,7 @@ const createConfigPlugin = (options) => {
14
18
  name: options.name,
15
19
  config(config) {
16
20
  state.root = config.root ?? state.root;
17
- return options.config?.();
21
+ return options.config?.(config);
18
22
  },
19
23
  resolveId: (id) => resolveVirtualId(id),
20
24
  load: (id) => loadVirtualModule(id, loadConfig, state),
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAM3G,MAAM,gBAAgB,GAAG,CAAC,EAAU,EAAiB,EAAE,CACnD,EAAE,KAAK,sBAAsB,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,IAAI,CAAC;AAE3E,MAAM,iBAAiB,GAAG,KAAK,EAC3B,EAAU,EACV,UAAwB,EACxB,KAAkB,EACS,EAAE;IAC7B,IAAI,EAAE,KAAK,+BAA+B,EAAE,CAAC;QACzC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,kBAAkB,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,OAI3B,EAAU,EAAE;IACT,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,EAAE,CAAC;IAC9D,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAE/C,OAAO;QACH,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,CAAC,MAAkB;YACrB,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;YAEvC,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9B,CAAC;QACD,SAAS,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/C,IAAI,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC;KACjE,CAAC;AACN,CAAC,CAAC;AAEF,eAAe,kBAAkB,CAAC","sourcesContent":["import type { Plugin, UserConfig } from \"vite\";\nimport { type ConfigLoader, createConfigLoader } from \"./loader.ts\";\nimport { GTKX_CONFIG_VIRTUAL_ID, renderConfigModule, RESOLVED_GTKX_CONFIG_VIRTUAL_ID } from \"./virtual.ts\";\n\ntype PluginState = {\n root: string | undefined;\n};\n\nconst resolveVirtualId = (id: string): string | null =>\n id === GTKX_CONFIG_VIRTUAL_ID ? RESOLVED_GTKX_CONFIG_VIRTUAL_ID : null;\n\nconst loadVirtualModule = async (\n id: string,\n loadConfig: ConfigLoader,\n state: PluginState,\n): Promise<string | undefined> => {\n if (id !== RESOLVED_GTKX_CONFIG_VIRTUAL_ID) {\n return undefined;\n }\n\n return renderConfigModule(await loadConfig.resolve(state.root ?? process.cwd()));\n};\n\nconst createConfigPlugin = (options: {\n name: string;\n loadConfig?: ConfigLoader;\n config?: () => Omit<UserConfig, \"plugins\">;\n}): Plugin => {\n const loadConfig = options.loadConfig ?? createConfigLoader();\n const state: PluginState = { root: undefined };\n\n return {\n name: options.name,\n config(config: UserConfig) {\n state.root = config.root ?? state.root;\n\n return options.config?.();\n },\n resolveId: (id: string) => resolveVirtualId(id),\n load: (id: string) => loadVirtualModule(id, loadConfig, state),\n };\n};\n\nexport default createConfigPlugin;\n"]}
1
+ {"version":3,"file":"vite-plugin.js","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAQ3G,MAAM,gBAAgB,GAAG,CAAC,EAAU,EAAiB,EAAE,CACnD,EAAE,KAAK,sBAAsB,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,IAAI,CAAC;AAE3E,MAAM,iBAAiB,GAAG,KAAK,EAC3B,EAAU,EACV,UAAwB,EACxB,KAAkB,EACS,EAAE;IAC7B,IAAI,EAAE,KAAK,+BAA+B,EAAE,CAAC;QACzC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO,kBAAkB,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACrF,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,kBAAkB,GAAG,CAAC,OAO3B,EAAU,EAAE;IACT,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,EAAE,CAAC;IAC9D,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAE/C,OAAO;QACH,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,CAAC,MAAkB;YACrB,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;YAEvC,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QACD,SAAS,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/C,IAAI,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC;KACjE,CAAC;AACN,CAAC,CAAC;AAEF,eAAe,kBAAkB,CAAC","sourcesContent":["import type { Plugin, UserConfig } from \"vite\";\nimport { type ConfigLoader, createConfigLoader } from \"./loader.ts\";\nimport { GTKX_CONFIG_VIRTUAL_ID, renderConfigModule, RESOLVED_GTKX_CONFIG_VIRTUAL_ID } from \"./virtual.ts\";\n\n/** State the plugin carries from Vite's `config` hook to the virtual module it serves. */\ntype PluginState = {\n /** Project root taken from Vite's `config` hook, undefined when the user config leaves it unset. */\n root: string | undefined;\n};\n\nconst resolveVirtualId = (id: string): string | null =>\n id === GTKX_CONFIG_VIRTUAL_ID ? RESOLVED_GTKX_CONFIG_VIRTUAL_ID : null;\n\nconst loadVirtualModule = async (\n id: string,\n loadConfig: ConfigLoader,\n state: PluginState,\n): Promise<string | undefined> => {\n if (id !== RESOLVED_GTKX_CONFIG_VIRTUAL_ID) {\n return undefined;\n }\n\n return renderConfigModule(await loadConfig.resolve(state.root ?? process.cwd()));\n};\n\n/**\n * Creates a Vite plugin serving `virtual:gtkx-config`, the module carrying the project's resolved\n * `gtkx.config.ts`.\n */\nconst createConfigPlugin = (options: {\n /** Name the plugin is registered under in Vite. */\n name: string;\n /** Loader the configuration is resolved through, defaulting to a fresh caching loader. */\n loadConfig?: ConfigLoader;\n /** Extra Vite configuration contributed from the plugin's `config` hook, given the user's own configuration. */\n config?: (config: UserConfig) => Omit<UserConfig, \"plugins\">;\n}): Plugin => {\n const loadConfig = options.loadConfig ?? createConfigLoader();\n const state: PluginState = { root: undefined };\n\n return {\n name: options.name,\n config(config: UserConfig) {\n state.root = config.root ?? state.root;\n\n return options.config?.(config);\n },\n resolveId: (id: string) => resolveVirtualId(id),\n load: (id: string) => loadVirtualModule(id, loadConfig, state),\n };\n};\n\nexport default createConfigPlugin;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/config",
3
- "version": "1.0.0-rc.4",
3
+ "version": "1.1.0",
4
4
  "description": "gtkx.config.ts schema, loader, and the element-prop mapping language shared across the GTKX toolchain",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -44,15 +44,25 @@
44
44
  "dist",
45
45
  "src"
46
46
  ],
47
+ "nx": {
48
+ "targets": {
49
+ "lint": {
50
+ "options": {
51
+ "cwd": ".",
52
+ "command": "eslint {projectRoot}"
53
+ }
54
+ }
55
+ }
56
+ },
47
57
  "engines": {
48
58
  "node": ">=24"
49
59
  },
50
60
  "dependencies": {
51
61
  "c12": "^3.3.4",
52
62
  "defu": "^6.1.7",
53
- "vite": "^8.2.0",
63
+ "vite": "^8.2.1",
54
64
  "zod": "^4.4.3",
55
- "@gtkx/utils": "1.0.0-rc.4"
65
+ "@gtkx/utils": "1.1.0"
56
66
  },
57
67
  "scripts": {
58
68
  "release": "tsx ../../scripts/release-package.ts"
@@ -3,6 +3,7 @@ import type { z } from "zod";
3
3
  type IssuePath = (string | number)[];
4
4
 
5
5
  const CONFIG_PREFIX = "gtkx.config.ts:";
6
+ const UNRECOGNIZED_KEY_REASON = "is not a recognized key";
6
7
 
7
8
  const isRecord = (value: unknown): value is Record<string, unknown> =>
8
9
  typeof value === "object" && value !== null && !Array.isArray(value);
@@ -37,12 +38,27 @@ const dottedPath = (segments: PropertyKey[]): string => {
37
38
  const isStandaloneIssue = (issue: z.core.$ZodIssue): boolean =>
38
39
  "params" in issue && isRecord(issue.params) && issue.params.standalone === true;
39
40
 
40
- const formatIssue = (issue: z.core.$ZodIssue, fullPath: PropertyKey[]): string => {
41
+ const unrecognizedKeyPath = (issue: z.core.$ZodIssue, fullPath: PropertyKey[]): string | undefined => {
41
42
  if (issue.code === "unrecognized_keys") {
42
43
  const [key] = issue.keys;
43
- const path = dottedPath(key === undefined ? fullPath : [...fullPath, key]);
44
44
 
45
- return `${CONFIG_PREFIX} \`${path}\` is not a recognized key`;
45
+ return dottedPath(key === undefined ? fullPath : [...fullPath, key]);
46
+ }
47
+
48
+ return issue.code === "invalid_key" ? dottedPath(fullPath) : undefined;
49
+ };
50
+
51
+ const keyRejectionReason = (issue: z.core.$ZodIssue): string => {
52
+ const nested = issue.code === "invalid_key" ? issue.issues[0] : undefined;
53
+
54
+ return nested?.code === "custom" ? nested.message : UNRECOGNIZED_KEY_REASON;
55
+ };
56
+
57
+ const formatIssue = (issue: z.core.$ZodIssue, fullPath: PropertyKey[]): string => {
58
+ const unrecognized = unrecognizedKeyPath(issue, fullPath);
59
+
60
+ if (unrecognized !== undefined) {
61
+ return `${CONFIG_PREFIX} \`${unrecognized}\` ${keyRejectionReason(issue)}`;
46
62
  }
47
63
 
48
64
  if (isStandaloneIssue(issue)) {
@@ -54,6 +70,9 @@ const formatIssue = (issue: z.core.$ZodIssue, fullPath: PropertyKey[]): string =
54
70
  return path === "" ? `${CONFIG_PREFIX} ${issue.message}` : `${CONFIG_PREFIX} \`${path}\` ${issue.message}`;
55
71
  };
56
72
 
73
+ const missingConfigFileError = (cwd: string): Error =>
74
+ new Error(`${CONFIG_PREFIX} no configuration file found in ${cwd}`);
75
+
57
76
  const configError = (error: z.ZodError): Error => {
58
77
  const issue = error.issues[0];
59
78
 
@@ -64,4 +83,4 @@ const configError = (error: z.ZodError): Error => {
64
83
  return new Error(formatIssue(issue, issue.path));
65
84
  };
66
85
 
67
- export { isRecord, rawIssue, configError };
86
+ export { isRecord, rawIssue, missingConfigFileError, configError };
package/src/config.ts CHANGED
@@ -3,6 +3,7 @@ import { defu } from "defu";
3
3
  import { resolve } from "node:path";
4
4
  import { z } from "zod";
5
5
  import { configError, isRecord, rawIssue } from "./config-error.ts";
6
+ import { deploySchema } from "./deploy.ts";
6
7
  import { resolveUserEventSignals } from "./user-event-signals.ts";
7
8
 
8
9
  /** Accepted `reactCompiler.compilationMode` values, choosing which functions the compiler processes. */
@@ -33,9 +34,7 @@ type ResolvedReactCompilerOptions = ReactCompilerOptions & {
33
34
  * Compiler, codegen, and user event signal settings.
34
35
  */
35
36
  type Config = z.infer<typeof configSchema>;
36
- /** A named export referenced as plain data, so codegen can emit an import for it without loading the module. */
37
37
  type ModuleExport = z.infer<typeof moduleExportSchema>;
38
- /** One `elements.config` entry, describing how a single GLib type's generated element is shaped. */
39
38
  type ElementConfigEntry = z.infer<typeof elementConfigSchema>;
40
39
 
41
40
  /** Configuration reduced to the values the app runtime and the build need, with paths already resolved. */
@@ -56,13 +55,14 @@ const LIBRARIES_WILDCARD = "*";
56
55
  const GIR_LIBRARY_PATTERN = /^[A-Za-z][A-Za-z0-9]*-\d+(?:\.\d+)*$/;
57
56
  const APPLICATION_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*(\.[A-Za-z_][A-Za-z0-9_-]*)+$/;
58
57
  const APPLICATION_ID_MAX_LENGTH = 255;
58
+ /** Compilation modes `babel-plugin-react-compiler` accepts. */
59
59
  const COMPILATION_MODES = ["infer", "syntax", "annotation", "all"] as const;
60
+ /** Panic thresholds `babel-plugin-react-compiler` accepts. */
60
61
  const PANIC_THRESHOLDS = ["none", "critical_errors", "all_errors"] as const;
61
62
  const REACT_COMPILER_TARGET = "19";
62
63
  const COMPILATION_MODE_SET: Set<string> = new Set(COMPILATION_MODES);
63
64
  const PANIC_THRESHOLD_SET: Set<string> = new Set(PANIC_THRESHOLDS);
64
65
 
65
- /** Validates `libraries`: the `"*"` wildcard on its own, or a non-empty array of `Name-Version` identifiers. */
66
66
  const librariesSchema = z.custom<typeof LIBRARIES_WILDCARD | string[]>().check((ctx) => {
67
67
  const value = ctx.value;
68
68
 
@@ -81,7 +81,6 @@ const librariesSchema = z.custom<typeof LIBRARIES_WILDCARD | string[]>().check((
81
81
  }
82
82
  });
83
83
 
84
- /** Validates `applicationId` against the reverse-DNS form `g_application_id_is_valid` accepts. */
85
84
  const applicationIdSchema = z.custom<string>().check((ctx) => {
86
85
  const value = ctx.value;
87
86
 
@@ -98,7 +97,6 @@ const applicationIdSchema = z.custom<string>().check((ctx) => {
98
97
  }
99
98
  });
100
99
 
101
- /** Validates `reactCompiler`: a boolean, or an options object whose mode and threshold are known values. */
102
100
  const reactCompilerSchema = z.custom<boolean | ReactCompilerOptions>().check((ctx) => {
103
101
  const value = ctx.value;
104
102
 
@@ -141,7 +139,6 @@ const reactCompilerSchema = z.custom<boolean | ReactCompilerOptions>().check((ct
141
139
  }
142
140
  });
143
141
 
144
- /** Validates `userEventSignals`: GLib type names mapped to arrays of non-empty signal names. */
145
142
  const userEventSignalsSchema = z.record(
146
143
  z.string(),
147
144
  z.array(
@@ -153,26 +150,18 @@ const userEventSignalsSchema = z.record(
153
150
  { error: "must be a record of GLib type names to signal name arrays" },
154
151
  );
155
152
 
156
- /** Validates a `{ module, export }` reference to a named export. */
157
153
  const moduleExportSchema = z.object(
158
154
  {
159
- /** Specifier the export is imported from. */
160
155
  module: z.string({ error: "must be a module specifier" }).min(1, { error: "must be a module specifier" }),
161
- /** Identifier the module exports it under. */
162
156
  export: z.string({ error: "must be an export name" }).min(1, { error: "must be an export name" }),
163
157
  },
164
158
  { error: "must be a { module, export } object" },
165
159
  );
166
160
 
167
- /** Validates one entry of `elements.config`. */
168
161
  const elementConfigSchema = z.object({
169
- /** Component that wraps the generated element. */
170
162
  component: moduleExportSchema.optional(),
171
- /** Base props interface the generated element props extend. */
172
163
  props: moduleExportSchema.optional(),
173
- /** Marks the element as having no GObject of its own, its parent container creating one instead. */
174
164
  isLazy: z.boolean({ error: "must be a boolean" }).optional(),
175
- /** GObject properties to leave out of the generated element props, such as those a behavior fills. */
176
165
  omittedProps: z
177
166
  .array(
178
167
  z.string({ error: "must be a non-empty property name" }).min(1, {
@@ -183,42 +172,24 @@ const elementConfigSchema = z.object({
183
172
  .optional(),
184
173
  });
185
174
 
186
- /** Validates `elements`: the behaviors module the app loads at runtime, plus the per-type entries. */
187
175
  const elementsSchema = z.object({
188
- /**
189
- * Path, resolved against the project root, of a module default-exporting element configs keyed by
190
- * GLib type name, as `defineElements` returns.
191
- */
192
176
  behaviors: z
193
177
  .string({ error: "must be a path to a module exporting element behaviors" })
194
178
  .min(1, { error: "must be a path to a module exporting element behaviors" })
195
179
  .optional(),
196
- /** Per-element entries, keyed by GLib type name. */
197
180
  config: z.record(z.string(), elementConfigSchema).optional(),
198
181
  });
199
182
 
200
- /** The shape every `gtkx.config.ts` is validated against, and the source of the {@link Config} type. */
183
+ /** Schema every `gtkx.config.ts` is validated against, and the source of the {@link Config} type. */
201
184
  const configSchema = z.object({
202
- /**
203
- * GIR namespaces to bind as `Name-Version`, or `"*"` for every one installed; omitting it gives
204
- * `Gtk-4.0`, which is also prepended to any list that names no Gtk version of its own.
205
- */
206
185
  libraries: librariesSchema.optional(),
207
- /** Directories searched for `.gir` files ahead of `GTKX_GIR_PATH` and the system locations. */
208
186
  girPath: z.array(z.string(), { error: "must be an array of strings if provided" }).optional(),
209
- /** Reverse-DNS GApplication identifier, and the default `applicationId` of the application element. */
210
187
  applicationId: applicationIdSchema,
211
- /** React Compiler settings; the compiler runs unless this is `false`. */
212
188
  reactCompiler: reactCompilerSchema.optional(),
213
- /** Whether to generate the binding stores; `false` makes the CLI resolve an already-installed one. */
214
189
  codegen: z.boolean({ error: "must be a boolean" }).optional(),
215
- /**
216
- * Signal names, keyed by GLib type name, that stay suppressed while a React commit applies props, so
217
- * their handlers only ever report user interaction. Unioned with the built-in GTK4 and Adwaita table.
218
- */
219
190
  userEventSignals: userEventSignalsSchema.optional(),
220
- /** Per-element customization: where the behaviors module lives and how each type's element is shaped. */
221
191
  elements: elementsSchema.optional(),
192
+ deploy: deploySchema.optional(),
222
193
  });
223
194
 
224
195
  /**
@@ -325,9 +296,9 @@ const resolveConfig = (config: Config, root?: string): ResolvedConfig => ({
325
296
  });
326
297
 
327
298
  export {
299
+ APPLICATION_ID_MAX_LENGTH,
328
300
  defineConfig,
329
301
  isValidApplicationId,
330
- resolveReactCompilerOptions,
331
302
  validateConfig,
332
303
  mergeConfig,
333
304
  resolveLazyElements,
@@ -337,6 +308,5 @@ export {
337
308
  resolveConfig,
338
309
  type ResolvedReactCompilerOptions,
339
310
  type Config,
340
- type ModuleExport,
341
311
  type ResolvedConfig,
342
312
  };