Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#IOPID-1449] enable strict=true on typescript config #307

Merged
merged 6 commits into from
Mar 6, 2024
2 changes: 1 addition & 1 deletion AbortUserDataProcessing/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export function AbortUserDataProcessingHandler(
)
),
// finally save the abortion
TE.chain(retrievedUserDataProcessing =>
TE.chainW(retrievedUserDataProcessing =>
pipe(
userDataProcessingModel.update({
...retrievedUserDataProcessing,
Expand Down
44 changes: 37 additions & 7 deletions GetServicePreferences/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as express from "express";

import * as O from "fp-ts/lib/Option";
import * as TE from "fp-ts/lib/TaskEither";
import * as t from "io-ts";

import { FiscalCode } from "@pagopa/io-functions-commons/dist/generated/definitions/FiscalCode";
import { ServiceId } from "@pagopa/io-functions-commons/dist/generated/definitions/ServiceId";
Expand All @@ -17,7 +18,10 @@ import {
ResponseErrorQuery
} from "@pagopa/io-functions-commons/dist/src/utils/response";

import { ProfileModel } from "@pagopa/io-functions-commons/dist/src/models/profile";
import {
Profile,
ProfileModel
} from "@pagopa/io-functions-commons/dist/src/models/profile";
import {
makeServicesPreferencesDocumentId,
ServicesPreferencesModel
Expand All @@ -35,7 +39,10 @@ import { ServicesPreferencesModeEnum } from "@pagopa/io-functions-commons/dist/g
import { NonNegativeInteger } from "@pagopa/ts-commons/lib/numbers";
import { pipe } from "fp-ts/lib/function";
import { sequenceS } from "fp-ts/lib/Apply";
import { ServiceModel } from "@pagopa/io-functions-commons/dist/src/models/service";
import {
Service,
ServiceModel
} from "@pagopa/io-functions-commons/dist/src/models/service";
import { ServiceCategory } from "@pagopa/io-functions-commons/dist/generated/definitions/ServiceCategory";
import { SpecialServiceCategoryEnum } from "@pagopa/io-functions-commons/dist/generated/definitions/SpecialServiceCategory";
import { ActivationModel } from "@pagopa/io-functions-commons/dist/src/models/activation";
Expand All @@ -57,6 +64,20 @@ type IGetServicePreferencesHandlerResult =
| IResponseErrorConflict
| IResponseErrorQuery;

const NonLegacyProfile = t.intersection([
Profile,
t.type({
servicePreferencesSettings: t.type({
mode: t.union([
t.literal(ServicesPreferencesModeEnum.AUTO),
t.literal(ServicesPreferencesModeEnum.MANUAL)
]),
version: NonNegativeInteger
})
})
]);
type NonLegacyProfile = t.TypeOf<typeof NonLegacyProfile>;

/**
* Type of a GetServicePreferences handler.
*
Expand Down Expand Up @@ -125,6 +146,8 @@ const getUserServicePreferencesOrDefault = (
return toDefaultEnabledUserServicePreference(version);
case ServicesPreferencesModeEnum.MANUAL:
return toDefaultDisabledUserServicePreference(version);
default:
return void 0 as never;
arcogabbo marked this conversation as resolved.
Show resolved Hide resolved
}
},
pref => toUserServicePreferenceFromModel(pref)
Expand Down Expand Up @@ -154,11 +177,18 @@ export const GetServicePreferencesHandler = (
profile: getProfileOrErrorResponse(profileModel)(fiscalCode),
service: getServiceOrErrorResponse(serviceModel)(serviceId)
}),
TE.filterOrElseW(
({ profile }) => nonLegacyServicePreferences(profile),
() => ResponseErrorConflict("Legacy service preferences not allowed")
TE.chainW(
TE.fromPredicate(
(
entities
): entities is {
readonly profile: NonLegacyProfile;
readonly service: Service;
} => nonLegacyServicePreferences(entities.profile),
() => ResponseErrorConflict("Legacy service preferences not allowed")
)
),
TE.chain(({ profile, service }) =>
TE.chainW(({ profile, service }) =>
pipe(
getServicePreferenceSettingsVersion(profile),
TE.mapLeft(_ =>
Expand All @@ -174,7 +204,7 @@ export const GetServicePreferencesHandler = (
)
),
TE.chainW(getUserServicePreferencesOrDefault(servicePreferencesModel)),
TE.chain(({ serviceCategory, servicePreferences }) => {
TE.chainW(({ serviceCategory, servicePreferences }) => {
if (serviceCategory === SpecialServiceCategoryEnum.SPECIAL) {
return getServicePreferencesForSpecialServices(activationModel)({
fiscalCode,
Expand Down
12 changes: 7 additions & 5 deletions MigrateServicePreferenceFromLegacy/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ export const createServicePreference = (

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export const blockedsToServicesPreferences = (
blocked: {
// eslint-disable-next-line functional/prefer-readonly-type, @typescript-eslint/array-type
[x: string]: readonly BlockedInboxOrChannelEnum[];
},
blocked:
| {
// eslint-disable-next-line functional/prefer-readonly-type, @typescript-eslint/array-type
[x: string]: readonly BlockedInboxOrChannelEnum[];
}
| undefined,
fiscalCode: FiscalCode,
version: NonNegativeInteger
) =>
Expand All @@ -91,7 +93,7 @@ export const blockedsToServicesPreferences = (
)
)
),
O.getOrElse(() => [])
O.getOrElseW(() => [])
);

export const MigrateServicePreferenceFromLegacy = (
Expand Down
10 changes: 5 additions & 5 deletions OnProfileUpdate/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ interface IDependencies {
readonly dataTableProfileEmailsRepository: IProfileEmailReader &
IProfileEmailWriter;
readonly profileModel: ProfileModel;
readonly telemetryClient: TelemetryClient;
readonly telemetryClient?: TelemetryClient;
}

const eventNamePrefix = "OnProfileUpdate";
Expand Down Expand Up @@ -190,7 +190,7 @@ const handleMissingEmail = (
O.fold(
() => TE.right(void 0),
previousEmail => {
dependencies.telemetryClient.trackEvent({
dependencies.telemetryClient?.trackEvent({
name: `${eventNamePrefix}.missingNewEmail`,
properties: {
_self: profile._self,
Expand Down Expand Up @@ -236,7 +236,7 @@ const handlePositiveVersion = ({
() =>
pipe(
RTE.asks(({ telemetryClient }: IDependencies) =>
telemetryClient.trackEvent({
telemetryClient?.trackEvent({
name: `${eventNamePrefix}.previousProfileNotFound`,
properties: {
_self,
Expand Down Expand Up @@ -290,7 +290,7 @@ export const handler = (documents: ReadonlyArray<unknown>) => (
ProfileDocument.decode,
E.foldW(
() => {
dependencies.telemetryClient.trackEvent({
dependencies.telemetryClient?.trackEvent({
name: `${eventNamePrefix}.decodingProfile`,
properties: {
_self:
Expand All @@ -309,7 +309,7 @@ export const handler = (documents: ReadonlyArray<unknown>) => (
dependencies,
handleProfile(profileDocument),
TE.mapLeft(error => {
dependencies.telemetryClient.trackEvent({
dependencies.telemetryClient?.trackEvent({
name: `${eventNamePrefix}.handlingProfile`,
properties: {
_self: profileDocument._self,
Expand Down
6 changes: 3 additions & 3 deletions SendTemplatedLoginEmailActivity/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ export const getSendLoginEmailActivityHandler = (
});
}),
E.bindTo("activityInput"),
E.bind("maybeMagicLink", ({ activityInput }) =>
E.bindW("maybeMagicLink", ({ activityInput }) =>
pipe(activityInput.magic_link, O.fromNullable, E.of)
),
E.bind("emailHtml", ({ activityInput, maybeMagicLink }) =>
E.bindW("emailHtml", ({ activityInput, maybeMagicLink }) =>
pipe(
maybeMagicLink,
O.fold(
Expand Down Expand Up @@ -115,7 +115,7 @@ export const getSendLoginEmailActivityHandler = (
E.of(HtmlToText.fromString(emailHtml, emailDefaults.htmlToTextOptions))
),
TE.fromEither,
TE.chain(({ activityInput, emailHtml, emailText }) =>
TE.chainW(({ activityInput, emailHtml, emailText }) =>
pipe(
sendMail(mailerTransporter, {
from: emailDefaults.from,
Expand Down
6 changes: 3 additions & 3 deletions SendWelcomeMessagesActivity/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,23 @@ const welcomeMessages: WelcomeMessages = {
NewMessage.decode({
content: welcomeMessageContent
}),
E.getOrElse(throwInvalidMessageError)
E.getOrElseW(throwInvalidMessageError)
),
// eslint-disable-next-line sort-keys
HOWTO: (_: RetrievedProfile) =>
pipe(
NewMessage.decode({
content: howToContent
}),
E.getOrElse(throwInvalidMessageError)
E.getOrElseW(throwInvalidMessageError)
),
// eslint-disable-next-line sort-keys
CASHBACK: (_: RetrievedProfile) =>
pipe(
NewMessage.decode({
content: cashbackContent
}),
E.getOrElse(throwInvalidMessageError)
E.getOrElseW(throwInvalidMessageError)
)
};

Expand Down
14 changes: 12 additions & 2 deletions StartEmailValidationProcess/__tests__/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ describe("StartEmailValidationProcessHandler", () => {
it("should start the orchestrator with the right input and return an accepted response", async () => {
const profileModelMock = {
findLastVersionByModelId: jest.fn(() =>
taskEither.of(some({ ...aRetrievedProfile, isEmailValidated: false }))
taskEither.of(
some({
...aRetrievedProfile,
isEmailValidated: false
})
)
)
};
mockStartNew.mockImplementationOnce(() => Promise.resolve("start"));
Expand All @@ -51,7 +56,12 @@ describe("StartEmailValidationProcessHandler", () => {
it("should not start a new orchestrator if there is an already running orchestrator and return an accepted response", async () => {
const profileModelMock = {
findLastVersionByModelId: jest.fn(() =>
taskEither.of(some({ ...aRetrievedProfile, isEmailValidated: false }))
taskEither.of(
some({
...aRetrievedProfile,
isEmailValidated: false
})
)
)
};

Expand Down
9 changes: 9 additions & 0 deletions StartEmailValidationProcess/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ export function StartEmailValidationProcessHandler(

const { email } = existingProfile;

// The API is available, but the client should never permit to call it
// when the email is undefined. The corner case is handled returning
// an Internal Server Error.
if (email === undefined) {
return ResponseErrorInternal(
"Unexpected missing email inside the user Profile"
);
}

// Start a orchestrator that handles the email validation process.
context.log.verbose(
`${logPrefix}|Starting the email validation with template process`
Expand Down
5 changes: 3 additions & 2 deletions UpdateProfile/__tests__/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ describe("UpdateProfileHandler", () => {
expect(result.value).toEqual(
expect.objectContaining({
service_preferences_settings: {
mode: autoApiProfileServicePreferencesSettings.mode,
mode: ServicesPreferencesModeEnum.AUTO,
version: expectedServicePreferencesSettingsVersion
}
})
Expand Down Expand Up @@ -718,7 +718,8 @@ describe("UpdateProfileHandler", () => {
isWebhookEnabled,
expectedIsInboxEnabled,
expectedIsWebHookEnabled,
acceptedTosVersion
acceptedTosVersion,
_
) => {
const profileModelMock = {
findLastVersionByModelId: jest.fn(() =>
Expand Down
5 changes: 2 additions & 3 deletions UpdateProfile/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export function UpdateProfileHandler(
}

// eslint-disable-next-line functional/no-let
let emailTaken: boolean;
let emailTaken: boolean | undefined;

// Check if the email has been changed
const emailChanged =
Expand Down Expand Up @@ -215,7 +215,7 @@ export function UpdateProfileHandler(
const profile = apiProfileToProfile(
profilePayload,
fiscalCode,
emailChanged ? false : existingProfile.isEmailValidated,
emailChanged ? false : existingProfile.isEmailValidated ?? false,
servicePreferencesSettingsVersion
);

Expand Down Expand Up @@ -334,7 +334,6 @@ export function UpdateProfileHandler(
)
)();
}

return ResponseSuccessJson(
retrievedProfileToExtendedProfile(updateProfile, emailTaken)
);
Expand Down
2 changes: 1 addition & 1 deletion UpdateSubscriptionsFeedActivity/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export const updateSubscriptionFeed = async (
];
}, [] as ReadonlyArray<SubscriptionFeedEntitySelector>)
),
O.getOrElse(() => [])
O.getOrElseW(() => [])
);

const allowInsertIfDeleted = decodedInput.subscriptionKind !== "SERVICE";
Expand Down
10 changes: 5 additions & 5 deletions UpsertServicePreferences/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ type IUpsertServicePreferencesHandler = (
context: Context,
fiscalCode: FiscalCode,
serviceId: ServiceId,
servicePreference: ServicePreference
servicePreference: UpsertServicePreference
) => Promise<IUpsertServicePreferencesHandlerResult>;

/**
Expand Down Expand Up @@ -199,7 +199,7 @@ const getFeedOperation = (
* Return a type safe GetServicePreferences handler.
*/
export const GetUpsertServicePreferencesHandler = (
telemetryClient: ReturnType<typeof initAppInsights>,
telemetryClient: ReturnType<typeof initAppInsights> | undefined,
profileModels: ProfileModel,
serviceModels: ServiceModel,
servicePreferencesModel: ServicesPreferencesModel,
Expand All @@ -220,7 +220,7 @@ export const GetUpsertServicePreferencesHandler = (
({ profile }) => nonLegacyServicePreferences(profile),
() => ResponseErrorConflict("Legacy service preferences not allowed")
),
TE.filterOrElse(
TE.filterOrElseW(
({ profile }) =>
servicePreference.settings_version ===
profile.servicePreferencesSettings.version,
Expand All @@ -229,7 +229,7 @@ export const GetUpsertServicePreferencesHandler = (
"Setting Preferences version not compatible with Profile's one"
)
),
TE.chain(({ profile, service }) =>
TE.chainW(({ profile, service }) =>
pipe(
profile,
getServicePreferenceSettingsVersion,
Expand Down Expand Up @@ -376,7 +376,7 @@ export const GetUpsertServicePreferencesHandler = (
*/
// eslint-disable-next-line max-params, prefer-arrow/prefer-arrow-functions
export function UpsertServicePreferences(
telemetryClient: ReturnType<typeof initAppInsights>,
telemetryClient: ReturnType<typeof initAppInsights> | undefined,
profileModels: ProfileModel,
serviceModels: ServiceModel,
servicePreferencesModel: ServicesPreferencesModel,
Expand Down
Loading
Loading