diff --git a/.changeset/itchy-impalas-remain.md b/.changeset/itchy-impalas-remain.md
new file mode 100644
index 000000000..e980aa1d9
--- /dev/null
+++ b/.changeset/itchy-impalas-remain.md
@@ -0,0 +1,5 @@
+---
+"@logto/connector-line": minor
+---
+
+add Line social connector
diff --git a/packages/connectors/connector-line/README.md b/packages/connectors/connector-line/README.md
new file mode 100644
index 000000000..f3df59762
--- /dev/null
+++ b/packages/connectors/connector-line/README.md
@@ -0,0 +1,57 @@
+# Line connector
+
+The official Logto connector for Line social sign-in.
+
+**Table of contents**
+- [Line connector](#line-connector)
+ - [Get started](#get-started)
+ - [Setup a Line channel](#setup-a-line-channel)
+ - [Configure your connector](#configure-your-connector)
+ - [Config types](#config-types)
+ - [Test Line connector](#test-line-connector)
+ - [Reference](#reference)
+
+## Get started
+
+The Line connector enables end-users to sign in to your application using their own Line accounts via the Line OAuth 2.0 authentication protocol.
+
+## Setup a Line channel
+
+Go to the [Line Developers](https://developers.line.biz/console/) and sign in with your Line business account. If you don’t have an account, you can register for one.
+
+Then, go to [this link](https://developers.line.biz/console/register/line-login/provider/) to create a channel.
+
+**Step 1:** Fill in the Channel Details.
+
+Complete the form and create the channel.
+
+**Step 2:** Setup callback URLs.
+
+Go to channel details page and find "LINE login" tab and edit the "Callback URL" field.
+
+In our case, this will be `${your_logto_endpoint}/callback/${connector_id}`. e.g. `https://foo.logto.app/callback/${connector_id}`. The `connector_id` can be found on the top bar of the Logto Admin Console connector details page.
+
+## Configure your connector
+
+In your Logto connector configuration, fill out the following fields with the values obtained from your App's "Auth" tab, "Application credentials" section:
+
+- **clientId:** Your App's Channel ID.
+- **clientSecret:** Your App's Channel Secret.
+
+`scope` is a space-delimited list of OIDC scopes. If not provided, the default scope is `openid profile`.
+
+### Config types
+
+| Name | Type |
+| ------------ | ------ |
+| clientId | string |
+| clientSecret | string |
+| scope | string |
+
+## Test Line connector
+
+That's it! The Line connector should now be available for end-users to sign in with their Line accounts. Don't forget to [Enable the connector in the sign-in experience](https://docs.logto.io/docs/recipes/configure-connectors/social-connector/enable-social-sign-in/).
+
+## Reference
+
+- [Line Developer Documentation](https://developers.line.biz/en/docs/line-login/overview/)
diff --git a/packages/connectors/connector-line/logo.svg b/packages/connectors/connector-line/logo.svg
new file mode 100644
index 000000000..5de90514f
--- /dev/null
+++ b/packages/connectors/connector-line/logo.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/packages/connectors/connector-line/package.json b/packages/connectors/connector-line/package.json
new file mode 100644
index 000000000..deefac363
--- /dev/null
+++ b/packages/connectors/connector-line/package.json
@@ -0,0 +1,70 @@
+{
+ "name": "@logto/connector-line",
+ "version": "0.0.0",
+ "description": "Line web connector implementation.",
+ "author": "Silverhand Inc. ",
+ "dependencies": {
+ "@logto/connector-kit": "workspace:^4.0.0",
+ "@silverhand/essentials": "^2.9.1",
+ "ky": "^1.2.3",
+ "query-string": "^9.0.0",
+ "snakecase-keys": "^8.0.1",
+ "zod": "^3.23.8"
+ },
+ "main": "./lib/index.js",
+ "module": "./lib/index.js",
+ "exports": "./lib/index.js",
+ "license": "MPL-2.0",
+ "type": "module",
+ "files": [
+ "lib",
+ "docs",
+ "logo.svg",
+ "logo-dark.svg"
+ ],
+ "scripts": {
+ "precommit": "lint-staged",
+ "check": "tsc --noEmit",
+ "build": "tsup",
+ "dev": "tsup --watch",
+ "lint": "eslint --ext .ts src",
+ "lint:report": "pnpm lint --format json --output-file report.json",
+ "test": "vitest src",
+ "test:ci": "pnpm run test --silent --coverage",
+ "prepublishOnly": "pnpm build"
+ },
+ "engines": {
+ "node": "^20.9.0"
+ },
+ "eslintConfig": {
+ "extends": "@silverhand",
+ "settings": {
+ "import/core-modules": [
+ "@silverhand/essentials",
+ "got",
+ "nock",
+ "snakecase-keys",
+ "zod"
+ ]
+ }
+ },
+ "prettier": "@silverhand/eslint-config/.prettierrc",
+ "publishConfig": {
+ "access": "public"
+ },
+ "devDependencies": {
+ "@silverhand/eslint-config": "6.0.1",
+ "@silverhand/ts-config": "6.0.0",
+ "@types/node": "^20.11.20",
+ "@types/supertest": "^6.0.2",
+ "@vitest/coverage-v8": "^2.1.8",
+ "eslint": "^8.56.0",
+ "lint-staged": "^15.0.2",
+ "nock": "14.0.0-beta.15",
+ "prettier": "^3.0.0",
+ "supertest": "^7.0.0",
+ "tsup": "^8.3.0",
+ "typescript": "^5.5.3",
+ "vitest": "^2.1.8"
+ }
+}
diff --git a/packages/connectors/connector-line/src/constant.ts b/packages/connectors/connector-line/src/constant.ts
new file mode 100644
index 000000000..35d727c47
--- /dev/null
+++ b/packages/connectors/connector-line/src/constant.ts
@@ -0,0 +1,54 @@
+import type { ConnectorMetadata } from '@logto/connector-kit';
+import { ConnectorPlatform, ConnectorConfigFormItemType } from '@logto/connector-kit';
+
+// See https://developers.line.biz/en/docs/line-login/overview/
+export const authorizationEndpoint = 'https://access.line.me/oauth2/v2.1/authorize';
+export const defaultScope = 'openid profile';
+export const accessTokenEndpoint = 'https://api.line.me/oauth2/v2.1/token';
+export const userInfoEndpoint = 'https://api.line.me/v2/profile';
+
+export const defaultMetadata: ConnectorMetadata = {
+ id: 'line-universal',
+ target: 'line',
+ platform: ConnectorPlatform.Universal,
+ name: {
+ en: 'Line',
+ 'zh-CN': 'Line',
+ 'tr-TR': 'Line',
+ ko: 'Line',
+ },
+ logo: './logo.svg',
+ logoDark: null,
+ description: {
+ en: 'Line is a social media platform for sharing information and connecting with friends.',
+ 'zh-CN': 'Line是一个分享信息和与朋友连接的社交媒体平台。',
+ 'tr-TR':
+ 'Line, bilgi paylaşma ve arkadaşlarınızla bağlantı kurma için bir sosyal medya platformudur.',
+ ko: 'Line은 정보 공유와 친구들과의 연결을 위한 소셜 미디어 플랫폼입니다.',
+ },
+ readme: './README.md',
+ formItems: [
+ {
+ key: 'clientId',
+ type: ConnectorConfigFormItemType.Text,
+ label: 'Client ID (Channel ID)',
+ required: true,
+ },
+ {
+ key: 'clientSecret',
+ type: ConnectorConfigFormItemType.Text,
+ label: 'Client Secret (Channel Secret)',
+ required: true,
+ },
+ {
+ key: 'scope',
+ type: ConnectorConfigFormItemType.Text,
+ label: 'Scope',
+ required: false,
+ description:
+ "The `scope` determines permissions granted by the user's authorization. If you are not sure what to enter, do not worry, just leave it blank.",
+ },
+ ],
+};
+
+export const defaultTimeout = 5000;
diff --git a/packages/connectors/connector-line/src/index.test.ts b/packages/connectors/connector-line/src/index.test.ts
new file mode 100644
index 000000000..3d9b6e287
--- /dev/null
+++ b/packages/connectors/connector-line/src/index.test.ts
@@ -0,0 +1,92 @@
+import nock from 'nock';
+
+import { accessTokenEndpoint, authorizationEndpoint, userInfoEndpoint } from './constant.js';
+import createConnector, { getAccessToken } from './index.js';
+import { mockedConfig } from './mock.js';
+
+const getConfig = vi.fn().mockResolvedValue(mockedConfig);
+const setSession = vi.fn();
+const getSession = vi.fn().mockResolvedValue({
+ redirectUri: 'http://localhost:3000/callback',
+});
+
+describe('getAuthorizationUri', () => {
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('should get a valid uri by redirectUri and state', async () => {
+ const connector = await createConnector({ getConfig });
+ const authorizationUri = await connector.getAuthorizationUri(
+ {
+ state: 'some_state',
+ redirectUri: 'http://localhost:3000/callback',
+ connectorId: 'some_connector_id',
+ connectorFactoryId: 'some_connector_factory_id',
+ jti: 'some_jti',
+ headers: {},
+ },
+ setSession
+ );
+ expect(setSession).toHaveBeenCalledWith({
+ redirectUri: 'http://localhost:3000/callback',
+ });
+ expect(authorizationUri).toEqual(
+ `${authorizationEndpoint}?response_type=code&client_id=%3Cclient-id%3E&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&scope=openid+profile&state=some_state`
+ );
+ });
+});
+
+describe('getAccessToken', () => {
+ afterEach(() => {
+ nock.cleanAll();
+ vi.clearAllMocks();
+ });
+
+ it('should get an accessToken by exchanging with code', async () => {
+ nock(accessTokenEndpoint).post('').reply(200, {
+ access_token: 'access_token',
+ });
+ const { access_token } = await getAccessToken(mockedConfig, 'code', 'redirectUri');
+ expect(access_token).toEqual('access_token');
+ });
+});
+
+describe('getUserInfo', () => {
+ beforeEach(() => {
+ nock(accessTokenEndpoint).post('').query(true).reply(200, {
+ access_token: 'access_token',
+ });
+ });
+
+ afterEach(() => {
+ nock.cleanAll();
+ vi.clearAllMocks();
+ });
+
+ it('should get valid SocialUserInfo', async () => {
+ nock(userInfoEndpoint).get('').reply(200, {
+ userId: '1',
+ displayName: 'monalisa',
+ });
+ const connector = await createConnector({ getConfig });
+ const socialUserInfo = await connector.getUserInfo(
+ { code: 'code', redirectUri: 'http://localhost:3000/callback' },
+ getSession
+ );
+ expect(socialUserInfo).toStrictEqual({
+ id: '1',
+ name: 'monalisa',
+ rawData: {
+ userId: '1',
+ displayName: 'monalisa',
+ },
+ });
+ });
+
+ it('throws unrecognized error', async () => {
+ nock(userInfoEndpoint).get('').reply(500);
+ const connector = await createConnector({ getConfig });
+ await expect(connector.getUserInfo({ code: 'code' }, vi.fn())).rejects.toThrow();
+ });
+});
diff --git a/packages/connectors/connector-line/src/index.ts b/packages/connectors/connector-line/src/index.ts
new file mode 100644
index 000000000..8bfb7d4a0
--- /dev/null
+++ b/packages/connectors/connector-line/src/index.ts
@@ -0,0 +1,145 @@
+import { conditional } from '@silverhand/essentials';
+
+import {
+ ConnectorError,
+ ConnectorErrorCodes,
+ validateConfig,
+ ConnectorType,
+ jsonGuard,
+} from '@logto/connector-kit';
+import type {
+ GetAuthorizationUri,
+ GetUserInfo,
+ SocialConnector,
+ CreateConnector,
+ GetConnectorConfig,
+} from '@logto/connector-kit';
+import ky, { HTTPError } from 'ky';
+
+import {
+ authorizationEndpoint,
+ accessTokenEndpoint,
+ defaultMetadata,
+ defaultTimeout,
+ defaultScope,
+ userInfoEndpoint,
+} from './constant.js';
+import type { LineConfig } from './types.js';
+import {
+ lineConfigGuard,
+ userInfoResponseGuard,
+ authResponseGuard,
+ accessTokenResponseGuard,
+} from './types.js';
+
+const getAuthorizationUri =
+ (getConfig: GetConnectorConfig): GetAuthorizationUri =>
+ async ({ state, redirectUri }, setSession) => {
+ const config = await getConfig(defaultMetadata.id);
+ validateConfig(config, lineConfigGuard);
+
+ await setSession({ redirectUri });
+
+ const queryParams = new URLSearchParams({
+ response_type: 'code',
+ client_id: config.clientId,
+ redirect_uri: redirectUri,
+ scope: config.scope ?? defaultScope,
+ state,
+ });
+
+ return `${authorizationEndpoint}?${queryParams.toString()}`;
+ };
+
+export const getAccessToken = async (config: LineConfig, code: string, redirectUri: string) => {
+ const response = await ky
+ .post(accessTokenEndpoint, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: new URLSearchParams({
+ grant_type: 'authorization_code',
+ code,
+ redirect_uri: redirectUri,
+ client_id: config.clientId,
+ client_secret: config.clientSecret,
+ }).toString(),
+ timeout: defaultTimeout,
+ })
+ .json();
+
+ return accessTokenResponseGuard.parse(response);
+};
+
+const getUserInfo =
+ (getConfig: GetConnectorConfig): GetUserInfo =>
+ async (data, getSession) => {
+ const config = await getConfig(defaultMetadata.id);
+ validateConfig(config, lineConfigGuard);
+
+ const authResponseResult = authResponseGuard.safeParse(data);
+
+ if (!authResponseResult.success) {
+ throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(data));
+ }
+
+ const { code } = authResponseResult.data;
+ const { redirectUri } = await getSession();
+
+ if (!redirectUri) {
+ throw new ConnectorError(ConnectorErrorCodes.General, {
+ message: 'Cannot find `redirectUri` from connector session.',
+ });
+ }
+
+ try {
+ const { access_token } = await getAccessToken(config, code, redirectUri);
+
+ const userInfo = await ky
+ .get(userInfoEndpoint, {
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ timeout: defaultTimeout,
+ })
+ .json();
+
+ const userInfoResult = userInfoResponseGuard.safeParse(userInfo);
+
+ if (!userInfoResult.success) {
+ throw new ConnectorError(ConnectorErrorCodes.InvalidResponse, userInfoResult.error);
+ }
+
+ const { userId, displayName } = userInfoResult.data;
+
+ return {
+ id: userId,
+ name: conditional(displayName),
+ rawData: jsonGuard.parse(userInfo),
+ };
+ } catch (error: unknown) {
+ if (error instanceof HTTPError) {
+ const { status, body: rawBody } = error.response;
+
+ if (status === 401) {
+ throw new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid);
+ }
+
+ throw new ConnectorError(ConnectorErrorCodes.General, JSON.stringify(rawBody));
+ }
+
+ throw error;
+ }
+ };
+
+const createLineConnector: CreateConnector = async ({ getConfig }) => {
+ return {
+ metadata: defaultMetadata,
+ type: ConnectorType.Social,
+ configGuard: lineConfigGuard,
+ getAuthorizationUri: getAuthorizationUri(getConfig),
+ getUserInfo: getUserInfo(getConfig),
+ };
+};
+
+export default createLineConnector;
diff --git a/packages/connectors/connector-line/src/mock.ts b/packages/connectors/connector-line/src/mock.ts
new file mode 100644
index 000000000..a52d77ccc
--- /dev/null
+++ b/packages/connectors/connector-line/src/mock.ts
@@ -0,0 +1,4 @@
+export const mockedConfig = {
+ clientId: '',
+ clientSecret: '',
+};
diff --git a/packages/connectors/connector-line/src/types.ts b/packages/connectors/connector-line/src/types.ts
new file mode 100644
index 000000000..cefe87a57
--- /dev/null
+++ b/packages/connectors/connector-line/src/types.ts
@@ -0,0 +1,24 @@
+import { z } from 'zod';
+
+export const lineConfigGuard = z.object({
+ clientId: z.string(),
+ clientSecret: z.string(),
+ scope: z.string().optional(),
+});
+
+export type LineConfig = z.infer;
+
+export const userInfoResponseGuard = z.object({
+ userId: z.string(),
+ displayName: z.string().nullish(),
+});
+
+export type UserInfoResponse = z.infer;
+
+export const authResponseGuard = z.object({
+ code: z.string(),
+});
+
+export const accessTokenResponseGuard = z.object({
+ access_token: z.string(),
+});
diff --git a/packages/connectors/connector-line/src/utils.ts b/packages/connectors/connector-line/src/utils.ts
new file mode 100644
index 000000000..7ab27db7d
--- /dev/null
+++ b/packages/connectors/connector-line/src/utils.ts
@@ -0,0 +1,12 @@
+import crypto from 'node:crypto';
+
+export const generateCodeVerifier = () => {
+ const buffer = crypto.randomBytes(32);
+ return buffer.toString('base64url');
+};
+
+export const generateCodeChallenge = (verifier: string) => {
+ const hash = crypto.createHash('sha256');
+ hash.update(verifier);
+ return hash.digest('base64url');
+};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2a3aef041..4e00a3522 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1440,6 +1440,67 @@ importers:
specifier: ^2.1.9
version: 2.1.9(@types/node@20.12.7)(jsdom@20.0.2)(lightningcss@1.25.1)(sass@1.77.8)
+ packages/connectors/connector-line:
+ dependencies:
+ '@logto/connector-kit':
+ specifier: workspace:^4.0.0
+ version: link:../../toolkit/connector-kit
+ '@silverhand/essentials':
+ specifier: ^2.9.1
+ version: 2.9.2
+ ky:
+ specifier: ^1.2.3
+ version: 1.2.3
+ query-string:
+ specifier: ^9.0.0
+ version: 9.0.0
+ snakecase-keys:
+ specifier: ^8.0.1
+ version: 8.0.1
+ zod:
+ specifier: ^3.23.8
+ version: 3.23.8
+ devDependencies:
+ '@silverhand/eslint-config':
+ specifier: 6.0.1
+ version: 6.0.1(eslint@8.57.0)(prettier@3.0.0)(typescript@5.5.3)
+ '@silverhand/ts-config':
+ specifier: 6.0.0
+ version: 6.0.0(typescript@5.5.3)
+ '@types/node':
+ specifier: ^20.11.20
+ version: 20.12.7
+ '@types/supertest':
+ specifier: ^6.0.2
+ version: 6.0.2
+ '@vitest/coverage-v8':
+ specifier: ^2.1.8
+ version: 2.1.9(vitest@2.1.9(@types/node@20.12.7)(jsdom@20.0.2)(lightningcss@1.25.1)(sass@1.77.8))
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.0
+ lint-staged:
+ specifier: ^15.0.2
+ version: 15.0.2
+ nock:
+ specifier: 14.0.0-beta.15
+ version: 14.0.0-beta.15
+ prettier:
+ specifier: ^3.0.0
+ version: 3.0.0
+ supertest:
+ specifier: ^7.0.0
+ version: 7.0.0
+ tsup:
+ specifier: ^8.3.0
+ version: 8.3.0(@swc/core@1.3.52(@swc/helpers@0.5.1))(jiti@1.21.0)(postcss@8.5.1)(typescript@5.5.3)(yaml@2.4.5)
+ typescript:
+ specifier: ^5.5.3
+ version: 5.5.3
+ vitest:
+ specifier: ^2.1.8
+ version: 2.1.9(@types/node@20.12.7)(jsdom@20.0.2)(lightningcss@1.25.1)(sass@1.77.8)
+
packages/connectors/connector-linkedin:
dependencies:
'@logto/connector-kit':
@@ -9600,10 +9661,6 @@ packages:
for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
- foreground-child@3.1.1:
- resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
- engines: {node: '>=14'}
-
foreground-child@3.3.0:
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
engines: {node: '>=14'}
@@ -9777,11 +9834,6 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
- glob@10.4.2:
- resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==}
- engines: {node: '>=16 || 14 >=14.18'}
- hasBin: true
-
glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
hasBin: true
@@ -10508,10 +10560,6 @@ packages:
iterator.prototype@1.1.2:
resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
- jackspeak@3.4.0:
- resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==}
- engines: {node: '>=14'}
-
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
@@ -11585,10 +11633,6 @@ packages:
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
- minimatch@9.0.4:
- resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
- engines: {node: '>=16 || 14 >=14.17'}
-
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -11994,9 +12038,6 @@ packages:
resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==}
engines: {node: '>= 14'}
- package-json-from-dist@1.0.0:
- resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==}
-
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
@@ -15044,12 +15085,12 @@ snapshots:
'@babel/helper-compilation-targets': 7.23.6
'@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4)
'@babel/helpers': 7.24.4
- '@babel/parser': 7.24.8
+ '@babel/parser': 7.26.3
'@babel/template': 7.24.0
'@babel/traverse': 7.24.1
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
convert-source-map: 2.0.0
- debug: 4.3.4
+ debug: 4.4.0
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
@@ -15078,20 +15119,20 @@ snapshots:
'@babel/generator@7.20.4':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@jridgewell/gen-mapping': 0.3.5
jsesc: 2.5.2
'@babel/generator@7.24.10':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
jsesc: 2.5.2
'@babel/generator@7.24.4':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
jsesc: 2.5.2
@@ -15116,34 +15157,34 @@ snapshots:
'@babel/helper-environment-visitor@7.24.7':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-function-name@7.23.0':
dependencies:
'@babel/template': 7.24.0
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-function-name@7.24.7':
dependencies:
'@babel/template': 7.24.7
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-hoist-variables@7.22.5':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-hoist-variables@7.24.7':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-module-imports@7.24.3':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-module-imports@7.24.7':
dependencies:
'@babel/traverse': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
transitivePeerDependencies:
- supports-color
@@ -15173,22 +15214,22 @@ snapshots:
'@babel/helper-simple-access@7.22.5':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-simple-access@7.24.7':
dependencies:
'@babel/traverse': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
transitivePeerDependencies:
- supports-color
'@babel/helper-split-export-declaration@7.22.6':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-split-export-declaration@7.24.7':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/helper-string-parser@7.23.4': {}
@@ -15212,14 +15253,14 @@ snapshots:
dependencies:
'@babel/template': 7.24.0
'@babel/traverse': 7.24.1
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
transitivePeerDependencies:
- supports-color
'@babel/helpers@7.24.8':
dependencies:
'@babel/template': 7.24.7
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/highlight@7.22.5':
dependencies:
@@ -15250,11 +15291,11 @@ snapshots:
'@babel/parser@7.24.4':
dependencies:
- '@babel/types': 7.24.0
+ '@babel/types': 7.26.3
'@babel/parser@7.24.8':
dependencies:
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@babel/parser@7.26.3':
dependencies:
@@ -15359,20 +15400,20 @@ snapshots:
'@babel/template@7.18.10':
dependencies:
'@babel/code-frame': 7.22.5
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
'@babel/template@7.24.0':
dependencies:
'@babel/code-frame': 7.24.2
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
'@babel/template@7.24.7':
dependencies:
'@babel/code-frame': 7.24.7
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
'@babel/traverse@7.24.1':
dependencies:
@@ -15382,9 +15423,9 @@ snapshots:
'@babel/helper-function-name': 7.23.0
'@babel/helper-hoist-variables': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- debug: 4.3.4
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
+ debug: 4.4.0
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -15397,9 +15438,9 @@ snapshots:
'@babel/helper-function-name': 7.24.7
'@babel/helper-hoist-variables': 7.24.7
'@babel/helper-split-export-declaration': 7.24.7
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- debug: 4.3.4
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
+ debug: 4.4.0
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -15616,7 +15657,7 @@ snapshots:
'@commitlint/is-ignored@19.0.3':
dependencies:
'@commitlint/types': 19.0.3
- semver: 7.6.0
+ semver: 7.6.3
'@commitlint/lint@19.0.3':
dependencies:
@@ -16411,7 +16452,7 @@ snapshots:
'@types/shimmer': 1.0.2
import-in-the-middle: 1.4.2
require-in-the-middle: 7.2.0
- semver: 7.6.0
+ semver: 7.6.3
shimmer: 1.2.1
transitivePeerDependencies:
- supports-color
@@ -17427,8 +17468,8 @@ snapshots:
'@types/babel__core@7.1.19':
dependencies:
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
'@types/babel__generator': 7.6.4
'@types/babel__template': 7.4.1
'@types/babel__traverse': 7.18.2
@@ -17443,16 +17484,16 @@ snapshots:
'@types/babel__generator@7.6.4':
dependencies:
- '@babel/types': 7.24.0
+ '@babel/types': 7.26.3
'@types/babel__template@7.4.1':
dependencies:
- '@babel/parser': 7.24.4
- '@babel/types': 7.24.0
+ '@babel/parser': 7.26.3
+ '@babel/types': 7.26.3
'@types/babel__traverse@7.18.2':
dependencies:
- '@babel/types': 7.24.0
+ '@babel/types': 7.26.3
'@types/body-parser@1.19.2':
dependencies:
@@ -18844,7 +18885,7 @@ snapshots:
babel-plugin-jest-hoist@29.6.3:
dependencies:
'@babel/template': 7.18.10
- '@babel/types': 7.24.9
+ '@babel/types': 7.26.3
'@types/babel__core': 7.1.19
'@types/babel__traverse': 7.18.2
@@ -20728,11 +20769,6 @@ snapshots:
dependencies:
is-callable: 1.2.7
- foreground-child@3.1.1:
- dependencies:
- cross-spawn: 7.0.6
- signal-exit: 4.1.0
-
foreground-child@3.3.0:
dependencies:
cross-spawn: 7.0.6
@@ -20934,15 +20970,6 @@ snapshots:
dependencies:
is-glob: 4.0.3
- glob@10.4.2:
- dependencies:
- foreground-child: 3.1.1
- jackspeak: 3.4.0
- minimatch: 9.0.4
- minipass: 7.1.2
- package-json-from-dist: 1.0.0
- path-scurry: 1.11.1
-
glob@10.4.5:
dependencies:
foreground-child: 3.3.0
@@ -21694,7 +21721,7 @@ snapshots:
istanbul-lib-instrument@5.2.1:
dependencies:
'@babel/core': 7.24.9
- '@babel/parser': 7.24.8
+ '@babel/parser': 7.26.3
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.2
semver: 6.3.1
@@ -21746,12 +21773,6 @@ snapshots:
reflect.getprototypeof: 1.0.6
set-function-name: 2.0.2
- jackspeak@3.4.0:
- dependencies:
- '@isaacs/cliui': 8.0.2
- optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
jackspeak@3.4.3:
dependencies:
'@isaacs/cliui': 8.0.2
@@ -22151,7 +22172,7 @@ snapshots:
'@babel/generator': 7.20.4
'@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.24.4)
'@babel/plugin-syntax-typescript': 7.18.6(@babel/core@7.24.4)
- '@babel/types': 7.24.0
+ '@babel/types': 7.26.3
'@jest/expect-utils': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
@@ -22166,7 +22187,7 @@ snapshots:
jest-util: 29.7.0
natural-compare: 1.4.0
pretty-format: 29.7.0
- semver: 7.6.0
+ semver: 7.6.3
transitivePeerDependencies:
- supports-color
@@ -23488,7 +23509,7 @@ snapshots:
micromark@3.2.0:
dependencies:
'@types/debug': 4.1.7
- debug: 4.3.4
+ debug: 4.4.0
decode-named-character-reference: 1.0.2
micromark-core-commonmark: 1.1.0
micromark-factory-space: 1.1.0
@@ -23510,7 +23531,7 @@ snapshots:
micromark@4.0.0:
dependencies:
'@types/debug': 4.1.7
- debug: 4.3.4
+ debug: 4.4.0
decode-named-character-reference: 1.0.1
devlop: 1.1.0
micromark-core-commonmark: 2.0.0
@@ -23562,10 +23583,6 @@ snapshots:
dependencies:
brace-expansion: 1.1.11
- minimatch@9.0.4:
- dependencies:
- brace-expansion: 2.0.1
-
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.1
@@ -23729,7 +23746,7 @@ snapshots:
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.13.1
- semver: 7.6.0
+ semver: 7.6.3
validate-npm-package-license: 3.0.4
normalize-path@3.0.0: {}
@@ -23994,8 +24011,6 @@ snapshots:
degenerator: 5.0.1
netmask: 2.0.2
- package-json-from-dist@1.0.0: {}
-
package-json-from-dist@1.0.1: {}
packet-reader@1.0.0: {}
@@ -25029,7 +25044,7 @@ snapshots:
rimraf@5.0.5:
dependencies:
- glob: 10.4.2
+ glob: 10.4.5
roarr@7.11.0:
dependencies: