@gtkx/cli 0.18.0 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builder.d.ts +26 -6
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +8 -31
- package/dist/builder.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -0
- package/dist/create.d.ts +1 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +1 -0
- package/dist/create.js.map +1 -0
- package/dist/dev-server.d.ts +1 -0
- package/dist/dev-server.d.ts.map +1 -0
- package/dist/dev-server.js +1 -0
- package/dist/dev-server.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-client.d.ts +1 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +1 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/refresh-runtime.d.ts +1 -0
- package/dist/refresh-runtime.d.ts.map +1 -0
- package/dist/refresh-runtime.js +1 -0
- package/dist/refresh-runtime.js.map +1 -0
- package/dist/templates.d.ts +1 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +1 -0
- package/dist/templates.js.map +1 -0
- package/dist/vite-plugin-gtkx-assets.d.ts +1 -0
- package/dist/vite-plugin-gtkx-assets.d.ts.map +1 -0
- package/dist/vite-plugin-gtkx-assets.js +1 -0
- package/dist/vite-plugin-gtkx-assets.js.map +1 -0
- package/dist/vite-plugin-gtkx-built-url.d.ts +18 -0
- package/dist/vite-plugin-gtkx-built-url.d.ts.map +1 -0
- package/dist/vite-plugin-gtkx-built-url.js +43 -0
- package/dist/vite-plugin-gtkx-built-url.js.map +1 -0
- package/dist/vite-plugin-gtkx-native.d.ts +14 -0
- package/dist/vite-plugin-gtkx-native.d.ts.map +1 -0
- package/dist/vite-plugin-gtkx-native.js +53 -0
- package/dist/vite-plugin-gtkx-native.js.map +1 -0
- package/dist/vite-plugin-gtkx-refresh.d.ts +1 -0
- package/dist/vite-plugin-gtkx-refresh.d.ts.map +1 -0
- package/dist/vite-plugin-gtkx-refresh.js +1 -0
- package/dist/vite-plugin-gtkx-refresh.js.map +1 -0
- package/dist/vite-plugin-swc-ssr-refresh.d.ts +1 -0
- package/dist/vite-plugin-swc-ssr-refresh.d.ts.map +1 -0
- package/dist/vite-plugin-swc-ssr-refresh.js +1 -0
- package/dist/vite-plugin-swc-ssr-refresh.js.map +1 -0
- package/package.json +8 -6
- package/src/builder.ts +94 -0
- package/src/cli.tsx +154 -0
- package/src/create.ts +310 -0
- package/src/dev-server.tsx +162 -0
- package/src/global.d.ts +6 -0
- package/src/index.ts +3 -0
- package/src/mcp-client.ts +518 -0
- package/src/refresh-runtime.ts +89 -0
- package/src/templates.ts +26 -0
- package/src/vite-plugin-gtkx-assets.ts +32 -0
- package/src/vite-plugin-gtkx-built-url.ts +48 -0
- package/src/vite-plugin-gtkx-native.ts +64 -0
- package/src/vite-plugin-gtkx-refresh.ts +54 -0
- package/src/vite-plugin-swc-ssr-refresh.ts +61 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import RefreshRuntime from "react-refresh/runtime";
|
|
2
|
+
|
|
3
|
+
type ComponentType = (...args: unknown[]) => unknown;
|
|
4
|
+
|
|
5
|
+
RefreshRuntime.injectIntoGlobalHook(globalThis);
|
|
6
|
+
globalThis.$RefreshReg$ = () => {};
|
|
7
|
+
globalThis.$RefreshSig$ = () => (type: unknown) => type;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates registration functions for a module's React components.
|
|
11
|
+
*
|
|
12
|
+
* Used internally by the Vite plugin to register components
|
|
13
|
+
* for React Fast Refresh.
|
|
14
|
+
*
|
|
15
|
+
* @param moduleId - Unique identifier for the module
|
|
16
|
+
* @returns Registration functions for the module
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export function createModuleRegistration(moduleId: string): {
|
|
20
|
+
$RefreshReg$: (type: ComponentType, id: string) => void;
|
|
21
|
+
$RefreshSig$: typeof RefreshRuntime.createSignatureFunctionForTransform;
|
|
22
|
+
} {
|
|
23
|
+
return {
|
|
24
|
+
$RefreshReg$: (type: ComponentType, id: string) => {
|
|
25
|
+
RefreshRuntime.register(type, `${moduleId} ${id}`);
|
|
26
|
+
},
|
|
27
|
+
$RefreshSig$: RefreshRuntime.createSignatureFunctionForTransform,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isLikelyComponentType(value: unknown): boolean {
|
|
32
|
+
if (typeof value !== "function") {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const func = value as { $$typeof?: symbol };
|
|
37
|
+
|
|
38
|
+
if (func.$$typeof === Symbol.for("react.memo") || func.$$typeof === Symbol.for("react.forward_ref")) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const name = (value as { name?: string }).name;
|
|
43
|
+
if (typeof name === "string" && /^[A-Z]/.test(name)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Checks if a module's exports form a React Refresh boundary.
|
|
52
|
+
*
|
|
53
|
+
* A module is a refresh boundary if all its exports are React components,
|
|
54
|
+
* allowing for fast refresh without full page reload.
|
|
55
|
+
*
|
|
56
|
+
* @param moduleExports - The module's exports object
|
|
57
|
+
* @returns `true` if the module can be fast-refreshed
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export function isReactRefreshBoundary(moduleExports: Record<string, unknown>): boolean {
|
|
61
|
+
if (RefreshRuntime.isLikelyComponentType(moduleExports)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const key in moduleExports) {
|
|
66
|
+
if (key === "__esModule") {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const value = moduleExports[key];
|
|
71
|
+
|
|
72
|
+
if (!isLikelyComponentType(value)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return Object.keys(moduleExports).filter((k) => k !== "__esModule").length > 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Triggers React Fast Refresh to re-render components.
|
|
82
|
+
*
|
|
83
|
+
* Called after module updates when all exports are React components.
|
|
84
|
+
*
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
export function performRefresh(): void {
|
|
88
|
+
RefreshRuntime.performReactRefresh();
|
|
89
|
+
}
|
package/src/templates.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import ejs from "ejs";
|
|
4
|
+
import type { TestingOption } from "./create.js";
|
|
5
|
+
|
|
6
|
+
export type TemplateContext = {
|
|
7
|
+
name: string;
|
|
8
|
+
appId: string;
|
|
9
|
+
title: string;
|
|
10
|
+
testing: TestingOption;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const getTemplatesDir = (): string => {
|
|
14
|
+
return join(import.meta.dirname, "..", "templates");
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const renderTemplate = (templatePath: string, context: TemplateContext): string => {
|
|
18
|
+
const templateContent = readFileSync(templatePath, "utf-8");
|
|
19
|
+
return ejs.render(templateContent, context);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const renderFile = (templateName: string, context: TemplateContext): string => {
|
|
23
|
+
const templatesDir = getTemplatesDir();
|
|
24
|
+
const templatePath = join(templatesDir, templateName);
|
|
25
|
+
return renderTemplate(templatePath, context);
|
|
26
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
const ASSET_RE = /\.(png|jpe?g|gif|svg|webp|webm|mp4|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf|ico|avif)$/i;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Vite plugin that resolves static asset imports to filesystem paths.
|
|
7
|
+
*
|
|
8
|
+
* In dev mode, asset imports resolve to the absolute source file path.
|
|
9
|
+
* In build mode, Vite's built-in asset pipeline handles emission and
|
|
10
|
+
* hashing; the `renderBuiltUrl` config in the builder converts the
|
|
11
|
+
* URL to a filesystem path via `import.meta.url`.
|
|
12
|
+
*/
|
|
13
|
+
export function gtkxAssets(): Plugin {
|
|
14
|
+
let isBuild = false;
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
name: "gtkx:assets",
|
|
18
|
+
enforce: "pre",
|
|
19
|
+
|
|
20
|
+
configResolved(config) {
|
|
21
|
+
isBuild = config.command === "build";
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
load(id) {
|
|
25
|
+
if (isBuild || !ASSET_RE.test(id)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return `export default ${JSON.stringify(id)};`;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vite plugin that configures `renderBuiltUrl` for resolving asset imports
|
|
5
|
+
* to filesystem paths at runtime.
|
|
6
|
+
*
|
|
7
|
+
* When `assetBase` is provided, assets resolve relative to the executable
|
|
8
|
+
* directory using `path.join(path.dirname(process.execPath), assetBase, filename)`.
|
|
9
|
+
* This supports FHS-compliant layouts where assets live in `../share/<app>/`.
|
|
10
|
+
*
|
|
11
|
+
* When `assetBase` is omitted, assets resolve relative to the bundle file
|
|
12
|
+
* via `import.meta.url`, which works when assets are co-located with the
|
|
13
|
+
* executable.
|
|
14
|
+
*
|
|
15
|
+
* Only applies when the user has not already configured
|
|
16
|
+
* `experimental.renderBuiltUrl` in their Vite config.
|
|
17
|
+
*/
|
|
18
|
+
export function gtkxBuiltUrl(assetBase?: string): Plugin {
|
|
19
|
+
return {
|
|
20
|
+
name: "gtkx:built-url",
|
|
21
|
+
|
|
22
|
+
config(userConfig) {
|
|
23
|
+
if (userConfig.experimental?.renderBuiltUrl) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
experimental: {
|
|
29
|
+
renderBuiltUrl(filename, { type }) {
|
|
30
|
+
if (type !== "asset") {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (assetBase) {
|
|
35
|
+
return {
|
|
36
|
+
runtime: `require("path").join(require("path").dirname(process.execPath),${JSON.stringify(assetBase)},${JSON.stringify(filename)})`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
runtime: `new URL(${JSON.stringify(`./${filename}`)}, import.meta.url).pathname`,
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { arch, platform } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import type { Plugin } from "vite";
|
|
6
|
+
|
|
7
|
+
const LOAD_NATIVE_BINDING_RE = /function loadNativeBinding\(\) \{[\s\S]*?\n\}/;
|
|
8
|
+
const NODE_OS_IMPORT_RE = /import\s*\{[^}]*\}\s*from\s*["']node:os["'];?\n?/;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Vite plugin that embeds the native `.node` binary into the build output.
|
|
12
|
+
*
|
|
13
|
+
* During production builds, resolves the platform-specific `.node` binary,
|
|
14
|
+
* copies it into the output directory as `gtkx.node`, and transforms the
|
|
15
|
+
* `loadNativeBinding` function in `@gtkx/native` to load `./gtkx.node`
|
|
16
|
+
* directly. This makes the bundle self-contained with no `node_modules`
|
|
17
|
+
* dependency at runtime.
|
|
18
|
+
*
|
|
19
|
+
* @param root - Project root directory used to resolve native packages
|
|
20
|
+
*/
|
|
21
|
+
export function gtkxNative(root: string): Plugin {
|
|
22
|
+
const projectRequire = createRequire(join(root, "package.json"));
|
|
23
|
+
let nativeIndexPath: string;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
name: "gtkx:native",
|
|
27
|
+
enforce: "pre",
|
|
28
|
+
|
|
29
|
+
buildStart() {
|
|
30
|
+
const currentPlatform = platform();
|
|
31
|
+
const currentArch = arch();
|
|
32
|
+
const packageName = `@gtkx/native-linux-${currentArch}`;
|
|
33
|
+
|
|
34
|
+
if (currentPlatform !== "linux") {
|
|
35
|
+
throw new Error(`Unsupported build platform: ${currentPlatform}. Only Linux is supported.`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (currentArch !== "x64" && currentArch !== "arm64") {
|
|
39
|
+
throw new Error(`Unsupported build architecture: ${currentArch}. Only x64 and arm64 are supported.`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
nativeIndexPath = projectRequire.resolve("@gtkx/native");
|
|
43
|
+
|
|
44
|
+
const nodePath = projectRequire.resolve(`${packageName}/index.node`);
|
|
45
|
+
const source = readFileSync(nodePath);
|
|
46
|
+
|
|
47
|
+
this.emitFile({
|
|
48
|
+
type: "asset",
|
|
49
|
+
fileName: "gtkx.node",
|
|
50
|
+
source,
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
transform(code, id) {
|
|
55
|
+
if (id !== nativeIndexPath) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return code
|
|
60
|
+
.replace(NODE_OS_IMPORT_RE, "")
|
|
61
|
+
.replace(LOAD_NATIVE_BINDING_RE, 'function loadNativeBinding() { return require("./gtkx.node"); }');
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
type GtkxRefreshOptions = {
|
|
4
|
+
include?: RegExp;
|
|
5
|
+
exclude?: RegExp;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const defaultInclude = /\.[tj]sx?$/;
|
|
9
|
+
const defaultExclude = /node_modules/;
|
|
10
|
+
|
|
11
|
+
const refreshRuntimePath = "@gtkx/cli/refresh-runtime";
|
|
12
|
+
|
|
13
|
+
export function gtkxRefresh(options: GtkxRefreshOptions = {}): Plugin {
|
|
14
|
+
const include = options.include ?? defaultInclude;
|
|
15
|
+
const exclude = options.exclude ?? defaultExclude;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
name: "gtkx:refresh",
|
|
19
|
+
enforce: "post",
|
|
20
|
+
|
|
21
|
+
transform(code, id, transformOptions) {
|
|
22
|
+
if (!transformOptions?.ssr) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!include.test(id)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (exclude.test(id)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const hasRefreshReg = code.includes("$RefreshReg$");
|
|
35
|
+
const hasRefreshSig = code.includes("$RefreshSig$");
|
|
36
|
+
|
|
37
|
+
if (!hasRefreshReg && !hasRefreshSig) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const moduleIdJson = JSON.stringify(id);
|
|
42
|
+
|
|
43
|
+
const header = `
|
|
44
|
+
import { createModuleRegistration as __createModuleRegistration__ } from "${refreshRuntimePath}";
|
|
45
|
+
const { $RefreshReg$, $RefreshSig$ } = __createModuleRegistration__(${moduleIdJson});
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
code: header + code,
|
|
50
|
+
map: null,
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type Options as SwcOptions, transform } from "@swc/core";
|
|
2
|
+
import type { Plugin } from "vite";
|
|
3
|
+
|
|
4
|
+
type SwcSsrRefreshOptions = {
|
|
5
|
+
include?: RegExp;
|
|
6
|
+
exclude?: RegExp;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const defaultInclude = /\.[tj]sx?$/;
|
|
10
|
+
const defaultExclude = /node_modules/;
|
|
11
|
+
|
|
12
|
+
export function swcSsrRefresh(options: SwcSsrRefreshOptions = {}): Plugin {
|
|
13
|
+
const include = options.include ?? defaultInclude;
|
|
14
|
+
const exclude = options.exclude ?? defaultExclude;
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
name: "gtkx:swc-ssr-refresh",
|
|
18
|
+
enforce: "pre",
|
|
19
|
+
|
|
20
|
+
async transform(code, id, transformOptions) {
|
|
21
|
+
if (!transformOptions?.ssr) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!include.test(id)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (exclude.test(id)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const isTsx = id.endsWith(".tsx");
|
|
34
|
+
const isTs = id.endsWith(".ts") || isTsx;
|
|
35
|
+
|
|
36
|
+
const swcOptions: SwcOptions = {
|
|
37
|
+
filename: id,
|
|
38
|
+
sourceFileName: id,
|
|
39
|
+
sourceMaps: true,
|
|
40
|
+
jsc: {
|
|
41
|
+
parser: isTs ? { syntax: "typescript", tsx: isTsx } : { syntax: "ecmascript", jsx: true },
|
|
42
|
+
transform: {
|
|
43
|
+
react: {
|
|
44
|
+
runtime: "automatic",
|
|
45
|
+
development: true,
|
|
46
|
+
refresh: true,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
target: "es2022",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const result = await transform(code, swcOptions);
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
code: result.code,
|
|
57
|
+
map: result.map,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|