0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

Merge pull request #6822 from logto-io/yemq-add-post-saml-app-api

feat(core): add `POST /saml-applications` and `DEL /saml-applications/:id` APIs
This commit is contained in:
Darcy Ye 2024-11-27 20:01:17 +08:00 committed by GitHub
commit 06fd450ab4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 619 additions and 113 deletions

3
.gitignore vendored
View file

@ -38,3 +38,6 @@ dump.rdb
# console auto generated files
/packages/console/src/consts/jwt-customizer-type-definition.ts
# Temporarily ignore SAML OpenAPI spec file (will be needed later)
packages/core/src/saml-applications/routes/index.openapi.json

View file

@ -80,6 +80,7 @@
"ky": "^1.2.3",
"lru-cache": "^11.0.0",
"nanoid": "^5.0.1",
"node-forge": "^1.3.1",
"oidc-provider": "^8.4.6",
"openapi-types": "^12.1.3",
"otplib": "^12.0.1",
@ -114,6 +115,7 @@
"@types/koa-send": "^4.1.3",
"@types/koa__cors": "^5.0.0",
"@types/node": "^20.9.5",
"@types/node-forge": "^1.3.1",
"@types/oidc-provider": "^8.4.4",
"@types/pluralize": "^0.0.33",
"@types/qrcode": "^1.5.2",

View file

