Просмотр исходного кода

Merge remote-tracking branch 'origin' into imprv/120624-123772-fix-user-group-settings

WNomunomu 2 лет назад
Родитель
Сommit
2d303f87a4
60 измененных файлов с 827 добавлено и 726 удалено
  1. 2 1
      .github/workflows/release-slackbot-proxy.yml
  2. 4 3
      .github/workflows/release.yml
  3. 12 11
      apps/app/package.json
  4. 2 1
      apps/app/public/static/locales/en_US/commons.json
  5. 2 1
      apps/app/public/static/locales/ja_JP/commons.json
  6. 2 1
      apps/app/public/static/locales/zh_CN/commons.json
  7. 11 2
      apps/app/src/components/Me/BasicInfoSettings.tsx
  8. 31 31
      apps/app/src/components/PageEditor/HandsontableModal.tsx
  9. 16 0
      apps/app/src/server/models/user.js
  10. 9 0
      apps/app/src/server/routes/apiv3/personal-setting.js
  11. 5 3
      apps/app/src/stores/personal-settings.tsx
  12. 2 2
      apps/app/src/styles/theme/apply-colors.scss
  13. 0 1
      apps/app/tsconfig.json
  14. 1 1
      apps/slackbot-proxy/package.json
  15. 0 4
      bin/github-actions/bump-versions/README.md
  16. 0 18
      bin/github-actions/bump-versions/cli.js
  17. 0 77
      bin/github-actions/bump-versions/flow/bump-versions.js
  18. 0 16
      bin/github-actions/bump-versions/index.js
  19. 0 58
      bin/github-actions/bump-versions/step/printHelp.js
  20. 2 6
      package.json
  21. 2 1
      packages/core/package.json
  22. 2 1
      packages/hackmd/package.json
  23. 1 0
      packages/pluginkit/.eslintignore
  24. 5 0
      packages/pluginkit/.eslintrc.js
  25. 1 0
      packages/pluginkit/.gitignore
  26. 23 0
      packages/pluginkit/package.json
  27. 1 0
      packages/pluginkit/src/consts/index.ts
  28. 6 0
      packages/pluginkit/src/consts/types.ts
  29. 2 0
      packages/pluginkit/src/index.ts
  30. 12 0
      packages/pluginkit/src/model/growi-plugin-validation-data.ts
  31. 15 0
      packages/pluginkit/src/model/growi-plugin-validation-error.ts
  32. 2 0
      packages/pluginkit/src/model/index.ts
  33. 2 0
      packages/pluginkit/src/server/utils/v4/index.ts
  34. 11 0
      packages/pluginkit/src/server/utils/v4/package-json/import.spec.ts
  35. 6 0
      packages/pluginkit/src/server/utils/v4/package-json/import.ts
  36. 2 0
      packages/pluginkit/src/server/utils/v4/package-json/index.ts
  37. 116 0
      packages/pluginkit/src/server/utils/v4/package-json/validate.spec.ts
  38. 41 0
      packages/pluginkit/src/server/utils/v4/package-json/validate.ts
  39. 162 0
      packages/pluginkit/src/server/utils/v4/template.ts
  40. 0 0
      packages/pluginkit/test/fixtures/example-package/template1/index.js
  41. 14 0
      packages/pluginkit/test/fixtures/example-package/template1/package.json
  42. 19 0
      packages/pluginkit/tsconfig.json
  43. 36 0
      packages/pluginkit/vite.config.ts
  44. 19 0
      packages/pluginkit/vitest.config.ts
  45. 3 2
      packages/presentation/package.json
  46. 3 0
      packages/preset-templates/dist/example/ja_JP/meta.json
  47. 1 0
      packages/preset-templates/dist/example/ja_JP/template.md
  48. 22 0
      packages/preset-templates/package.json
  49. 36 0
      packages/preset-templates/test/index.test.ts
  50. 10 0
      packages/preset-templates/tsconfig.json
  51. 9 0
      packages/preset-templates/vitest.config.ts
  52. 2 1
      packages/preset-themes/package.json
  53. 5 4
      packages/remark-attachment-refs/package.json
  54. 2 1
      packages/remark-drawio/package.json
  55. 2 1
      packages/remark-growi-directive/package.json
  56. 5 4
      packages/remark-lsx/package.json
  57. 2 1
      packages/slack/package.json
  58. 3 2
      packages/ui/package.json
  59. 9 0
      turbo.json
  60. 112 471
      yarn.lock

+ 2 - 1
.github/workflows/release-slackbot-proxy.yml

@@ -112,8 +112,9 @@ jobs:
         yarn --frozen-lockfile
 
     - name: Bump versions for next RC
+      working-directory: ./apps/slackbot-proxy
       run: |
-        yarn bump-versions:slackbot-proxy
+        yarn version --no-git-tag-version --prepatch --preid=slackbot-proxy
 
     - name: Retrieve information from package.json
       uses: myrotvorets/info-from-package-json-action@1.2.0

+ 4 - 3
.github/workflows/release.yml

@@ -35,7 +35,8 @@ jobs:
 
     - name: Bump versions
       run: |
-        yarn bump-versions:patch
+        turbo run bump-versions:patch
+        yarn upgrade --scope=@growi
         sh ./apps/app/bin/github-actions/update-readme.sh
 
     - name: Retrieve information from package.json
@@ -97,8 +98,8 @@ jobs:
 
     - name: Bump versions for next RC
       run: |
-        yarn bump-versions:rc
-        yarn bump-versions:slackbot-proxy
+        turbo run bump-versions:rc
+        yarn upgrade --scope=@growi
 
     - name: Retrieve information from package.json
       uses: myrotvorets/info-from-package-json-action@1.2.0

+ 12 - 11
apps/app/package.json

@@ -46,7 +46,8 @@
     "openapi:v3": "yarn cross-env API_VERSION=3 yarn swagger-jsdoc -- \"src/server/routes/apiv3/**/*.js\" \"src/server/models/**/*.js\"",
     "openapi:v1": "yarn cross-env API_VERSION=1 yarn swagger-jsdoc -- \"src/server/*/*.js\" \"src/server/models/**/*.js\"",
     "ts-node": "node -r ts-node/register -r tsconfig-paths/register -r dotenv-flow/config",
