0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00
logto/packages/schemas/alterations/1.0.0_beta.18-1669702299-sign-up.ts
2023-01-06 16:48:18 +08:00

124 lines
3.2 KiB
TypeScript

import { isSameArray } from '@silverhand/essentials';
import type { DatabaseTransactionConnection } from 'slonik';
import { sql } from 'slonik';
import type { AlterationScript } from '../lib/types/alteration.js';
enum DeprecatedSignUpIdentifier {
Email = 'email',
Sms = 'sms',
Username = 'username',
EmailOrSms = 'emailOrSms',
None = 'none',
}
type DeprecatedSignUp = {
identifier: DeprecatedSignUpIdentifier;
password: boolean;
verify: boolean;
};
type DeprecatedSignInExperience = {
id: string;
signUp: DeprecatedSignUp;
};
enum SignInIdentifier {
Username = 'username',
Email = 'email',
Sms = 'sms',
}
type SignUp = {
identifiers: SignInIdentifier[];
password: boolean;
verify: boolean;
};
type SignInExperience = {
id: string;
signUp: SignUp;
};
const signUpIdentifierMapping: {
[key in DeprecatedSignUpIdentifier]: SignInIdentifier[];
} = {
[DeprecatedSignUpIdentifier.Email]: [SignInIdentifier.Email],
[DeprecatedSignUpIdentifier.Sms]: [SignInIdentifier.Sms],
[DeprecatedSignUpIdentifier.Username]: [SignInIdentifier.Username],
[DeprecatedSignUpIdentifier.EmailOrSms]: [SignInIdentifier.Email, SignInIdentifier.Sms],
[DeprecatedSignUpIdentifier.None]: [],
};
const mapDeprecatedSignUpIdentifierToIdentifiers = (signUpIdentifier: DeprecatedSignUpIdentifier) =>
signUpIdentifierMapping[signUpIdentifier];
const alterSignUp = async (
signInExperience: DeprecatedSignInExperience,
pool: DatabaseTransactionConnection
) => {
const {
id,
signUp: { identifier, ...signUpSettings },
} = signInExperience;
const signUpIdentifiers = mapDeprecatedSignUpIdentifierToIdentifiers(identifier);
const signUp: SignUp = {
identifiers: signUpIdentifiers,
...signUpSettings,
};
await pool.query(
sql`update sign_in_experiences set sign_up = ${JSON.stringify(signUp)} where id = ${id}`
);
};
const mapIdentifiersToDeprecatedSignUpIdentifier = (
identifiers: SignInIdentifier[]
): DeprecatedSignUpIdentifier => {
for (const [key, mappedIdentifiers] of Object.entries(signUpIdentifierMapping)) {
if (isSameArray(identifiers, mappedIdentifiers)) {
// eslint-disable-next-line no-restricted-syntax
return key as DeprecatedSignUpIdentifier;
}
}
throw new Error('Invalid identifiers in the sign up settings.');
};
const rollbackSignUp = async (
signInExperience: SignInExperience,
pool: DatabaseTransactionConnection
) => {
const {
id,
signUp: { identifiers, ...signUpSettings },
} = signInExperience;
const signUpIdentifier = mapIdentifiersToDeprecatedSignUpIdentifier(identifiers);
const signUp: DeprecatedSignUp = {
identifier: signUpIdentifier,
...signUpSettings,
};
await pool.query(
sql`update sign_in_experiences set sign_up = ${JSON.stringify(signUp)} where id = ${id}`
);
};
const alteration: AlterationScript = {
up: async (pool) => {
const rows = await pool.many<DeprecatedSignInExperience>(
sql`select * from sign_in_experiences`
);
await Promise.all(rows.map(async (row) => alterSignUp(row, pool)));
},
down: async (pool) => {
const rows = await pool.many<SignInExperience>(sql`select * from sign_in_experiences`);
await Promise.all(rows.map(async (row) => rollbackSignUp(row, pool)));
},
};
export default alteration;