@ -152,7 +152,7 @@ export default function applicationRoutes<T extends ManagementApiRouter>(
const { oidcClientMetadata, protectedAppMetadata, ...rest } = ctx.guard.body;
if (rest.type === ApplicationType.SAML) {
throw new RequestError('application.use_saml_app_api');
throw new RequestError('application.saml.use_saml_app_api');
}
await Promise.all([
@ -268,7 +268,7 @@ export default function applicationRoutes<T extends ManagementApiRouter>(
const pendingUpdateApplication = await queries.applications.findApplicationById(id);
if (pendingUpdateApplication.type === ApplicationType.SAML) {
throw new RequestError('application.use_saml_app_api');
throw new RequestError('application.saml.use_saml_app_api');
}
// @deprecated
@ -348,7 +348,7 @@ export default function applicationRoutes<T extends ManagementApiRouter>(
const { type, protectedAppMetadata } = await queries.applications.findApplicationById(id);
if (type === ApplicationType.SAML) {
throw new RequestError('application.use_saml_app_api');
throw new RequestError('application.saml.use_saml_app_api');
}
if (type === ApplicationType.Protected && protectedAppMetadata) {

View file

@ -7,6 +7,7 @@ import koaAuditLog from '#src/middleware/koa-audit-log.js';
import koaBodyEtag from '#src/middleware/koa-body-etag.js';
import { koaManagementApiHooks } from '#src/middleware/koa-management-api-hooks.js';
import koaTenantGuard from '#src/middleware/koa-tenant-guard.js';
import samlApplicationRoutes from '#src/saml-applications/routes/index.js';
import type TenantContext from '#src/tenants/TenantContext.js';
import koaAuth from '../middleware/koa-auth/index.js';
@ -99,6 +100,13 @@ const createRouters = (tenant: TenantContext) => {
systemRoutes(managementRouter, tenant);
subjectTokenRoutes(managementRouter, tenant);
accountCentersRoutes(managementRouter, tenant);
// TODO: @darcy per our design, we will move related routes to Cloud repo and the routes will be loaded from remote.
if (
(EnvSet.values.isDevFeaturesEnabled && EnvSet.values.isCloud) ||
EnvSet.values.isIntegrationTest
) {
samlApplicationRoutes(managementRouter, tenant);
}
const anonymousRouter: AnonymousRouter = new Router();

View file

@ -138,9 +138,7 @@ const validateSupplementPaths = (
if (
isKeyInObject(operation, 'tags') &&
Array.isArray(operation.tags) &&
!operation.tags.every(
(tag) => typeof tag === 'string' && [cloudOnlyTag, devFeatureTag].includes(tag)
)
!operation.tags.every((tag) => typeof tag === 'string' && reservedTags.has(tag))
) {
throw new TypeError(
`Cannot use \`tags\` in supplement document on path \`${path}\` and operation \`${method}\` except for tag \`${cloudOnlyTag}\` and \`${devFeatureTag}\`. Define tags in the document root instead.`

View file

@ -133,6 +133,9 @@ export const buildRouterObjects = <T extends UnknownRouter>(routers: T[], option
router.stack
// Filter out universal routes (mostly like a proxy route to withtyped)
.filter(({ path }) => !path.includes('.*'))
// TODO: Remove this and bring back `/saml-applications` routes before release.
// Exclude `/saml-applications` routes for now.
.filter(({ path }) => !path.startsWith('/saml-applications'))
.flatMap<RouteObject>(({ path: routerPath, stack, methods }) =>
methods
.map((method) => method.toLowerCase())

View file

@ -0,0 +1,34 @@
import { generateStandardId } from '@logto/shared';
import type Queries from '#src/tenants/Queries.js';
import { generateKeyPairAndCertificate } from './utils.js';
export const createSamlApplicationSecretsLibrary = (queries: Queries) => {
const {
samlApplicationSecrets: { insertSamlApplicationSecret },
} = queries;
const createSamlApplicationSecret = async (
applicationId: string,
// Set certificate life span to 1 year by default.
lifeSpanInDays = 365
) => {
const { privateKey, certificate, notAfter } = await generateKeyPairAndCertificate(
lifeSpanInDays
);
return insertSamlApplicationSecret({
id: generateStandardId(),
applicationId,
privateKey,
certificate,
expiresAt: Math.floor(notAfter.getTime() / 1000),
active: false,
});
};
return {
createSamlApplicationSecret,
};
};

View file

@ -0,0 +1,59 @@
import { addDays } from 'date-fns';
import forge from 'node-forge';
import { generateKeyPairAndCertificate } from './utils.js';
describe('generateKeyPairAndCertificate', () => {
it('should generate valid key pair and certificate', async () => {
const result = await generateKeyPairAndCertificate();
// Verify private key format
expect(result.privateKey).toContain('-----BEGIN RSA PRIVATE KEY-----');
expect(result.privateKey).toContain('-----END RSA PRIVATE KEY-----');
// Verify certificate format
expect(result.certificate).toContain('-----BEGIN CERTIFICATE-----');
expect(result.certificate).toContain('-----END CERTIFICATE-----');
// Verify expiration date (default 365 days)
const expectedNotAfter = addDays(new Date(), 365);
expect(result.notAfter.getDate()).toBe(expectedNotAfter.getDate());
expect(result.notAfter.getMonth()).toBe(expectedNotAfter.getMonth());
expect(result.notAfter.getFullYear()).toBe(expectedNotAfter.getFullYear());
// Verify certificate content
const cert = forge.pki.certificateFromPem(result.certificate);
expect(cert.subject.getField('CN').value).toBe('example.com');
expect(cert.issuer.getField('CN').value).toBe('logto.io');
expect(cert.issuer.getField('O').value).toBe('Logto');
expect(cert.issuer.getField('C').value).toBe('US');
});
it('should generate certificate with custom lifespan', async () => {
const customDays = 30;
const result = await generateKeyPairAndCertificate(customDays);
const expectedNotAfter = addDays(new Date(), customDays);
expect(result.notAfter.getDate()).toBe(expectedNotAfter.getDate());
expect(result.notAfter.getMonth()).toBe(expectedNotAfter.getMonth());
expect(result.notAfter.getFullYear()).toBe(expectedNotAfter.getFullYear());
});
it('should generate unique serial numbers for different certificates', async () => {
const result1 = await generateKeyPairAndCertificate();
const result2 = await generateKeyPairAndCertificate();
const cert1 = forge.pki.certificateFromPem(result1.certificate);
const cert2 = forge.pki.certificateFromPem(result2.certificate);
expect(cert1.serialNumber).not.toBe(cert2.serialNumber);
});
it('should generate RSA key pair with 4096 bits', async () => {
const result = await generateKeyPairAndCertificate();
const privateKey = forge.pki.privateKeyFromPem(result.privateKey);
// RSA key should be 4096 bits
expect(forge.pki.privateKeyToPem(privateKey).length).toBeGreaterThan(3000); // A 4096-bit RSA private key in PEM format is typically longer than 3000 characters
});
});

View file

@ -0,0 +1,58 @@
import crypto from 'node:crypto';
import { addDays } from 'date-fns';
import forge from 'node-forge';
export const generateKeyPairAndCertificate = async (lifeSpanInDays = 365) => {
const keypair = forge.pki.rsa.generateKeyPair({ bits: 4096 });
return createCertificate(keypair, lifeSpanInDays);
};
const createCertificate = (keypair: forge.pki.KeyPair, lifeSpanInDays: number) => {
const cert = forge.pki.createCertificate();
const notBefore = new Date();
const notAfter = addDays(notBefore, lifeSpanInDays);
// Can not initialize the certificate with the keypair directly, so we need to set the public key manually.
/* eslint-disable @silverhand/fp/no-mutation */
cert.publicKey = keypair.publicKey;
// Use cryptographically secure pseudorandom number generator (CSPRNG) to generate a random serial number (usually more than 8 bytes).
// `serialNumber` should be IDENTICAL across different certificates, better not to be incremental.
cert.serialNumber = crypto.randomBytes(16).toString('hex');
cert.validity.notBefore = notBefore;
cert.validity.notAfter = notAfter;
/* eslint-enable @silverhand/fp/no-mutation */
// TODO: read from tenant config or let user customize before downloading
const subjectAttributes: forge.pki.CertificateField[] = [
{
name: 'commonName',
value: 'example.com',
},
];
const issuerAttributes: forge.pki.CertificateField[] = [
{
name: 'commonName',
value: 'logto.io',
},
{
name: 'organizationName',
value: 'Logto',
},
{
name: 'countryName',
value: 'US',
},
];
cert.setSubject(subjectAttributes);
cert.setIssuer(issuerAttributes);
cert.sign(keypair.privateKey);
return {
privateKey: forge.pki.privateKeyToPem(keypair.privateKey),
certificate: forge.pki.certificateToPem(cert),
notAfter,
};
};

View file

@ -0,0 +1,30 @@
import { type SamlApplicationConfig, SamlApplicationConfigs } from '@logto/schemas';
import type { CommonQueryMethods } from '@silverhand/slonik';
import { sql } from '@silverhand/slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { buildUpdateWhereWithPool } from '#src/database/update-where.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(SamlApplicationConfigs);
export const createSamlApplicationConfigQueries = (pool: CommonQueryMethods) => {
const insertSamlApplicationConfig = buildInsertIntoWithPool(pool)(SamlApplicationConfigs, {
returning: true,
});
const updateSamlApplicationConfig = buildUpdateWhereWithPool(pool)(SamlApplicationConfigs, true);
const findSamlApplicationConfigByApplicationId = async (applicationId: string) =>
pool.maybeOne<SamlApplicationConfig>(sql`
select ${sql.join(Object.values(fields), sql`, `)}
from ${table}
where ${fields.applicationId}=${applicationId}
`);
return {
insertSamlApplicationConfig,
updateSamlApplicationConfig,
findSamlApplicationConfigByApplicationId,
};
};

View file

@ -0,0 +1,39 @@
import { SamlApplicationSecrets, type SamlApplicationSecret } from '@logto/schemas';
import type { CommonQueryMethods } from '@silverhand/slonik';
import { sql } from '@silverhand/slonik';
import { buildInsertIntoWithPool } from '#src/database/insert-into.js';
import { DeletionError } from '#src/errors/SlonikError/index.js';
import { convertToIdentifiers } from '#src/utils/sql.js';
const { table, fields } = convertToIdentifiers(SamlApplicationSecrets);
export const createSamlApplicationSecretsQueries = (pool: CommonQueryMethods) => {
const insertSamlApplicationSecret = buildInsertIntoWithPool(pool)(SamlApplicationSecrets, {
returning: true,
});
const findSamlApplicationSecretsByApplicationId = async (applicationId: string) =>
pool.any<SamlApplicationSecret>(sql`
select ${sql.join(Object.values(fields), sql`, `)}
from ${table}
where ${fields.applicationId}=${applicationId}
`);
const deleteSamlApplicationSecretById = async (id: string) => {
const { rowCount } = await pool.query(sql`
delete from ${table}
where ${fields.id} = ${id}
`);
if (rowCount < 1) {
throw new DeletionError(SamlApplicationSecrets.table);
}
};
return {
insertSamlApplicationSecret,
findSamlApplicationSecretsByApplicationId,
deleteSamlApplicationSecretById,
};
};

View file

@ -0,0 +1,94 @@
import {
ApplicationType,
samlApplicationCreateGuard,
samlApplicationResponseGuard,
} from '@logto/schemas';
import { generateStandardId } from '@logto/shared';
import { removeUndefinedKeys } from '@silverhand/essentials';
import { z } from 'zod';
import koaGuard from '#src/middleware/koa-guard.js';
import { buildOidcClientMetadata } from '#src/oidc/utils.js';
import { generateInternalSecret } from '#src/routes/applications/application-secret.js';
import type { ManagementApiRouter, RouterInitArgs } from '#src/routes/types.js';
import { ensembleSamlApplication, validateAcsUrl } from '#src/saml-applications/routes/utils.js';
import assertThat from '#src/utils/assert-that.js';
export default function samlApplicationRoutes<T extends ManagementApiRouter>(
...[router, { queries, libraries }]: RouterInitArgs<T>
) {
const {
applications: { insertApplication, findApplicationById, deleteApplicationById },
samlApplicationConfigs: { insertSamlApplicationConfig },
} = queries;
const {
samlApplicationSecrets: { createSamlApplicationSecret },
} = libraries;
router.post(
'/saml-applications',
koaGuard({
body: samlApplicationCreateGuard,
response: samlApplicationResponseGuard,
status: [201, 400],
}),
async (ctx, next) => {
const { name, description, customData, config } = ctx.guard.body;
if (config?.acsUrl) {
validateAcsUrl(config.acsUrl);
}
const application = await insertApplication(
removeUndefinedKeys({
id: generateStandardId(),
secret: generateInternalSecret(),
name,
description,
customData,
oidcClientMetadata: buildOidcClientMetadata(),
isThirdParty: true,
type: ApplicationType.SAML,
})
);
try {
const [samlConfig, _] = await Promise.all([
insertSamlApplicationConfig({
applicationId: application.id,
...config,
}),
createSamlApplicationSecret(application.id),
]);
ctx.status = 201;
ctx.body = ensembleSamlApplication({ application, samlConfig });
} catch (error) {
await deleteApplicationById(application.id);
throw error;
}
return next();
}
);
router.delete(
'/saml-applications/:id',
koaGuard({
params: z.object({ id: z.string() }),
status: [204, 400, 404],
}),
async (ctx, next) => {
const { id } = ctx.guard.params;
const { type } = await findApplicationById(id);
assertThat(type === ApplicationType.SAML, 'application.saml.saml_application_only');
await deleteApplicationById(id);
ctx.status = 204;
return next();
}
);
}

View file

@ -0,0 +1,42 @@
import {
type SamlApplicationResponse,
type Application,
type SamlApplicationConfig,
type SamlAcsUrl,
BindingType,
} from '@logto/schemas';
import RequestError from '#src/errors/RequestError/index.js';
import assertThat from '#src/utils/assert-that.js';
/**
* According to the design, a SAML app will be associated with multiple records from various tables.
* Therefore, when complete SAML app data is required, it is necessary to retrieve multiple related records and assemble them into a comprehensive SAML app dataset. This dataset includes:
* - A record from the `applications` table with a `type` of `SAML`
* - A record from the `saml_application_configs` table
*/
export const ensembleSamlApplication = ({
application,
samlConfig,
}: {
application: Application;
samlConfig: Pick<SamlApplicationConfig, 'attributeMapping' | 'entityId' | 'acsUrl'>;
}): SamlApplicationResponse => {
return {
...application,
...samlConfig,
};
};
/**
* Only HTTP-POST binding is supported for receiving SAML assertions at the moment.
*/
export const validateAcsUrl = (acsUrl: SamlAcsUrl) => {
assertThat(
acsUrl.binding === BindingType.POST,
new RequestError({
code: 'application.saml.acs_url_binding_not_supported',
status: 422,
})
);
};

View file

@ -17,6 +17,7 @@ import { createSocialLibrary } from '#src/libraries/social.js';
import { createSsoConnectorLibrary } from '#src/libraries/sso-connector.js';
import { createUserLibrary } from '#src/libraries/user.js';
import { createVerificationStatusLibrary } from '#src/libraries/verification-status.js';
import { createSamlApplicationSecretsLibrary } from '#src/saml-applications/libraries/secrets.js';
import type Queries from './Queries.js';
@ -37,6 +38,7 @@ export default class Libraries {
passcodes = createPasscodeLibrary(this.queries, this.connectors);
applications = createApplicationLibrary(this.queries);
verificationStatuses = createVerificationStatusLibrary(this.queries);
samlApplicationSecrets = createSamlApplicationSecretsLibrary(this.queries);
roleScopes = createRoleScopeLibrary(this.queries);
domains = createDomainLibrary(this.queries);
protectedApps = createProtectedAppLibrary(this.queries);

View file

@ -28,6 +28,8 @@ import UserSsoIdentityQueries from '#src/queries/user-sso-identities.js';
import { createUserQueries } from '#src/queries/user.js';
import { createUsersRolesQueries } from '#src/queries/users-roles.js';
import { createVerificationStatusQueries } from '#src/queries/verification-status.js';
import { createSamlApplicationConfigQueries } from '#src/saml-applications/queries/configs.js';
import { createSamlApplicationSecretsQueries } from '#src/saml-applications/queries/secrets.js';
import { AccountCenterQueries } from '../queries/account-center.js';
import { PersonalAccessTokensQueries } from '../queries/personal-access-tokens.js';
@ -60,6 +62,8 @@ export default class Queries {
ssoConnectors = new SsoConnectorQueries(this.pool);
userSsoIdentities = new UserSsoIdentityQueries(this.pool);
subjectTokens = createSubjectTokenQueries(this.pool);
samlApplicationSecrets = createSamlApplicationSecretsQueries(this.pool);
samlApplicationConfigs = createSamlApplicationConfigQueries(this.pool);
personalAccessTokens = new PersonalAccessTokensQueries(this.pool);
verificationRecords = new VerificationRecordQueries(this.pool);
accountCenters = new AccountCenterQueries(this.pool);

View file

@ -0,0 +1,13 @@
import { type SamlApplicationResponse, type CreateSamlApplication } from '@logto/schemas';
import { authedAdminApi } from './api.js';
export const createSamlApplication = async (createSamlApplication: CreateSamlApplication) =>
authedAdminApi
.post('saml-applications', {
json: createSamlApplication,
})
.json<SamlApplicationResponse>();
export const deleteSamlApplication = async (id: string) =>
authedAdminApi.delete(`saml-applications/${id}`);

View file

@ -37,7 +37,7 @@ describe('application APIs', () => {
it('should throw error when creating a SAML application', async () => {
await expectRejects(createApplication('test-create-saml-app', ApplicationType.SAML), {
code: 'application.use_saml_app_api',
code: 'application.saml.use_saml_app_api',
status: 400,
});
});
@ -54,6 +54,7 @@ describe('application APIs', () => {
expect(application.name).toBe(applicationName);
expect(application.type).toBe(ApplicationType.Traditional);
expect(application.isThirdParty).toBe(true);
await deleteApplication(application.id);
});

View file

@ -0,0 +1,68 @@
import { ApplicationType, BindingType } from '@logto/schemas';
import { createApplication, deleteApplication } from '#src/api/application.js';
import { createSamlApplication, deleteSamlApplication } from '#src/api/saml-application.js';
import { expectRejects } from '#src/helpers/index.js';
import { devFeatureTest } from '#src/utils.js';
const { it, describe } = devFeatureTest;
describe('SAML application', () => {
it('should create and delete a SAML application successfully', async () => {
const createdSamlApplication = await createSamlApplication({
name: 'test',
description: 'test',
});
await deleteSamlApplication(createdSamlApplication.id);
});
it('should not support HTTP-Redirect binding', async () => {
await expectRejects(
createSamlApplication({
name: 'test',
description: 'test',
config: {
acsUrl: {
binding: BindingType.REDIRECT,
url: 'https://example.com',
},
},
}),
{
code: 'application.saml.acs_url_binding_not_supported',
status: 422,
}
);
});
it('should be able to create SAML application with `config` field', async () => {
const config = {
entityId: 'https://example.logto.io',
acsUrl: {
binding: BindingType.POST,
url: 'https://example.logto.io/sso/saml',
},
};
const createdSamlApplication = await createSamlApplication({
name: 'test',
description: 'test',
config,
});
expect(createdSamlApplication.entityId).toEqual(config.entityId);
expect(createdSamlApplication.acsUrl).toEqual(config.acsUrl);
await deleteSamlApplication(createdSamlApplication.id);
});
it('can not delete non-SAML applications with `DEL /saml-applications/:id` API', async () => {
const application = await createApplication('test-non-saml-app', ApplicationType.Traditional, {
isThirdParty: true,
});
await expectRejects(deleteSamlApplication(application.id), {
code: 'application.saml.saml_application_only',
status: 400,
});
await deleteApplication(application.id);
});
});

View file

@ -10,7 +10,6 @@ const application = {
protected_app_metadata_is_required: 'Protected app metadata is required.',
protected_app_not_configured:
'Protected app provider is not configured. This feature is not available for open source version.',
use_saml_app_api: 'Use `[METHOD] /saml-applications(/.*)?` API to operate SAML app.',
cloudflare_unknown_error: 'Got unknown error when requesting Cloudflare API',
protected_application_only: 'The feature is only available for protected applications.',
protected_application_misconfigured: 'Protected application is misconfigured.',
@ -21,6 +20,12 @@ const application = {
should_delete_custom_domains_first: 'Should delete custom domains first.',
no_legacy_secret_found: 'The application does not have a legacy secret.',
secret_name_exists: 'Secret name already exists.',
saml: {
use_saml_app_api: 'Use `[METHOD] /saml-applications(/.*)?` API to operate SAML app.',
saml_application_only: 'The API is only available for SAML applications.',
acs_url_binding_not_supported:
'Only HTTP-POST binding is supported for receiving SAML assertions.',
},
};
export default Object.freeze(application);

View file

@ -30,3 +30,4 @@ export * from './onboarding.js';
export * from './sign-in-experience.js';
export * from './subject-token.js';
export * from './ssr.js';
export * from './saml-application.js';

View file

@ -0,0 +1,33 @@
import { type z } from 'zod';
import { Applications } from '../db-entries/application.js';
import { SamlApplicationConfigs } from '../db-entries/saml-application-config.js';
import { applicationCreateGuard } from './application.js';
const samlAppConfigGuard = SamlApplicationConfigs.guard.pick({
attributeMapping: true,
entityId: true,
acsUrl: true,
});
export const samlApplicationCreateGuard = applicationCreateGuard
.pick({
name: true,
description: true,
customData: true,
})
.extend({
// The reason for encapsulating attributeMapping and spMetadata into an object within the config field is that you cannot provide only one of `attributeMapping` or `spMetadata`. Due to the structure of the `saml_application_configs` table, both must be not null.
config: samlAppConfigGuard.partial().optional(),
});
export type CreateSamlApplication = z.infer<typeof samlApplicationCreateGuard>;
export const samlApplicationResponseGuard = Applications.guard.merge(
// Partial to allow the optional fields to be omitted in the response.
// When starting to create a SAML application, SAML configuration is optional, which can lead to the absence of SAML configuration.
samlAppConfigGuard
);
export type SamlApplicationResponse = z.infer<typeof samlApplicationResponseGuard>;

View file

@ -1,10 +1,6 @@
/* init_order = 2 */
/**
* The SAML application config and SAML-type application have a one-to-one correspondence:
* - a SAML-type application can only have one SAML application config
* - a SAML application config can only configure one SAML-type application
*/
/** The SAML application config and SAML-type application have a one-to-one correspondence: 1. a SAML-type application can only have one SAML application config. (CANNOT use "semicolon" in comments, since it indicates the end of query.) 2. a SAML application config can only configure one SAML-type application. */
create table saml_application_configs (
application_id varchar(21) not null
references applications (id) on update cascade on delete cascade,

View file

@ -44,7 +44,7 @@ importers:
version: 8.8.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.4.39)(typescript@5.0.2)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.0.2)(yaml@2.4.5)
typescript:
specifier: ^5.0.0
version: 5.0.2
@ -266,7 +266,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -333,7 +333,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -391,7 +391,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -449,7 +449,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -513,7 +513,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -577,7 +577,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -638,7 +638,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -705,7 +705,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -763,7 +763,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -821,7 +821,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -879,7 +879,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -937,7 +937,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -998,7 +998,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1068,7 +1068,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1129,7 +1129,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1184,7 +1184,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1242,7 +1242,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1300,7 +1300,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1358,7 +1358,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1419,7 +1419,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1477,7 +1477,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1535,7 +1535,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1593,7 +1593,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1651,7 +1651,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1709,7 +1709,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1767,7 +1767,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1825,7 +1825,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1883,7 +1883,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -1950,7 +1950,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2020,7 +2020,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2078,7 +2078,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2133,7 +2133,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2197,7 +2197,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2255,7 +2255,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2313,7 +2313,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2377,7 +2377,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2435,7 +2435,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2493,7 +2493,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2548,7 +2548,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2606,7 +2606,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2664,7 +2664,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -2722,7 +2722,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -3182,6 +3182,9 @@ importers:
nanoid:
specifier: ^5.0.1
version: 5.0.1
node-forge:
specifier: ^1.3.1
version: 1.3.1
oidc-provider:
specifier: ^8.4.6
version: 8.4.6
@ -3279,6 +3282,9 @@ importers:
'@types/node':
specifier: ^20.9.5
version: 20.10.4
'@types/node-forge':
specifier: ^1.3.1
version: 1.3.11
'@types/oidc-provider':
specifier: ^8.4.4
version: 8.4.4
@ -3305,7 +3311,7 @@ importers:
version: 8.57.0
jest:
specifier: ^29.7.0
version: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
version: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
jest-matcher-specific-error:
specifier: ^1.0.0
version: 1.0.0
@ -3335,7 +3341,7 @@ importers:
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -3504,7 +3510,7 @@ importers:
version: 3.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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
packages/experience:
devDependencies:
@ -3979,7 +3985,7 @@ importers:
version: 10.0.0
jest:
specifier: ^29.7.0
version: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
version: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
jest-matcher-specific-error:
specifier: ^1.0.0
version: 1.0.0
@ -4006,7 +4012,7 @@ importers:
version: 22.6.5(typescript@5.5.3)
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.4.39)(typescript@5.5.3)(yaml@2.4.5)
version: 8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5)
typescript:
specifier: ^5.5.3
version: 5.5.3
@ -7088,6 +7094,9 @@ packages:
'@types/node-fetch@2.6.2':
resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==}
'@types/node-forge@1.3.11':
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
@ -15868,7 +15877,7 @@ snapshots:
jest-util: 29.7.0
slash: 3.0.0
'@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))':
'@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.5.3))':
dependencies:
'@jest/console': 29.7.0
'@jest/reporters': 29.7.0
@ -15882,7 +15891,7 @@ snapshots:
exit: 0.1.2
graceful-fs: 4.2.11
jest-changed-files: 29.7.0
jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.5.3))
jest-haste-map: 29.7.0
jest-message-util: 29.7.0
jest-regex-util: 29.6.3
@ -15903,7 +15912,7 @@ snapshots:
- supports-color
- ts-node
'@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.5.3))':
'@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))':
dependencies:
'@jest/console': 29.7.0
'@jest/reporters': 29.7.0
@ -15917,7 +15926,7 @@ snapshots:
exit: 0.1.2
graceful-fs: 4.2.11
jest-changed-files: 29.7.0
jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.5.3))
jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
jest-haste-map: 29.7.0
jest-message-util: 29.7.0
jest-regex-util: 29.6.3
@ -17641,6 +17650,10 @@ snapshots:
'@types/node': 20.12.7
form-data: 3.0.2
'@types/node-forge@1.3.11':
dependencies:
'@types/node': 20.12.7
'@types/node@12.20.55': {}
'@types/node@20.10.4':
@ -19305,13 +19318,13 @@ snapshots:
dependencies:
lodash.get: 4.4.2
create-jest@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)):
create-jest@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)):
dependencies:
'@jest/types': 29.6.3
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.11
jest-config: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
jest-config: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
jest-util: 29.7.0
prompts: 2.4.2
transitivePeerDependencies:
@ -21725,16 +21738,16 @@ snapshots:
- babel-plugin-macros
- supports-color
jest-cli@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)):
jest-cli@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)):
dependencies:
'@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
'@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
chalk: 4.1.2
create-jest: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
create-jest: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
exit: 0.1.2
import-local: 3.1.0
jest-config: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
jest-config: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
jest-util: 29.7.0
jest-validate: 29.7.0
yargs: 17.7.2
@ -21763,7 +21776,7 @@ snapshots:
- supports-color
- ts-node
jest-config@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)):
jest-config@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)):
dependencies:
'@babel/core': 7.24.4
'@jest/test-sequencer': 29.7.0
@ -21789,38 +21802,7 @@ snapshots:
strip-json-comments: 3.1.1
optionalDependencies:
'@types/node': 20.10.4
ts-node: 10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
jest-config@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)):
dependencies:
'@babel/core': 7.24.4
'@jest/test-sequencer': 29.7.0
'@jest/types': 29.6.3
babel-jest: 29.7.0(@babel/core@7.24.4)
chalk: 4.1.2
ci-info: 3.8.0
deepmerge: 4.3.1
glob: 7.2.3
graceful-fs: 4.2.11
jest-circus: 29.7.0
jest-environment-node: 29.7.0
jest-get-type: 29.6.3
jest-regex-util: 29.6.3
jest-resolve: 29.7.0
jest-runner: 29.7.0
jest-util: 29.7.0
jest-validate: 29.7.0
micromatch: 4.0.5
parse-json: 5.2.0
pretty-format: 29.7.0
slash: 3.0.0
strip-json-comments: 3.1.1
optionalDependencies:
'@types/node': 20.12.7
ts-node: 10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)
ts-node: 10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
@ -21856,6 +21838,37 @@ snapshots:
- babel-plugin-macros
- supports-color
jest-config@29.7.0(@types/node@20.12.7)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)):
dependencies:
'@babel/core': 7.24.4
'@jest/test-sequencer': 29.7.0
'@jest/types': 29.6.3
babel-jest: 29.7.0(@babel/core@7.24.4)
chalk: 4.1.2
ci-info: 3.8.0
deepmerge: 4.3.1
glob: 7.2.3
graceful-fs: 4.2.11
jest-circus: 29.7.0
jest-environment-node: 29.7.0
jest-get-type: 29.6.3
jest-regex-util: 29.6.3
jest-resolve: 29.7.0
jest-runner: 29.7.0
jest-util: 29.7.0
jest-validate: 29.7.0
micromatch: 4.0.5
parse-json: 5.2.0
pretty-format: 29.7.0
slash: 3.0.0
strip-json-comments: 3.1.1
optionalDependencies:
'@types/node': 20.12.7
ts-node: 10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
jest-dev-server@10.1.1:
dependencies:
chalk: 4.1.2
@ -22164,12 +22177,12 @@ snapshots:
merge-stream: 2.0.0
supports-color: 8.1.1
jest@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3)):
jest@29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3)):
dependencies:
'@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
'@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
'@jest/types': 29.6.3
import-local: 3.1.0
jest-cli: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3))
jest-cli: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@ -25819,14 +25832,14 @@ snapshots:
ts-interface-checker@0.1.13: {}
ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.10.4)(typescript@5.5.3):
ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.5.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 20.10.4
'@types/node': 20.12.7
acorn: 8.13.0
acorn-walk: 8.3.4
arg: 4.1.3
@ -25840,14 +25853,14 @@ snapshots:
'@swc/core': 1.3.52(@swc/helpers@0.5.1)
optional: true
ts-node@10.9.2(@swc/core@1.3.52(@swc/helpers@0.5.1))(@types/node@20.12.7)(typescript@5.5.3):
ts-node@10.9.2(@swc/core@1.3.52)(@types/node@20.10.4)(typescript@5.5.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 20.12.7
'@types/node': 20.10.4
acorn: 8.13.0
acorn-walk: 8.3.4
arg: 4.1.3
@ -25884,7 +25897,7 @@ snapshots:
tsscmp@1.0.6: {}
tsup@8.3.0(@swc/core@1.3.52(@swc/helpers@0.5.1))(jiti@1.21.0)(postcss@8.4.39)(typescript@5.0.2)(yaml@2.4.5):
tsup@8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.0.2)(yaml@2.4.5):
dependencies:
bundle-require: 5.0.0(esbuild@0.23.1)
cac: 6.7.14
@ -25912,7 +25925,7 @@ snapshots:
- tsx
- yaml
tsup@8.3.0(@swc/core@1.3.52(@swc/helpers@0.5.1))(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5):
tsup@8.3.0(@swc/core@1.3.52)(jiti@1.21.0)(postcss@8.4.39)(typescript@5.5.3)(yaml@2.4.5):
dependencies:
bundle-require: 5.0.0(esbuild@0.23.1)
cac: 6.7.14