-    "ts-node-dev": "ts-node-dev -r tsconfig-paths/register -r dotenv-flow/config"
+    "ts-node-dev": "ts-node-dev -r tsconfig-paths/register -r dotenv-flow/config",
+    "version": "yarn version --no-git-tag-version"
   },
   "// comments for dependencies": {
     "escape-string-regexp": "5.0.0 or above exports only ESM",
@@ -63,14 +64,14 @@
     "@elastic/elasticsearch8": "npm:@elastic/elasticsearch@^8.7.0",
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
-    "@growi/core": "^6.1.4-RC.0",
-    "@growi/hackmd": "^6.1.4-RC.0",
-    "@growi/preset-themes": "^6.1.4-RC.0",
-    "@growi/remark-attachment-refs": "^6.1.4-RC.0",
-    "@growi/remark-drawio": "^6.1.4-RC.0",
-    "@growi/remark-growi-directive": "^6.1.4-RC.0",
-    "@growi/remark-lsx": "^6.1.4-RC.0",
-    "@growi/slack": "^6.1.4-RC.0",
+    "@growi/core": "link:../../packages/core",
+    "@growi/hackmd": "link:../../packages/hackmd",
+    "@growi/preset-themes": "link:../../packages/preset-themes",
+    "@growi/remark-attachment-refs": "link:../../packages/remark-attachment-refs",
+    "@growi/remark-drawio": "link:../../packages/remark-drawio",
+    "@growi/remark-growi-directive": "link:../../packages/remark-growi-directive",
+    "@growi/remark-lsx": "link:../../packages/remark-lsx",
+    "@growi/slack": "link:../../packages/slack",
     "@promster/express": "^7.0.6",
     "@promster/server": "^7.0.8",
     "@slack/web-api": "^6.2.4",
@@ -208,8 +209,8 @@
     "handsontable": "v7.0.0 or above is no loger MIT lisence."
   },
   "devDependencies": {
-    "@growi/presentation": "^6.1.4-RC.0",
-    "@growi/ui": "^6.1.4-RC.0",
+    "@growi/presentation": "link:../../packages/presentation",
+    "@growi/ui": "link:../../packages/ui",
     "@handsontable/react": "=2.1.0",
     "@icon/themify-icons": "1.0.1-alpha.3",
     "@next/bundle-analyzer": "^13.2.3",

+ 2 - 1
apps/app/public/static/locales/en_US/commons.json

@@ -23,7 +23,8 @@
   "alert": {
     "siteUrl_is_not_set": "'Site URL' is NOT set. Set it from the {{link}}",
     "please_enable_mailer": "Please setup mailer first.",
-    "password_reset_please_enable_mailer": "Please setup mailer first."
+    "password_reset_please_enable_mailer": "Please setup mailer first.",
+    "email_is_already_in_use": "The email address is already in use."
   },
   "headers": {
     "app_settings": "App Settings"

+ 2 - 1
apps/app/public/static/locales/ja_JP/commons.json

@@ -22,7 +22,8 @@
   "alert": {
     "siteUrl_is_not_set": "'サイトURL' が設定されていません。{{link}} から設定してください。",
     "please_enable_mailer": "メール認証を有効にするには、メール設定を完了させてください。",
-    "password_reset_please_enable_mailer": "パスワード再設定を有効にするには、メール設定を完了させてください。"
+    "password_reset_please_enable_mailer": "パスワード再設定を有効にするには、メール設定を完了させてください。",
+    "email_is_already_in_use": "そのメールアドレスは既に使用されています。"
   },
   "headers": {
     "app_settings": "アプリ設定"

+ 2 - 1
apps/app/public/static/locales/zh_CN/commons.json

@@ -23,7 +23,8 @@
   "alert": {
     "siteUrl_is_not_set": "主页URL未设置,通过 {{link}} 设置",
     "please_enable_mailer": "请先设置邮件程序。",
-    "password_reset_please_enable_mailer": "请先设置邮件程序。"
+    "password_reset_please_enable_mailer": "请先设置邮件程序。",
+    "email_is_already_in_use": "这个电子邮件地址已经在使用了。"
   },
   "headers": {
     "app_settings": "系统设置"

+ 11 - 2
apps/app/src/components/Me/BasicInfoSettings.tsx

@@ -24,8 +24,17 @@ export const BasicInfoSettings = (): JSX.Element => {
       sync();
       toastSuccess(t('toaster.update_successed', { target: t('Basic Info'), ns: 'commons' }));
     }
-    catch (err) {
-      toastError(err);
+    catch (errs) {
+      const err = errs[0];
+      const message = err.message;
+      const code = err.code;
+
+      if (code === 'email-is-already-in-use') {
+        toastError(t('alert.email_is_already_in_use', { ns: 'commons' }));
+      }
+      else {
+        toastError(message);
+      }
     }
   };
 

+ 31 - 31
apps/app/src/components/PageEditor/HandsontableModal.tsx

@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState } from 'react';
 
 import { HotTable } from '@handsontable/react';
 import Handsontable from 'handsontable';
@@ -7,7 +7,6 @@ import {
   Collapse,
   Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
-import { debounce } from 'throttle-debounce';
 
 import MarkdownTable from '~/client/models/MarkdownTable';
 import mtu from '~/components/PageEditor/MarkdownTableUtil';
@@ -19,6 +18,7 @@ import { MarkdownTableDataImportForm } from './MarkdownTableDataImportForm';
 
 import styles from './HandsontableModal.module.scss';
 import 'handsontable/dist/handsontable.full.min.css';
+import { debounce } from 'throttle-debounce';
 
 const DEFAULT_HOT_HEIGHT = 300;
 const MARKDOWNTABLE_TO_HANDSONTABLE_ALIGNMENT_SYMBOL_MAPPING = {
@@ -88,13 +88,37 @@ export const HandsontableModal = (): JSX.Element => {
   const [markdownTable, setMarkdownTable] = useState<MarkdownTable>(defaultMarkdownTable);
   const [markdownTableOnInit, setMarkdownTableOnInit] = useState<MarkdownTable>(defaultMarkdownTable);
   const [handsontableHeight, setHandsontableHeight] = useState<number>(DEFAULT_HOT_HEIGHT);
+  const [handsontableWidth, setHandsontableWidth] = useState<number>(0);
 
-  useEffect(() => {
+  const handleWindowExpandedChange = () => {
+    if (hotTableContainer != null) {
+      // Get the width and height of hotTableContainer
+      const { width, height } = hotTableContainer.getBoundingClientRect();
+      setHandsontableWidth(width);
+      setHandsontableHeight(height);
+    }
+  };
+
+  const debouncedHandleWindowExpandedChange = debounce(100, handleWindowExpandedChange);
+
+  const handleModalOpen = () => {
     const initTableInstance = table == null ? defaultMarkdownTable : table.clone();
     setMarkdownTable(table ?? defaultMarkdownTable);
     setMarkdownTableOnInit(initTableInstance);
-  // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [isOpened]);
+    debouncedHandleWindowExpandedChange();
+  };
+
+  const expandWindow = () => {
+    setIsWindowExpanded(true);
+    debouncedHandleWindowExpandedChange();
+  };
+
+  const contractWindow = () => {
+    setIsWindowExpanded(false);
+    // Set the height to the default value
+    setHandsontableHeight(DEFAULT_HOT_HEIGHT);
+    debouncedHandleWindowExpandedChange();
+  };
 
   const markdownTableOption = {
     get latest() {
@@ -363,32 +387,6 @@ export const HandsontableModal = (): JSX.Element => {
     toggleDataImportArea();
   };
 
-  /**
-   * Expand the height of the Handsontable
-   *  by updating 'handsontableHeight' state
-   *  according to the height of this.refs.hotTableContainer
-   */
-  const expandHotTableHeight = () => {
-    if (isWindowExpanded && hotTableContainer != null) {
-      const height = hotTableContainer.getBoundingClientRect().height;
-      setHandsontableHeight(height);
-    }
-  };
-
-  const expandWindow = () => {
-    setIsWindowExpanded(true);
-
-    // create debounced method for expanding HotTable
-    // invoke updateHotTableHeight method with delay
-    // cz. Resizing this.refs.hotTableContainer is completed after a little delay after 'isWindowExpanded' set with 'true'
-    debounce(100, expandHotTableHeight);
-  };
-
-  const contractWindow = () => {
-    setIsWindowExpanded(false);
-    setHandsontableHeight(DEFAULT_HOT_HEIGHT);
-  };
-
   const createCustomizedContextMenu = () => {
     return {
       items: {
@@ -453,6 +451,7 @@ export const HandsontableModal = (): JSX.Element => {
       size="lg"
       wrapClassName={`${styles['grw-handsontable']}`}
       className={`handsontable-modal ${isWindowExpanded && 'grw-modal-expanded'}`}
+      onOpened={handleModalOpen}
     >
       <ModalHeader tag="h4" toggle={cancel} close={closeButton} className="bg-primary text-light">
         {t('handsontable_modal.title')}
@@ -493,6 +492,7 @@ export const HandsontableModal = (): JSX.Element => {
             data={markdownTable.table}
             settings={handsontableSettings as Handsontable.DefaultSettings}
             height={handsontableHeight}
+            width={handsontableWidth}
             afterLoadData={afterLoadDataHandler}
             modifyColWidth={modifyColWidthHandler}
             beforeColumnMove={beforeColumnMoveHandler}

+ 16 - 0
apps/app/src/server/models/user.js

@@ -144,6 +144,22 @@ module.exports = function(crowi) {
     return hasher.digest('base64');
   }
 
+  userSchema.methods.isUniqueEmail = async function() {
+    const query = this.model('User').find();
+
+    const count = await query.count((
+      {
+        username: { $ne: this.username },
+        email: this.email,
+      }
+    ));
+
+    if (count > 0) {
+      return false;
+    }
+    return true;
+  };
+
   userSchema.methods.isPasswordSet = function() {
     if (this.password) {
       return true;

+ 9 - 0
apps/app/src/server/routes/apiv3/personal-setting.js

@@ -1,5 +1,7 @@
+import { ErrorV3 } from '@growi/core';
 import { body } from 'express-validator';
 
+
 import { i18n } from '^/config/next-i18next.config';
 
 import { SupportedAction } from '~/interfaces/activity';
@@ -238,6 +240,13 @@ module.exports = (crowi) => {
       user.isEmailPublished = req.body.isEmailPublished;
       user.slackMemberId = req.body.slackMemberId;
 
+      const isUniqueEmail = await user.isUniqueEmail();
+
+      if (!isUniqueEmail) {
+        logger.error('email-is-not-unique');
+        return res.apiv3Err(new ErrorV3('The email is already in use', 'email-is-already-in-use'));
+      }
+
       const updatedUser = await user.save();
 
       const parameters = { action: SupportedAction.ACTION_USER_PERSONAL_SETTINGS_UPDATE };

+ 5 - 3
apps/app/src/stores/personal-settings.tsx

@@ -1,3 +1,4 @@
+import { ErrorV3 } from '@growi/core';
 import { useTranslation } from 'next-i18next';
 import useSWR, { SWRConfiguration, SWRResponse } from 'swr';
 
@@ -10,6 +11,7 @@ import { apiv3Get, apiv3Put } from '../client/util/apiv3-client';
 
 import { useStaticSWR } from './use-static-swr';
 
+
 const logger = loggerFactory('growi:stores:personal-settings');
 
 
@@ -66,9 +68,9 @@ export const usePersonalSettings = (config?: SWRConfiguration): SWRResponse<IUse
       await apiv3Put('/personal-setting/', updateData);
       i18n.changeLanguage(updateData.lang);
     }
-    catch (err) {
-      logger.error(err);
-      throw new Error('Failed to update personal data');
+    catch (errs) {
+      logger.error(errs);
+      throw errs;
     }
   };
 

+ 2 - 2
apps/app/src/styles/theme/apply-colors.scss

@@ -145,8 +145,8 @@ ul.pagination {
 //
 
 .grw-logo {
-  set transition for fill
-  svg * {
+  // set transition for fill
+  svg, svg * {
     transition: fill 0.8s ease-out;
   }
 

+ 0 - 1
apps/app/tsconfig.json

@@ -14,7 +14,6 @@
     "paths": {
       "~/*": ["./src/*"],
       "^/*": ["./*"],
-
       "debug": ["./src/server/utils/logger/alias-for-debug"]
     }
   },

+ 1 - 1
apps/slackbot-proxy/package.json

@@ -25,7 +25,7 @@
   },
   "dependencies": {
     "@godaddy/terminus": "^4.9.0",
-    "@growi/slack": "^6.1.4-RC.0",
+    "@growi/slack": "link:../../packages/slack",
     "@slack/oauth": "^2.0.1",
     "@slack/web-api": "^6.2.4",
     "@tsed/common": "^6.43.0",

+ 0 - 4
bin/github-actions/bump-versions/README.md

@@ -1,4 +0,0 @@
-bump-versions.js
-==============
-
-Custom cli for bumping package versions based on [algolia/shipjs@0.23.3](https://github.com/algolia/shipjs/tree/v0.23.3/packages/shipjs)

+ 0 - 18
bin/github-actions/bump-versions/cli.js

@@ -1,18 +0,0 @@
-import { print, parseArgs } from 'shipjs/src/util';
-import bumpVersions from './flow/bump-versions';
-
-export async function cli(argv) {
-  const { fn, arg: argSpec } = bumpVersions;
-  try {
-    const opts = parseArgs(argSpec, argv);
-    await fn(opts);
-  }
-  catch (error) {
-    if (error.code === 'ARG_UNKNOWN_OPTION') {
-      print(error);
-    }
-    else {
-      throw error;
-    }
-  }
-}

+ 0 - 77
bin/github-actions/bump-versions/flow/bump-versions.js

@@ -1,77 +0,0 @@
-import semver from 'semver';
-import { loadConfig, getCurrentVersion, getReleaseType } from 'shipjs-lib';
-
-import printDryRunBanner from 'shipjs/src/step/printDryRunBanner';
-import confirmNextVersion from 'shipjs/src/step/prepare/confirmNextVersion';
-import updateVersion from 'shipjs/src/step/prepare/updateVersion';
-import updateVersionMonorepo from 'shipjs/src/step/prepare/updateVersionMonorepo';
-import installDependencies from 'shipjs/src/step/prepare/installDependencies';
-
-import printHelp from '../step/printHelp';
-
-async function bumpVersions({
-  help = false,
-  dir = '.',
-  dryRun = false,
-  updateDependencies = true,
-  increment = 'patch',
-  preid = 'RC',
-}) {
-  if (help) {
-    printHelp();
-    return;
-  }
-  if (dryRun) {
-    printDryRunBanner();
-  }
-
-  const config = await loadConfig(dir, 'bump-versions.config');
-
-  const { monorepo } = config;
-  if (!updateDependencies) {
-    monorepo.updateDependencies = false;
-  }
-
-  // get current version
-  const currentVersion = monorepo && monorepo.mainVersionFile
-    ? getCurrentVersion(dir, monorepo.mainVersionFile)
-    : getCurrentVersion(dir);
-
-  // determine next version
-  let nextVersion = semver.inc(currentVersion, increment, preid); // set preid if type is 'prerelease'
-  nextVersion = await confirmNextVersion({
-    yes: true,
-    currentVersion,
-    nextVersion,
-    dryRun,
-  });
-  const releaseType = getReleaseType(nextVersion);
-
-  // update
-  const updateVersionFn = monorepo
-    ? updateVersionMonorepo
-    : updateVersion;
-  await updateVersionFn({
-    config, nextVersion, releaseType, dir, dryRun,
-  });
-}
-
-const arg = {
-  '--dir': String,
-  '--help': Boolean,
-  '--dry-run': Boolean,
-  '--update-dependencies': Boolean,
-  '--increment': String,
-  '--preid': String,
-
-  // Aliases
-  '-d': '--dir',
-  '-h': '--help',
-  '-D': '--dry-run',
-  '-i': '--increment',
-};
-
-export default {
-  arg,
-  fn: bumpVersions,
-};

+ 0 - 16
bin/github-actions/bump-versions/index.js

@@ -1,16 +0,0 @@
-#!/usr/bin/env node
-
-// eslint-disable-next-line no-global-assign
-require = require('esm')(module);
-
-(async function() {
-  try {
-    process.env.SHIPJS = true;
-    await require('./cli').cli(process.argv);
-  }
-  catch (e) {
-    // eslint-disable-next-line no-console
-    console.error(e);
-    process.exit(1);
-  }
-}());

+ 0 - 58
bin/github-actions/bump-versions/step/printHelp.js

@@ -1,58 +0,0 @@
-import runStep from 'shipjs/src/step/runStep';
-import { print } from 'shipjs/src/util';
-import { bold, underline } from 'shipjs/src/color';
-
-export default () => runStep({}, () => {
-  const indent = line => `\t${line}`;
-
-  const help = '--help';
-  const dir = `--dir ${underline('PATH')}`;
-  const increment = `--increment ${underline('LEVEL')}`;
-  const preId = `--preid ${underline('IDENTIFIER')}`;
-  const updateDependencies = `--update-dependencies ${underline('true/false')}`;
-  const dryRun = '--dry-run';
-  const all = [help, dir, increment, preId, updateDependencies, dryRun]
-    .map(x => `[${x}]`)
-    .join(' ');
-
-  const messages = [
-    bold('NAME'),
-    indent('bump-versions - Bump versions of packages.'),
-    '',
-    bold('USAGE'),
-    indent(`node ./bin/github-actions/bump-versions ${all}`),
-    '',
-    bold('OPTIONS'),
-    indent(`-h, ${help}`),
-    indent('  Print this help'),
-    '',
-    indent(`-d, ${dir}`),
-    indent(
-      `  Specify the ${underline(
-        'PATH',
-      )} of the repository (default: the current directory).`,
-    ),
-    '',
-    indent(`-i, ${increment}`),
-    indent(
-      `  Specify the ${underline(
-        'LEVEL',
-      )} for semver.inc() to increment a version (default: 'patch').`,
-    ),
-    '',
-    indent(`${preId}`),
-    indent(
-      `  Specify the ${underline(
-        'IDENTIFIER',
-      )} for semver.inc() with 'prerelease' type (default: 'RC').`,
-    ),
-    '',
-    indent(`${updateDependencies}`),
-    indent('  Update dependencies or not (default: true).'),
-    '',
-    indent(`-D, ${dryRun}`),
-    indent('  Displays the steps without actually doing them.'),
-    '',
-  ];
-  print(messages.join('\n'));
-});

+ 2 - 6
package.json

@@ -38,11 +38,8 @@
     "app:server": "cd apps/app && yarn server",
     "slackbot-proxy:build": "turbo run build --filter @growi/slackbot-proxy",
     "slackbot-proxy:server": "cd apps/slackbot-proxy && yarn start:prod",
-    "bump-versions:premajor": "node ./bin/github-actions/bump-versions -i premajor",
-    "bump-versions:preminor": "node ./bin/github-actions/bump-versions -i preminor",
-    "bump-versions:patch": "node ./bin/github-actions/bump-versions -i patch",
-    "bump-versions:rc": "node ./bin/github-actions/bump-versions -i prerelease",
-    "bump-versions:slackbot-proxy": "node ./bin/github-actions/bump-versions -i prerelease -d apps/slackbot-proxy --preid slackbot-proxy --update-dependencies false"
+    "bump-versions:patch": "turbo run version -- --patch",
+    "bump-versions:rc": "turbo run version -- --prepatch --preid=RC"
   },
   "dependencies": {
     "cross-env": "^7.0.0",
@@ -89,7 +86,6 @@
     "reg-notify-slack-plugin": "^0.11.0",
     "reg-publish-s3-plugin": "^0.11.0",
     "reg-suit": "^0.12.1",
-    "shipjs": "^0.24.1",
     "stylelint": "^14.2.0",
     "stylelint-config-recess-order": "^3.0.0",
     "ts-node-dev": "^2.0.0",

+ 2 - 1
packages/core/package.json

@@ -20,7 +20,8 @@
     "lint:js": "yarn eslint **/*.{js,ts}",
     "lint:typecheck": "tsc",
     "lint": "npm-run-all -p lint:*",
-    "test": "vitest run --coverage"
+    "test": "vitest run --coverage",
+    "version": "yarn version --no-git-tag-version"
   },
   "// comments for dependencies": {
     "escape-string-regexp": "5.0.0 or above exports only ESM"

+ 2 - 1
packages/hackmd/package.json

@@ -14,7 +14,8 @@
     "watch": "yarn dev -w --emptyOutDir=false",
     "lint:js": "yarn eslint **/*.{js,ts}",
     "lint:typecheck": "tsc",
-    "lint": "npm-run-all -p lint:*"
+    "lint": "npm-run-all -p lint:*",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {},
   "devDependencies": {

+ 1 - 0
packages/pluginkit/.eslintignore

@@ -0,0 +1 @@
+/dist/**

+ 5 - 0
packages/pluginkit/.eslintrc.js

@@ -0,0 +1,5 @@
+module.exports = {
+  extends: [
+    'plugin:vitest/recommended',
+  ],
+};

+ 1 - 0
packages/pluginkit/.gitignore

@@ -0,0 +1 @@
+/dist

+ 23 - 0
packages/pluginkit/package.json

@@ -0,0 +1,23 @@
+{
+  "name": "@growi/pluginkit",
+  "version": "0.1.0",
+  "license": "MIT",
+  "main": "dist/index.js",
+  "module": "dist/index.mjs",
+  "types": "dist/index.d.ts",
+  "scripts": {
+    "build": "vite build",
+    "clean": "npx -y shx rm -rf dist",
+    "dev": "vite build --mode dev",
+    "watch": "yarn dev -w --emptyOutDir=false",
+    "lint:js": "yarn eslint **/*.{js,ts}",
+    "lint:typecheck": "tsc",
+    "lint": "npm-run-all -p lint:*",
+    "test": "vitest run --coverage"
+  },
+  "dependencies": {
+    "extensible-custom-error": "^0.0.7"
+  },
+  "devDependencies": {
+  }
+}

+ 1 - 0
packages/pluginkit/src/consts/index.ts

@@ -0,0 +1 @@
+export * from './types';

+ 6 - 0
packages/pluginkit/src/consts/types.ts

@@ -0,0 +1,6 @@
+export const GrowiPluginType = {
+  SCRIPT: 'script',
+  TEMPLATE: 'template',
+  THEME: 'theme',
+} as const;
+export type GrowiPluginType = typeof GrowiPluginType[keyof typeof GrowiPluginType];

+ 2 - 0
packages/pluginkit/src/index.ts

@@ -0,0 +1,2 @@
+export * from './consts';
+export * from './model';

+ 12 - 0
packages/pluginkit/src/model/growi-plugin-validation-data.ts

@@ -0,0 +1,12 @@
+import { GrowiPluginType } from '../consts/types';
+
+export type GrowiPluginValidationData = {
+  projectDirRoot: string,
+  schemaVersion?: number,
+  expectedPluginType?: GrowiPluginType,
+  actualPluginTypes?: GrowiPluginType[],
+};
+
+export type GrowiTemplatePluginValidationData = GrowiPluginValidationData & {
+  supportingLocales: string[],
+}

+ 15 - 0
packages/pluginkit/src/model/growi-plugin-validation-error.ts

@@ -0,0 +1,15 @@
+import ExtensibleCustomError from 'extensible-custom-error';
+
+import type { GrowiPluginValidationData } from './growi-plugin-validation-data';
+
+
+export class GrowiPluginValidationError<E extends GrowiPluginValidationData = GrowiPluginValidationData> extends ExtensibleCustomError {
+
+  data?: E;
+
+  constructor(message: string, data?: E) {
+    super(message);
+    this.data = data;
+  }
+
+}

+ 2 - 0
packages/pluginkit/src/model/index.ts

@@ -0,0 +1,2 @@
+export * from './growi-plugin-validation-data';
+export * from './growi-plugin-validation-error';

+ 2 - 0
packages/pluginkit/src/server/utils/v4/index.ts

@@ -0,0 +1,2 @@
+export * from './package-json';
+export * from './template';

+ 11 - 0
packages/pluginkit/src/server/utils/v4/package-json/import.spec.ts

@@ -0,0 +1,11 @@
+import path from 'path';
+
+import { importPackageJson } from './import';
+
+it('importPackageJson() returns an object', async() => {
+  // when
+  const pkg = await importPackageJson(path.resolve(__dirname, '../../../../../test/fixtures/example-package/template1'));
+
+  // then
+  expect(pkg).not.toBeNull();
+});

+ 6 - 0
packages/pluginkit/src/server/utils/v4/package-json/import.ts

@@ -0,0 +1,6 @@
+import path from 'path';
+
+export const importPackageJson = async(projectDirRoot: string): Promise<any> => {
+  const packageJsonUrl = path.resolve(projectDirRoot, 'package.json');
+  return import(packageJsonUrl);
+};

+ 2 - 0
packages/pluginkit/src/server/utils/v4/package-json/index.ts

@@ -0,0 +1,2 @@
+export * from './import';
+export * from './validate';

+ 116 - 0
packages/pluginkit/src/server/utils/v4/package-json/validate.spec.ts

@@ -0,0 +1,116 @@
+import examplePkg from '^/test/fixtures/example-package/template1/package.json';
+
+import { GrowiPluginType } from '~/consts';
+
+import { validatePackageJson } from './validate';
+
+const mocks = vi.hoisted(() => {
+  return {
+    importPackageJsonMock: vi.fn(),
+  };
+});
+
+vi.mock('./import', () => {
+  return { importPackageJson: mocks.importPackageJsonMock };
+});
+
+describe('validatePackageJson()', () => {
+
+  it('returns a data object', async() => {
+    // setup
+    mocks.importPackageJsonMock.mockResolvedValue(examplePkg);
+
+    // when
+    const data = await validatePackageJson('package.json');
+
+    // then
+    expect(data).not.toBeNull();
+  });
+
+  it("with the 'expectedPluginType' argument returns a data object", async() => {
+    // setup
+    mocks.importPackageJsonMock.mockResolvedValue(examplePkg);
+
+    // when
+    const data = await validatePackageJson('package.json', GrowiPluginType.TEMPLATE);
+
+    // then
+    expect(data).not.toBeNull();
+  });
+
+  describe('should throw an GrowiPluginValidationError', () => {
+
+    it("when the pkg does not have 'growiPlugin' directive", async() => {
+      // setup
+      mocks.importPackageJsonMock.mockResolvedValue({});
+
+      // when
+      const caller = async() => { await validatePackageJson('package.json') };
+
+      // then
+      await expect(caller).rejects.toThrow("The package.json does not have 'growiPlugin' directive.");
+    });
+
+    it("when the 'schemaVersion' is NaN", async() => {
+      // setup
+      mocks.importPackageJsonMock.mockResolvedValue({
+        growiPlugin: {
+          schemaVersion: 'foo',
+        },
+      });
+
+      // when
+      const caller = async() => { await validatePackageJson('package.json') };
+
+      // then
+      await expect(caller).rejects.toThrow("The growiPlugin directive must have a valid 'schemaVersion' directive.");
+    });
+
+    it("when the 'schemaVersion' is less than 4", async() => {
+      // setup
+      mocks.importPackageJsonMock.mockResolvedValue({
+        growiPlugin: {
+          schemaVersion: 3,
+        },
+      });
+
+      // when
+      const caller = async() => { await validatePackageJson('package.json') };
+
+      // then
+      await expect(caller).rejects.toThrow("The growiPlugin directive must have a valid 'schemaVersion' directive.");
+    });
+
+    it("when the 'types' directive does not exist", async() => {
+      // setup
+      mocks.importPackageJsonMock.mockResolvedValue({
+        growiPlugin: {
+          schemaVersion: 4,
+        },
+      });
+
+      // when
+      const caller = async() => { await validatePackageJson('package.json') };
+
+      // then
+      await expect(caller).rejects.toThrow("The growiPlugin directive does not have 'types' directive.");
+    });
+
+    it("when the 'types' directive does not have expected plugin type", async() => {
+      // setup
+      mocks.importPackageJsonMock.mockResolvedValue({
+        growiPlugin: {
+          schemaVersion: 4,
+          types: [GrowiPluginType.TEMPLATE],
+        },
+      });
+
+      // when
+      const caller = async() => { await validatePackageJson('package.json', GrowiPluginType.SCRIPT) };
+
+      // then
+      await expect(caller).rejects.toThrow("The growiPlugin directive does not have expected plugin type in 'types' directive.");
+    });
+  });
+
+});

+ 41 - 0
packages/pluginkit/src/server/utils/v4/package-json/validate.ts

@@ -0,0 +1,41 @@
+import { GrowiPluginType } from '~/consts';
+import { type GrowiPluginValidationData, GrowiPluginValidationError } from '~/model';
+
+import { importPackageJson } from './import';
+
+
+export const validatePackageJson = async(projectDirRoot: string, expectedPluginType?: GrowiPluginType): Promise<GrowiPluginValidationData> => {
+  const pkg = await importPackageJson(projectDirRoot);
+
+  const data: GrowiPluginValidationData = { projectDirRoot };
+
+  const { growiPlugin } = pkg;
+
+  if (growiPlugin == null) {
+    throw new GrowiPluginValidationError("The package.json does not have 'growiPlugin' directive.", data);
+  }
+
+  // schema version checking
+  const schemaVersion = Number(growiPlugin.schemaVersion);
+  data.schemaVersion = schemaVersion;
+  if (Number.isNaN(schemaVersion) || schemaVersion < 4) {
+    throw new GrowiPluginValidationError("The growiPlugin directive must have a valid 'schemaVersion' directive.", data);
+  }
+
+  const types: GrowiPluginType[] = growiPlugin.types;
+  data.actualPluginTypes = types;
+  if (types == null) {
+    throw new GrowiPluginValidationError("The growiPlugin directive does not have 'types' directive.", data);
+  }
+
+  // type checking
+  if (expectedPluginType != null) {
+    data.expectedPluginType = expectedPluginType;
+
+    if (!types.includes(expectedPluginType)) {
+      throw new GrowiPluginValidationError("The growiPlugin directive does not have expected plugin type in 'types' directive.", data);
+    }
+  }
+
+  return data;
+};

+ 162 - 0
packages/pluginkit/src/server/utils/v4/template.ts

@@ -0,0 +1,162 @@
+import assert from 'assert';
+import fs from 'fs';
+import path from 'path';
+import { promisify } from 'util';
+
+import { GrowiPluginType } from '~/consts';
+import type { GrowiPluginValidationData, GrowiTemplatePluginValidationData } from '~/model';
+import { GrowiPluginValidationError } from '~/model';
+
+import { importPackageJson, validatePackageJson } from './package-json';
+
+
+const statAsync = promisify(fs.stat);
+
+
+/**
+ * An utility for template plugin which wrap 'validatePackageJson' of './package-json.ts' module
+ * @param projectDirRoot
+ */
+export const validateTemplatePluginPackageJson = async(projectDirRoot: string): Promise<GrowiTemplatePluginValidationData> => {
+  const data = await validatePackageJson(projectDirRoot, GrowiPluginType.TEMPLATE);
+
+  const pkg = await importPackageJson(projectDirRoot);
+
+  // check supporting locales
+  const supportingLocales: string[] | undefined = pkg.growiPlugin.locales;
+  if (supportingLocales == null || supportingLocales.length === 0) {
+    throw new GrowiPluginValidationError<GrowiPluginValidationData & { supportingLocales?: string[] }>(
+      "Template plugin must have 'supportingLocales' and that must have one or more locales",
+      {
+        ...data,
+        supportingLocales,
+      },
+    );
+  }
+
+  return {
+    ...data,
+    supportingLocales,
+  };
+};
+
+export type TemplateStatus = {
+  id: string,
+  locale: string,
+  isValid: boolean,
+  invalidReason?: string,
+}
+
+type TemplateDirStatus = {
+  isTemplateExists: boolean,
+  isMetaDataFileExists: boolean,
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  meta?: any,
+}
+
+async function getStats(tplDir: string): Promise<TemplateDirStatus> {
+  const markdownPath = path.resolve(tplDir, 'template.md');
+  const statForMarkdown = await statAsync(markdownPath);
+  const isTemplateExists = statForMarkdown.isFile();
+
+  const metaDataPath = path.resolve(tplDir, 'meta.json');
+  const statForMetaDataFile = await statAsync(metaDataPath);
+  const isMetaDataFileExists = statForMetaDataFile.isFile();
+
+  const result: TemplateDirStatus = {
+    isTemplateExists,
+    isMetaDataFileExists,
+  };
+
+  if (isMetaDataFileExists) {
+    result.meta = await import(metaDataPath);
+  }
+
+  return result;
+}
+
+export const scanTemplateStatus = async(projectDirRoot: string, templateId: string, data: GrowiTemplatePluginValidationData): Promise<TemplateStatus[]> => {
+  const status: TemplateStatus[] = [];
+
+  const tplRootDirPath = path.resolve(projectDirRoot, 'dist', templateId);
+
+  for await (const locale of data.supportingLocales) {
+    const tplDir = path.resolve(tplRootDirPath, locale);
+
+    try {
+      const {
+        isTemplateExists, isMetaDataFileExists, meta,
+      } = await getStats(tplDir);
+
+      if (!isTemplateExists) throw new Error("'template.md does not exist.");
+      if (!isMetaDataFileExists) throw new Error("'meta.md does not exist.");
+      if (meta?.title == null) throw new Error("'meta.md does not contain the title.");
+
+      status.push({ id: templateId, locale, isValid: true });
+    }
+    catch (err) {
+      status.push({
+        id: templateId,
+        locale,
+        isValid: false,
+        invalidReason: err.message,
+      });
+    }
+  }
+
+  // eslint-disable-next-line no-console
+  console.debug({ status });
+
+  return status;
+};
+
+export const scanAllTemplateStatus = async(projectDirRoot: string, data: GrowiTemplatePluginValidationData): Promise<TemplateStatus[]> => {
+  const status: TemplateStatus[] = [];
+
+  const distDirPath = path.resolve(projectDirRoot, 'dist');
+  const distDirFiles = fs.readdirSync(distDirPath);
+
+  for await (const templateId of distDirFiles) {
+    status.push(...await scanTemplateStatus(projectDirRoot, templateId, data));
+  }
+
+  return status;
+};
+
+
+export const validateTemplatePlugin = async(projectDirRoot: string): Promise<boolean> => {
+  const data = await validateTemplatePluginPackageJson(projectDirRoot);
+
+  const results = await scanAllTemplateStatus(projectDirRoot, data);
+
+  if (results.length === 0) {
+    throw new Error('This plugin does not have any templates');
+  }
+
+  // construct map
+  // key: id
+  // value: isValid properties
+  const idValidMap: { [id: string]: boolean[] } = {};
+  results.forEach((status) => {
+    const validMap = idValidMap[status.id] ?? [];
+    validMap.push(status.isValid);
+    idValidMap[status.id] = validMap;
+  });
+
+  for (const [id, validMap] of Object.entries(idValidMap)) {
+    assert(validMap.length === data.supportingLocales.length);
+
+    // warn
+    if (!validMap.every(bool => bool)) {
+      // eslint-disable-next-line no-console
+      console.warn(`[WARN] Template '${id}' has invalid status`);
+    }
+
+    // This means the template directory does not have any valid template
+    if (!validMap.some(bool => bool)) {
+      return false;
+    }
+  }
+
+  return true;
+};

+ 0 - 0
packages/pluginkit/test/fixtures/example-package/template1/index.js


+ 14 - 0
packages/pluginkit/test/fixtures/example-package/template1/package.json

@@ -0,0 +1,14 @@
+{
+  "name": "example-package-template1",
+  "version": "1.0.0",
+  "main": "index.js",
+  "growiPlugin": {
+    "schemaVersion": "4",
+    "types": [
+      "template"
+    ],
+    "locales": [
+      "en_US", "ja_JP", "zh_CN"
+    ]
+  }
+}

+ 19 - 0
packages/pluginkit/tsconfig.json

@@ -0,0 +1,19 @@
+{
+  "$schema": "http://json.schemastore.org/tsconfig",
+  "extends": "../../tsconfig.base.json",
+  "compilerOptions": {
+    "module": "CommonJS",
+    "types": [
+      "node",
+      "vitest/globals"
+    ],
+    "baseUrl": ".",
+    "paths": {
+      "^/*": ["./*"],
+      "~/*": ["./src/*"]
+    }
+  },
+  "include": [
+    "src"
+  ]
+}

+ 36 - 0
packages/pluginkit/vite.config.ts

@@ -0,0 +1,36 @@
+import path from 'path';
+
+
+import glob from 'glob';
+import { defineConfig } from 'vite';
+import dts from 'vite-plugin-dts';
+import tsconfigPaths from 'vite-tsconfig-paths';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [
+    dts(),
+    tsconfigPaths(),
+  ],
+  build: {
+    outDir: 'dist',
+    sourcemap: true,
+    lib: {
+      entry: glob.sync(path.resolve(__dirname, 'src/**/*.ts')),
+      name: 'pluginkit-libs',
+      formats: ['es', 'cjs'],
+    },
+    rollupOptions: {
+      output: {
+        preserveModules: true,
+        preserveModulesRoot: 'src',
+      },
+      external: [
+        'assert',
+        'fs',
+        'path',
+        'util',
+      ],
+    },
+  },
+});

+ 19 - 0
packages/pluginkit/vitest.config.ts

@@ -0,0 +1,19 @@
+import tsconfigPaths from 'vite-tsconfig-paths';
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+  plugins: [
+    tsconfigPaths(),
+  ],
+  test: {
+    environment: 'node',
+    clearMocks: true,
+    globals: true,
+    coverage: {
+      lines: 100,
+      functions: 100,
+      branches: 100,
+      statements: 100,
+    },
+  },
+});

+ 3 - 2
packages/presentation/package.json

@@ -15,10 +15,11 @@
     "lint:js": "yarn eslint **/*.{js,jsx,ts,tsx}",
     "lint:styles": "stylelint --allow-empty-input src/**/*.scss src/**/*.css",
     "lint:typecheck": "tsc",
-    "lint": "run-p lint:*"
+    "lint": "run-p lint:*",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {
-    "@growi/core": "^6.1.4-RC.0"
+    "@growi/core": "link:../core"
   },
   "devDependencies": {
     "@marp-team/marp-core": "^3.6.0",

+ 3 - 0
packages/preset-templates/dist/example/ja_JP/meta.json

@@ -0,0 +1,3 @@
+{
+  "title": "Example"
+}

+ 1 - 0
packages/preset-templates/dist/example/ja_JP/template.md

@@ -0,0 +1 @@
+# Example

+ 22 - 0
packages/preset-templates/package.json

@@ -0,0 +1,22 @@
+{
+  "name": "@growi/preset-templates",
+  "version": "6.1.4-RC.0",
+  "scripts": {
+    "test": "vitest run",
+    "version": "yarn version --no-git-tag-version"
+  },
+  "dependencies": {
+  },
+  "devDependencies": {
+    "@growi/pluginkit": "link:../pluginkit"
+  },
+  "growiPlugin": {
+    "schemaVersion": "4",
+    "types": [
+      "template"
+    ],
+    "locales": [
+      "en_US", "ja_JP", "zh_CN"
+    ]
+  }
+}

+ 36 - 0
packages/preset-templates/test/index.test.ts

@@ -0,0 +1,36 @@
+import path from 'node:path';
+
+import { scanAllTemplateStatus, validateTemplatePluginPackageJson, validateTemplatePlugin } from '@growi/pluginkit/dist/server/utils/v4';
+
+
+const projectDirRoot = path.resolve(__dirname, '../');
+
+
+it('Validation for package.json should be passed', () => {
+
+  // when
+  const caller = () => validateTemplatePluginPackageJson(projectDirRoot);
+
+  // then
+  expect(caller).not.toThrow();
+});
+
+it('Scanning the templates ends up with no errors', async() => {
+
+  // setup
+  const data = await validateTemplatePluginPackageJson(projectDirRoot);
+
+  // when
+  const caller = () => scanAllTemplateStatus(projectDirRoot, data);
+
+  // then
+  expect(caller).not.toThrow();
+});
+
+it('Validation templates returns true', async() => {
+  // when
+  const result = await validateTemplatePlugin(projectDirRoot);
+
+  // then
+  expect(result).toBeTruthy();
+});

+ 10 - 0
packages/preset-templates/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "$schema": "http://json.schemastore.org/tsconfig",
+  "compilerOptions": {
+    "esModuleInterop": true,
+    "resolveJsonModule": true,
+    "types": [
+      "vitest/globals"
+    ]
+  }
+}

+ 9 - 0
packages/preset-templates/vitest.config.ts

@@ -0,0 +1,9 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+  test: {
+    environment: 'node',
+    clearMocks: true,
+    globals: true,
+  },
+});

+ 2 - 1
packages/preset-themes/package.json

@@ -23,7 +23,8 @@
     "lint:styles": "stylelint src/**/*.scss",
     "lint:typecheck": "tsc",
     "lint": "run-p lint:*",
-    "preview": "vite preview"
+    "preview": "vite preview",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {},
   "devDependencies": {

+ 5 - 4
packages/remark-attachment-refs/package.json

@@ -21,14 +21,15 @@
     "lint:styles": "stylelint src/**/*.scss src/**/*.css",
     "lint:typecheck": "tsc",
     "lint": "run-p lint:*",
-    "test": ""
+    "test": "",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {
     "bunyan": "^1.8.15",
     "universal-bunyan": "^0.9.2",
-    "@growi/core": "^6.1.4-RC.0",
-    "@growi/remark-growi-directive": "^6.1.4-RC.0",
-    "@growi/ui": "^6.1.4-RC.0"
+    "@growi/core": "link:../core",
+    "@growi/remark-growi-directive": "link:../remark-growi-directive",
+    "@growi/ui": "link:../ui"
   },
   "devDependencies": {
     "eslint-plugin-regex": "^1.8.0",

+ 2 - 1
packages/remark-drawio/package.json

@@ -27,7 +27,8 @@
     "lint:js": "yarn eslint **/*.{js,jsx,ts,tsx}",
     "lint:styles": "stylelint --allow-empty-input src/**/*.scss src/**/*.css",
     "lint:typecheck": "tsc",
-    "lint": "run-p lint:*"
+    "lint": "run-p lint:*",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {
     "pako": "^2.1.0"

+ 2 - 1
packages/remark-growi-directive/package.json

@@ -24,7 +24,8 @@
     "test-api": "tape --conditions development test/**.test.js",
     "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api",
     "lint": "yarn eslint \"**/*.{cjs, js,jsx,ts,tsx}\"",
-    "lint:fix": "yarn eslint \"**/*.{cjs, js,jsx,ts,tsx}\" --fix"
+    "lint:fix": "yarn eslint \"**/*.{cjs, js,jsx,ts,tsx}\" --fix",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {
     "@types/mdast": "^3.0.0",

+ 5 - 4
packages/remark-lsx/package.json

@@ -20,15 +20,16 @@
     "lint:styles": "stylelint --allow-empty-input src/**/*.scss src/**/*.css",
     "lint:typecheck": "tsc",
     "lint": "run-p lint:*",
-    "test": "vitest run --coverage"
+    "test": "vitest run --coverage",
+    "version": "yarn version --no-git-tag-version"
   },
   "// comments for dependencies": {
     "escape-string-regexp": "5.0.0 or above exports only ESM"
   },
   "dependencies": {
-    "@growi/core": "^6.1.4-RC.0",
-    "@growi/remark-growi-directive": "^6.1.4-RC.0",
-    "@growi/ui": "^6.1.4-RC.0",
+    "@growi/core": "link:../core",
+    "@growi/remark-growi-directive": "link:../remark-growi-directive",
+    "@growi/ui": "link:../ui",
     "escape-string-regexp": "^4.0.0",
     "express": "^4.16.1",
     "mongoose": "^6.5.0",

+ 2 - 1
packages/slack/package.json

@@ -13,7 +13,8 @@
     "lint:js": "yarn eslint **/*.{js,ts}",
     "lint:typecheck": "tsc",
     "lint": "npm-run-all -p lint:*",
-    "test": "vitest run --coverage"
+    "test": "vitest run --coverage",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {
     "@slack/oauth": "^2.0.1",

+ 3 - 2
packages/ui/package.json

@@ -13,10 +13,11 @@
     "watch": "yarn dev -w --emptyOutDir=false",
     "lint:js": "yarn eslint **/*.{js,ts}",
     "lint:typecheck": "tsc",
-    "lint": "npm-run-all -p lint:*"
+    "lint": "npm-run-all -p lint:*",
+    "version": "yarn version --no-git-tag-version"
   },
   "dependencies": {
-    "@growi/core": "^6.1.4-RC.0"
+    "@growi/core": "link:../core"
   },
   "devDependencies": {
     "react": "^18.2.0"

+ 9 - 0
turbo.json

@@ -160,12 +160,21 @@
       "dependsOn": ["@growi/slack#dev"],
       "outputMode": "new-only"
     },
+    "@growi/preset-templates#test": {
+      "dependsOn": ["@growi/pluginkit#dev"],
+      "outputMode": "new-only"
+    },
     "@growi/remark-lsx#test": {
       "dependsOn": ["@growi/core#dev"],
       "outputMode": "new-only"
     },
     "test": {
       "outputMode": "new-only"
+    },
+    "version": {
+      "outputMode": "new-only",
+      "outputs": ["package.json"],
+      "inputs": ["package.json"]
     }
 
   }

Разница между файлами не показана из-за своего большого размера
+ 112 - 471
yarn.lock


Некоторые файлы не были показаны из-за большого количества измененных файлов