diff --git a/.github/actions/package.json b/.github/actions/package.json index 58a842dcf9..8530bf124b 100644 --- a/.github/actions/package.json +++ b/.github/actions/package.json @@ -5,7 +5,6 @@ "type": "module", "devDependencies": { "@sourceacademy/modules-repotools": "workspace:^", - "@types/lodash": "^4.14.198", "@types/node": "^22.15.30", "typescript": "^5.8.2", "vitest": "^4.0.18" @@ -14,7 +13,7 @@ "@actions/artifact": "^6.0.0", "@actions/core": "^1.11.1", "@actions/exec": "^3.0.0", - "lodash": "^4.17.23", + "es-toolkit": "^1.44.0", "snyk-nodejs-lockfile-parser": "^2.4.2" }, "scripts": { diff --git a/.github/actions/src/__tests__/commons.test.ts b/.github/actions/src/__tests__/commons.test.ts index 82447d6487..3b7598c623 100644 --- a/.github/actions/src/__tests__/commons.test.ts +++ b/.github/actions/src/__tests__/commons.test.ts @@ -2,9 +2,13 @@ import * as exec from '@actions/exec'; import { describe, expect, it, test, vi } from 'vitest'; import * as commons from '../commons.js'; -vi.mock(import('lodash/memoize.js'), () => ({ - default: (x: any) => x -}) as any); +vi.mock(import('es-toolkit'), async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + memoize: (x: any) => x + }; +}); const mockedExecOutput = vi.spyOn(exec, 'getExecOutput'); diff --git a/.github/actions/src/__tests__/lockfiles.test.ts b/.github/actions/src/__tests__/lockfiles.test.ts index 973f4674d8..279fefa5f4 100644 --- a/.github/actions/src/__tests__/lockfiles.test.ts +++ b/.github/actions/src/__tests__/lockfiles.test.ts @@ -12,8 +12,8 @@ describe(utils.extractPackageName, () => { }); it('works with regular package names', () => { - expect(utils.extractPackageName('lodash@npm:^4.17.20')) - .toEqual('lodash'); + expect(utils.extractPackageName('es-toolkit@npm:^1.44.0')) + .toEqual('es-toolkit'); }); it('throws an error on an invalid package name', () => { diff --git a/.github/actions/src/__tests__/sample_why.txt b/.github/actions/src/__tests__/sample_why.txt index 240cec0056..7c697a6046 100644 --- a/.github/actions/src/__tests__/sample_why.txt +++ b/.github/actions/src/__tests__/sample_why.txt @@ -23,18 +23,18 @@ {"value":"@sourceacademy/bundle-sound@workspace:src/bundles/sound","children":{"@sourceacademy/bundle-midi@workspace:src/bundles/midi":{"value":{"locator":"@sourceacademy/bundle-midi@workspace:src/bundles/midi","descriptor":"@sourceacademy/bundle-midi@workspace:^"},"children":{}},"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-lib@workspace:lib/modules-lib":{"value":{"locator":"@sourceacademy/modules-lib@workspace:lib/modules-lib","descriptor":"@sourceacademy/modules-lib@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}}}} {"value":"@sourceacademy/bundle-sound_matrix@workspace:src/bundles/sound_matrix","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}}}} {"value":"@sourceacademy/bundle-stereo_sound@workspace:src/bundles/stereo_sound","children":{"@sourceacademy/bundle-midi@workspace:src/bundles/midi":{"value":{"locator":"@sourceacademy/bundle-midi@workspace:src/bundles/midi","descriptor":"@sourceacademy/bundle-midi@workspace:^"},"children":{}},"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}}}} -{"value":"@sourceacademy/bundle-unittest@workspace:src/bundles/unittest","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}},"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}}}} +{"value":"@sourceacademy/bundle-unittest@workspace:src/bundles/unittest","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}},"es-toolkit@npm:1.44.0":{"value":{"locator":"es-toolkit@npm:1.44.0","descriptor":"es-toolkit@npm:^1.44.0"},"children":{}}}} {"value":"@sourceacademy/bundle-unity_academy@workspace:src/bundles/unity_academy","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}}}} {"value":"@sourceacademy/bundle-wasm@workspace:src/bundles/wasm","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"source-academy-wabt@npm:1.1.3":{"value":{"locator":"source-academy-wabt@npm:1.1.3","descriptor":"source-academy-wabt@npm:^1.0.4"},"children":{"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}}}}}} {"value":"@sourceacademy/lint-plugin@workspace:lib/lintplugin","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:^"},"children":{}}}} -{"value":"@sourceacademy/markdown-plugin-directory-tree@workspace:lib/markdown-tree","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}},"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:^"},"children":{}}}} -{"value":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","children":{"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}},"@sourceacademy/modules-repotools@virtual:1448f4d06c0cf02cc986bce0139b31c0f3c95af1573e69673bc11ad2928a2fc505818a40d3f1caf168c35ce00c20238d52dfdba1940c59c81fd5df1b08ba49d6#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:1448f4d06c0cf02cc986bce0139b31c0f3c95af1573e69673bc11ad2928a2fc505818a40d3f1caf168c35ce00c20238d52dfdba1940c59c81fd5df1b08ba49d6#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:1448f4d06c0cf02cc986bce0139b31c0f3c95af1573e69673bc11ad2928a2fc505818a40d3f1caf168c35ce00c20238d52dfdba1940c59c81fd5df1b08ba49d6#workspace:^"},"children":{}}}} +{"value":"@sourceacademy/markdown-plugin-directory-tree@workspace:lib/markdown-tree","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:^"},"children":{}},"es-toolkit@npm:1.44.0":{"value":{"locator":"es-toolkit@npm:1.44.0","descriptor":"es-toolkit@npm:^1.44.0"},"children":{}}}} +{"value":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","children":{"@sourceacademy/modules-repotools@virtual:1448f4d06c0cf02cc986bce0139b31c0f3c95af1573e69673bc11ad2928a2fc505818a40d3f1caf168c35ce00c20238d52dfdba1940c59c81fd5df1b08ba49d6#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:1448f4d06c0cf02cc986bce0139b31c0f3c95af1573e69673bc11ad2928a2fc505818a40d3f1caf168c35ce00c20238d52dfdba1940c59c81fd5df1b08ba49d6#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:1448f4d06c0cf02cc986bce0139b31c0f3c95af1573e69673bc11ad2928a2fc505818a40d3f1caf168c35ce00c20238d52dfdba1940c59c81fd5df1b08ba49d6#workspace:^"},"children":{}},"es-toolkit@npm:1.44.0":{"value":{"locator":"es-toolkit@npm:1.44.0","descriptor":"es-toolkit@npm:^1.44.0"},"children":{}}}} {"value":"@sourceacademy/modules-devserver@workspace:devserver","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-lib@workspace:lib/modules-lib":{"value":{"locator":"@sourceacademy/modules-lib@workspace:lib/modules-lib","descriptor":"@sourceacademy/modules-lib@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}}}} {"value":"@sourceacademy/modules-docserver@workspace:docs","children":{"@sourceacademy/modules-lib@workspace:lib/modules-lib":{"value":{"locator":"@sourceacademy/modules-lib@workspace:lib/modules-lib","descriptor":"@sourceacademy/modules-lib@workspace:^"},"children":{}},"@sourceacademy/lint-plugin@virtual:f0562030a653a107496800a80ececfadfd737a6a260bbd2572ca4e42de1d6b97749197bb1c41d0d71c9f18ab009789560666041994678fe1aba63902e9fb15bd#workspace:lib/lintplugin":{"value":{"locator":"@sourceacademy/lint-plugin@virtual:f0562030a653a107496800a80ececfadfd737a6a260bbd2572ca4e42de1d6b97749197bb1c41d0d71c9f18ab009789560666041994678fe1aba63902e9fb15bd#workspace:lib/lintplugin","descriptor":"@sourceacademy/lint-plugin@virtual:f0562030a653a107496800a80ececfadfd737a6a260bbd2572ca4e42de1d6b97749197bb1c41d0d71c9f18ab009789560666041994678fe1aba63902e9fb15bd#workspace:^"},"children":{}},"@sourceacademy/markdown-plugin-directory-tree@virtual:f0562030a653a107496800a80ececfadfd737a6a260bbd2572ca4e42de1d6b97749197bb1c41d0d71c9f18ab009789560666041994678fe1aba63902e9fb15bd#workspace:lib/markdown-tree":{"value":{"locator":"@sourceacademy/markdown-plugin-directory-tree@virtual:f0562030a653a107496800a80ececfadfd737a6a260bbd2572ca4e42de1d6b97749197bb1c41d0d71c9f18ab009789560666041994678fe1aba63902e9fb15bd#workspace:lib/markdown-tree","descriptor":"@sourceacademy/markdown-plugin-directory-tree@virtual:f0562030a653a107496800a80ececfadfd737a6a260bbd2572ca4e42de1d6b97749197bb1c41d0d71c9f18ab009789560666041994678fe1aba63902e9fb15bd#workspace:^"},"children":{}}}} -{"value":"@sourceacademy/modules-github-actions@workspace:.github/actions","children":{"@actions/artifact@npm:2.3.2":{"value":{"locator":"@actions/artifact@npm:2.3.2","descriptor":"@actions/artifact@npm:^2.3.2"},"children":{"archiver@npm:7.0.1":{"value":{"locator":"archiver@npm:7.0.1","descriptor":"archiver@npm:^7.0.1"},"children":{"archiver-utils@npm:5.0.2":{"value":{"locator":"archiver-utils@npm:5.0.2","descriptor":"archiver-utils@npm:^5.0.2"},"children":{"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.15"},"children":{}}}},"zip-stream@npm:6.0.1":{"value":{"locator":"zip-stream@npm:6.0.1","descriptor":"zip-stream@npm:^6.0.1"},"children":{"archiver-utils@npm:5.0.2":{"value":{"locator":"archiver-utils@npm:5.0.2","descriptor":"archiver-utils@npm:^5.0.0"},"children":{}}}}}}}},"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}},"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:^"},"children":{}}}} +{"value":"@sourceacademy/modules-github-actions@workspace:.github/actions","children":{"@actions/artifact@npm:2.3.2":{"value":{"locator":"@actions/artifact@npm:2.3.2","descriptor":"@actions/artifact@npm:^2.3.2"},"children":{"archiver@npm:7.0.1":{"value":{"locator":"archiver@npm:7.0.1","descriptor":"archiver@npm:^7.0.1"},"children":{"archiver-utils@npm:5.0.2":{"value":{"locator":"archiver-utils@npm:5.0.2","descriptor":"archiver-utils@npm:^5.0.2"},"children":{"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.15"},"children":{}}}},"zip-stream@npm:6.0.1":{"value":{"locator":"zip-stream@npm:6.0.1","descriptor":"zip-stream@npm:^6.0.1"},"children":{"archiver-utils@npm:5.0.2":{"value":{"locator":"archiver-utils@npm:5.0.2","descriptor":"archiver-utils@npm:^5.0.0"},"children":{}}}}}}}},"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:420fa510eaf06edbb20ddb72fbcd454e937e7e266b8c6b7a55ab314e0562f2688175809f2b44c78563a0467da21b6d34688fe0020ecef5e669997fe518ee56e1#workspace:^"},"children":{}},"es-toolkit@npm:1.44.0":{"value":{"locator":"es-toolkit@npm:1.44.0","descriptor":"es-toolkit@npm:^1.44.0"},"children":{}}}} {"value":"@sourceacademy/modules-lib@workspace:lib/modules-lib","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}}}} -{"value":"@sourceacademy/modules-repotools@workspace:lib/repotools","children":{"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}}}} -{"value":"@sourceacademy/modules@workspace:.","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}},"lodash@npm:4.17.21":{"value":{"locator":"lodash@npm:4.17.21","descriptor":"lodash@npm:^4.17.21"},"children":{}},"@sourceacademy/lint-plugin@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/lintplugin":{"value":{"locator":"@sourceacademy/lint-plugin@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/lintplugin","descriptor":"@sourceacademy/lint-plugin@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:^"},"children":{}},"@sourceacademy/modules-repotools@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:^"},"children":{}}}} +{"value":"@sourceacademy/modules-repotools@workspace:lib/repotools","children":{"es-toolkit@npm:1.44.0":{"value":{"locator":"es-toolkit@npm:1.44.0","descriptor":"es-toolkit@npm:^1.44.0"},"children":{}}}} +{"value":"@sourceacademy/modules@workspace:.","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"js-slang@npm:1.0.85":{"value":{"locator":"js-slang@npm:1.0.85","descriptor":"js-slang@npm:^1.0.81"},"children":{}},"@sourceacademy/lint-plugin@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/lintplugin":{"value":{"locator":"@sourceacademy/lint-plugin@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/lintplugin","descriptor":"@sourceacademy/lint-plugin@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:^"},"children":{}},"@sourceacademy/modules-repotools@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/repotools":{"value":{"locator":"@sourceacademy/modules-repotools@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:lib/repotools","descriptor":"@sourceacademy/modules-repotools@virtual:72a684de9912e8b42da7a581a5478d78ad73e0a505830e61e9b2fbc990fcc10719f71ef5373c26313c28b9295f1381b0d95a4d0ab2ae6e33671c2ba25a5c1dc2#workspace:^"},"children":{}},"es-toolkit@npm:1.44.0":{"value":{"locator":"es-toolkit@npm:1.44.0","descriptor":"es-toolkit@npm:^1.44.0"},"children":{}}}} {"value":"@sourceacademy/tab-ArcadeTwod@workspace:src/tabs/ArcadeTwod","children":{"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-lib@workspace:lib/modules-lib":{"value":{"locator":"@sourceacademy/modules-lib@workspace:lib/modules-lib","descriptor":"@sourceacademy/modules-lib@workspace:^"},"children":{}}}} {"value":"@sourceacademy/tab-AugmentedReality@workspace:src/tabs/AugmentedReality","children":{"@sourceacademy/bundle-ar@workspace:src/bundles/ar":{"value":{"locator":"@sourceacademy/bundle-ar@workspace:src/bundles/ar","descriptor":"@sourceacademy/bundle-ar@workspace:^"},"children":{}},"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-lib@workspace:lib/modules-lib":{"value":{"locator":"@sourceacademy/modules-lib@workspace:lib/modules-lib","descriptor":"@sourceacademy/modules-lib@workspace:^"},"children":{}}}} {"value":"@sourceacademy/tab-CopyGc@workspace:src/tabs/CopyGc","children":{"@sourceacademy/bundle-copy_gc@workspace:src/bundles/copy_gc":{"value":{"locator":"@sourceacademy/bundle-copy_gc@workspace:src/bundles/copy_gc","descriptor":"@sourceacademy/bundle-copy_gc@workspace:^"},"children":{}},"@sourceacademy/modules-buildtools@workspace:lib/buildtools":{"value":{"locator":"@sourceacademy/modules-buildtools@workspace:lib/buildtools","descriptor":"@sourceacademy/modules-buildtools@workspace:^"},"children":{}},"@sourceacademy/modules-lib@workspace:lib/modules-lib":{"value":{"locator":"@sourceacademy/modules-lib@workspace:lib/modules-lib","descriptor":"@sourceacademy/modules-lib@workspace:^"},"children":{}}}} diff --git a/.github/actions/src/commons.ts b/.github/actions/src/commons.ts index 4d02975ea7..bd3185a2a4 100644 --- a/.github/actions/src/commons.ts +++ b/.github/actions/src/commons.ts @@ -1,5 +1,5 @@ import { getExecOutput } from '@actions/exec'; -import memoize from 'lodash/memoize.js'; +import { memoize } from 'es-toolkit'; export interface RawPackageRecord { directory: string; diff --git a/.github/actions/src/info/__tests__/index.test.ts b/.github/actions/src/info/__tests__/index.test.ts index 0effab3c01..6fcefaf68b 100644 --- a/.github/actions/src/info/__tests__/index.test.ts +++ b/.github/actions/src/info/__tests__/index.test.ts @@ -55,7 +55,7 @@ const mockDirectory: Record> = { 'package.json': JSON.stringify({ name: '@sourceacademy/tab-Tab0', dependencies: { - lodash: '^4.1.1', + 'es-toolkit': '^1.44.0', '@sourceacademy/bundle-bundle0': 'workspace:^', }, devDependencies: { diff --git a/.github/actions/src/lockfiles.ts b/.github/actions/src/lockfiles.ts index 59656f3c5b..d8c47e7760 100644 --- a/.github/actions/src/lockfiles.ts +++ b/.github/actions/src/lockfiles.ts @@ -2,7 +2,7 @@ import fs from 'fs/promises'; import pathlib from 'path'; import * as core from '@actions/core'; import { getExecOutput } from '@actions/exec'; -import memoize from 'lodash/memoize.js'; +import { memoize } from 'es-toolkit'; import { extractPkgsFromYarnLockV2 } from 'snyk-nodejs-lockfile-parser'; import { gitRoot } from './gitRoot.js'; diff --git a/.yarnrc.yml b/.yarnrc.yml index 3186f3f079..09d6a8236b 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1 +1,2 @@ nodeLinker: node-modules +checksumBehavior: update diff --git a/docs/src/lib/lintplugin/2-rules.md b/docs/src/lib/lintplugin/2-rules.md index 9dbf81e572..9401e8178e 100644 --- a/docs/src/lib/lintplugin/2-rules.md +++ b/docs/src/lib/lintplugin/2-rules.md @@ -62,6 +62,7 @@ import path from 'pathlib'; ## `no-barrel-imports` +_Note: Due to the migration to es-toolkit, this rule is no longer used_ Enforces that imports from a certain source uses individual imports instead of the main barrel import. This rule was primarily motivated by packages like `lodash` and `@mui`, which re-export all their functionalities diff --git a/docs/src/modules/2-bundle/3-editing.md b/docs/src/modules/2-bundle/3-editing.md index 69272bea32..35e7cd5d49 100644 --- a/docs/src/modules/2-bundle/3-editing.md +++ b/docs/src/modules/2-bundle/3-editing.md @@ -62,7 +62,7 @@ You can also add the dependency directly by modifying your `package.json`: { "name": "@sourceacademy/bundle-bundle0", "dependencies": { - "lodash": "^4.0.0" + "es-toolkit": "^1.44.0" } } ``` diff --git a/docs/src/modules/3-tabs/3-editing.md b/docs/src/modules/3-tabs/3-editing.md index 465f410b41..c04f95ac93 100644 --- a/docs/src/modules/3-tabs/3-editing.md +++ b/docs/src/modules/3-tabs/3-editing.md @@ -62,7 +62,7 @@ You can also add the dependency directly by modifying your `package.json`: { "name": "@sourceacademy/tab-Tab0", "dependencies": { - "lodash": "^4.0.0" + "es-toolkit": "^1.44.0" } } ``` diff --git a/eslint.config.js b/eslint.config.js index bd5a53239b..9a9be45c45 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -286,7 +286,6 @@ export default defineConfig( 'prefer-const': ['warn', { destructuring: 'all' }], '@sourceacademy/default-import-name': ['warn', { path: 'pathlib' }], - '@sourceacademy/no-barrel-imports': ['error', ['lodash']], '@sourceacademy/region-comment': 'error', } }, diff --git a/lib/buildtools/package.json b/lib/buildtools/package.json index ff4cc44195..85cc71370c 100644 --- a/lib/buildtools/package.json +++ b/lib/buildtools/package.json @@ -7,7 +7,6 @@ "@commander-js/extra-typings": "^14.0.0", "@types/estree": "^1.0.0", "@types/http-server": "^0.12.4", - "@types/lodash": "^4.14.198", "@types/node": "^22.15.30", "typescript": "^5.8.2" }, @@ -26,11 +25,11 @@ "astring": "^1.8.6", "chalk": "^5.0.1", "commander": "^14.0.0", + "es-toolkit": "^1.44.0", "esbuild": "^0.27.0", "eslint": "^9.35.0", "http-server": "^14.1.1", "jsdom": "^26.1.0", - "lodash": "^4.17.23", "typedoc": "^0.28.9", "vite": "^7.1.11", "vitest": "^4.0.18" diff --git a/lib/buildtools/src/commands/commandUtils.ts b/lib/buildtools/src/commands/commandUtils.ts index 1820aa2602..1aa92f21b1 100644 --- a/lib/buildtools/src/commands/commandUtils.ts +++ b/lib/buildtools/src/commands/commandUtils.ts @@ -2,7 +2,7 @@ import { InvalidArgumentError, Option } from '@commander-js/extra-typings'; import type { ErrorResult, Severity } from '@sourceacademy/modules-repotools/types'; import { isSeverity, objectKeys, objectValues } from '@sourceacademy/modules-repotools/utils'; import chalk from 'chalk'; -import capitalize from 'lodash/capitalize.js'; +import { capitalize } from 'es-toolkit'; import { LogLevel } from 'typedoc'; export const lintOption = new Option('--lint', 'Run ESLint when building') diff --git a/lib/buildtools/src/commands/list.ts b/lib/buildtools/src/commands/list.ts index 77058ff756..e21a1eab5d 100644 --- a/lib/buildtools/src/commands/list.ts +++ b/lib/buildtools/src/commands/list.ts @@ -2,7 +2,7 @@ import { Command } from '@commander-js/extra-typings'; import { bundlesDir, tabsDir } from '@sourceacademy/modules-repotools/getGitRoot'; import { resolveAllBundles, resolveAllTabs, resolveSingleBundle, resolveSingleTab } from '@sourceacademy/modules-repotools/manifest'; import chalk from 'chalk'; -import omit from 'lodash/omit.js'; +import { omit } from 'es-toolkit'; import { logCommandErrorAndExit } from './commandUtils.js'; export const getListBundlesCommand = () => new Command('bundle') @@ -23,7 +23,7 @@ export const getListBundlesCommand = () => new Command('bundle') return; } - const bundlesStr = bundleNames.map((each, i) => `${i+1}. ${each}`).join('\n'); + const bundlesStr = bundleNames.map((each, i) => `${i + 1}. ${each}`).join('\n'); console.log(`${chalk.magentaBright(`Detected ${bundleNames.length} bundles in ${bundlesDir}:`)}\n${bundlesStr}`); } else { logCommandErrorAndExit(`No bundles in ${bundlesDir}!`); @@ -49,7 +49,7 @@ export const getListTabsCommand = () => new Command('tabs') return; } - const tabsStr = tabNames.map((each, i) => `${i+1}. ${each}`).join('\n'); + const tabsStr = tabNames.map((each, i) => `${i + 1}. ${each}`).join('\n'); console.log(`${chalk.magentaBright(`Detected ${tabNames.length} tabs in ${tabsDir}:`)}\n${tabsStr}`); } else { logCommandErrorAndExit(`No tabs in ${tabsDir}`); @@ -73,7 +73,7 @@ export const getValidateCommand = () => new Command('validate') } else if (manifestResult.severity === 'error') { logCommandErrorAndExit(manifestResult); } else { - const bundle = omit(manifestResult.bundle, 'type'); + const bundle = omit(manifestResult.bundle, ['type']); const manifestStr = JSON.stringify(bundle, null, 2); console.log(`${chalk.magentaBright(`Bundle '${manifestResult.bundle.name}' found in ${directory}`)}:\n${manifestStr}`); } diff --git a/lib/buildtools/src/templates/tab.ts b/lib/buildtools/src/templates/tab.ts index f689752e1f..a251715dcc 100644 --- a/lib/buildtools/src/templates/tab.ts +++ b/lib/buildtools/src/templates/tab.ts @@ -3,7 +3,7 @@ import pathlib from 'path'; import type { Interface } from 'readline/promises'; import { getBundleManifests } from '@sourceacademy/modules-repotools/manifest'; import type { BundleManifest, ModulesManifest } from '@sourceacademy/modules-repotools/types'; -import omit from 'lodash/omit.js'; +import { omit } from 'es-toolkit/object'; import _package from '../../../../package.json' with { type: 'json' }; import { formatResult } from '../build/formatter.js'; import { askQuestion, error, success, warn } from './print.js'; @@ -79,7 +79,7 @@ export async function addNew(bundlesDir: string, tabsDir: string, rl: Interface) }; // Version property gets stored in package.json, not manifest.json - const requiredProperties = omit(manifest[moduleName], 'version'); + const requiredProperties = omit(manifest[moduleName], ['version']); const newManifest: BundleManifest = { ...requiredProperties, diff --git a/lib/markdown-tree/package.json b/lib/markdown-tree/package.json index d08ffaa91b..fa58a00eab 100644 --- a/lib/markdown-tree/package.json +++ b/lib/markdown-tree/package.json @@ -7,7 +7,6 @@ "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", "@sourceacademy/modules-repotools": "workspace:^", - "@types/lodash": "^4.14.198", "@types/markdown-it": "^14.1.2", "shiki": "^3.15.0", "typescript": "^5.8.2" @@ -23,7 +22,7 @@ "shiki": ">=2" }, "dependencies": { - "lodash": "^4.17.23", + "es-toolkit": "^1.44.0", "tm-themes": "^1.10.12", "yaml": "^2.8.0" }, diff --git a/lib/markdown-tree/src/tree.ts b/lib/markdown-tree/src/tree.ts index 7c6a728609..c6826117e0 100644 --- a/lib/markdown-tree/src/tree.ts +++ b/lib/markdown-tree/src/tree.ts @@ -1,9 +1,6 @@ // Adapted from: https://gitlab.com/nfriend/tree-online/-/tree/master?ref_type=heads -import type { RecursiveArray } from 'lodash'; -import defaultsDeep from 'lodash/defaultsDeep'; -import flattenDeep from 'lodash/flattenDeep'; -import last from 'lodash/last'; +import { flattenDeep, last } from 'es-toolkit'; import type { FileStructure } from './types'; /** @@ -73,11 +70,11 @@ export function generateTree( commentLoc: number, options?: GenerateTreeOptions ): string { - const combinedOptions = defaultsDeep({}, options, defaultOptions); + const combinedOptions = { ...defaultOptions, ...options }; return flattenDeep([ getAsciiLine(structure, commentLoc, combinedOptions), - structure.children.map(c => generateTree(c, commentLoc, options)) as RecursiveArray, + structure.children.map(c => generateTree(c, commentLoc, options)), ]) // Remove null entries. Should only occur for the very first node // when `options.rootDot === false` @@ -161,7 +158,7 @@ const getName = ( nameChunks.unshift( getName( structure.parent, - defaultsDeep({}, { trailingDirSlash: true }, options), + { ...{ trailingDirSlash: true }, ...options }, ), ); } diff --git a/lib/modules-lib/package.json b/lib/modules-lib/package.json index 0227e90625..e328b8ea5c 100644 --- a/lib/modules-lib/package.json +++ b/lib/modules-lib/package.json @@ -5,7 +5,6 @@ "type": "module", "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", - "@types/lodash": "^4.14.198", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^5.1.0", @@ -34,8 +33,8 @@ "dependencies": { "@blueprintjs/core": "^6.0.0", "@blueprintjs/icons": "^6.0.0", + "es-toolkit": "^1.44.0", "js-slang": "^1.0.85", - "lodash": "^4.17.23", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx b/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx index 375d6658d8..00924348f2 100644 --- a/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx +++ b/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx @@ -1,6 +1,6 @@ import { Button, EditableText } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; -import clamp from 'lodash/clamp'; +import { clamp } from 'es-toolkit'; import { useState } from 'react'; export interface MultiItemDisplayProps { @@ -31,7 +31,7 @@ export default function MultiItemDisplay(props: MultiItemDisplayProps) { const elementsDigitCount = Math.floor(Math.log10(Math.max(1, props.elements.length))) + 1; return ( -
{props.elements[currentStep]}
- + ) ); } diff --git a/lib/modules-lib/src/tabs/NumberSelector.tsx b/lib/modules-lib/src/tabs/NumberSelector.tsx index f3e3f91cae..d2d87ff18b 100644 --- a/lib/modules-lib/src/tabs/NumberSelector.tsx +++ b/lib/modules-lib/src/tabs/NumberSelector.tsx @@ -1,5 +1,5 @@ import { EditableText, type EditableTextProps } from '@blueprintjs/core'; -import clamp from 'lodash/clamp'; +import { clamp } from 'es-toolkit'; import { useState } from 'react'; export type NumberSelectorProps = { diff --git a/lib/modules-lib/vitest.config.ts b/lib/modules-lib/vitest.config.ts index 1fb0389d8a..bfed783156 100644 --- a/lib/modules-lib/vitest.config.ts +++ b/lib/modules-lib/vitest.config.ts @@ -12,7 +12,7 @@ export default mergeConfig( include: [ '@blueprintjs/core', '@blueprintjs/icons', - 'lodash', + 'es-toolkit', 'vitest-browser-react', ] }, diff --git a/lib/repotools/package.json b/lib/repotools/package.json index 15089477fb..319de7c24a 100644 --- a/lib/repotools/package.json +++ b/lib/repotools/package.json @@ -6,7 +6,6 @@ "description": "Common library for tooling used by the modules repository", "devDependencies": { "@commander-js/extra-typings": "^14.0.0", - "@types/lodash": "^4.14.198", "@types/node": "^22.15.30", "@vitejs/plugin-react": "^5.1.0", "@vitest/coverage-v8": "^4.0.18", @@ -18,9 +17,9 @@ "@vitest/browser-playwright": "^4.0.18", "chalk": "^5.0.1", "commander": "^14.0.0", + "es-toolkit": "^1.44.0", "esbuild": "^0.27.0", - "jsonschema": "^1.5.0", - "lodash": "^4.17.23" + "jsonschema": "^1.5.0" }, "peerDependencies": { "@vitejs/plugin-react": "*", diff --git a/lib/repotools/src/manifest.ts b/lib/repotools/src/manifest.ts index fc84d0b231..fa7ee78a37 100644 --- a/lib/repotools/src/manifest.ts +++ b/lib/repotools/src/manifest.ts @@ -1,8 +1,8 @@ import type { Dirent } from 'fs'; import fs from 'fs/promises'; import pathlib from 'path'; +import { uniq } from 'es-toolkit'; import { validate } from 'jsonschema'; -import uniq from 'lodash/uniq.js'; import { tabsDir } from './getGitRoot.js'; import manifestSchema from './manifest.schema.json' with { type: 'json' }; import type { BundleManifest, InputAsset, ResolvedBundle, ResolvedTab, ResultType } from './types.js'; diff --git a/lib/repotools/src/testing/index.ts b/lib/repotools/src/testing/index.ts index 11d21ed853..6af79ee703 100644 --- a/lib/repotools/src/testing/index.ts +++ b/lib/repotools/src/testing/index.ts @@ -2,8 +2,7 @@ import fs from 'fs/promises'; import pathlib from 'path'; import react from '@vitejs/plugin-react'; import { playwright } from '@vitest/browser-playwright'; -import cloneDeep from 'lodash/cloneDeep.js'; -import partition from 'lodash/partition.js'; +import { cloneDeep, partition } from 'es-toolkit'; import { loadConfigFromFile } from 'vite'; import type { LabelColor } from 'vitest'; import { defineProject, mergeConfig, type TestProjectInlineConfiguration, type ViteUserConfig } from 'vitest/config'; @@ -82,7 +81,7 @@ export const sharedTabsConfig = mergeConfig( '@blueprintjs/icons', 'gl-matrix', 'js-slang', - 'lodash', + 'es-toolkit', 'vitest-browser-react' ] }, diff --git a/package.json b/package.json index 5797b4e9aa..9e4a4d23ee 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,8 @@ "husky": "^9.1.7", "jsdom": "^26.1.0", "jsonc-eslint-parser": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", "typescript": "^5.8.2", "typescript-eslint": "^8.53.1", "vitest": "^4.0.18", @@ -82,8 +84,8 @@ "peerDependencies": { "@blueprintjs/core": "^6.0.0", "@blueprintjs/icons": "^6.0.0", + "es-toolkit": "^1.44.0", "js-slang": "^1.0.85", - "lodash": "^4.17.23", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/src/bundles/curve/package.json b/src/bundles/curve/package.json index 805f8c10d6..5a047f83c8 100644 --- a/src/bundles/curve/package.json +++ b/src/bundles/curve/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@sourceacademy/modules-lib": "workspace:^", + "es-toolkit": "^1.44.0", "gl-matrix": "^3.3.0", "js-slang": "^1.0.85" }, diff --git a/src/bundles/curve/src/functions.ts b/src/bundles/curve/src/functions.ts index c2fce8b1b4..ff13a3a224 100644 --- a/src/bundles/curve/src/functions.ts +++ b/src/bundles/curve/src/functions.ts @@ -1,4 +1,4 @@ -import clamp from 'lodash/clamp'; +import { clamp } from 'es-toolkit'; import { Point, type Curve } from './curves_webgl'; import { functionDeclaration } from './type_interface'; import type { CurveTransformer } from './types'; diff --git a/src/bundles/midi/src/types.ts b/src/bundles/midi/src/types.ts index 6291c6790a..df28275a29 100644 --- a/src/bundles/midi/src/types.ts +++ b/src/bundles/midi/src/types.ts @@ -11,7 +11,7 @@ type NotesWithFlats = 'A' | 'B' | 'D' | 'E' | 'G'; // & {} is a weird trick with typescript that causes intellisense to evaluate every single option // so you see all the valid notes instead of just the type definition below export type Note = {} & (NoteName | `${NoteName}${Accidental.NATURAL}` | `${NotesWithFlats}${Accidental.FLAT}` | `${NotesWithSharps}${Accidental.SHARP}`); -export type NoteWithOctave = (Note | `${Note}${number}`); +export type NoteWithOctave = Note | `${Note}${number}`; /** * An integer representing a MIDI note value. Refer to {@link https://i.imgur.com/qGQgmYr.png|this} mapping from diff --git a/src/bundles/repl/src/programmable_repl.ts b/src/bundles/repl/src/programmable_repl.ts index 7bb7678417..1d9bfc9720 100644 --- a/src/bundles/repl/src/programmable_repl.ts +++ b/src/bundles/repl/src/programmable_repl.ts @@ -10,7 +10,7 @@ import { COLOR_ERROR_MESSAGE, COLOR_RUN_CODE_RESULT, DEFAULT_EDITOR_HEIGHT } fro import { evaluatorSymbol } from './functions'; export class ProgrammableRepl { - public evalFunction: ((code: string) => any); + public evalFunction: (code: string) => any; public userCodeInEditor: string; public outputStrings: any[]; private _editorInstance; diff --git a/src/bundles/robot_simulation/package.json b/src/bundles/robot_simulation/package.json index c8d974932b..22b0d99d57 100644 --- a/src/bundles/robot_simulation/package.json +++ b/src/bundles/robot_simulation/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@sourceacademy/modules-lib": "workspace:^", + "es-toolkit": "^1.44.0", "js-slang": "^1.0.85", "three": "^0.181.0" }, diff --git a/src/bundles/robot_simulation/src/controllers/program/evaluate.ts b/src/bundles/robot_simulation/src/controllers/program/evaluate.ts index 4107595edb..940d030875 100644 --- a/src/bundles/robot_simulation/src/controllers/program/evaluate.ts +++ b/src/bundles/robot_simulation/src/controllers/program/evaluate.ts @@ -1,3 +1,4 @@ +import { merge } from 'es-toolkit'; import { Control, Stash, @@ -5,7 +6,6 @@ import { } from 'js-slang/dist/cse-machine/interpreter'; import { parse } from 'js-slang/dist/parser/parser'; import { Variant, type Context } from 'js-slang/dist/types'; -import * as _ from 'lodash'; export const DEFAULT_SOURCE_OPTIONS = { scheduler: 'async', @@ -30,7 +30,7 @@ export function* runECEvaluator( context: Context, options: any ): Generator<{ steps: number }, void, undefined> { - const theOptions = _.merge({ ...DEFAULT_SOURCE_OPTIONS }, options); + const theOptions = merge({ ...DEFAULT_SOURCE_OPTIONS }, options); const program = parse(code, context); if (!program) { diff --git a/src/bundles/robot_simulation/src/controllers/utils/mergeConfig.ts b/src/bundles/robot_simulation/src/controllers/utils/mergeConfig.ts index ce7c9c824f..5123c33973 100644 --- a/src/bundles/robot_simulation/src/controllers/utils/mergeConfig.ts +++ b/src/bundles/robot_simulation/src/controllers/utils/mergeConfig.ts @@ -1,9 +1,9 @@ import type { DeepPartial } from '@sourceacademy/modules-lib/types'; -import * as _ from 'lodash'; +import { merge } from 'es-toolkit'; -export const mergeConfig = (defaultConfig: T, userConfig?: DeepPartial): T => { +export const mergeConfig = >(defaultConfig: T, userConfig?: DeepPartial): T => { if (userConfig === undefined) { return defaultConfig; } - return _.merge({ ...defaultConfig }, userConfig); + return merge({ ...defaultConfig }, userConfig); }; diff --git a/src/bundles/rune/package.json b/src/bundles/rune/package.json index 212ea20643..badc8ccb84 100644 --- a/src/bundles/rune/package.json +++ b/src/bundles/rune/package.json @@ -4,12 +4,11 @@ "private": true, "dependencies": { "@sourceacademy/modules-lib": "workspace:^", - "gl-matrix": "^3.3.0", - "lodash": "^4.17.23" + "es-toolkit": "^1.44.0", + "gl-matrix": "^3.3.0" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", - "@types/lodash": "^4.14.198", "js-slang": "^1.0.85", "typescript": "^5.8.2" }, diff --git a/src/bundles/rune/src/functions.ts b/src/bundles/rune/src/functions.ts index 84731063b2..a4d3ea6695 100644 --- a/src/bundles/rune/src/functions.ts +++ b/src/bundles/rune/src/functions.ts @@ -1,5 +1,5 @@ +import { clamp } from 'es-toolkit'; import { mat4, vec3 } from 'gl-matrix'; -import clamp from 'lodash/clamp'; import { DrawnRune, Rune, diff --git a/src/bundles/unittest/package.json b/src/bundles/unittest/package.json index cd0e741960..9e380e5ea8 100644 --- a/src/bundles/unittest/package.json +++ b/src/bundles/unittest/package.json @@ -3,12 +3,11 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.85", - "lodash": "^4.17.23" + "es-toolkit": "^1.44.0", + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", - "@types/lodash": "^4.14.198", "typescript": "^5.8.2" }, "type": "module", diff --git a/src/bundles/unittest/src/asserts.ts b/src/bundles/unittest/src/asserts.ts index abba0c02ed..a1d337271e 100644 --- a/src/bundles/unittest/src/asserts.ts +++ b/src/bundles/unittest/src/asserts.ts @@ -1,6 +1,6 @@ +import { isEqualWith } from 'es-toolkit'; import * as list from 'js-slang/dist/stdlib/list'; import { stringify } from 'js-slang/dist/utils/stringify'; -import isEqualWith from 'lodash/isEqualWith'; /** * Asserts that a predicate returns true. diff --git a/src/tabs/Curve/vitest.config.ts b/src/tabs/Curve/vitest.config.ts index baecefa1d1..abfd2ed98a 100644 --- a/src/tabs/Curve/vitest.config.ts +++ b/src/tabs/Curve/vitest.config.ts @@ -5,7 +5,6 @@ export default defineProject({ optimizeDeps: { include: [ 'js-slang/dist/utils/stringify', - 'lodash/clamp', ] }, test: { diff --git a/src/tabs/Rune/package.json b/src/tabs/Rune/package.json index cc8b731107..ad254efc28 100644 --- a/src/tabs/Rune/package.json +++ b/src/tabs/Rune/package.json @@ -5,7 +5,7 @@ "dependencies": { "@sourceacademy/bundle-rune": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", - "lodash": "^4.17.23", + "es-toolkit": "^1.44.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/src/tabs/Rune/vitest.config.ts b/src/tabs/Rune/vitest.config.ts index 2bff4313b7..b52f142c40 100644 --- a/src/tabs/Rune/vitest.config.ts +++ b/src/tabs/Rune/vitest.config.ts @@ -4,7 +4,6 @@ import { defineProject } from 'vitest/config'; export default defineProject({ optimizeDeps: { include: [ - 'lodash/clamp', 'js-slang/dist/utils/stringify' ] }, diff --git a/src/tabs/Unittest/index.tsx b/src/tabs/Unittest/index.tsx index 4b6776b8fd..9d852782f0 100644 --- a/src/tabs/Unittest/index.tsx +++ b/src/tabs/Unittest/index.tsx @@ -5,7 +5,7 @@ import type { SuiteResult, UnittestModuleState } from '@sourceacademy/bundle-unittest/types'; import { defineTab, getModuleState } from '@sourceacademy/modules-lib/tabs/utils'; -import partition from 'lodash/partition'; +import { partition } from 'es-toolkit'; const colfixed = { border: '1px solid gray', diff --git a/src/tabs/Unittest/package.json b/src/tabs/Unittest/package.json index 3654f6abe4..0109117c7c 100644 --- a/src/tabs/Unittest/package.json +++ b/src/tabs/Unittest/package.json @@ -5,6 +5,7 @@ "dependencies": { "@sourceacademy/bundle-unittest": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", + "es-toolkit": "^1.44.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/yarn.lock b/yarn.lock index f0bbac4b19..d8fae7387d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4345,6 +4345,7 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" + es-toolkit: "npm:^1.44.0" gl-matrix: "npm:^3.3.0" js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" @@ -4485,6 +4486,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/three": "npm:^0.181.0" + es-toolkit: "npm:^1.44.0" js-slang: "npm:^1.0.85" three: "npm:^0.181.0" typescript: "npm:^5.8.2" @@ -4497,10 +4499,9 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" - "@types/lodash": "npm:^4.14.198" + es-toolkit: "npm:^1.44.0" gl-matrix: "npm:^3.3.0" js-slang: "npm:^1.0.85" - lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4561,9 +4562,8 @@ __metadata: resolution: "@sourceacademy/bundle-unittest@workspace:src/bundles/unittest" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - "@types/lodash": "npm:^4.14.198" + es-toolkit: "npm:^1.44.0" js-slang: "npm:^1.0.85" - lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4633,9 +4633,8 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-repotools": "workspace:^" - "@types/lodash": "npm:^4.14.198" "@types/markdown-it": "npm:^14.1.2" - lodash: "npm:^4.17.23" + es-toolkit: "npm:^1.44.0" shiki: "npm:^3.15.0" tm-themes: "npm:^1.10.12" typescript: "npm:^5.8.2" @@ -4654,7 +4653,6 @@ __metadata: "@sourceacademy/modules-repotools": "workspace:^" "@types/estree": "npm:^1.0.0" "@types/http-server": "npm:^0.12.4" - "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" "@vitejs/plugin-react": "npm:^5.1.0" "@vitest/browser-playwright": "npm:^4.0.18" @@ -4664,11 +4662,11 @@ __metadata: astring: "npm:^1.8.6" chalk: "npm:^5.0.1" commander: "npm:^14.0.0" + es-toolkit: "npm:^1.44.0" esbuild: "npm:^0.27.0" eslint: "npm:^9.35.0" http-server: "npm:^14.1.1" jsdom: "npm:^26.1.0" - lodash: "npm:^4.17.23" typedoc: "npm:^0.28.9" typescript: "npm:^5.8.2" vite: "npm:^7.1.11" @@ -4736,9 +4734,8 @@ __metadata: "@actions/core": "npm:^1.11.1" "@actions/exec": "npm:^3.0.0" "@sourceacademy/modules-repotools": "workspace:^" - "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" - lodash: "npm:^4.17.23" + es-toolkit: "npm:^1.44.0" snyk-nodejs-lockfile-parser: "npm:^2.4.2" typescript: "npm:^5.8.2" vitest: "npm:^4.0.18" @@ -4752,14 +4749,13 @@ __metadata: "@blueprintjs/core": "npm:^6.0.0" "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" - "@types/lodash": "npm:^4.14.198" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" "@vitejs/plugin-react": "npm:^5.1.0" "@vitest/browser-playwright": "npm:^4.0.18" + es-toolkit: "npm:^1.44.0" eslint: "npm:^9.35.0" js-slang: "npm:^1.0.85" - lodash: "npm:^4.17.23" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -4778,16 +4774,15 @@ __metadata: resolution: "@sourceacademy/modules-repotools@workspace:lib/repotools" dependencies: "@commander-js/extra-typings": "npm:^14.0.0" - "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" "@vitejs/plugin-react": "npm:^5.1.0" "@vitest/browser-playwright": "npm:^4.0.18" "@vitest/coverage-v8": "npm:^4.0.18" chalk: "npm:^5.0.1" commander: "npm:^14.0.0" + es-toolkit: "npm:^1.44.0" esbuild: "npm:^0.27.0" jsonschema: "npm:^1.5.0" - lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" vitest: "npm:^4.0.18" vitest-browser-react: "npm:^2.0.4" @@ -4825,6 +4820,8 @@ __metadata: husky: "npm:^9.1.7" jsdom: "npm:^26.1.0" jsonc-eslint-parser: "npm:^2.4.0" + react: "npm:^18.3.1" + react-dom: "npm:^18.3.1" typescript: "npm:^5.8.2" typescript-eslint: "npm:^8.53.1" vitest: "npm:^4.0.18" @@ -4832,8 +4829,8 @@ __metadata: peerDependencies: "@blueprintjs/core": ^6.0.0 "@blueprintjs/icons": ^6.0.0 + es-toolkit: ^1.44.0 js-slang: ^1.0.85 - lodash: ^4.17.23 react: ^18.3.1 react-dom: ^18.3.1 languageName: unknown @@ -5079,7 +5076,7 @@ __metadata: "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" "@vitest/browser-playwright": "npm:^4.0.18" - lodash: "npm:^4.17.23" + es-toolkit: "npm:^1.44.0" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -5138,6 +5135,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" + es-toolkit: "npm:^1.44.0" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" languageName: unknown @@ -5743,13 +5741,6 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.198": - version: 4.17.23 - resolution: "@types/lodash@npm:4.17.23" - checksum: 10c0/9d9cbfb684e064a2b78aab9e220d398c9c2a7d36bc51a07b184ff382fa043a99b3d00c16c7f109b4eb8614118f4869678dbae7d5c6700ed16fb9340e26cc0bf6 - languageName: node - linkType: hard - "@types/markdown-it@npm:^14.1.2": version: 14.1.2 resolution: "@types/markdown-it@npm:14.1.2" @@ -9804,6 +9795,18 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.44.0": + version: 1.44.0 + resolution: "es-toolkit@npm:1.44.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + checksum: 10c0/b80ff52ddc85ba26914cda57c9d4e46379ccc38c60dc097ef0d065cc0b20f95a16cf8d537969eea600b51c6687b5900a6cce67489db16d5ccc14d47597a29c34 + languageName: node + linkType: hard + "esbuild@npm:^0.21.3": version: 0.21.5 resolution: "esbuild@npm:0.21.5" @@ -13024,13 +13027,6 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.23": - version: 4.17.23 - resolution: "lodash@npm:4.17.23" - checksum: 10c0/1264a90469f5bb95d4739c43eb6277d15b6d9e186df4ac68c3620443160fc669e2f14c11e7d8b2ccf078b81d06147c01a8ccced9aab9f9f63d50dcf8cace6bf6 - languageName: node - linkType: hard - "longest-streak@npm:^3.0.0": version: 3.1.0 resolution: "longest-streak@npm:3.1.0"