@cocreate/webpack 1.6.2 → 1.8.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.
@@ -9,33 +9,36 @@ jobs:
9
9
  about:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
- - name: Checkout
13
- uses: actions/checkout@v3
14
- - name: Setup Node.js
15
- uses: actions/setup-node@v3
16
- with:
17
- node-version: 16
18
- - name: Jaid/action-sync-node-meta
19
- uses: jaid/action-sync-node-meta@v1.4.0
20
- with:
21
- direction: overwrite-github
22
- githubToken: "${{ secrets.GITHUB }}"
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v7
14
+
15
+ - name: Sync package.json description to GitHub About
16
+ env:
17
+ GITHUB_TOKEN: ${{ secrets.GITHUB }}
18
+ run: |
19
+ DESC=$(jq -r '.description // empty' package.json)
20
+ if [ -n "$DESC" ]; then
21
+ echo "Updating repository description to: $DESC"
22
+ gh api -X PATCH repos/${{ github.repository }} -f description="$DESC"
23
+ else
24
+ echo "No description found in package.json."
25
+ fi
23
26
 
24
27
  release:
25
28
  runs-on: ubuntu-latest
26
29
  steps:
27
- - name: Checkout
28
- uses: actions/checkout@v4
30
+ - name: Checkout repository
31
+ uses: actions/checkout@v7
29
32
  with:
30
- fetch-depth: 0 # Required so semantic-release can trace git tags/history
33
+ fetch-depth: 0
34
+ token: ${{ secrets.GITHUB }} # Authenticates git CLI for tag/commit pushes
31
35
 
32
36
  - name: Setup Node.js
33
- uses: actions/setup-node@v4
37
+ uses: actions/setup-node@v7
34
38
  with:
35
- node-version: 22
39
+ node-version: '24'
36
40
 
37
41
  - name: Install Semantic Release & Plugins
38
- # Installs semantic-release and its plugins on the runner
39
42
  run: |
40
43
  npm install -g semantic-release \
41
44
  @semantic-release/changelog \
@@ -43,12 +46,11 @@ jobs:
43
46
  @semantic-release/github \
44
47
  @semantic-release/git
45
48
 
46
- - name: Run Semantic Release (Native)
49
+ - name: Run Semantic Release
47
50
  id: semantic
48
- # This will automatically pick up your export default config file in the repository root
49
51
  run: npx semantic-release
50
52
  env:
51
- GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
53
+ GITHUB_TOKEN: "${{ secrets.GITHUB }}"
52
54
  NPM_TOKEN: "${{ secrets.NPM_TOKEN }}"
53
55
 
54
56
  outputs:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/webpack",
3
- "version": "1.6.2",
3
+ "version": "1.8.0",
4
4
  "description": "A Webpack integration tool for CoCreate applications, enabling file watching, automated chunking, lazy loading, and file uploading. It leverages CoCreate.config for streamlined project builds and development workflows.",
