Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"private": false,
"version": "0.14.0",
"type": "module",
"sideEffects": ["**/*.css"],
"sideEffects": [
"**/*.css"
],
"description": "maxGraph is a fully client side JavaScript diagramming library that uses SVG and HTML for rendering.",
"keywords": [
"browser",
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Client {
/**
* The version of the `maxGraph` library.
*/
// WARN: this constant is updated at release time by the script located at `scripts/update-versions.mjs`.
// So, if you modify the name of this file or this constant, please update the script accordingly.
static VERSION = '0.14.0';

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/website/docs/development/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ Apply changes in the source code
- Releases are done from the default branch, so all changes are done in the `main` branch.
- These changes are going to be done locally, and then pushed to the repository.
- Make sure that the code is up-to-date with the `main` branch. Run `git pull` to get the latest changes.
- Update the version in `packages/core/package.json` and the `VERSION` constant in the `packages/core/src/Client.ts` file.
- Update the `package-lock.json` file by running `npm install` at the root of the repository. It should only change the version of `@maxgraph/core`.
- Update the version in various files by running, from the repository root: `node scripts/update-versions.mjs <version>` (replace `<version>` with the new version).
- Update the `CHANGELOG` file to list the major changes included in the new version. Be generic and add a
link to the future GitHub release that will contain detailed release notes, as shown below.
```
Expand Down
66 changes: 66 additions & 0 deletions scripts/update-versions.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright 2025-present The maxGraph project Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// IMPORTANT: this script is intended to run as part of a GitHub workflow which is not installing the dependencies of the project.
// So please, do not import code that is not provided by the node runtime. Otherwise, update the GitHub workflow definition
import { readFileSync, writeFileSync } from 'node:fs';

// run from the root of the repository: node scripts/update-versions.mjs 0.12.0.alpha-1
const newVersion = process.argv[2];

console.info('Updating version in various files, version:', newVersion);
updateVersionInRootPackageLockJsonFile(newVersion);
updateVersionInCorePackageJsonFile(newVersion);
updateVersionInSourceFile(newVersion);
console.info('Files have been updated');
Comment on lines +21 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add version format validation.

The script should validate the version format and handle missing arguments gracefully.

Consider adding this validation:

 const newVersion = process.argv[2];
+if (!newVersion) {
+  console.error('Error: Version argument is required');
+  console.error('Usage: node scripts/update-versions.mjs <version>');
+  process.exit(1);
+}
+if (!/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newVersion)) {
+  console.error('Error: Invalid version format. Must follow semver (e.g., 1.2.3, 1.2.3-alpha.1)');
+  process.exit(1);
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// run from the root of the repository: node scripts/update-versions.mjs 0.12.0.alpha-1
const newVersion = process.argv[2];
console.info('Updating version in various files, version:', newVersion);
updateVersionInRootPackageLockJsonFile(newVersion);
updateVersionInCorePackageJsonFile(newVersion);
updateVersionInSourceFile(newVersion);
console.info('Files have been updated');
// run from the root of the repository: node scripts/update-versions.mjs 0.12.0.alpha-1
const newVersion = process.argv[2];
if (!newVersion) {
console.error('Error: Version argument is required');
console.error('Usage: node scripts/update-versions.mjs <version>');
process.exit(1);
}
if (!/^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newVersion)) {
console.error('Error: Invalid version format. Must follow semver (e.g., 1.2.3, 1.2.3-alpha.1)');
process.exit(1);
}
console.info('Updating version in various files, version:', newVersion);
updateVersionInRootPackageLockJsonFile(newVersion);
updateVersionInCorePackageJsonFile(newVersion);
updateVersionInSourceFile(newVersion);
console.info('Files have been updated');
🧰 Tools
🪛 ESLint

[error] 22-22: 'process' is not defined.

(no-undef)


[error] 24-24: Unexpected console statement.

(no-console)


[error] 28-28: Unexpected console statement.

(no-console)


function updateVersionInRootPackageLockJsonFile(newVersion) {
const path = 'package-lock.json';
console.info('Updating', path);
const fileContent = readFileContent(path);
const packageJson = JSON.parse(fileContent);
packageJson.packages['packages/core'].version = newVersion;
writeJsonContentToFile(path, packageJson);
}
Comment on lines +30 to +37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for file operations and package structure validation.

The function should handle file operation errors and validate the package-lock.json structure.

Consider this implementation:

 function updateVersionInRootPackageLockJsonFile(newVersion) {
   const path = 'package-lock.json';
   console.info('Updating', path);
-  const fileContent = readFileContent(path);
-  const packageJson = JSON.parse(fileContent);
-  packageJson.packages['packages/core'].version = newVersion;
-  writeJsonContentToFile(path, packageJson);
+  try {
+    const fileContent = readFileContent(path);
+    const packageJson = JSON.parse(fileContent);
+    if (!packageJson.packages?.['packages/core']) {
+      throw new Error('packages/core not found in package-lock.json');
+    }
+    packageJson.packages['packages/core'].version = newVersion;
+    writeJsonContentToFile(path, packageJson);
+  } catch (error) {
+    console.error(`Failed to update ${path}:`, error.message);
+    process.exit(1);
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function updateVersionInRootPackageLockJsonFile(newVersion) {
const path = 'package-lock.json';
console.info('Updating', path);
const fileContent = readFileContent(path);
const packageJson = JSON.parse(fileContent);
packageJson.packages['packages/core'].version = newVersion;
writeJsonContentToFile(path, packageJson);
}
function updateVersionInRootPackageLockJsonFile(newVersion) {
const path = 'package-lock.json';
console.info('Updating', path);
try {
const fileContent = readFileContent(path);
const packageJson = JSON.parse(fileContent);
if (!packageJson.packages?.['packages/core']) {
throw new Error('packages/core not found in package-lock.json');
}
packageJson.packages['packages/core'].version = newVersion;
writeJsonContentToFile(path, packageJson);
} catch (error) {
console.error(`Failed to update ${path}:`, error.message);
process.exit(1);
}
}
🧰 Tools
🪛 ESLint

[error] 32-32: Unexpected console statement.

(no-console)


function updateVersionInCorePackageJsonFile(newVersion) {
const path = 'packages/core/package.json';
console.info('Updating', path);
const fileContent = readFileContent(path);
const packageJson = JSON.parse(fileContent);
packageJson.version = newVersion;
writeJsonContentToFile(path, packageJson);
}
Comment on lines +39 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for core package.json operations.

Similar to the previous function, add error handling and file validation.

Consider this implementation:

 function updateVersionInCorePackageJsonFile(newVersion) {
   const path = 'packages/core/package.json';
   console.info('Updating', path);
-  const fileContent = readFileContent(path);
-  const packageJson = JSON.parse(fileContent);
-  packageJson.version = newVersion;
-  writeJsonContentToFile(path, packageJson);
+  try {
+    const fileContent = readFileContent(path);
+    const packageJson = JSON.parse(fileContent);
+    packageJson.version = newVersion;
+    writeJsonContentToFile(path, packageJson);
+  } catch (error) {
+    console.error(`Failed to update ${path}:`, error.message);
+    process.exit(1);
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function updateVersionInCorePackageJsonFile(newVersion) {
const path = 'packages/core/package.json';
console.info('Updating', path);
const fileContent = readFileContent(path);
const packageJson = JSON.parse(fileContent);
packageJson.version = newVersion;
writeJsonContentToFile(path, packageJson);
}
function updateVersionInCorePackageJsonFile(newVersion) {
const path = 'packages/core/package.json';
console.info('Updating', path);
try {
const fileContent = readFileContent(path);
const packageJson = JSON.parse(fileContent);
packageJson.version = newVersion;
writeJsonContentToFile(path, packageJson);
} catch (error) {
console.error(`Failed to update ${path}:`, error.message);
process.exit(1);
}
}
🧰 Tools
🪛 ESLint

[error] 41-41: Unexpected console statement.

(no-console)


function updateVersionInSourceFile(newVersion) {
const path = 'packages/core/src/Client.ts';
console.info('Updating', path);
const content = readFileContent(path);
// replace the 1st occurrence, this is OK as the constant appears only once in the file
const updatedContent = content.replace(
/static VERSION =.*/,
`static VERSION = '${newVersion}';`
);
writeFileSync(path, updatedContent);
}
Comment on lines +48 to +58

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve version replacement reliability in source file.

The current implementation could be more robust with better error handling and replacement verification.

Consider this enhanced implementation:

 function updateVersionInSourceFile(newVersion) {
   const path = 'packages/core/src/Client.ts';
   console.info('Updating', path);
-  const content = readFileContent(path);
-  // replace the 1st occurrence, this is OK as the constant appears only once in the file
-  const updatedContent = content.replace(
-    /static VERSION =.*/,
-    `static VERSION = '${newVersion}';`
-  );
-  writeFileSync(path, updatedContent);
+  try {
+    const content = readFileContent(path);
+    const versionRegex = /static\s+VERSION\s*=\s*['"]([^'"]+)['"]\s*;/;
+    if (!versionRegex.test(content)) {
+      throw new Error('VERSION constant not found in expected format');
+    }
+    const updatedContent = content.replace(
+      versionRegex,
+      `static VERSION = '${newVersion}';`
+    );
+    if (content === updatedContent) {
+      throw new Error('Failed to update version in file');
+    }
+    writeFileSync(path, updatedContent);
+  } catch (error) {
+    console.error(`Failed to update ${path}:`, error.message);
+    process.exit(1);
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function updateVersionInSourceFile(newVersion) {
const path = 'packages/core/src/Client.ts';
console.info('Updating', path);
const content = readFileContent(path);
// replace the 1st occurrence, this is OK as the constant appears only once in the file
const updatedContent = content.replace(
/static VERSION =.*/,
`static VERSION = '${newVersion}';`
);
writeFileSync(path, updatedContent);
}
function updateVersionInSourceFile(newVersion) {
const path = 'packages/core/src/Client.ts';
console.info('Updating', path);
try {
const content = readFileContent(path);
const versionRegex = /static\s+VERSION\s*=\s*['"]([^'"]+)['"]\s*;/;
if (!versionRegex.test(content)) {
throw new Error('VERSION constant not found in expected format');
}
const updatedContent = content.replace(
versionRegex,
`static VERSION = '${newVersion}';`
);
if (content === updatedContent) {
throw new Error('Failed to update version in file');
}
writeFileSync(path, updatedContent);
} catch (error) {
console.error(`Failed to update ${path}:`, error.message);
process.exit(1);
}
}
🧰 Tools
🪛 ESLint

[error] 50-50: Unexpected console statement.

(no-console)


function readFileContent(path) {
return readFileSync(path, 'utf8').toString();
}

function writeJsonContentToFile(path, obj) {
writeFileSync(path, JSON.stringify(obj, null, 2) + '\n');
}