@gtkx/cli 1.4.0 → 1.6.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.
- package/README.md +1 -1
- package/dist/builder.d.ts +1 -0
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +2 -2
- package/dist/builder.js.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/codegen/freshness.d.ts.map +1 -1
- package/dist/codegen/freshness.js +2 -1
- package/dist/codegen/freshness.js.map +1 -1
- package/dist/codegen/reference.d.ts +17 -0
- package/dist/codegen/reference.d.ts.map +1 -0
- package/dist/codegen/reference.js +37 -0
- package/dist/codegen/reference.js.map +1 -0
- package/dist/codegen/report.d.ts.map +1 -1
- package/dist/codegen/report.js +17 -3
- package/dist/codegen/report.js.map +1 -1
- package/dist/codegen/run-codegen.d.ts +4 -0
- package/dist/codegen/run-codegen.d.ts.map +1 -1
- package/dist/codegen/run-codegen.js +93 -27
- package/dist/codegen/run-codegen.js.map +1 -1
- package/dist/commands/codegen.js +1 -1
- package/dist/commands/codegen.js.map +1 -1
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +10 -16
- package/dist/commands/docs.js.map +1 -1
- package/dist/commands/mcp.d.ts +13 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +68 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/deploy/freedesktop/localize.d.ts +6 -0
- package/dist/deploy/freedesktop/localize.d.ts.map +1 -0
- package/dist/deploy/freedesktop/localize.js +107 -0
- package/dist/deploy/freedesktop/localize.js.map +1 -0
- package/dist/deploy/install-hints.d.ts.map +1 -1
- package/dist/deploy/install-hints.js +5 -0
- package/dist/deploy/install-hints.js.map +1 -1
- package/dist/deploy/notices/gtkx.js +1 -1
- package/dist/deploy/notices/gtkx.js.map +1 -1
- package/dist/deploy/notices/libraries.d.ts.map +1 -1
- package/dist/deploy/notices/libraries.js +2 -1
- package/dist/deploy/notices/libraries.js.map +1 -1
- package/dist/deploy/payload/launcher.d.ts.map +1 -1
- package/dist/deploy/payload/launcher.js +2 -0
- package/dist/deploy/payload/launcher.js.map +1 -1
- package/dist/deploy/payload/stage.d.ts +1 -1
- package/dist/deploy/payload/stage.d.ts.map +1 -1
- package/dist/deploy/payload/stage.js +20 -11
- package/dist/deploy/payload/stage.js.map +1 -1
- package/dist/deploy/run-deploy.d.ts.map +1 -1
- package/dist/deploy/run-deploy.js +87 -15
- package/dist/deploy/run-deploy.js.map +1 -1
- package/dist/deploy/settings/libraries.d.ts.map +1 -1
- package/dist/deploy/settings/libraries.js +7 -9
- package/dist/deploy/settings/libraries.js.map +1 -1
- package/dist/deploy/targets/flatpak-source.d.ts.map +1 -1
- package/dist/deploy/targets/flatpak-source.js +21 -10
- package/dist/deploy/targets/flatpak-source.js.map +1 -1
- package/dist/deploy/tools.d.ts +6 -1
- package/dist/deploy/tools.d.ts.map +1 -1
- package/dist/deploy/tools.js +27 -4
- package/dist/deploy/tools.js.map +1 -1
- package/dist/dev/locale-dir.d.ts +3 -0
- package/dist/dev/locale-dir.d.ts.map +1 -0
- package/dist/dev/locale-dir.js +17 -0
- package/dist/dev/locale-dir.js.map +1 -0
- package/dist/dev/runner-main.d.ts.map +1 -1
- package/dist/dev/runner-main.js +4 -1
- package/dist/dev/runner-main.js.map +1 -1
- package/dist/dev/runner.d.ts.map +1 -1
- package/dist/dev/runner.js +6 -0
- package/dist/dev/runner.js.map +1 -1
- package/dist/dev/vite-dev-server.d.ts +1 -0
- package/dist/dev/vite-dev-server.d.ts.map +1 -1
- package/dist/dev/vite-dev-server.js.map +1 -1
- package/dist/i18n/binding-extractor.d.ts +30 -0
- package/dist/i18n/binding-extractor.d.ts.map +1 -0
- package/dist/i18n/binding-extractor.js +1324 -0
- package/dist/i18n/binding-extractor.js.map +1 -0
- package/dist/i18n/catalog-template.d.ts +3 -0
- package/dist/i18n/catalog-template.d.ts.map +1 -0
- package/dist/i18n/catalog-template.js +18 -0
- package/dist/i18n/catalog-template.js.map +1 -0
- package/dist/i18n/catalogs.d.ts +21 -0
- package/dist/i18n/catalogs.d.ts.map +1 -0
- package/dist/i18n/catalogs.js +139 -0
- package/dist/i18n/catalogs.js.map +1 -0
- package/dist/i18n/extractor-plugin.d.ts +8 -0
- package/dist/i18n/extractor-plugin.d.ts.map +1 -0
- package/dist/i18n/extractor-plugin.js +247 -0
- package/dist/i18n/extractor-plugin.js.map +1 -0
- package/dist/i18n/metadata-templates.d.ts +11 -0
- package/dist/i18n/metadata-templates.d.ts.map +1 -0
- package/dist/i18n/metadata-templates.js +11 -0
- package/dist/i18n/metadata-templates.js.map +1 -0
- package/dist/i18n/source-messages.d.ts +23 -0
- package/dist/i18n/source-messages.d.ts.map +1 -0
- package/dist/i18n/source-messages.js +403 -0
- package/dist/i18n/source-messages.js.map +1 -0
- package/dist/i18n/types.d.ts +10 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +108 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/internal/agent-rules.d.ts +7 -0
- package/dist/internal/agent-rules.d.ts.map +1 -0
- package/dist/internal/agent-rules.js +106 -0
- package/dist/internal/agent-rules.js.map +1 -0
- package/dist/internal/docs-elements.d.ts +8 -0
- package/dist/internal/docs-elements.d.ts.map +1 -0
- package/dist/internal/docs-elements.js +12 -0
- package/dist/internal/docs-elements.js.map +1 -0
- package/dist/internal/source-imports.d.ts +5 -1
- package/dist/internal/source-imports.d.ts.map +1 -1
- package/dist/internal/source-imports.js +25 -47
- package/dist/internal/source-imports.js.map +1 -1
- package/dist/mcp/client-config.d.ts +22 -0
- package/dist/mcp/client-config.d.ts.map +1 -0
- package/dist/mcp/client-config.js +94 -0
- package/dist/mcp/client-config.js.map +1 -0
- package/dist/mcp/client.d.ts +0 -1
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +11 -39
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/handlers.d.ts +2 -1
- package/dist/mcp/handlers.d.ts.map +1 -1
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/settings/render.d.ts +4 -1
- package/dist/settings/render.d.ts.map +1 -1
- package/dist/settings/render.js +11 -2
- package/dist/settings/render.js.map +1 -1
- package/dist/settings/schema.d.ts.map +1 -1
- package/dist/settings/schema.js +3 -1
- package/dist/settings/schema.js.map +1 -1
- package/dist/vite-plugins/animated.d.ts +5 -0
- package/dist/vite-plugins/animated.d.ts.map +1 -0
- package/dist/vite-plugins/animated.js +325 -0
- package/dist/vite-plugins/animated.js.map +1 -0
- package/dist/vite-plugins/asset-imports.d.ts.map +1 -1
- package/dist/vite-plugins/asset-imports.js +4 -14
- package/dist/vite-plugins/asset-imports.js.map +1 -1
- package/dist/vite-plugins/i18n.d.ts +5 -0
- package/dist/vite-plugins/i18n.d.ts.map +1 -0
- package/dist/vite-plugins/i18n.js +88 -0
- package/dist/vite-plugins/i18n.js.map +1 -0
- package/dist/vite-plugins/index.d.ts +1 -1
- package/dist/vite-plugins/index.d.ts.map +1 -1
- package/dist/vite-plugins/index.js +5 -1
- package/dist/vite-plugins/index.js.map +1 -1
- package/dist/vite-plugins/resources.d.ts.map +1 -1
- package/dist/vite-plugins/resources.js +12 -57
- package/dist/vite-plugins/resources.js.map +1 -1
- package/dist/vite-plugins/self-contained.d.ts.map +1 -1
- package/dist/vite-plugins/self-contained.js +128 -135
- package/dist/vite-plugins/self-contained.js.map +1 -1
- package/dist/vite-plugins/settings-worker-env.js +2 -2
- package/dist/vite-plugins/settings-worker-env.js.map +1 -1
- package/dist/vite-plugins/settings.d.ts.map +1 -1
- package/dist/vite-plugins/settings.js +2 -1
- package/dist/vite-plugins/settings.js.map +1 -1
- package/package.json +11 -9
- package/src/builder.ts +3 -2
- package/src/cli.ts +5 -0
- package/src/codegen/freshness.ts +2 -1
- package/src/codegen/reference.ts +59 -0
- package/src/codegen/report.ts +18 -3
- package/src/codegen/run-codegen.ts +134 -31
- package/src/commands/codegen.ts +1 -1
- package/src/commands/docs.ts +10 -28
- package/src/commands/mcp.ts +81 -0
- package/src/deploy/freedesktop/localize.ts +144 -0
- package/src/deploy/install-hints.ts +5 -0
- package/src/deploy/notices/gtkx.ts +1 -1
- package/src/deploy/notices/libraries.ts +2 -1
- package/src/deploy/payload/launcher.ts +2 -0
- package/src/deploy/payload/stage.ts +35 -10
- package/src/deploy/run-deploy.ts +128 -13
- package/src/deploy/settings/libraries.ts +7 -10
- package/src/deploy/targets/flatpak-source.ts +33 -10
- package/src/deploy/tools.ts +36 -3
- package/src/dev/locale-dir.ts +22 -0
- package/src/dev/runner-main.ts +4 -1
- package/src/dev/runner.ts +8 -0
- package/src/dev/vite-dev-server.ts +1 -0
- package/src/i18n/binding-extractor.ts +1969 -0
- package/src/i18n/catalog-template.ts +24 -0
- package/src/i18n/catalogs.ts +216 -0
- package/src/i18n/extractor-plugin.ts +413 -0
- package/src/i18n/metadata-templates.ts +29 -0
- package/src/i18n/source-messages.ts +608 -0
- package/src/i18n/types.ts +154 -0
- package/src/internal/agent-rules.ts +135 -0
- package/src/internal/docs-elements.ts +21 -0
- package/src/internal/source-imports.ts +31 -60
- package/src/mcp/client-config.ts +130 -0
- package/src/mcp/client.ts +17 -44
- package/src/mcp/handlers.ts +7 -6
- package/src/settings/render.ts +16 -2
- package/src/settings/schema.ts +3 -1
- package/src/vite-plugins/animated.ts +486 -0
- package/src/vite-plugins/asset-imports.ts +5 -17
- package/src/vite-plugins/i18n.ts +146 -0
- package/src/vite-plugins/index.ts +5 -0
- package/src/vite-plugins/resources.ts +12 -74
- package/src/vite-plugins/self-contained.ts +150 -169
- package/src/vite-plugins/settings-worker-env.ts +2 -2
- package/src/vite-plugins/settings.ts +2 -1
package/src/builder.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { gtkxWorker } from "./vite-plugins/worker.js";
|
|
|
10
10
|
|
|
11
11
|
type BuildOptions = {
|
|
12
12
|
entry: string;
|
|
13
|
+
shouldPreserveI18nMetadata?: boolean | undefined;
|
|
13
14
|
vite?: InlineConfig | undefined;
|
|
14
15
|
};
|
|
15
16
|
|
|
@@ -32,14 +33,14 @@ const buildDefaults: InlineConfig = {
|
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
const build = async (options: BuildOptions): Promise<string> => {
|
|
35
|
-
const { entry, vite: viteConfig } = options;
|
|
36
|
+
const { entry, shouldPreserveI18nMetadata = true, vite: viteConfig } = options;
|
|
36
37
|
const root = viteConfig?.root ?? process.cwd();
|
|
37
38
|
const assetsDir = viteConfig?.build?.assetsDir ?? DEFAULT_ASSETS_DIR;
|
|
38
39
|
const buildManifest = createBuildManifestCollector();
|
|
39
40
|
|
|
40
41
|
const forced: InlineConfig = {
|
|
41
42
|
plugins: [
|
|
42
|
-
...gtkxVitePlugins(BUILD_MODE,
|
|
43
|
+
...gtkxVitePlugins(BUILD_MODE, entry, buildManifest, shouldPreserveI18nMetadata),
|
|
43
44
|
gtkxWorker(),
|
|
44
45
|
gtkxNative(root),
|
|
45
46
|
gtkxBuildManifest(root, buildManifest),
|
package/src/cli.ts
CHANGED
|
@@ -38,6 +38,11 @@ const main = defineCommand({
|
|
|
38
38
|
|
|
39
39
|
return withErrorBoundary(docs);
|
|
40
40
|
},
|
|
41
|
+
mcp: async () => {
|
|
42
|
+
const { mcp } = await import("./commands/mcp.js");
|
|
43
|
+
|
|
44
|
+
return withErrorBoundary(mcp);
|
|
45
|
+
},
|
|
41
46
|
create: async () => {
|
|
42
47
|
const { scaffoldCommand } = await import("create-gtkx");
|
|
43
48
|
|
package/src/codegen/freshness.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Config } from "@gtkx/config";
|
|
2
2
|
import { resolveGirPath, resolveLibraries } from "@gtkx/codegen";
|
|
3
|
+
import { resolveFuture } from "@gtkx/config/internal";
|
|
3
4
|
import { existsSync } from "node:fs";
|
|
4
5
|
import { join } from "node:path";
|
|
5
6
|
import { type CodegenStore, resolveCodegenStore } from "./store-resolver.js";
|
|
@@ -14,7 +15,7 @@ const REACT_GENERATED_MODULES: string[] = ["index.js", "metadata.js", join("gtk"
|
|
|
14
15
|
|
|
15
16
|
const resolveCodegenInputs = (cwd: string, config: Config): CodegenInputs => {
|
|
16
17
|
const girPath = resolveGirPath(config.girPath);
|
|
17
|
-
const libraries = resolveLibraries(config.libraries, girPath);
|
|
18
|
+
const libraries = resolveLibraries(config.libraries, girPath, resolveFuture(config.future).isAdwaitaDefault);
|
|
18
19
|
const store = resolveCodegenStore(cwd);
|
|
19
20
|
|
|
20
21
|
return { girPath, libraries, store };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Config } from "@gtkx/config";
|
|
2
|
+
import { mergeOmittedProps } from "@gtkx/codegen";
|
|
3
|
+
import { writeDocs } from "@gtkx/codegen/internal";
|
|
4
|
+
import { isAgentReferenceEnabled, resolveOmittedProps } from "@gtkx/config/internal";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { resolveDocsElements } from "../internal/docs-elements.js";
|
|
7
|
+
|
|
8
|
+
type WriteReferenceOptions = {
|
|
9
|
+
root: string;
|
|
10
|
+
config: Config;
|
|
11
|
+
girPath: string[];
|
|
12
|
+
libraries: string[];
|
|
13
|
+
isForced?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type ReferenceResult = {
|
|
17
|
+
isRegenerated: boolean;
|
|
18
|
+
elements: number;
|
|
19
|
+
namespaces: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const REFERENCE_PATH = ".gtkx/reference";
|
|
23
|
+
const SKIPPED: ReferenceResult = { isRegenerated: false, elements: 0, namespaces: 0 };
|
|
24
|
+
|
|
25
|
+
const resolveReferenceDir = (root: string): string => join(root, ".gtkx", "reference");
|
|
26
|
+
|
|
27
|
+
const writeReference = async (options: WriteReferenceOptions): Promise<ReferenceResult> => {
|
|
28
|
+
const { root, config, girPath, libraries } = options;
|
|
29
|
+
|
|
30
|
+
if (!isAgentReferenceEnabled(config) || girPath.length === 0 || libraries.length === 0) {
|
|
31
|
+
return SKIPPED;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const builtin = await resolveDocsElements(root);
|
|
35
|
+
|
|
36
|
+
const { isRegenerated, namespaces } = writeDocs({
|
|
37
|
+
libraries,
|
|
38
|
+
girPath,
|
|
39
|
+
outDir: resolveReferenceDir(root),
|
|
40
|
+
basePath: REFERENCE_PATH,
|
|
41
|
+
linkStyle: "file",
|
|
42
|
+
props: builtin.props,
|
|
43
|
+
omittedProps: mergeOmittedProps(builtin.omittedProps, resolveOmittedProps(config.elements)),
|
|
44
|
+
isForced: options.isForced === true,
|
|
45
|
+
isByteArrayTyped: config.future?.v2ByteArrays === true,
|
|
46
|
+
isValueUnwrapped: config.future?.v2ValueReturns === true,
|
|
47
|
+
isFinishTrimmed: config.future?.v2FinishResults === true,
|
|
48
|
+
isInoutInPlace: config.future?.v2InoutReturns === true,
|
|
49
|
+
isTreeShaken: config.future?.v2TreeShaking === true,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
isRegenerated,
|
|
54
|
+
elements: namespaces.reduce((total, namespace) => total + namespace.elements.length, 0),
|
|
55
|
+
namespaces: namespaces.length,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export { REFERENCE_PATH, writeReference, type ReferenceResult };
|
package/src/codegen/report.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { RunCodegenResult } from "./run-codegen.js";
|
|
2
|
+
import { REFERENCE_PATH } from "./reference.js";
|
|
2
3
|
|
|
3
4
|
const PREFIX = "codegen: ";
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const contextDetails = (result: RunCodegenResult): string[] => {
|
|
6
7
|
const details: string[] = [];
|
|
7
8
|
|
|
8
9
|
if (result.configFile) {
|
|
@@ -21,10 +22,24 @@ const formatCodegenResult = (result: RunCodegenResult, totalMs: number): string[
|
|
|
21
22
|
details.push(`future=${result.future.join(", ")}`);
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
details
|
|
25
|
+
return details;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const referenceDetails = (result: RunCodegenResult): string[] => {
|
|
29
|
+
if (result.reference?.isRegenerated !== true) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return [`${String(result.reference.elements)} reference pages in ${REFERENCE_PATH}`];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const formatCodegenResult = (result: RunCodegenResult, totalMs: number): string[] => {
|
|
37
|
+
const details = [
|
|
38
|
+
...contextDetails(result),
|
|
25
39
|
`${String(result.namespaces)} namespaces, ${String(result.intrinsicElements)} intrinsic elements ` +
|
|
26
40
|
`in ${String(result.duration)}ms (total ${String(totalMs)}ms)`,
|
|
27
|
-
|
|
41
|
+
...referenceDetails(result),
|
|
42
|
+
];
|
|
28
43
|
|
|
29
44
|
return details.map((detail) => PREFIX + detail);
|
|
30
45
|
};
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import { runCodegen as runCodegenCore } from "@gtkx/codegen";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getShadowingStorePaths,
|
|
4
|
+
LIBRARIES_WILDCARD,
|
|
5
|
+
redundantLibraries,
|
|
6
|
+
sweepProjectStaging,
|
|
7
|
+
} from "@gtkx/codegen/internal";
|
|
3
8
|
import { type Config, loadConfig } from "@gtkx/config";
|
|
4
9
|
import {
|
|
10
|
+
isAgentRulesEnabled,
|
|
11
|
+
type ResolvedFuture,
|
|
5
12
|
resolveElementComponents,
|
|
6
13
|
resolveElementProps,
|
|
14
|
+
resolveFuture,
|
|
7
15
|
resolveLazyElements,
|
|
8
16
|
resolveOmittedProps,
|
|
17
|
+
unknownFutureKeys,
|
|
9
18
|
} from "@gtkx/config/internal";
|
|
10
19
|
import { info, warn } from "@gtkx/utils";
|
|
11
|
-
import { rmSync } from "node:fs";
|
|
12
|
-
import { resolve } from "node:path";
|
|
20
|
+
import { existsSync, rmSync } from "node:fs";
|
|
21
|
+
import { join, resolve } from "node:path";
|
|
22
|
+
import { resolveCatalogProject, synchronizeCatalogs } from "../i18n/catalogs.js";
|
|
23
|
+
import { extractSourceCatalog } from "../i18n/source-messages.js";
|
|
24
|
+
import { emitI18nTypes } from "../i18n/types.js";
|
|
25
|
+
import { upsertAgentRules } from "../internal/agent-rules.js";
|
|
13
26
|
import { resolveDataDir } from "../internal/data-dir.js";
|
|
27
|
+
import { discoverSourceFiles } from "../internal/source-imports.js";
|
|
14
28
|
import { emitSchemaEnv } from "../settings/schema.js";
|
|
15
29
|
import { type CodegenInputs, isCodegenStale, resolveCodegenInputs } from "./freshness.js";
|
|
30
|
+
import { type ReferenceResult, writeReference } from "./reference.js";
|
|
16
31
|
import { type CodegenContext, type CodegenStore, resolveCodegenContext } from "./store-resolver.js";
|
|
17
32
|
|
|
18
33
|
type RunCodegenOptions = {
|
|
@@ -21,6 +36,7 @@ type RunCodegenOptions = {
|
|
|
21
36
|
isForced?: boolean;
|
|
22
37
|
inputs?: CodegenInputs;
|
|
23
38
|
resolved?: LoadedConfig;
|
|
39
|
+
shouldPreserveI18nMetadata?: boolean | undefined;
|
|
24
40
|
};
|
|
25
41
|
|
|
26
42
|
type LoadedConfig = {
|
|
@@ -38,6 +54,7 @@ type RunCodegenResult = {
|
|
|
38
54
|
configFile?: string | undefined;
|
|
39
55
|
libraries?: string[] | undefined;
|
|
40
56
|
future?: string[] | undefined;
|
|
57
|
+
reference?: ReferenceResult | undefined;
|
|
41
58
|
};
|
|
42
59
|
|
|
43
60
|
type CodegenOptionsInput = {
|
|
@@ -45,20 +62,23 @@ type CodegenOptionsInput = {
|
|
|
45
62
|
libraries: string[];
|
|
46
63
|
girPath: string[];
|
|
47
64
|
elements: Config["elements"];
|
|
48
|
-
|
|
49
|
-
isValueUnwrapped: boolean;
|
|
50
|
-
isFinishTrimmed: boolean;
|
|
51
|
-
isInoutInPlace: boolean;
|
|
65
|
+
future: ResolvedFuture;
|
|
52
66
|
};
|
|
53
67
|
|
|
54
68
|
type PreparedCodegen = CodegenInputs & { isForced: boolean };
|
|
55
|
-
|
|
69
|
+
|
|
70
|
+
type EnsureGeneratedOptions = {
|
|
71
|
+
shouldAnnounce?: boolean;
|
|
72
|
+
mode?: string;
|
|
73
|
+
shouldPreserveI18nMetadata?: boolean | undefined;
|
|
74
|
+
};
|
|
56
75
|
|
|
57
76
|
type RunOptionsInput = {
|
|
58
77
|
root: string;
|
|
59
78
|
mode: string | undefined;
|
|
60
79
|
inputs: CodegenInputs | null;
|
|
61
80
|
resolved: LoadedConfig;
|
|
81
|
+
shouldPreserveI18nMetadata: boolean | undefined;
|
|
62
82
|
};
|
|
63
83
|
|
|
64
84
|
const GIR_PATH_MISSING_MESSAGE =
|
|
@@ -77,13 +97,14 @@ const removeShadowingStores = (cwd: string): void => {
|
|
|
77
97
|
removeStores(getShadowingStorePaths(cwd));
|
|
78
98
|
};
|
|
79
99
|
|
|
80
|
-
const codegenOptions = ({ store, libraries, girPath, elements,
|
|
100
|
+
const codegenOptions = ({ store, libraries, girPath, elements, future }: CodegenOptionsInput) => ({
|
|
81
101
|
libraries,
|
|
82
102
|
girPath,
|
|
83
103
|
isByteArrayTyped: future.isByteArrayTyped,
|
|
84
104
|
isValueUnwrapped: future.isValueUnwrapped,
|
|
85
105
|
isFinishTrimmed: future.isFinishTrimmed,
|
|
86
106
|
isInoutInPlace: future.isInoutInPlace,
|
|
107
|
+
isTreeShaken: future.isTreeShaken,
|
|
87
108
|
gi: {
|
|
88
109
|
storeDir: store.giStoreDir,
|
|
89
110
|
linkDir: store.giLinkDir,
|
|
@@ -104,16 +125,19 @@ const codegenOptions = ({ store, libraries, girPath, elements, ...future }: Code
|
|
|
104
125
|
userOmittedProps: resolveOmittedProps(elements),
|
|
105
126
|
});
|
|
106
127
|
|
|
107
|
-
const enabledFutureFlags = (config: Config): string[] =>
|
|
108
|
-
|
|
109
|
-
|
|
128
|
+
const enabledFutureFlags = (config: Config): string[] => {
|
|
129
|
+
const unknown: Set<string> = new Set(unknownFutureKeys(config.future));
|
|
130
|
+
|
|
131
|
+
return Object.entries(config.future ?? {})
|
|
132
|
+
.filter(([name, value]) => value === true && !unknown.has(name))
|
|
110
133
|
.map(([name]) => name);
|
|
134
|
+
};
|
|
111
135
|
|
|
112
|
-
const disabledCodegenResult = (configFile: string): RunCodegenResult => ({
|
|
136
|
+
const disabledCodegenResult = (configFile: string, notices: string[]): RunCodegenResult => ({
|
|
113
137
|
isRegenerated: false,
|
|
114
138
|
namespaces: 0,
|
|
115
139
|
intrinsicElements: 0,
|
|
116
|
-
notices
|
|
140
|
+
notices,
|
|
117
141
|
duration: 0,
|
|
118
142
|
girPath: [],
|
|
119
143
|
configFile,
|
|
@@ -126,6 +150,46 @@ const warnNotices = (notices: string[]): void => {
|
|
|
126
150
|
}
|
|
127
151
|
};
|
|
128
152
|
|
|
153
|
+
const unknownFutureNotice = (keys: string[]): string[] => {
|
|
154
|
+
if (keys.length === 0) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return [
|
|
159
|
+
`gtkx.config.ts: \`future\` has no ${keys.join(", ")} flag, so the key is ignored. Check it against ` +
|
|
160
|
+
"the flags the configuration guide lists.",
|
|
161
|
+
];
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const redundantLibraryNotice = (entries: string[]): string[] => {
|
|
165
|
+
if (entries.length === 0) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return [
|
|
170
|
+
`gtkx.config.ts: \`future.v2DefaultLibraries\` binds ${entries.join(", ")} on its own, so naming them ` +
|
|
171
|
+
"in `libraries` changes nothing. Drop them; naming them becomes a configuration error in GTKX 2.0.",
|
|
172
|
+
];
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const wildcardLibrariesNotice = (libraries: Config["libraries"]): string[] => {
|
|
176
|
+
if (libraries !== LIBRARIES_WILDCARD) {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return [
|
|
181
|
+
'gtkx.config.ts: `libraries: "*"` binds whatever the build host happens to have installed, so the ' +
|
|
182
|
+
"store changes with the machine. Instead, list the libraries the project needs; the wildcard is " +
|
|
183
|
+
"removed in GTKX 2.0.",
|
|
184
|
+
];
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const configNotices = (config: Config, future: ResolvedFuture): string[] => [
|
|
188
|
+
...unknownFutureNotice(unknownFutureKeys(config.future)),
|
|
189
|
+
...wildcardLibrariesNotice(config.libraries),
|
|
190
|
+
...redundantLibraryNotice(redundantLibraries(config.libraries, future.isAdwaitaDefault)),
|
|
191
|
+
];
|
|
192
|
+
|
|
129
193
|
const regeneratedStorePaths = (store: CodegenStore): string[] => {
|
|
130
194
|
if (store.react === null) {
|
|
131
195
|
return [store.giStoreDir, store.giLinkDir];
|
|
@@ -156,12 +220,16 @@ const prepareCodegen = (options: RunCodegenOptions, cwd: string, config: Config)
|
|
|
156
220
|
const runCodegen = async (options: RunCodegenOptions = {}): Promise<RunCodegenResult> => {
|
|
157
221
|
const cwd = options.cwd ?? process.cwd();
|
|
158
222
|
const { config, configFile } = await resolveLoadedConfig(options, cwd);
|
|
159
|
-
|
|
223
|
+
const future = resolveFuture(config.future);
|
|
224
|
+
const configured = configNotices(config, future);
|
|
225
|
+
warnNotices(configured);
|
|
226
|
+
await syncI18n(cwd, config.applicationId, options.shouldPreserveI18nMetadata);
|
|
227
|
+
syncSchemaEnv(cwd, future.isResourceImported);
|
|
160
228
|
|
|
161
229
|
if (config.codegen === false) {
|
|
162
230
|
removeShadowingStores(cwd);
|
|
163
231
|
|
|
164
|
-
return disabledCodegenResult(configFile);
|
|
232
|
+
return disabledCodegenResult(configFile, configured);
|
|
165
233
|
}
|
|
166
234
|
|
|
167
235
|
const { girPath, libraries, store, isForced } = prepareCodegen(options, cwd, config);
|
|
@@ -171,34 +239,55 @@ const runCodegen = async (options: RunCodegenOptions = {}): Promise<RunCodegenRe
|
|
|
171
239
|
}
|
|
172
240
|
|
|
173
241
|
const result = await runCodegenCore({
|
|
174
|
-
...codegenOptions({
|
|
175
|
-
store,
|
|
176
|
-
libraries,
|
|
177
|
-
girPath,
|
|
178
|
-
elements: config.elements,
|
|
179
|
-
isByteArrayTyped: config.future?.v2ByteArrays === true,
|
|
180
|
-
isValueUnwrapped: config.future?.v2ValueReturns === true,
|
|
181
|
-
isFinishTrimmed: config.future?.v2FinishResults === true,
|
|
182
|
-
isInoutInPlace: config.future?.v2InoutReturns === true,
|
|
183
|
-
}),
|
|
242
|
+
...codegenOptions({ store, libraries, girPath, elements: config.elements, future }),
|
|
184
243
|
isForced,
|
|
185
244
|
});
|
|
186
245
|
|
|
187
246
|
warnNotices(result.notices);
|
|
247
|
+
const notices = [...configured, ...result.notices];
|
|
248
|
+
const reference = await writeReference({ root: cwd, config, girPath, libraries, isForced });
|
|
249
|
+
syncAgentRules(cwd, config);
|
|
188
250
|
|
|
189
251
|
return {
|
|
190
252
|
isRegenerated: result.isRegenerated,
|
|
191
253
|
namespaces: result.namespaces,
|
|
192
254
|
intrinsicElements: result.intrinsicElements,
|
|
193
|
-
notices
|
|
255
|
+
notices,
|
|
194
256
|
duration: result.duration,
|
|
195
257
|
girPath,
|
|
196
258
|
configFile,
|
|
197
259
|
libraries,
|
|
198
260
|
future: enabledFutureFlags(config),
|
|
261
|
+
reference,
|
|
199
262
|
};
|
|
200
263
|
};
|
|
201
264
|
|
|
265
|
+
const syncAgentRules = (root: string, config: Config): void => {
|
|
266
|
+
if (isAgentRulesEnabled(config)) {
|
|
267
|
+
upsertAgentRules(root);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const syncI18n = async (
|
|
272
|
+
root: string,
|
|
273
|
+
applicationId: string,
|
|
274
|
+
shouldPreserveMetadataMessages = true,
|
|
275
|
+
): Promise<void> => {
|
|
276
|
+
const project = resolveCatalogProject(root, applicationId);
|
|
277
|
+
|
|
278
|
+
if (project === null) {
|
|
279
|
+
emitI18nTypes(root, [], false);
|
|
280
|
+
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const srcDir = join(root, "src");
|
|
285
|
+
const sourceFiles = discoverSourceFiles(existsSync(srcDir) ? srcDir : root);
|
|
286
|
+
const catalog = await extractSourceCatalog(project, sourceFiles, shouldPreserveMetadataMessages);
|
|
287
|
+
synchronizeCatalogs(project);
|
|
288
|
+
emitI18nTypes(root, catalog.messages);
|
|
289
|
+
};
|
|
290
|
+
|
|
202
291
|
const isCodegenDisabled = async (cwd: string, mode?: string): Promise<boolean> => {
|
|
203
292
|
try {
|
|
204
293
|
const { config } = await loadConfig(cwd, { mode });
|
|
@@ -232,12 +321,18 @@ const maybeAnnounceStale = (shouldAnnounce: boolean | undefined, inputs: Codegen
|
|
|
232
321
|
}
|
|
233
322
|
};
|
|
234
323
|
|
|
235
|
-
const getRunOptions = ({
|
|
324
|
+
const getRunOptions = ({
|
|
325
|
+
root,
|
|
326
|
+
mode,
|
|
327
|
+
inputs,
|
|
328
|
+
resolved,
|
|
329
|
+
shouldPreserveI18nMetadata,
|
|
330
|
+
}: RunOptionsInput): RunCodegenOptions => {
|
|
236
331
|
if (inputs === null) {
|
|
237
|
-
return { cwd: root, mode, resolved };
|
|
332
|
+
return { cwd: root, mode, resolved, shouldPreserveI18nMetadata };
|
|
238
333
|
}
|
|
239
334
|
|
|
240
|
-
return { cwd: root, mode, inputs, resolved };
|
|
335
|
+
return { cwd: root, mode, inputs, resolved, shouldPreserveI18nMetadata };
|
|
241
336
|
};
|
|
242
337
|
|
|
243
338
|
const isPreflightSkipped = (options: EnsureGeneratedOptions): boolean =>
|
|
@@ -250,6 +345,7 @@ const generate = async (context: CodegenContext, options: EnsureGeneratedOptions
|
|
|
250
345
|
cwd: context.root,
|
|
251
346
|
mode: options.mode,
|
|
252
347
|
resolved: { config: context.config, configFile: context.configFile },
|
|
348
|
+
shouldPreserveI18nMetadata: options.shouldPreserveI18nMetadata,
|
|
253
349
|
});
|
|
254
350
|
|
|
255
351
|
return result.isRegenerated;
|
|
@@ -258,7 +354,14 @@ const generate = async (context: CodegenContext, options: EnsureGeneratedOptions
|
|
|
258
354
|
const inputs = resolveInputsOrNull(context.root, context.config);
|
|
259
355
|
maybeAnnounceStale(options.shouldAnnounce, inputs);
|
|
260
356
|
const resolved = { config: context.config, configFile: context.configFile };
|
|
261
|
-
|
|
357
|
+
|
|
358
|
+
const result = await runCodegen(getRunOptions({
|
|
359
|
+
root: context.root,
|
|
360
|
+
mode: options.mode,
|
|
361
|
+
inputs,
|
|
362
|
+
resolved,
|
|
363
|
+
shouldPreserveI18nMetadata: options.shouldPreserveI18nMetadata,
|
|
364
|
+
}));
|
|
262
365
|
|
|
263
366
|
return result.isRegenerated;
|
|
264
367
|
};
|
package/src/commands/codegen.ts
CHANGED
|
@@ -12,7 +12,7 @@ const FORCED_WHILE_DISABLED_MESSAGE =
|
|
|
12
12
|
const codegen = defineCommand({
|
|
13
13
|
meta: {
|
|
14
14
|
name: "codegen",
|
|
15
|
-
description: "Generate
|
|
15
|
+
description: "Generate project bindings, translation catalogs, and TypeScript declarations",
|
|
16
16
|
},
|
|
17
17
|
args: {
|
|
18
18
|
force: {
|
package/src/commands/docs.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ElementProps,
|
|
3
|
-
mergeOmittedProps,
|
|
4
|
-
type OmittedProps,
|
|
5
|
-
readBuiltinElements,
|
|
6
|
-
resolveGirPath,
|
|
7
|
-
resolveLibraries,
|
|
8
|
-
resolveStore,
|
|
9
|
-
} from "@gtkx/codegen";
|
|
1
|
+
import { mergeOmittedProps, resolveGirPath, resolveLibraries } from "@gtkx/codegen";
|
|
10
2
|
import { writeDocs } from "@gtkx/codegen/internal";
|
|
11
3
|
import { loadConfig } from "@gtkx/config";
|
|
12
|
-
import { resolveOmittedProps } from "@gtkx/config/internal";
|
|
4
|
+
import { resolveFuture, resolveOmittedProps } from "@gtkx/config/internal";
|
|
13
5
|
import { info } from "@gtkx/utils";
|
|
14
6
|
import { defineCommand } from "citty";
|
|
15
|
-
import { existsSync } from "node:fs";
|
|
16
7
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
8
|
+
import { resolveDocsElements } from "../internal/docs-elements.js";
|
|
17
9
|
import { cwdArg, resolveCwd } from "../internal/entry-arg.js";
|
|
18
10
|
|
|
19
11
|
const docs = defineCommand({
|
|
@@ -65,7 +57,8 @@ const docs = defineCommand({
|
|
|
65
57
|
);
|
|
66
58
|
}
|
|
67
59
|
|
|
68
|
-
const
|
|
60
|
+
const future = resolveFuture(config.future);
|
|
61
|
+
const libraries = resolveLibraries(config.libraries, girPath, future.isAdwaitaDefault);
|
|
69
62
|
const startedAt = Date.now();
|
|
70
63
|
const outDir = resolveOutDir(cwd, args.out);
|
|
71
64
|
const builtin = await resolveDocsElements(cwd);
|
|
@@ -78,10 +71,11 @@ const docs = defineCommand({
|
|
|
78
71
|
props: builtin.props,
|
|
79
72
|
omittedProps: mergeOmittedProps(builtin.omittedProps, resolveOmittedProps(config.elements)),
|
|
80
73
|
isForced: args.force,
|
|
81
|
-
isByteArrayTyped:
|
|
82
|
-
isValueUnwrapped:
|
|
83
|
-
isFinishTrimmed:
|
|
84
|
-
isInoutInPlace:
|
|
74
|
+
isByteArrayTyped: future.isByteArrayTyped,
|
|
75
|
+
isValueUnwrapped: future.isValueUnwrapped,
|
|
76
|
+
isFinishTrimmed: future.isFinishTrimmed,
|
|
77
|
+
isInoutInPlace: future.isInoutInPlace,
|
|
78
|
+
isTreeShaken: future.isTreeShaken,
|
|
85
79
|
});
|
|
86
80
|
|
|
87
81
|
if (!isRegenerated) {
|
|
@@ -130,16 +124,4 @@ const resolveOutDir = (cwd: string, out: string): string => {
|
|
|
130
124
|
);
|
|
131
125
|
};
|
|
132
126
|
|
|
133
|
-
const resolveDocsElements = async (cwd: string): Promise<{ props: ElementProps; omittedProps: OmittedProps }> => {
|
|
134
|
-
const { gi, reactSubexports } = resolveStore(cwd);
|
|
135
|
-
|
|
136
|
-
if (!existsSync(gi.storeDir)) {
|
|
137
|
-
return { props: {}, omittedProps: {} };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const { props, omittedProps } = await readBuiltinElements(reactSubexports, gi.storeDir);
|
|
141
|
-
|
|
142
|
-
return { props, omittedProps };
|
|
143
|
-
};
|
|
144
|
-
|
|
145
127
|
export { docs };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { info } from "@gtkx/utils";
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
import { cwdArg, resolveCwd } from "../internal/entry-arg.js";
|
|
4
|
+
import { type ClientName, type ClientResult, CLIENTS, isClientName, writeClientConfig } from "../mcp/client-config.js";
|
|
5
|
+
|
|
6
|
+
const clientList = CLIENTS.map((client) => client.name).join(", ");
|
|
7
|
+
|
|
8
|
+
const init = defineCommand({
|
|
9
|
+
meta: {
|
|
10
|
+
name: "init",
|
|
11
|
+
description: "Write the gtkx MCP server into an editor's configuration file",
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
client: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: `Which editor to configure: one of ${clientList}`,
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
...cwdArg,
|
|
20
|
+
},
|
|
21
|
+
run({ args }) {
|
|
22
|
+
const cwd = resolveCwd(args);
|
|
23
|
+
const name = args.client;
|
|
24
|
+
|
|
25
|
+
if (!isClientName(name)) {
|
|
26
|
+
throw new Error(`Unknown --client "${name}". Pass one of ${clientList}.`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
report(name, writeClientConfig(cwd, name));
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const mcp = defineCommand({
|
|
34
|
+
meta: {
|
|
35
|
+
name: "mcp",
|
|
36
|
+
description: "Run the MCP server that exposes this project's running app and generated API reference",
|
|
37
|
+
},
|
|
38
|
+
args: {
|
|
39
|
+
tools: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description:
|
|
42
|
+
"Comma-separated tool name patterns to register, `*` matching any run of characters and a " +
|
|
43
|
+
"leading `!` excluding. Overrides `mcp.tools` in gtkx.config.ts",
|
|
44
|
+
},
|
|
45
|
+
"read-only": {
|
|
46
|
+
type: "boolean",
|
|
47
|
+
description: "Register only the tools that read state, leaving out the ones that drive the app",
|
|
48
|
+
},
|
|
49
|
+
...cwdArg,
|
|
50
|
+
},
|
|
51
|
+
subCommands: { init },
|
|
52
|
+
async run({ args }) {
|
|
53
|
+
const { runMcpServer } = await import("@gtkx/mcp/server");
|
|
54
|
+
|
|
55
|
+
await runMcpServer({
|
|
56
|
+
cwd: resolveCwd(args),
|
|
57
|
+
...(args.tools !== undefined && { tools: splitPatterns(args.tools) }),
|
|
58
|
+
...(args["read-only"] !== undefined && { isReadOnly: args["read-only"] }),
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const splitPatterns = (value: string): string[] =>
|
|
64
|
+
value.split(",").map((pattern) => pattern.trim()).filter((pattern) => pattern.length > 0);
|
|
65
|
+
|
|
66
|
+
const report = (name: ClientName, result: ClientResult): void => {
|
|
67
|
+
if (result.kind === "manual") {
|
|
68
|
+
info(`mcp: ${name} keeps its servers in ${result.path}, which is outside this project. Add:`);
|
|
69
|
+
|
|
70
|
+
for (const line of result.snippet.split("\n")) {
|
|
71
|
+
info(`mcp: ${line}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
info(`mcp: ${result.isCreated ? "created" : "updated"} ${result.path} for ${name}`);
|
|
78
|
+
info("mcp: restart the editor for it to pick the server up");
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export { mcp };
|