5
5
  "keywords": [
6
6
  "webpack",
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "main": "./src/index.js",
43
43
  "dependencies": {
44
- "@cocreate/cli": "^1.56.1",
44
+ "@cocreate/cli": "^1.60.0",
45
45
  "css-loader": "^7.1.4",
46
46
  "esbuild": "^0.25.12",
47
47
  "esbuild-loader": "^4.5.0",
@@ -55,7 +55,7 @@
55
55
  "webpack-node-externals": "^3.0.0"
56
56
  },
57
57
  "allowScripts": {
58
- "@cocreate/acme@1.3.2": true,
58
+ "@cocreate/certificates@1.3.2": true,
59
59
  "@cocreate/actions@1.21.4": true,
60
60
  "@cocreate/api@1.22.5": true,
61
61
  "@cocreate/config@1.13.4": true,
@@ -71,7 +71,6 @@
71
71
  "@cocreate/render@1.46.1": true,
72
72
  "@cocreate/socket-client@1.40.5": true,
73
73
  "@cocreate/utils@1.42.2": true,
74
- "@cocreate/uuid@1.12.4": true,
75
74
  "@cocreate/webpack@1.4.3": true,
76
75
  "@parcel/watcher@2.5.6": true,
77
76
  "esbuild@0.25.12": true,
package/src/index.js CHANGED
@@ -1,106 +1,112 @@
1
1
  /**
2
2
  * @fileoverview Webpack plugins and loaders for the CoCreate ecosystem.
3
- * Includes module generation, automated file uploading, and symlink management.
3
+ * Includes unified entry generation (`CoCreate.entry.js`), automated file uploading, and symlink management.
4
4
  */
5
5
 
6
6
  const fs = require("fs");
7
7
  const path = require("path");
8
8
 
9
- /**
10
- * Import the upload function from CoCreate CLI to handle automated file uploads.
11
- * This function synchronizes local changes with the CoCreate cloud environment.
12
- */
13
- const upload = require("@cocreate/cli/src/commands/upload.js");
9
+ let upload;
10
+ try {
11
+ upload = require("@cocreate/cli/src/commands/upload.js");
12
+ } catch (e) {
13
+ // Graceful fallback if @cocreate/cli is not present in local dependencies
14
+ upload = null;
15
+ }
14
16
 
15
17
  /**
16
18
  * @class ModuleGenerator
17
- * @description A Webpack plugin that dynamically generates a module entry file
18
- * (typically `CoCreate.modules.js`) based on a configuration object. It leverages
19
- * `@cocreate/lazy-loader` for efficient code splitting and dependency management.
19
+ * @description Webpack plugin that generates a single unified entry file (`CoCreate.entry.js`)
20
+ * containing both global plugin configuration and `@cocreate/lazy-loader` declarations.
20
21
  */
21
22
  class ModuleGenerator {
22
23
  /**
23
24
  * @constructor
24
- * @param {Object} pluginOptions - The configuration for the plugin.
25
+ * @param {Object} [pluginOptions={}] - Options for the generator plugin.
25
26
  * @param {Object} [pluginOptions.config] - Direct CoCreate configuration object.
26
27
  * @param {string} [pluginOptions.configPath] - Path to a CoCreate config file.
28
+ * @param {string} [pluginOptions.entryOutputPath="./CoCreate.entry.js"] - Path for generated unified entry file.
27
29
  */
28
- constructor(pluginOptions) {
30
+ constructor(pluginOptions = {}) {
29
31
  /** @type {Object} */
30
32
  this.pluginOptions = pluginOptions;
31
33
  }
32
34
 
33
35
  /**
34
36
  * @method apply
35
- * @description Entry point for the Webpack plugin. Taps into the `beforeCompile` hook.
37
+ * @description Taps into Webpack's `beforeCompile` hook to write the unified entry file.
36
38
  * @param {import('webpack').Compiler} compiler - The Webpack compiler instance.
37
39
  */
38
40
  apply(compiler) {
39
- let CoCreateConfig;
41
+ let CoCreateConfig = null;
40
42
 
41
- // Resolve configuration source
42
- if (typeof this.pluginOptions === "object") {
43
- CoCreateConfig = this.pluginOptions;
44
- } else if (this.pluginOptions && this.pluginOptions.configPath) {
43
+ if (this.pluginOptions.config && typeof this.pluginOptions.config === "object") {
44
+ CoCreateConfig = this.pluginOptions.config;
45
+ } else if (this.pluginOptions.configPath) {
45
46
  try {
46
- CoCreateConfig = require(this.pluginOptions.configPath);
47
+ const resolvedPath = path.isAbsolute(this.pluginOptions.configPath)
48
+ ? this.pluginOptions.configPath
49
+ : path.resolve(process.cwd(), this.pluginOptions.configPath);
50
+ CoCreateConfig = require(resolvedPath);
47
51
  } catch (error) {
48
- console.error("Error loading CoCreate config file:", error);
52
+ console.error("[ModuleGenerator] Error loading CoCreate config file:", error);
49
53
  throw error;
50
54
  }
51
- } else {
52
- console.error("ModuleGenerator requires either a 'config' object or 'configPath' string.");
55
+ } else if (typeof this.pluginOptions === "object" && Object.keys(this.pluginOptions).length > 0) {
56
+ CoCreateConfig = this.pluginOptions;
57
+ }
58
+
59
+ if (!CoCreateConfig) {
60
+ console.error("[ModuleGenerator] Requires either a 'config' object or 'configPath' string.");
53
61
  return;
54
62
  }
55
63
 
56
- /** @type {boolean} Track if modules have already been generated to avoid redundant writes. */
57
- let modulesGenerated = false;
64
+ /** @type {boolean} State flag to avoid redundant disk writes during watch mode recompiles. */
65
+ let entryGenerated = false;
58
66
 
59
67
  compiler.hooks.beforeCompile.tapAsync(
60
- "CoCreateLazyloader",
68
+ "CoCreateGenerator",
61
69
  (params, callback) => {
62
- if (modulesGenerated) {
63
- callback();
64
- } else {
65
- // Fetch the output path from the root of the config, with a fallback
66
- const outputPath = this.pluginOptions.moduleOutputPath || "./CoCreate.modules.js";
67
- let moduleContent = `import { dependency, lazyLoad } from '@cocreate/lazy-loader';\n\n`;
68
-
69
- // Ensure we are explicitly targeting the 'modules' namespace
70
- const modulesObj = CoCreateConfig.modules || {};
71
-
72
- // Generate import statements based on module metadata
73
- Object.entries(modulesObj).forEach(
74
- ([moduleName, moduleInfo]) => {
75
- // Skip non-objects
76
- if (typeof moduleInfo !== "object" || moduleInfo === null) return;
77
-
78
- // Skip items that do not have an import defined (acts as 'continue' in forEach)
79
- if (!moduleInfo.import) return;
80
-
81
- if (moduleInfo.selector) {
82
- // Logic for lazy-loading based on DOM selectors
83
- const sanitizedSelector = moduleInfo.selector.replaceAll("'", '"');
84
- moduleContent += `lazyLoad('${moduleName}', '${sanitizedSelector}', () => import(/*webpackChunkName: "${moduleName}-chunk"*/ '${moduleInfo.import}'));\n`;
85
- } else {
86
- // Logic for standard dependencies
87
- moduleContent += `dependency('${moduleName}', import(/*webpackChunkName: "${moduleName}-chunk"*/ '${moduleInfo.import}'));\n`;
88
- }
89
- }
90
- );
91
-
92
- // Persist the generated module file to disk
93
- fs.writeFile(outputPath, moduleContent, (err) => {
94
- if (err) {
95
- console.error(`Error writing ${outputPath}:`, err);
96
- callback(err);
97
- } else {
98
- modulesGenerated = true;
99
- console.log(`${outputPath} generated successfully.`);
100
- callback();
101
- }
102
- });
70
+ if (entryGenerated) {
71
+ return callback();
103
72
  }
73
+
74
+ const entryOutputPath = this.pluginOptions.entryOutputPath || "./CoCreate.index.js";
75
+
76
+ let entryContent = `import { dependency, lazyLoad } from '@cocreate/lazy-loader';\n\n`;
77
+
78
+ const pluginsObj = CoCreateConfig.plugins || {};
79
+ entryContent += `if (typeof window !== 'undefined') {\n`;
80
+ entryContent += ` window.CoCreateConfig = window.CoCreateConfig || {};\n`;
81
+ entryContent += ` window.CoCreateConfig.plugins = Object.assign(\n`;
82
+ entryContent += ` {},\n`;
83
+ entryContent += ` window.CoCreateConfig.plugins || {},\n`;
84
+ entryContent += ` ${JSON.stringify(pluginsObj, null, 4)}\n`;
85
+ entryContent += ` );\n`;
86
+ entryContent += `}\n\n`;
87
+
88
+ const modulesObj = CoCreateConfig.modules || {};
89
+ Object.entries(modulesObj).forEach(([moduleName, moduleInfo]) => {
90
+ if (typeof moduleInfo !== "object" || moduleInfo === null) return;
91
+ if (!moduleInfo.import) return;
92
+
93
+ if (moduleInfo.selector) {
94
+ const sanitizedSelector = moduleInfo.selector.replaceAll("'", '"');
95
+ entryContent += `lazyLoad('${moduleName}', '${sanitizedSelector}', () => import(/*webpackChunkName: "${moduleName}-chunk"*/ '${moduleInfo.import}'));\n`;
96
+ } else {
97
+ entryContent += `dependency('${moduleName}', import(/*webpackChunkName: "${moduleName}-chunk"*/ '${moduleInfo.import}'));\n`;
98
+ }
99
+ });
100
+
101
+ fs.writeFile(entryOutputPath, entryContent, "utf8", (err) => {
102
+ if (err) {
103
+ console.error(`[@cocreate/webpack] Error writing ${entryOutputPath}:`, err);
104
+ return callback(err);
105
+ }
106
+ entryGenerated = true;
107
+ console.log(`[@cocreate/webpack] ${entryOutputPath} generated successfully.`);
108
+ callback();
109
+ });
104
110
  }
105
111
  );
106
112
  }
@@ -108,37 +114,31 @@ class ModuleGenerator {
108
114
 
109
115
  /**
110
116
  * @class FileUploader
111
- * @description Handles automated file uploads to the CoCreate platform,
112
- * primarily intended for use during Webpack's 'watch' mode to sync local changes.
117
+ * @description Handles automated file uploads to the CoCreate platform during Webpack watch mode.
113
118
  */
114
119
  class FileUploader {
115
120
  /**
116
121
  * @constructor
117
- * @param {Object} env - Environment variables passed from the Webpack CLI.
118
- * @param {Object} argv - Command line arguments (used to detect --watch).
122
+ * @param {Object} [env={}] - Environment variables passed from the Webpack CLI.
123
+ * @param {Object} [argv={}] - Command line arguments.
119
124
  */
120
- constructor(env, argv) {
121
- /** @type {Object} */
125
+ constructor(env = {}, argv = {}) {
122
126
  this.env = env;
123
- /** @type {boolean} Internal state to prevent multiple upload triggers. */
124
127
  this.isWatching = false;
125
- /** @type {boolean} Flag indicating if Webpack is in watch mode. */
126
128
  this.isWatch = argv.watch === true;
127
129
  }
128
130
 
129
131
  /**
130
132
  * @method apply
131
- * @description Hooks into the compilation process to trigger uploads.
133
+ * @description Hooks into compilation hooks to upload files to CoCreate.
132
134
  * @param {import('webpack').Compiler} compiler - The Webpack compiler instance.
133
135
  */
134
136
  apply(compiler) {
135
- if (this.isWatch) {
136
- // Optional: Upload files before the first compilation starts
137
+ if (this.isWatch && upload) {
137
138
  if (this.env.beforeCompilation) {
138
139
  upload(process.cwd(), ["../", "-w"]);
139
140
  }
140
141
 
141
- // Upload files after assets are emitted to the output directory
142
142
  if (this.env.afterCompilation) {
143
143
  compiler.hooks.emit.tapAsync(
144
144
  "watchFiles",
@@ -155,67 +155,12 @@ class FileUploader {
155
155
  }
156
156
  }
157
157
 
158
- /**
159
- * @class SymlinkCreator
160
- * @description A utility plugin that creates symbolic links after the build process.
161
- * This is used to map PWA assets and distribution folders to the project root.
162
- */
163
158
  class SymlinkCreator {
164
- /**
165
- * @constructor
166
- * @param {Object} [options] - Configuration options for symlink behavior.
167
- */
168
- constructor(options) {
169
- /** @type {Object|undefined} */
170
- this.options = options;
171
- }
172
-
173
- /**
174
- * @method apply
175
- * @description Taps into the `afterEmit` hook to create symlinks once files are generated.
176
- * @param {import('webpack').Compiler} compiler - The Webpack compiler instance.
177
- */
178
159
  apply(compiler) {
179
- compiler.hooks.afterEmit.tap("SymlinkPlugin", (compilation) => {
180
- // Standard symlink mappings for CoCreate PWA structure
181
- // this.createSymlink("./dist", "../dist", "dir");
182
- // this.createSymlink("./node_modules/@cocreate/pwa/src/service-worker.js", "../service-worker.js", "file");
183
- // this.createSymlink("./node_modules/@cocreate/pwa/src/manifest.webmanifest", "../manifest.webmanifest", "file");
184
- // this.createSymlink("./node_modules/@cocreate/pwa/src/offline.html", "../offline.html", "file");
185
- });
186
- }
187
-
188
- /**
189
- * @method createSymlink
190
- * @description Helper method to safely create a symlink if the target exists and the destination is free.
191
- * @param {string} target - The source path (relative or absolute).
192
- * @param {string} destination - The target link path (relative or absolute).
193
- * @param {string} type - The type of symlink ('file', 'dir', or 'junction').
194
- */
195
- createSymlink(target, destination, type) {
196
- if (fs.existsSync(target)) {
197
- const absoluteTarget = path.resolve(target);
198
- if (!fs.existsSync(destination)) {
199
- const absoluteDestination = path.resolve(destination);
200
- fs.symlink(absoluteTarget, absoluteDestination, type, (err) => {
201
- if (err) {
202
- console.error(`Failed to create symlink at ${destination}:`, err);
203
- } else {
204
- console.log(`Symlink created: ${target} -> ${destination}`);
205
- }
206
- });
207
- }
208
- }
160
+ // Symlink creation logic can be tapped here if required
209
161
  }
210
162
  }
211
163
 
212
- /**
213
- * @exports
214
- * @property {ModuleGenerator} ModuleGenerator - Dynamic module builder plugin.
215
- * @property {FileUploader} FileUploader - CLI upload integration plugin.
216
- * @property {SymlinkCreator} SymlinkCreator - PWA/dist symlink management plugin.
217
- * @property {string} UnicodeLoader - Absolute path to the unicode replacement loader.
218
- */
219
164
  module.exports = {
220
165
  ModuleGenerator,
221
166
  FileUploader,