jac-client 0.2.3__py3-none-any.whl → 0.2.6__py3-none-any.whl
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.
- jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
- jac_client/examples/all-in-one/src/app.jac +841 -0
- jac_client/examples/all-in-one/{button.jac → src/button.jac} +1 -1
- jac_client/examples/all-in-one/{components → src/components}/button.jac +1 -1
- jac_client/examples/asset-serving/css-with-image/{app.jac → src/app.jac} +2 -2
- jac_client/examples/asset-serving/image-asset/{app.jac → src/app.jac} +2 -2
- jac_client/examples/asset-serving/import-alias/{app.jac → src/app.jac} +3 -3
- jac_client/examples/basic/{app.jac → src/app.jac} +2 -2
- jac_client/examples/basic-auth/src/app.jac +377 -0
- jac_client/examples/basic-auth-with-router/{app.jac → src/app.jac} +18 -18
- jac_client/examples/basic-full-stack/{app.jac → src/app.jac} +175 -130
- jac_client/examples/css-styling/js-styling/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/material-ui/{app.jac → src/app.jac} +5 -5
- jac_client/examples/css-styling/pure-css/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/sass-example/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/styled-components/{app.jac → src/app.jac} +5 -5
- jac_client/examples/css-styling/tailwind-example/{app.jac → src/app.jac} +6 -6
- jac_client/examples/full-stack-with-auth/{app.jac → src/app.jac} +37 -37
- jac_client/examples/little-x/{app.jac → src/app.jac} +27 -32
- jac_client/examples/little-x/src/submit-button.jac +16 -0
- jac_client/examples/nested-folders/nested-advance/{ButtonRoot.jac → src/ButtonRoot.jac} +1 -1
- jac_client/examples/nested-folders/nested-advance/{app.jac → src/app.jac} +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/ButtonSecondL.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/Card.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/level2/ButtonThirdL.jac +1 -1
- jac_client/examples/nested-folders/nested-basic/{app.jac → src/app.jac} +2 -2
- jac_client/examples/nested-folders/nested-basic/{button.jac → src/button.jac} +1 -1
- jac_client/examples/nested-folders/nested-basic/{components → src/components}/button.jac +1 -1
- jac_client/examples/ts-support/src/app.jac +35 -0
- jac_client/examples/with-router/{app.jac → src/app.jac} +11 -11
- jac_client/plugin/cli.jac +547 -0
- jac_client/plugin/client.jac +52 -0
- jac_client/plugin/client_runtime.cl.jac +38 -0
- jac_client/plugin/impl/client.impl.jac +134 -0
- jac_client/plugin/impl/client_runtime.impl.jac +177 -0
- jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
- jac_client/plugin/plugin_config.jac +195 -0
- jac_client/plugin/src/__init__.jac +20 -0
- jac_client/plugin/src/asset_processor.jac +33 -0
- jac_client/plugin/src/babel_processor.jac +18 -0
- jac_client/plugin/src/compiler.jac +66 -0
- jac_client/plugin/src/config_loader.jac +32 -0
- jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
- jac_client/plugin/src/impl/babel_processor.impl.jac +84 -0
- jac_client/plugin/src/impl/compiler.impl.jac +251 -0
- jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
- jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
- jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
- jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
- jac_client/plugin/src/impl/vite_bundler.impl.jac +513 -0
- jac_client/plugin/src/import_processor.jac +19 -0
- jac_client/plugin/src/jac_to_js.jac +35 -0
- jac_client/plugin/src/package_installer.jac +26 -0
- jac_client/plugin/src/vite_bundler.jac +36 -0
- jac_client/plugin/vite_client_bundle.jac +31 -0
- jac_client/tests/conftest.py +281 -0
- jac_client/tests/fixtures/basic-app/app.jac +2 -2
- jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
- jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
- jac_client/tests/fixtures/js_import/app.jac +5 -5
- jac_client/tests/fixtures/spawn_test/app.jac +7 -7
- jac_client/tests/fixtures/with-ts/app.jac +35 -0
- jac_client/tests/test_cli.py +755 -0
- jac_client/tests/test_it.py +347 -67
- {jac_client-0.2.3.dist-info → jac_client-0.2.6.dist-info}/METADATA +28 -30
- jac_client-0.2.6.dist-info/RECORD +74 -0
- {jac_client-0.2.3.dist-info → jac_client-0.2.6.dist-info}/WHEEL +2 -1
- jac_client-0.2.6.dist-info/entry_points.txt +4 -0
- jac_client-0.2.6.dist-info/top_level.txt +1 -0
- jac_client/docs/README.md +0 -689
- jac_client/docs/advanced-state.md +0 -1265
- jac_client/docs/asset-serving/intro.md +0 -209
- jac_client/docs/assets/pipe_line-v2.svg +0 -32
- jac_client/docs/assets/pipe_line.png +0 -0
- jac_client/docs/file-system/app.jac.md +0 -121
- jac_client/docs/file-system/backend-frontend.md +0 -217
- jac_client/docs/file-system/intro.md +0 -72
- jac_client/docs/file-system/nested-imports.md +0 -348
- jac_client/docs/guide-example/intro.md +0 -115
- jac_client/docs/guide-example/step-01-setup.md +0 -270
- jac_client/docs/guide-example/step-02-components.md +0 -416
- jac_client/docs/guide-example/step-03-styling.md +0 -478
- jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
- jac_client/docs/guide-example/step-05-local-state.md +0 -530
- jac_client/docs/guide-example/step-06-events.md +0 -749
- jac_client/docs/guide-example/step-07-effects.md +0 -468
- jac_client/docs/guide-example/step-08-walkers.md +0 -534
- jac_client/docs/guide-example/step-09-authentication.md +0 -586
- jac_client/docs/guide-example/step-10-routing.md +0 -539
- jac_client/docs/guide-example/step-11-final.md +0 -963
- jac_client/docs/imports.md +0 -1141
- jac_client/docs/lifecycle-hooks.md +0 -773
- jac_client/docs/routing.md +0 -659
- jac_client/docs/styling/intro.md +0 -249
- jac_client/docs/styling/js-styling.md +0 -367
- jac_client/docs/styling/material-ui.md +0 -341
- jac_client/docs/styling/pure-css.md +0 -299
- jac_client/docs/styling/sass.md +0 -403
- jac_client/docs/styling/styled-components.md +0 -395
- jac_client/docs/styling/tailwind.md +0 -298
- jac_client/examples/all-in-one/.babelrc +0 -9
- jac_client/examples/all-in-one/README.md +0 -16
- jac_client/examples/all-in-one/app.jac +0 -426
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/package.json +0 -29
- jac_client/examples/all-in-one/styles.css +0 -26
- jac_client/examples/all-in-one/vite.config.js +0 -28
- jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
- jac_client/examples/asset-serving/css-with-image/README.md +0 -91
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +0 -28
- jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
- jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
- jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
- jac_client/examples/asset-serving/image-asset/README.md +0 -119
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +0 -28
- jac_client/examples/asset-serving/image-asset/styles.css +0 -26
- jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
- jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
- jac_client/examples/asset-serving/import-alias/README.md +0 -83
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +0 -28
- jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
- jac_client/examples/basic/.babelrc +0 -9
- jac_client/examples/basic/README.md +0 -16
- jac_client/examples/basic/package.json +0 -27
- jac_client/examples/basic/vite.config.js +0 -27
- jac_client/examples/basic-auth/.babelrc +0 -9
- jac_client/examples/basic-auth/README.md +0 -16
- jac_client/examples/basic-auth/app.jac +0 -308
- jac_client/examples/basic-auth/package.json +0 -27
- jac_client/examples/basic-auth/vite.config.js +0 -27
- jac_client/examples/basic-auth-with-router/.babelrc +0 -9
- jac_client/examples/basic-auth-with-router/README.md +0 -60
- jac_client/examples/basic-auth-with-router/package.json +0 -28
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
- jac_client/examples/basic-full-stack/.babelrc +0 -9
- jac_client/examples/basic-full-stack/README.md +0 -18
- jac_client/examples/basic-full-stack/package.json +0 -28
- jac_client/examples/basic-full-stack/vite.config.js +0 -27
- jac_client/examples/css-styling/js-styling/.babelrc +0 -9
- jac_client/examples/css-styling/js-styling/README.md +0 -183
- jac_client/examples/css-styling/js-styling/package.json +0 -28
- jac_client/examples/css-styling/js-styling/styles.js +0 -100
- jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
- jac_client/examples/css-styling/material-ui/.babelrc +0 -9
- jac_client/examples/css-styling/material-ui/README.md +0 -16
- jac_client/examples/css-styling/material-ui/package.json +0 -32
- jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
- jac_client/examples/css-styling/pure-css/.babelrc +0 -9
- jac_client/examples/css-styling/pure-css/README.md +0 -16
- jac_client/examples/css-styling/pure-css/package.json +0 -28
- jac_client/examples/css-styling/pure-css/styles.css +0 -111
- jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
- jac_client/examples/css-styling/sass-example/.babelrc +0 -9
- jac_client/examples/css-styling/sass-example/README.md +0 -16
- jac_client/examples/css-styling/sass-example/package.json +0 -29
- jac_client/examples/css-styling/sass-example/styles.scss +0 -153
- jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
- jac_client/examples/css-styling/styled-components/.babelrc +0 -9
- jac_client/examples/css-styling/styled-components/README.md +0 -16
- jac_client/examples/css-styling/styled-components/package.json +0 -29
- jac_client/examples/css-styling/styled-components/styled.js +0 -90
- jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
- jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
- jac_client/examples/css-styling/tailwind-example/README.md +0 -16
- jac_client/examples/css-styling/tailwind-example/global.css +0 -1
- jac_client/examples/css-styling/tailwind-example/package.json +0 -30
- jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
- jac_client/examples/full-stack-with-auth/.babelrc +0 -9
- jac_client/examples/full-stack-with-auth/README.md +0 -16
- jac_client/examples/full-stack-with-auth/package.json +0 -28
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
- jac_client/examples/little-x/package.json +0 -23
- jac_client/examples/little-x/submit-button.jac +0 -8
- jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client/examples/nested-folders/nested-advance/package.json +0 -29
- jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
- jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-basic/README.md +0 -183
- jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client/examples/nested-folders/nested-basic/package.json +0 -28
- jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
- jac_client/examples/with-router/.babelrc +0 -9
- jac_client/examples/with-router/README.md +0 -17
- jac_client/examples/with-router/package.json +0 -28
- jac_client/examples/with-router/vite.config.js +0 -27
- jac_client/plugin/cli.py +0 -244
- jac_client/plugin/client.py +0 -152
- jac_client/plugin/client_runtime.jac +0 -234
- jac_client/plugin/vite_client_bundle.py +0 -503
- jac_client/tests/fixtures/js_import/utils.js +0 -21
- jac_client/tests/fixtures/package-lock.json +0 -329
- jac_client/tests/fixtures/package.json +0 -11
- jac_client/tests/test_asset_examples.py +0 -322
- jac_client/tests/test_cl.py +0 -530
- jac_client/tests/test_create_jac_app.py +0 -131
- jac_client/tests/test_nested_file.py +0 -374
- jac_client-0.2.3.dist-info/RECORD +0 -171
- jac_client-0.2.3.dist-info/entry_points.txt +0 -4
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
"""Create package.json from config.json during bundling."""
|
|
2
|
+
|
|
3
|
+
impl ViteBundler.create_package_json(
|
|
4
|
+
self: ViteBundler, project_name: Optional[str] = None
|
|
5
|
+
) -> Path {
|
|
6
|
+
build_dir = self.project_dir / '.client-build';
|
|
7
|
+
build_dir.mkdir(exist_ok=True);
|
|
8
|
+
configs_dir = build_dir / '.jac-client.configs';
|
|
9
|
+
configs_dir.mkdir(exist_ok=True);
|
|
10
|
+
package_config = self.config_loader.get_package_config();
|
|
11
|
+
package_json_path = configs_dir / 'package.json';
|
|
12
|
+
name = package_config.get('name', '');
|
|
13
|
+
if (not name and project_name) {
|
|
14
|
+
name = project_name;
|
|
15
|
+
}
|
|
16
|
+
if not name {
|
|
17
|
+
existing_package = self.project_dir / 'package.json';
|
|
18
|
+
if existing_package.exists() {
|
|
19
|
+
try {
|
|
20
|
+
with existing_package.open() as f {
|
|
21
|
+
existing_data = json.load(f);
|
|
22
|
+
name = existing_data.get('name', '');
|
|
23
|
+
}
|
|
24
|
+
} except (json.JSONDecodeError, KeyError) {
|
|
25
|
+
;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if not name {
|
|
30
|
+
name = self.project_dir.name or 'jac-app';
|
|
31
|
+
}
|
|
32
|
+
# Default hardcoded dependencies (always included)
|
|
33
|
+
default_dependencies = {
|
|
34
|
+
'react': '^18.2.0',
|
|
35
|
+
'react-dom': '^18.2.0',
|
|
36
|
+
'react-router-dom': '^6.22.0'
|
|
37
|
+
};
|
|
38
|
+
default_dev_dependencies = {
|
|
39
|
+
'vite': '^6.4.1',
|
|
40
|
+
'@babel/cli': '^7.28.3',
|
|
41
|
+
'@babel/core': '^7.28.5',
|
|
42
|
+
'@babel/preset-env': '^7.28.5',
|
|
43
|
+
'@babel/preset-react': '^7.28.5',
|
|
44
|
+
'@vitejs/plugin-react': '^4.2.1',
|
|
45
|
+
'typescript': '^5.3.3',
|
|
46
|
+
'@types/react': '^18.2.0',
|
|
47
|
+
'@types/react-dom': '^18.2.0'
|
|
48
|
+
};
|
|
49
|
+
# Merge user dependencies from TOML with defaults (user can override)
|
|
50
|
+
user_dependencies = package_config.get('dependencies', {});
|
|
51
|
+
user_dev_dependencies = package_config.get('devDependencies', {});
|
|
52
|
+
dependencies = {** default_dependencies, ** user_dependencies};
|
|
53
|
+
dev_dependencies = {** default_dev_dependencies, ** user_dev_dependencies};
|
|
54
|
+
scripts = {
|
|
55
|
+
'build': 'npm run compile && vite build --config .client-build/.jac-client.configs/vite.config.js',
|
|
56
|
+
'dev': 'vite dev --config .client-build/.jac-client.configs/vite.config.js',
|
|
57
|
+
'preview': 'vite preview --config .client-build/.jac-client.configs/vite.config.js',
|
|
58
|
+
'compile': 'babel compiled --out-dir build --extensions ".jsx,.js" --out-file-extension .js'
|
|
59
|
+
};
|
|
60
|
+
user_scripts = package_config.get('scripts', {});
|
|
61
|
+
scripts.update(user_scripts);
|
|
62
|
+
babel_config = {
|
|
63
|
+
'presets': [['@babel/preset-env', {'modules': False}], '@babel/preset-react']
|
|
64
|
+
};
|
|
65
|
+
package_data = {
|
|
66
|
+
'name': name,
|
|
67
|
+
'version': package_config.get('version', '1.0.0'),
|
|
68
|
+
'description': package_config.get('description', f"Jac application: {name}"),
|
|
69
|
+
'type': 'module',
|
|
70
|
+
'main': 'index.js',
|
|
71
|
+
'scripts': scripts,
|
|
72
|
+
'dependencies': dependencies,
|
|
73
|
+
'devDependencies': dev_dependencies,
|
|
74
|
+
'babel': babel_config
|
|
75
|
+
};
|
|
76
|
+
for (key, value) in package_config.items() {
|
|
77
|
+
if (
|
|
78
|
+
key not in {'name','version','description','dependencies','devDependencies'}
|
|
79
|
+
) {
|
|
80
|
+
package_data[key] = value;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
with package_json_path.open('w', encoding='utf-8') as f {
|
|
84
|
+
json.dump(package_data, f, indent=2);
|
|
85
|
+
}
|
|
86
|
+
# Generate tsconfig.json during build time
|
|
87
|
+
self.create_tsconfig();
|
|
88
|
+
return package_json_path;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
"""Create tsconfig.json during build time, merging user config from jac.toml."""
|
|
92
|
+
impl ViteBundler.create_tsconfig(self: ViteBundler) -> Path {
|
|
93
|
+
build_dir = self.project_dir / '.client-build';
|
|
94
|
+
build_dir.mkdir(exist_ok=True);
|
|
95
|
+
configs_dir = build_dir / '.jac-client.configs';
|
|
96
|
+
configs_dir.mkdir(exist_ok=True);
|
|
97
|
+
tsconfig_path = configs_dir / 'tsconfig.json';
|
|
98
|
+
# Default tsconfig settings
|
|
99
|
+
default_compiler_options = {
|
|
100
|
+
'target': 'ES2020',
|
|
101
|
+
'useDefineForClassFields': True,
|
|
102
|
+
'lib': ['ES2020', 'DOM', 'DOM.Iterable'],
|
|
103
|
+
'module': 'ESNext',
|
|
104
|
+
'skipLibCheck': True,
|
|
105
|
+
'moduleResolution': 'bundler',
|
|
106
|
+
'allowImportingTsExtensions': True,
|
|
107
|
+
'resolveJsonModule': True,
|
|
108
|
+
'isolatedModules': True,
|
|
109
|
+
'noEmit': True,
|
|
110
|
+
'jsx': 'react-jsx',
|
|
111
|
+
'strict': True,
|
|
112
|
+
'noUnusedLocals': True,
|
|
113
|
+
'noUnusedParameters': True,
|
|
114
|
+
'noFallthroughCasesInSwitch': True
|
|
115
|
+
};
|
|
116
|
+
default_include = ['components/**/*'];
|
|
117
|
+
default_exclude = ['.client-build'];
|
|
118
|
+
# Get user config from [plugins.client.ts] in jac.toml
|
|
119
|
+
user_ts_config = self.config_loader.get_ts_config();
|
|
120
|
+
user_compiler_options = user_ts_config.get('compilerOptions', {});
|
|
121
|
+
user_include = user_ts_config.get('include', []);
|
|
122
|
+
user_exclude = user_ts_config.get('exclude', []);
|
|
123
|
+
# Merge compiler options (user overrides defaults)
|
|
124
|
+
merged_compiler_options = {** default_compiler_options, ** user_compiler_options};
|
|
125
|
+
# For include/exclude, use user values if provided, otherwise defaults
|
|
126
|
+
merged_include = user_include or default_include;
|
|
127
|
+
merged_exclude = user_exclude or default_exclude;
|
|
128
|
+
tsconfig_data = {
|
|
129
|
+
'compilerOptions': merged_compiler_options,
|
|
130
|
+
'include': merged_include,
|
|
131
|
+
'exclude': merged_exclude
|
|
132
|
+
};
|
|
133
|
+
# Write the config to .client-build/.jac-client.configs/tsconfig.json (no root config file)
|
|
134
|
+
tsconfig_path.write_text(json.dumps(tsconfig_data, indent=2), encoding='utf-8');
|
|
135
|
+
return tsconfig_path;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
Clean up root package.json and move package-lock.json to .jac-client.configs/.
|
|
140
|
+
|
|
141
|
+
Remove root package.json and move package-lock.json to .jac-client.configs/.
|
|
142
|
+
"""
|
|
143
|
+
impl ViteBundler._cleanup_root_package_files(self: ViteBundler) -> None {
|
|
144
|
+
root_package_json = self.project_dir / 'package.json';
|
|
145
|
+
root_package_lock = self.project_dir / 'package-lock.json';
|
|
146
|
+
build_dir = self.project_dir / '.client-build';
|
|
147
|
+
configs_dir = build_dir / '.jac-client.configs';
|
|
148
|
+
configs_package_lock = configs_dir / 'package-lock.json';
|
|
149
|
+
if root_package_lock.exists() {
|
|
150
|
+
configs_dir.mkdir(exist_ok=True);
|
|
151
|
+
if configs_package_lock.exists() {
|
|
152
|
+
configs_package_lock.unlink();
|
|
153
|
+
}
|
|
154
|
+
shutil.move(str(root_package_lock), str(configs_package_lock));
|
|
155
|
+
}
|
|
156
|
+
if root_package_json.exists() {
|
|
157
|
+
root_package_json.unlink();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
"""
|
|
162
|
+
Ensure root package.json exists temporarily for npm commands.
|
|
163
|
+
|
|
164
|
+
Create root package.json temporarily if it doesn't exist.
|
|
165
|
+
"""
|
|
166
|
+
impl ViteBundler._ensure_root_package_json(self: ViteBundler) -> None {
|
|
167
|
+
generated_package_json = self.project_dir / '.client-build' / '.jac-client.configs' / 'package.json';
|
|
168
|
+
root_package_json = self.project_dir / 'package.json';
|
|
169
|
+
if not generated_package_json.exists() {
|
|
170
|
+
self.create_package_json();
|
|
171
|
+
}
|
|
172
|
+
if not root_package_json.exists() {
|
|
173
|
+
shutil.copy2(generated_package_json, root_package_json);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
"""Format config object as JavaScript object string."""
|
|
178
|
+
impl ViteBundler._format_config_object(
|
|
179
|
+
self: ViteBundler, config: dict, indent: int = 0
|
|
180
|
+
) -> str {
|
|
181
|
+
if not config {
|
|
182
|
+
return '';
|
|
183
|
+
}
|
|
184
|
+
indent_str = ' ' * indent;
|
|
185
|
+
items = [];
|
|
186
|
+
for (key, value) in config.items() {
|
|
187
|
+
if isinstance(value, str) {
|
|
188
|
+
items.append(f"{indent_str} {key}: '{value}',");
|
|
189
|
+
} elif isinstance(value, bool) {
|
|
190
|
+
items.append(f"{indent_str} {key}: {str(value).lower()},");
|
|
191
|
+
} elif isinstance(value, (int, float)) {
|
|
192
|
+
items.append(f"{indent_str} {key}: {value},");
|
|
193
|
+
} elif isinstance(value, <>list) {
|
|
194
|
+
list_str = ', '.join(repr(v) for v in value);
|
|
195
|
+
items.append(f"{indent_str} {key}: [{list_str}],");
|
|
196
|
+
} elif isinstance(value, <>dict) {
|
|
197
|
+
nested = self._format_config_object(value, (indent + 2));
|
|
198
|
+
items.append(f"{indent_str} {key}: {{{nested}{indent_str} }},");
|
|
199
|
+
} else {
|
|
200
|
+
items.append(f"{indent_str} {key}: {repr(value)},");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return '\n'.join(items);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
"""Format plugin options as JavaScript object string."""
|
|
207
|
+
impl ViteBundler._format_plugin_options(self: ViteBundler, options: dict) -> str {
|
|
208
|
+
if not options {
|
|
209
|
+
return '';
|
|
210
|
+
}
|
|
211
|
+
items = [];
|
|
212
|
+
for (key, value) in options.items() {
|
|
213
|
+
if isinstance(value, str) {
|
|
214
|
+
items.append(f"{key}: '{value}'");
|
|
215
|
+
} elif isinstance(value, bool) {
|
|
216
|
+
items.append(f"{key}: {str(value).lower()}");
|
|
217
|
+
} elif isinstance(value, (int, float)) {
|
|
218
|
+
items.append(f"{key}: {value}");
|
|
219
|
+
} elif isinstance(value, <>list) {
|
|
220
|
+
items.append(f"{key}: [{', '.join(repr(v) for v in value)}]");
|
|
221
|
+
} else {
|
|
222
|
+
items.append(f"{key}: {repr(value)}");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return '{ ' + ', '.join(items) + ' }';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
"""Get a valid JavaScript variable name from plugin module name."""
|
|
229
|
+
impl ViteBundler._get_plugin_var_name(self: ViteBundler, plugin_name: str) -> str {
|
|
230
|
+
name = plugin_name.split('/')[-1];
|
|
231
|
+
name = name.replace('-', '_').replace('.', '_');
|
|
232
|
+
name = name.lstrip('@');
|
|
233
|
+
return name;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
"""Create vite.config.js from config.json during bundling."""
|
|
237
|
+
impl ViteBundler.create_vite_config(self: ViteBundler, entry_file: Path) -> Path {
|
|
238
|
+
build_dir = self.project_dir / '.client-build';
|
|
239
|
+
build_dir.mkdir(exist_ok=True);
|
|
240
|
+
configs_dir = build_dir / '.jac-client.configs';
|
|
241
|
+
configs_dir.mkdir(exist_ok=True);
|
|
242
|
+
vite_config_data = self.config_loader.get_vite_config();
|
|
243
|
+
config_path = configs_dir / 'vite.config.js';
|
|
244
|
+
# TypeScript is always enabled by default
|
|
245
|
+
build_dir = self.project_dir / '.client-build';
|
|
246
|
+
try {
|
|
247
|
+
# Entry file path relative to .client-build/ (not project root)
|
|
248
|
+
entry_relative = entry_file.relative_to(build_dir).as_posix();
|
|
249
|
+
} except ValueError {
|
|
250
|
+
# Fallback: try relative to project_dir and strip .client-build/ prefix
|
|
251
|
+
try {
|
|
252
|
+
entry_relative_full = entry_file.relative_to(self.project_dir).as_posix();
|
|
253
|
+
prefix = '.client-build/';
|
|
254
|
+
if entry_relative_full.startswith(prefix) {
|
|
255
|
+
# Remove '.client-build/' prefix (15 characters)
|
|
256
|
+
entry_relative = entry_relative_full[15:];
|
|
257
|
+
} else {
|
|
258
|
+
entry_relative = entry_relative_full;
|
|
259
|
+
}
|
|
260
|
+
} except ValueError {
|
|
261
|
+
entry_relative = entry_file.as_posix();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
try {
|
|
265
|
+
# Output dir path relative to .client-build/ (not project root)
|
|
266
|
+
output_relative = self.output_dir.relative_to(build_dir).as_posix();
|
|
267
|
+
} except ValueError {
|
|
268
|
+
# Fallback: try relative to project_dir and strip .client-build/ prefix
|
|
269
|
+
try {
|
|
270
|
+
output_relative_full = self.output_dir.relative_to(self.project_dir).as_posix();
|
|
271
|
+
prefix = '.client-build/';
|
|
272
|
+
if output_relative_full.startswith(prefix) {
|
|
273
|
+
# Remove '.client-build/' prefix (15 characters)
|
|
274
|
+
output_relative = output_relative_full[15:];
|
|
275
|
+
} else {
|
|
276
|
+
output_relative = output_relative_full;
|
|
277
|
+
}
|
|
278
|
+
} except ValueError {
|
|
279
|
+
output_relative = self.output_dir.as_posix();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
# Calculate compiled directory path for aliases (relative to .client-build/)
|
|
283
|
+
if entry_relative.endswith('/build/main.js') {
|
|
284
|
+
compiled_utils_relative = entry_relative[:-13] + '/compiled/client_runtime.js';
|
|
285
|
+
compiled_assets_relative = entry_relative[:-13] + '/compiled/assets';
|
|
286
|
+
} elif entry_relative.endswith('build/main.js') {
|
|
287
|
+
compiled_utils_relative = 'compiled/client_runtime.js';
|
|
288
|
+
compiled_assets_relative = 'compiled/assets';
|
|
289
|
+
} else {
|
|
290
|
+
compiled_utils_relative = 'compiled/client_runtime.js';
|
|
291
|
+
compiled_assets_relative = 'compiled/assets';
|
|
292
|
+
}
|
|
293
|
+
plugins = [];
|
|
294
|
+
plugin_imports = [];
|
|
295
|
+
# TypeScript support is always enabled, so always include React plugin
|
|
296
|
+
plugin_imports.append('import react from "@vitejs/plugin-react";');
|
|
297
|
+
plugins.append(' react()');
|
|
298
|
+
lib_imports = vite_config_data.get('lib_imports', []);
|
|
299
|
+
for lib_import in lib_imports {
|
|
300
|
+
if (isinstance(lib_import, str) and lib_import.strip()) {
|
|
301
|
+
plugin_imports.append(lib_import);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
custom_plugins = vite_config_data.get('plugins', []);
|
|
305
|
+
for plugin in custom_plugins {
|
|
306
|
+
if isinstance(plugin, str) {
|
|
307
|
+
plugins.append(f" {plugin}");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
plugins_str = ',\n'.join(plugins) if plugins else '';
|
|
311
|
+
imports_str = '\n'.join(plugin_imports) if plugin_imports else '';
|
|
312
|
+
# TypeScript extensions are always included
|
|
313
|
+
extensions = ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'];
|
|
314
|
+
extensions_str = ', '.join(f'"{ext}"' for ext in extensions);
|
|
315
|
+
build_config = vite_config_data.get('build', {});
|
|
316
|
+
build_overrides_str = self._format_config_object(build_config, indent=4)
|
|
317
|
+
if (isinstance(build_config, <>dict) and build_config)
|
|
318
|
+
else '';
|
|
319
|
+
server_config = vite_config_data.get('server', {});
|
|
320
|
+
server_config_str = self._format_config_object(server_config, indent=2)
|
|
321
|
+
if (isinstance(server_config, <>dict) and server_config)
|
|
322
|
+
else '';
|
|
323
|
+
resolve_config = vite_config_data.get('resolve', {});
|
|
324
|
+
resolve_overrides_str = self._format_config_object(resolve_config, indent=6)
|
|
325
|
+
if (isinstance(resolve_config, <>dict) and resolve_config)
|
|
326
|
+
else '';
|
|
327
|
+
imports_section = f"{imports_str}\n" if imports_str else '';
|
|
328
|
+
newline = '\n';
|
|
329
|
+
server_section = f" server: {{{newline}{server_config_str}{newline} }},{newline}"
|
|
330
|
+
if server_config_str
|
|
331
|
+
else '';
|
|
332
|
+
config_content = f'''import {{ defineConfig }} from "vite";
|
|
333
|
+
import path from "path";
|
|
334
|
+
import {{ fileURLToPath }} from "url";
|
|
335
|
+
{imports_section}const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
336
|
+
// Config is in .jac-client.configs/ inside .client-build/, so go up one level to .client-build/, then up one more to project root
|
|
337
|
+
const buildDir = path.resolve(__dirname, "..");
|
|
338
|
+
const projectRoot = path.resolve(__dirname, "../..");
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Vite configuration generated from config.json (in project root)
|
|
342
|
+
* To customize, edit config.json instead of this file.
|
|
343
|
+
*/
|
|
344
|
+
|
|
345
|
+
export default defineConfig({{
|
|
346
|
+
plugins: [{(newline + plugins_str + newline + ' ') if plugins_str else ''}],
|
|
347
|
+
root: buildDir, // base folder (.client-build/) so vite can find node_modules
|
|
348
|
+
build: {{
|
|
349
|
+
rollupOptions: {{
|
|
350
|
+
input: path.resolve(buildDir, "{entry_relative}"), // your compiled entry file
|
|
351
|
+
output: {{
|
|
352
|
+
entryFileNames: "client.[hash].js", // name of the final js file
|
|
353
|
+
assetFileNames: "[name].[ext]",
|
|
354
|
+
}},
|
|
355
|
+
}},
|
|
356
|
+
outDir: path.resolve(buildDir, "{output_relative}"), // final bundled output
|
|
357
|
+
emptyOutDir: true,
|
|
358
|
+
{build_overrides_str}
|
|
359
|
+
}},
|
|
360
|
+
publicDir: false,
|
|
361
|
+
{server_section} resolve: {{
|
|
362
|
+
alias: {{
|
|
363
|
+
"@jac-client/utils": path.resolve(buildDir, "{compiled_utils_relative}"),
|
|
364
|
+
"@jac-client/assets": path.resolve(buildDir, "{compiled_assets_relative}"),
|
|
365
|
+
}},
|
|
366
|
+
extensions: [{extensions_str}],
|
|
367
|
+
{resolve_overrides_str}
|
|
368
|
+
}},
|
|
369
|
+
}});
|
|
370
|
+
''';
|
|
371
|
+
config_path.write_text(config_content, encoding='utf-8');
|
|
372
|
+
return config_path;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
"""Check if the project has TypeScript support. TypeScript is now enabled by default."""
|
|
376
|
+
impl ViteBundler._has_typescript_support(self: ViteBundler) -> bool {
|
|
377
|
+
# TypeScript is always enabled by default
|
|
378
|
+
return True;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
"""Read the bundled code and compute its hash."""
|
|
382
|
+
impl ViteBundler.read_bundle(self: ViteBundler) -> tuple[str, str] {
|
|
383
|
+
bundle_file = self.find_bundle();
|
|
384
|
+
if not bundle_file {
|
|
385
|
+
raise ClientBundleError('Vite build completed but no bundle file found') ;
|
|
386
|
+
}
|
|
387
|
+
bundle_code = bundle_file.read_text(encoding='utf-8');
|
|
388
|
+
bundle_hash = hashlib.sha256(bundle_code.encode('utf-8')).hexdigest();
|
|
389
|
+
return (bundle_code, bundle_hash);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
"""Find the generated Vite CSS file."""
|
|
393
|
+
impl ViteBundler.find_css(self: ViteBundler) -> Optional[Path] {
|
|
394
|
+
css_file = self.output_dir / 'main.css';
|
|
395
|
+
if css_file.exists() {
|
|
396
|
+
return css_file;
|
|
397
|
+
}
|
|
398
|
+
for file in self.output_dir.glob('*.css') {
|
|
399
|
+
return file;
|
|
400
|
+
}
|
|
401
|
+
return None;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
"""Find the generated Vite bundle file."""
|
|
405
|
+
impl ViteBundler.find_bundle(self: ViteBundler) -> Optional[Path] {
|
|
406
|
+
for file in self.output_dir.glob('client.*.js') {
|
|
407
|
+
return file;
|
|
408
|
+
}
|
|
409
|
+
return None;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
"""Run Vite build with generated config in .client-build/.jac-client.configs/."""
|
|
413
|
+
impl ViteBundler.build(self: ViteBundler, entry_file: Optional[Path] = None) -> None {
|
|
414
|
+
self.output_dir.mkdir(parents=True, exist_ok=True);
|
|
415
|
+
generated_package_json = self.project_dir / '.client-build' / '.jac-client.configs' / 'package.json';
|
|
416
|
+
if not generated_package_json.exists() {
|
|
417
|
+
self.create_package_json();
|
|
418
|
+
} else {
|
|
419
|
+
# Ensure tsconfig.json exists even if package.json already exists
|
|
420
|
+
self.create_tsconfig();
|
|
421
|
+
}
|
|
422
|
+
try {
|
|
423
|
+
build_dir = self.project_dir / '.client-build';
|
|
424
|
+
node_modules = build_dir / 'node_modules';
|
|
425
|
+
if not node_modules.exists() {
|
|
426
|
+
# Temporarily copy package.json to .client-build/ for npm install
|
|
427
|
+
build_package_json = build_dir / 'package.json';
|
|
428
|
+
configs_package_json = build_dir / '.jac-client.configs' / 'package.json';
|
|
429
|
+
if configs_package_json.exists() and not build_package_json.exists() {
|
|
430
|
+
import shutil;
|
|
431
|
+
shutil.copy2(configs_package_json, build_package_json);
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
# Install to .client-build/node_modules
|
|
435
|
+
subprocess.run(
|
|
436
|
+
['npm', 'install'],
|
|
437
|
+
cwd=build_dir,
|
|
438
|
+
check=True,
|
|
439
|
+
capture_output=True,
|
|
440
|
+
text=True
|
|
441
|
+
);
|
|
442
|
+
} except subprocess.CalledProcessError as e {
|
|
443
|
+
raise e from ClientBundleError(
|
|
444
|
+
f"Failed to install npm dependencies: {e.stderr}"
|
|
445
|
+
) ;
|
|
446
|
+
} except FileNotFoundError {
|
|
447
|
+
raise None from ClientBundleError(
|
|
448
|
+
'npm command not found. Ensure Node.js and npm are installed.'
|
|
449
|
+
) ;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
build_dir = self.project_dir / '.client-build';
|
|
453
|
+
if self.config_path {
|
|
454
|
+
# Make config path relative to build_dir (where vite runs from)
|
|
455
|
+
config_str = str(self.config_path);
|
|
456
|
+
if '.client-build' in config_str {
|
|
457
|
+
# Config is in .client-build/, make it relative to build_dir
|
|
458
|
+
config_rel = self.config_path.relative_to(build_dir);
|
|
459
|
+
command = ['npx', 'vite', 'build', '--config', str(config_rel)];
|
|
460
|
+
} else {
|
|
461
|
+
# Config is outside .client-build/, use absolute path
|
|
462
|
+
command = ['npx', 'vite', 'build', '--config', str(self.config_path)];
|
|
463
|
+
}
|
|
464
|
+
} elif entry_file {
|
|
465
|
+
generated_config = self.create_vite_config(entry_file);
|
|
466
|
+
# Config is in .client-build/.jac-client.configs/, make it relative to build_dir
|
|
467
|
+
config_rel = generated_config.relative_to(build_dir);
|
|
468
|
+
command = ['npx', 'vite', 'build', '--config', str(config_rel)];
|
|
469
|
+
} else {
|
|
470
|
+
command = ['npm', 'run', 'build'];
|
|
471
|
+
}
|
|
472
|
+
# Run vite from .client-build/ directory so it can find node_modules
|
|
473
|
+
result = subprocess.run(
|
|
474
|
+
command, cwd=build_dir, check=False, capture_output=True, text=True
|
|
475
|
+
);
|
|
476
|
+
if result.returncode != 0 {
|
|
477
|
+
error_msg = result.stderr or result.stdout or 'Unknown error';
|
|
478
|
+
raise ClientBundleError(
|
|
479
|
+
f"Vite build failed:\n{error_msg}\nCommand: {' '.join(command)}"
|
|
480
|
+
) from None ;
|
|
481
|
+
}
|
|
482
|
+
} finally {
|
|
483
|
+
# Clean up temporary package.json in .client-build/
|
|
484
|
+
build_package_json = build_dir / 'package.json';
|
|
485
|
+
if build_package_json.exists() {
|
|
486
|
+
build_package_json.unlink();
|
|
487
|
+
}
|
|
488
|
+
# Move package-lock.json to .jac-client.configs/ if it exists
|
|
489
|
+
build_package_lock = build_dir / 'package-lock.json';
|
|
490
|
+
if build_package_lock.exists() {
|
|
491
|
+
configs_package_lock = build_dir / '.jac-client.configs' / 'package-lock.json';
|
|
492
|
+
if configs_package_lock.exists() {
|
|
493
|
+
configs_package_lock.unlink();
|
|
494
|
+
}
|
|
495
|
+
build_package_lock.rename(configs_package_lock);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
"""Initialize the Vite bundler."""
|
|
501
|
+
impl ViteBundler.init(
|
|
502
|
+
self: ViteBundler,
|
|
503
|
+
project_dir: Path,
|
|
504
|
+
output_dir: Optional[Path] = None,
|
|
505
|
+
minify: bool = False,
|
|
506
|
+
config_path: Optional[Path] = None
|
|
507
|
+
) {
|
|
508
|
+
self.project_dir = project_dir;
|
|
509
|
+
self.output_dir = output_dir or (project_dir / '.client-build' / 'dist');
|
|
510
|
+
self.minify = minify;
|
|
511
|
+
self.config_path = config_path;
|
|
512
|
+
self.config_loader = JacClientConfig(project_dir);
|
|
513
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Import processing for Vite bundling."""
|
|
2
|
+
import from pathlib { Path }
|
|
3
|
+
import from typing { TYPE_CHECKING }
|
|
4
|
+
import from jaclang.runtimelib.client_bundle { ClientBundleError }
|
|
5
|
+
|
|
6
|
+
with entry {
|
|
7
|
+
if TYPE_CHECKING {
|
|
8
|
+
import from jaclang.compiler.codeinfo { ClientManifest }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
"""Processes client imports for Vite bundling."""
|
|
13
|
+
class ImportProcessor {
|
|
14
|
+
def process_vite_imports(
|
|
15
|
+
self: ImportProcessor, manifest: (ClientManifest | None), module_path: Path
|
|
16
|
+
) -> list[(Path | None)];
|
|
17
|
+
|
|
18
|
+
def should_process_import(self: ImportProcessor, import_path: Path) -> bool;
|
|
19
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Jac to JavaScript compilation module."""
|
|
2
|
+
import from collections.abc { Callable }
|
|
3
|
+
import from pathlib { Path }
|
|
4
|
+
import from types { ModuleType }
|
|
5
|
+
import from typing { TYPE_CHECKING, Any }
|
|
6
|
+
|
|
7
|
+
with entry {
|
|
8
|
+
if TYPE_CHECKING {
|
|
9
|
+
import from jaclang.compiler.codeinfo { ClientManifest }
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
"""Handles compilation of Jac files to JavaScript."""
|
|
14
|
+
class JacToJSCompiler {
|
|
15
|
+
def init(
|
|
16
|
+
self: JacToJSCompiler,
|
|
17
|
+
compile_to_js_func: Callable[([Path], tuple[(str, (ModuleType | None))])],
|
|
18
|
+
extract_exports_func: Callable[([Any], list[str])],
|
|
19
|
+
extract_globals_func: Callable[([Any, ModuleType], dict[(str, Any)])]
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
def compile_module(
|
|
23
|
+
self: JacToJSCompiler, module_path: Path
|
|
24
|
+
) -> tuple[str, (ModuleType | None), (ClientManifest | None)];
|
|
25
|
+
|
|
26
|
+
def extract_exports(
|
|
27
|
+
self: JacToJSCompiler, manifest: (ClientManifest | None)
|
|
28
|
+
) -> list[str];
|
|
29
|
+
|
|
30
|
+
def extract_globals(
|
|
31
|
+
self: JacToJSCompiler, manifest: (ClientManifest | None), module: ModuleType
|
|
32
|
+
) -> dict[str, Any];
|
|
33
|
+
|
|
34
|
+
def add_runtime_imports(self: JacToJSCompiler, js_code: str) -> str;
|
|
35
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Package installer for managing npm dependencies in jac.toml."""
|
|
2
|
+
|
|
3
|
+
import shutil;
|
|
4
|
+
import subprocess;
|
|
5
|
+
import from pathlib { Path }
|
|
6
|
+
import from jaclang.runtimelib.client_bundle { ClientBundleError }
|
|
7
|
+
import from .config_loader { JacClientConfig }
|
|
8
|
+
import from .vite_bundler { ViteBundler }
|
|
9
|
+
|
|
10
|
+
class PackageInstaller {
|
|
11
|
+
def init(self: PackageInstaller, project_dir: Path);
|
|
12
|
+
def install_package(
|
|
13
|
+
self: PackageInstaller,
|
|
14
|
+
package_name: str,
|
|
15
|
+
version: (str | None) = None,
|
|
16
|
+
is_dev: bool = False
|
|
17
|
+
) -> None;
|
|
18
|
+
|
|
19
|
+
def install_all(self: PackageInstaller) -> None;
|
|
20
|
+
def _regenerate_and_install(self: PackageInstaller) -> None;
|
|
21
|
+
def uninstall_package(
|
|
22
|
+
self: PackageInstaller, package_name: str, is_dev: bool = False
|
|
23
|
+
) -> None;
|
|
24
|
+
|
|
25
|
+
def list_packages(self: PackageInstaller) -> dict[str, dict[str, str]];
|
|
26
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Vite bundling module."""
|
|
2
|
+
import hashlib;
|
|
3
|
+
import json;
|
|
4
|
+
import shutil;
|
|
5
|
+
import subprocess;
|
|
6
|
+
import from pathlib { Path }
|
|
7
|
+
import from typing { Optional }
|
|
8
|
+
import from jaclang.runtimelib.client_bundle { ClientBundleError }
|
|
9
|
+
import from .config_loader { JacClientConfig }
|
|
10
|
+
"""Handles Vite bundling operations."""
|
|
11
|
+
class ViteBundler {
|
|
12
|
+
def init(
|
|
13
|
+
self: ViteBundler,
|
|
14
|
+
project_dir: Path,
|
|
15
|
+
output_dir: Optional[Path] = None,
|
|
16
|
+
minify: bool = False,
|
|
17
|
+
config_path: Optional[Path] = None
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
def build(self: ViteBundler, entry_file: Optional[Path] = None) -> None;
|
|
21
|
+
def find_bundle(self: ViteBundler) -> Optional[Path];
|
|
22
|
+
def find_css(self: ViteBundler) -> Optional[Path];
|
|
23
|
+
def read_bundle(self: ViteBundler) -> tuple[str, str];
|
|
24
|
+
def _has_typescript_support(self: ViteBundler) -> bool;
|
|
25
|
+
def create_vite_config(self: ViteBundler, entry_file: Path) -> Path;
|
|
26
|
+
def _get_plugin_var_name(self: ViteBundler, plugin_name: str) -> str;
|
|
27
|
+
def _format_plugin_options(self: ViteBundler, options: dict) -> str;
|
|
28
|
+
def _format_config_object(self: ViteBundler, config: dict, indent: int = 0) -> str;
|
|
29
|
+
def _ensure_root_package_json(self: ViteBundler) -> None;
|
|
30
|
+
def _cleanup_root_package_files(self: ViteBundler) -> None;
|
|
31
|
+
def create_package_json(
|
|
32
|
+
self: ViteBundler, project_name: Optional[str] = None
|
|
33
|
+
) -> Path;
|
|
34
|
+
|
|
35
|
+
def create_tsconfig(self: ViteBundler) -> Path;
|
|
36
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Vite-enhanced client bundle generation for Jac web front-ends."""
|
|
2
|
+
import contextlib;
|
|
3
|
+
import shutil;
|
|
4
|
+
import from collections.abc { Callable }
|
|
5
|
+
import from pathlib { Path }
|
|
6
|
+
import from types { ModuleType }
|
|
7
|
+
import from typing { cast }
|
|
8
|
+
import from jaclang.runtimelib.client_bundle {
|
|
9
|
+
ClientBundle,
|
|
10
|
+
ClientBundleBuilder,
|
|
11
|
+
ClientBundleError
|
|
12
|
+
}
|
|
13
|
+
import from .src { ViteCompiler }
|
|
14
|
+
|
|
15
|
+
"""Enhanced ClientBundleBuilder that uses Vite for optimized bundling."""
|
|
16
|
+
class ViteClientBundleBuilder(ClientBundleBuilder) {
|
|
17
|
+
def init(
|
|
18
|
+
self: ViteClientBundleBuilder,
|
|
19
|
+
runtime_path: (Path | None) = None,
|
|
20
|
+
vite_output_dir: (Path | None) = None,
|
|
21
|
+
vite_package_json: (Path | None) = None,
|
|
22
|
+
vite_minify: bool = False
|
|
23
|
+
) -> None;
|
|
24
|
+
|
|
25
|
+
def _get_compiler(self: ViteClientBundleBuilder) -> ViteCompiler;
|
|
26
|
+
def _compile_bundle(
|
|
27
|
+
self: ViteClientBundleBuilder, module: ModuleType, module_path: Path
|
|
28
|
+
) -> ClientBundle;
|
|
29
|
+
|
|
30
|
+
def cleanup_temp_dir(self: ViteClientBundleBuilder) -> None;
|
|
31
|
+
}
|