From edf235a644421894d7af8c818fd4c82ef98284f0 Mon Sep 17 00:00:00 2001 From: Ethan Gardner Date: Fri, 10 Jan 2025 11:39:48 -0500 Subject: [PATCH 1/4] Add jsdoc comments to forms package (#426) * add jsdoc comments for the forms package builder, context, and repository files * add jsdoc comments to forms package * Update packages/forms/src/builder/index.ts Co-authored-by: Daniel Naab --------- Co-authored-by: Daniel Naab --- packages/forms/src/blueprint.ts | 56 +++++++++++++++++++ packages/forms/src/builder/index.ts | 5 ++ packages/forms/src/builder/parse-form.ts | 3 + packages/forms/src/components.ts | 5 ++ .../forms/src/context/browser/form-repo.ts | 19 +++++++ .../forms/src/context/browser/session-repo.ts | 3 + packages/forms/src/pattern.ts | 45 +++++++++++++++ packages/forms/src/repository/add-document.ts | 3 + packages/forms/src/repository/add-form.ts | 3 + packages/forms/src/repository/delete-form.ts | 3 + packages/forms/src/repository/get-document.ts | 3 + .../forms/src/repository/get-form-list.ts | 3 + .../forms/src/repository/get-form-session.ts | 8 ++- packages/forms/src/repository/get-form.ts | 3 + packages/forms/src/repository/save-form.ts | 9 ++- .../src/repository/upsert-form-session.ts | 3 + packages/forms/src/services/add-form.ts | 4 ++ packages/forms/src/services/delete-form.ts | 4 ++ packages/forms/src/services/get-form-list.ts | 4 ++ .../forms/src/services/get-form-session.ts | 4 ++ packages/forms/src/services/get-form.ts | 4 ++ packages/forms/src/services/index.ts | 5 ++ .../forms/src/services/initialize-form.ts | 4 ++ packages/forms/src/services/save-form.ts | 4 ++ packages/forms/src/services/submit-form.ts | 7 +++ packages/forms/src/session.ts | 26 +++++++++ packages/forms/src/submission.ts | 7 +++ packages/forms/src/util/base64.ts | 17 ++++++ packages/forms/src/util/zod.ts | 16 ++++++ 29 files changed, 278 insertions(+), 2 deletions(-) diff --git a/packages/forms/src/blueprint.ts b/packages/forms/src/blueprint.ts index 4bcfae758..d7c7a2bd2 100644 --- a/packages/forms/src/blueprint.ts +++ b/packages/forms/src/blueprint.ts @@ -33,6 +33,9 @@ export const nullBlueprint: Blueprint = { outputs: [], }; +/** + * Creates an empty blueprint with 1 page to start a form from scratch. + */ export const createOnePageBlueprint = (): Blueprint => { const page1 = generatePatternId(); return { @@ -62,6 +65,9 @@ export const createOnePageBlueprint = (): Blueprint => { }; }; +/** + * Creates a form blueprint based on the provided summary and initial configuration. + */ export const createForm = ( summary: FormSummary, initial: { @@ -88,10 +94,16 @@ export const createForm = ( }; }; +/** + * Retrieves the root pattern from a Blueprint object. The root pattern is the page set data type. + */ export const getRootPattern = (form: Blueprint) => { return form.patterns[form.root]; }; +/** + * Updates the form object by adding new patterns and optionally setting a new root pattern. + */ export const addPatternMap = ( form: Blueprint, patterns: PatternMap, @@ -104,6 +116,9 @@ export const addPatternMap = ( }; }; +/** + * Adds multiple patterns to the given form. Primarily intended for bulk operations like the document import feature. + */ export const addPatterns = ( form: Blueprint, patterns: Pattern[], @@ -113,6 +128,9 @@ export const addPatterns = ( return addPatternMap(form, formPatternMap, root); }; +/** + * Adds a pattern to a specific page within the blueprint at the specified index or at the end if no index is provided. + */ export const addPatternToPage = ( bp: Blueprint, pagePatternId: PatternId, @@ -152,6 +170,10 @@ export const addPatternToPage = ( }; }; +/** + * Moves a pattern from one page to another within a blueprint or repositions it + * within the same page based on the specified position. + */ export const movePatternBetweenPages = ( bp: Blueprint, sourcePageId: PatternId, @@ -230,6 +252,13 @@ export const movePatternBetweenPages = ( }; }; +/** + * Copies a pattern from a blueprint by creating a duplicate with a new ID. + * + * Depending on the type of pattern, specific properties + * such as title, label, text, or legend are modified to indicate a copy, + * including a timestamp in their names/descriptions. + */ export const copyPattern = ( bp: Blueprint, parentPatternId: PatternId, @@ -396,6 +425,11 @@ export const copyPattern = ( return { bp: updatedBp, pattern: newPattern }; }; +/** + * Adds a new pattern to an existing fieldset pattern within a blueprint. + * If an index is specified, the pattern is inserted at that position within the fieldset's patterns. + * Otherwise, the pattern is appended to the end of the fieldset's patterns. + */ export const addPatternToFieldset = ( bp: Blueprint, fieldsetPatternId: PatternId, @@ -435,6 +469,13 @@ export const addPatternToFieldset = ( }; }; +/** + * Adds a new pattern (page) to the `pageSet` of a given blueprint. + * + * This function takes a blueprint and a pattern as arguments, adds the pattern + * to the `pages` property of the root page set within the blueprint, and returns + * an updated blueprint with the modifications. + */ export const addPageToPageSet = ( bp: Blueprint, pattern: Pattern @@ -458,6 +499,9 @@ export const addPageToPageSet = ( }; }; +/** + * Replaces the patterns in a given blueprint with a new set of patterns. + */ export const replacePatterns = ( form: Blueprint, patterns: Pattern[] @@ -474,6 +518,9 @@ export const replacePatterns = ( }; }; +/** + * Updates the patterns within a form's blueprint using the provided configuration and new patterns map. + */ export const updatePatterns = ( config: FormConfig, form: Blueprint, @@ -493,6 +540,9 @@ export const updatePatterns = ( }; }; +/** + * Adds a new form output to an existing blueprint. + */ export const addFormOutput = ( form: Blueprint, document: FormOutput @@ -503,6 +553,9 @@ export const addFormOutput = ( }; }; +/** + * Updates the summary of a given form with the provided summary details. + */ export const updateFormSummary = ( form: Blueprint, summary: FormSummary @@ -513,6 +566,9 @@ export const updateFormSummary = ( }; }; +/** + * Removes a specified pattern and its references from the blueprint. + */ export const removePatternFromBlueprint = ( config: FormConfig, blueprint: Blueprint, diff --git a/packages/forms/src/builder/index.ts b/packages/forms/src/builder/index.ts index 74323ccb9..b6462d402 100644 --- a/packages/forms/src/builder/index.ts +++ b/packages/forms/src/builder/index.ts @@ -25,6 +25,11 @@ import { type PageSetPattern } from '../patterns/page-set/config.js'; import type { Blueprint, FormSummary } from '../types.js'; import type { ParsedPdf } from '../documents/pdf/parsing-api.js'; +/** + * Constructs and manipulates a Blueprint object for forms. A Blueprint + * defines the structure of a form. The `BuildprintBuilder` provides methods to dynamically + * modify pages, patterns, field sets, and documents within a hierarchical form structure. + */ export class BlueprintBuilder { bp: Blueprint; diff --git a/packages/forms/src/builder/parse-form.ts b/packages/forms/src/builder/parse-form.ts index ea86f1f24..0ca814084 100644 --- a/packages/forms/src/builder/parse-form.ts +++ b/packages/forms/src/builder/parse-form.ts @@ -4,6 +4,9 @@ import { failure, success, type Result } from '@atj/common'; import type { FormConfig } from '../pattern'; import type { Blueprint } from '../types'; +/** + * Parses and validates an object against a form schema defined by the given configuration. + */ export const parseForm = (config: FormConfig, obj: any): Result => { const formSchema = createFormSchema(config); const result = formSchema.safeParse(obj); diff --git a/packages/forms/src/components.ts b/packages/forms/src/components.ts index a3da04802..00cec014d 100644 --- a/packages/forms/src/components.ts +++ b/packages/forms/src/components.ts @@ -241,6 +241,11 @@ export type CreatePrompt = ( options: { validate: boolean } ) => PromptComponent; +/** + * This variable is a function that generates a prompt based on the provided pattern configuration. + * It accepts a specific configuration, session, pattern, and additional options needed to create the prompt. + * A prompt defines what is presented to the end user. + */ export const createPromptForPattern: CreatePrompt = ( config, session, diff --git a/packages/forms/src/context/browser/form-repo.ts b/packages/forms/src/context/browser/form-repo.ts index 9e4107db5..589ef6dd3 100644 --- a/packages/forms/src/context/browser/form-repo.ts +++ b/packages/forms/src/context/browser/form-repo.ts @@ -22,6 +22,10 @@ const getFormIdFromKey = (key: string) => { const formSessionKey = (sessionId: string) => `formSessions/${sessionId}`; //const isFormSessionKey = (key: string) => key.startsWith('formSessions/'); +/** + * Repository for managing forms, form sessions, and associated documents in the browser storage. + * Provides functionality for CRUD operations on forms, form sessions, and documents. + */ export class BrowserFormRepository implements FormRepository { constructor(private storage: Storage) {} @@ -176,6 +180,11 @@ export class BrowserFormRepository implements FormRepository { } } +/** + * Retrieves a list of form IDs stored in the provided storage object. + * + * @param {Storage} storage - The storage object to retrieve form keys from. + */ export const getFormList = (storage: Storage) => { const keys = []; for (let i = 0; i < storage.length; i++) { @@ -191,6 +200,16 @@ export const getFormList = (storage: Storage) => { return keys; }; +/** + * Saves a form object to a provided storage mechanism with a specified form ID as the key. + * + * This function serializes the provided form object into JSON and stores it + * in the given storage using the form ID transformed by `formKey` as the key. + * + * @param {Storage} storage - The storage mechanism where the form data will be saved. + * @param {string} formId - The unique identifier for the form, used as the key in storage. + * @param {Blueprint} form - The form object to be saved in storage. + */ export const saveForm = (storage: Storage, formId: string, form: Blueprint) => { try { storage.setItem(formKey(formId), JSON.stringify(form)); diff --git a/packages/forms/src/context/browser/session-repo.ts b/packages/forms/src/context/browser/session-repo.ts index cff4590fa..552cdb9f1 100644 --- a/packages/forms/src/context/browser/session-repo.ts +++ b/packages/forms/src/context/browser/session-repo.ts @@ -1,6 +1,9 @@ import { type Result, type VoidResult } from '@atj/common'; import { type FormSession } from '../../index.js'; +/** + * Adds a form session to the specified storage and returns a unique identifier for the session. + */ export const addFormToStorage = ( storage: Storage, session: FormSession diff --git a/packages/forms/src/pattern.ts b/packages/forms/src/pattern.ts index 36c337ca6..e552f36b7 100644 --- a/packages/forms/src/pattern.ts +++ b/packages/forms/src/pattern.ts @@ -46,6 +46,9 @@ export abstract class PatternBuilder

{ abstract toPattern(): P; } +/** + * Retrieves a specific pattern from the given blueprint using its unique identifier. + */ export const getPattern = ( form: Blueprint, id: PatternId @@ -53,6 +56,10 @@ export const getPattern = ( return form.patterns[id] as T; }; +/** + * Retrieves a pattern of a specific type safely from a blueprint form. + * Validates if the pattern exists and if its type matches the specified type. + */ export const getPatternSafely =

(opts: { type: string; form: Blueprint; @@ -70,6 +77,10 @@ export const getPatternSafely =

(opts: { return r.success(pattern as P); }; +/** + * Updates the `patterns` property of a given Blueprint object by adding or replacing + * a Pattern object with the specified ID. + */ export const updatePattern = (form: Blueprint, pattern: Pattern): Blueprint => { return { ...form, @@ -101,6 +112,9 @@ export type FormConfig = { patterns: Record>; }; +/** + * Constructs a map from an array of patterns, using each pattern's `id` as the key. + */ export const getPatternMap = (patterns: Pattern[]) => { return Object.fromEntries( patterns.map(pattern => { @@ -109,6 +123,9 @@ export const getPatternMap = (patterns: Pattern[]) => { ); }; +/** + * Retrieves the pattern configuration for a specified element type from the given form configuration. + */ export const getPatternConfig = ( config: FormConfig, elementType: Pattern['type'] @@ -116,6 +133,9 @@ export const getPatternConfig = ( return config.patterns[elementType]; }; +/** + * Validates a given value against a specified pattern using the provided pattern configuration. + */ export const validatePattern = ( patternConfig: PatternConfig, pattern: Pattern, @@ -146,6 +166,11 @@ const aggregateValuesByPrefix = ( return aggregatedValues; }; +/** + * Processes and aggregates values and errors for a given pattern and its children within a session. + * This function ensures that user input is parsed and validated per pattern configuration and + * recursively handles child patterns within the associated form. + */ export const aggregatePatternSessionValues = ( config: FormConfig, form: Blueprint, @@ -185,6 +210,10 @@ export const aggregatePatternSessionValues = ( return result; }; +/** + * Retrieves the first pattern from a form blueprint based on the specified configuration + * and the provided or default starting pattern. + */ export const getFirstPattern = ( config: FormConfig, form: Blueprint, @@ -201,6 +230,10 @@ export const getFirstPattern = ( return getFirstPattern(config, form, children[0]); }; +/** + * Updates a specific pattern in a form blueprint by parsing the provided form data and + * applying the updated pattern configuration to the form. + */ export const updatePatternFromFormData = ( config: FormConfig, form: Blueprint, @@ -222,8 +255,14 @@ export const updatePatternFromFormData = ( }; }; +/** + * Generates a unique identifier string using the `crypto.randomUUID` method. + */ export const generatePatternId = () => crypto.randomUUID(); +/** + * Generates a default pattern object based on the provided configuration and pattern type. + */ export const createDefaultPattern = ( config: FormConfig, patternType: string @@ -235,6 +274,9 @@ export const createDefaultPattern = ( }; }; +/** + * Creates a new pattern instance based on the provided configuration, pattern type, config data, and optionally a pattern ID. + */ export const createPattern = ( config: FormConfig, patternType: keyof FormConfig['patterns'], @@ -254,6 +296,9 @@ export const createPattern = ( } as T); }; +/** + * A function that removes a child pattern from a given pattern within a configuration. + */ export const removeChildPattern = ( config: FormConfig, pattern: Pattern, diff --git a/packages/forms/src/repository/add-document.ts b/packages/forms/src/repository/add-document.ts index 7945cb6e8..7c4842f5e 100644 --- a/packages/forms/src/repository/add-document.ts +++ b/packages/forms/src/repository/add-document.ts @@ -16,6 +16,9 @@ export type AddDocument = ( } ) => Promise>; +/** + * Asynchronously adds a document entry to the database. + */ export const addDocument: AddDocument = async (ctx, document) => { const uuid = crypto.randomUUID(); const db = await ctx.db.getKysely(); diff --git a/packages/forms/src/repository/add-form.ts b/packages/forms/src/repository/add-form.ts index c272f2c76..198b8c45e 100644 --- a/packages/forms/src/repository/add-form.ts +++ b/packages/forms/src/repository/add-form.ts @@ -8,6 +8,9 @@ export type AddForm = ( form: Blueprint ) => Promise>; +/** + * Adds a new form entry to the database. + */ export const addForm: AddForm = async (ctx, form) => { const uuid = crypto.randomUUID(); const db = await ctx.db.getKysely(); diff --git a/packages/forms/src/repository/delete-form.ts b/packages/forms/src/repository/delete-form.ts index 022b55394..2fe5d5d90 100644 --- a/packages/forms/src/repository/delete-form.ts +++ b/packages/forms/src/repository/delete-form.ts @@ -8,6 +8,9 @@ export type DeleteForm = ( formId: string ) => Promise>; +/** + * Asynchronously deletes a form and its associated documents from the database. + */ export const deleteForm: DeleteForm = async (ctx, formId) => { const db = await ctx.db.getKysely(); diff --git a/packages/forms/src/repository/get-document.ts b/packages/forms/src/repository/get-document.ts index 35b6c028b..42e2c30d9 100644 --- a/packages/forms/src/repository/get-document.ts +++ b/packages/forms/src/repository/get-document.ts @@ -17,6 +17,9 @@ export type GetDocument = ( }> >; +/** + * Asynchronously retrieves a document from the database and returns its details. + */ export const getDocument: GetDocument = async (ctx, id) => { const db = await ctx.db.getKysely(); diff --git a/packages/forms/src/repository/get-form-list.ts b/packages/forms/src/repository/get-form-list.ts index 2f25fc7f4..77822733a 100644 --- a/packages/forms/src/repository/get-form-list.ts +++ b/packages/forms/src/repository/get-form-list.ts @@ -9,6 +9,9 @@ export type GetFormList = (ctx: FormRepositoryContext) => Promise< | null >; +/** + * Retrieves a list of forms from the database. + */ export const getFormList: GetFormList = async ctx => { const db = await ctx.db.getKysely(); const rows = await db.selectFrom('forms').select(['id', 'data']).execute(); diff --git a/packages/forms/src/repository/get-form-session.ts b/packages/forms/src/repository/get-form-session.ts index d2aa7af70..d791592df 100644 --- a/packages/forms/src/repository/get-form-session.ts +++ b/packages/forms/src/repository/get-form-session.ts @@ -13,7 +13,13 @@ export type GetFormSession = ( }> >; -export const getFormSession: GetFormSession = async (ctx, id) => { +/** + * Asynchronously retrieves a form session by its unique identifier from the database. + */ +export const getFormSession: GetFormSession = async ( + ctx: FormRepositoryContext, + id: FormSessionId +) => { const db = await ctx.db.getKysely(); return await db .selectFrom('form_sessions') diff --git a/packages/forms/src/repository/get-form.ts b/packages/forms/src/repository/get-form.ts index eeb11de2d..564783bf0 100644 --- a/packages/forms/src/repository/get-form.ts +++ b/packages/forms/src/repository/get-form.ts @@ -8,6 +8,9 @@ export type GetForm = ( formId: string ) => Promise>; +/** + * Retrieves and parses a form from the database using the provided form ID. + */ export const getForm: GetForm = async (ctx, formId) => { const db = await ctx.db.getKysely(); const selectResult = await db diff --git a/packages/forms/src/repository/save-form.ts b/packages/forms/src/repository/save-form.ts index 438f5d652..50c929786 100644 --- a/packages/forms/src/repository/save-form.ts +++ b/packages/forms/src/repository/save-form.ts @@ -9,7 +9,14 @@ export type SaveForm = ( form: Blueprint ) => Promise; -export const saveForm: SaveForm = async (ctx, id, blueprint) => { +/** + * Asynchronously saves a form blueprint by updating the corresponding entry in the database. + */ +export const saveForm: SaveForm = async ( + ctx: FormRepositoryContext, + id: string, + blueprint: Blueprint +) => { const db = await ctx.db.getKysely(); return await db diff --git a/packages/forms/src/repository/upsert-form-session.ts b/packages/forms/src/repository/upsert-form-session.ts index 830f71d7d..f82f23e84 100644 --- a/packages/forms/src/repository/upsert-form-session.ts +++ b/packages/forms/src/repository/upsert-form-session.ts @@ -11,6 +11,9 @@ export type UpsertFormSession = ( } ) => Promise>; +/** + * Asynchronously inserts or updates a form session in the database. + */ export const upsertFormSession: UpsertFormSession = async (ctx, opts) => { const db = await ctx.db.getKysely(); const strData = JSON.stringify(opts.data); diff --git a/packages/forms/src/services/add-form.ts b/packages/forms/src/services/add-form.ts index 9845f8f4d..b58457584 100644 --- a/packages/forms/src/services/add-form.ts +++ b/packages/forms/src/services/add-form.ts @@ -17,6 +17,10 @@ export type AddForm = ( form: Blueprint ) => Promise>; +/** + * This is meant to sit in front of the form repository and manage the HTTP status codes + * and message returned in the response when forms are added to the repository. + */ export const addForm: AddForm = async (ctx, form) => { if (!ctx.isUserLoggedIn()) { return failure({ diff --git a/packages/forms/src/services/delete-form.ts b/packages/forms/src/services/delete-form.ts index f3eb1b60d..d882b1d1a 100644 --- a/packages/forms/src/services/delete-form.ts +++ b/packages/forms/src/services/delete-form.ts @@ -12,6 +12,10 @@ export type DeleteForm = ( formId: string ) => Promise>; +/** + * This is meant to sit in front of the form repository and manage the HTTP status codes + * and message returned in the response when forms are deleted from the repository. + */ export const deleteForm: DeleteForm = async (ctx, formId) => { if (!ctx.isUserLoggedIn()) { return failure({ diff --git a/packages/forms/src/services/get-form-list.ts b/packages/forms/src/services/get-form-list.ts index b89b5764f..3848cfcd3 100644 --- a/packages/forms/src/services/get-form-list.ts +++ b/packages/forms/src/services/get-form-list.ts @@ -16,6 +16,10 @@ export type GetFormList = ( ctx: FormServiceContext ) => Promise>; +/** + * This is meant to sit in front of the form repository and manage the HTTP status codes + * and message returned in the response when a list of forms is fetched from the repository. + */ export const getFormList: GetFormList = async ctx => { if (!ctx.isUserLoggedIn()) { return failure({ diff --git a/packages/forms/src/services/get-form-session.ts b/packages/forms/src/services/get-form-session.ts index 13767d4df..daed8b70a 100644 --- a/packages/forms/src/services/get-form-session.ts +++ b/packages/forms/src/services/get-form-session.ts @@ -23,6 +23,10 @@ export type GetFormSession = ( }> >; +/** + * Retrieves or creates a form session based on the provided context and options. + * Handles the fetching of an existing form or session and creates a new session if one does not exist. + */ export const getFormSession: GetFormSession = async (ctx, opts) => { const formResult = await ctx.repository.getForm(opts.formId); if (!formResult.success) { diff --git a/packages/forms/src/services/get-form.ts b/packages/forms/src/services/get-form.ts index d2c0f67ac..31e8c14dc 100644 --- a/packages/forms/src/services/get-form.ts +++ b/packages/forms/src/services/get-form.ts @@ -14,6 +14,10 @@ export type GetForm = ( formId: string ) => Promise>; +/** + * This is meant to sit in front of the form repository and manage the HTTP status codes + * and message returned in the response when forms are fetched from the repository. + */ export const getForm: GetForm = async (ctx, formId) => { const formResult = await ctx.repository.getForm(formId); if (!formResult.success) { diff --git a/packages/forms/src/services/index.ts b/packages/forms/src/services/index.ts index d426dc291..7729c8401 100644 --- a/packages/forms/src/services/index.ts +++ b/packages/forms/src/services/index.ts @@ -11,6 +11,11 @@ import { type InitializeForm, initializeForm } from './initialize-form.js'; import { type SaveForm, saveForm } from './save-form.js'; import { type SubmitForm, submitForm } from './submit-form.js'; +/** + * Factory function to create a form management service. + * + * @param {FormServiceContext} ctx - The context required to initialize the form service. + */ export const createFormService = (ctx: FormServiceContext) => createService(ctx, { addForm, diff --git a/packages/forms/src/services/initialize-form.ts b/packages/forms/src/services/initialize-form.ts index 218d16416..c31ea4e72 100644 --- a/packages/forms/src/services/initialize-form.ts +++ b/packages/forms/src/services/initialize-form.ts @@ -49,6 +49,10 @@ const optionSchema = z.object({ .optional(), }); +/** + * Asynchronously initializes a new form based on the provided context and options. Handles schema validation, + * document import (parses uploaded PDF), builds a Blueprint, and saves to the repository. + */ export const initializeForm: InitializeForm = async (ctx, opts) => { if (!ctx.isUserLoggedIn()) { return failure({ diff --git a/packages/forms/src/services/save-form.ts b/packages/forms/src/services/save-form.ts index 73d7245a9..6cda2df61 100644 --- a/packages/forms/src/services/save-form.ts +++ b/packages/forms/src/services/save-form.ts @@ -15,6 +15,10 @@ export type SaveForm = ( form: Blueprint ) => Promise>; +/** + * This is meant to sit in front of the form repository and manage the HTTP status codes + * and message returned in the response when forms are updated or saved in the repository. + */ export const saveForm: SaveForm = async (ctx, formId, form) => { if (!ctx.isUserLoggedIn()) { return failure({ diff --git a/packages/forms/src/services/submit-form.ts b/packages/forms/src/services/submit-form.ts index 533d1e6ef..f97bd7b7e 100644 --- a/packages/forms/src/services/submit-form.ts +++ b/packages/forms/src/services/submit-form.ts @@ -41,6 +41,10 @@ registry.registerHandler({ handler: downloadPackageHandler, }); +/** + * Asynchronously submits a form by processing the provided data, managing session information, and + * invoking the appropriate handler based on the action. + */ export const submitForm: SubmitForm = async ( ctx, sessionId, @@ -140,6 +144,9 @@ export const submitForm: SubmitForm = async ( }); }; +/** + * Retrieves an existing form session by its id or creates a new form session. + */ const getFormSessionOrCreate = async ( ctx: FormServiceContext, form: Blueprint, diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 9823e0341..49f25fc58 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -27,6 +27,9 @@ export type FormSession = { }; }; +/** + * Representation of an initial or empty form session. + */ export const nullSession: FormSession = { data: { errors: {}, @@ -53,6 +56,9 @@ export const nullSession: FormSession = { }, }; +/** + * Creates a form session object using the provided form blueprint and optional route. + */ export const createFormSession = ( form: Blueprint, route?: FormRoute @@ -75,6 +81,9 @@ export const createFormSession = ( }; }; +/** + * Retrieves a specific value from the form session data based on the provided pattern ID. + */ export const getFormSessionValue = ( session: FormSession, patternId: PatternId @@ -111,6 +120,10 @@ export const updateSessionValue = ( return nextSession; }; +/** + * Updates a form session with new values and errors, ensuring the + * validity of the pattern references provided. + */ export const updateSession = ( session: FormSession, values: PatternValueMap, @@ -139,6 +152,10 @@ export const updateSession = ( }; }; +/** + * Checks if a form session is complete and valid by validating all patterns + * against their corresponding configurations. + */ export const sessionIsComplete = (config: FormConfig, session: FormSession) => { return Object.values(session.form.patterns).every(pattern => { const patternConfig = getPatternConfig(config, pattern.type); @@ -154,6 +171,9 @@ export const sessionIsComplete = (config: FormConfig, session: FormSession) => { }); }; +/** + * Updates the specified form session by adding or updating the value of a specific pattern. + */ const addValue = ( form: FormSession, id: PatternId, @@ -192,6 +212,9 @@ export const mergeSession = ( ...newSession, }); +/** + * Calculates the total number of pages in the page set of the provided blueprint's root pattern. + */ export const getPageCount = (bp: Blueprint) => { const rootPattern = bp.patterns[bp.root]; if (rootPattern.type !== 'page-set') { @@ -201,6 +224,9 @@ export const getPageCount = (bp: Blueprint) => { return rootPattern.data.pages.length; }; +/** + * Determines the current session page index based on the session's route parameters and form data. + */ export const getSessionPage = (session: FormSession) => { const currentPageIndex = parseInt(session.route?.params.page as string) || 0; const lastPageIndex = getPageCount(session.form) - 1; diff --git a/packages/forms/src/submission.ts b/packages/forms/src/submission.ts index 8b7b3a93d..70790d0e3 100644 --- a/packages/forms/src/submission.ts +++ b/packages/forms/src/submission.ts @@ -50,6 +50,9 @@ const actionSchema = z }); export type ActionName = `action/${string}/${PatternId}`; +/** + * Constructs an action string based on the provided options. + */ export const getActionString = (opts: { handlerId: string; patternId: string; @@ -57,6 +60,10 @@ export const getActionString = (opts: { return `action/${opts.handlerId}/${opts.patternId}`; }; +/** + * The SubmissionRegistry class manages submission handlers for forms and provides + * mechanisms to register and retrieve them based on specified action identifiers. + */ export class SubmissionRegistry { constructor(private config: FormConfig) {} diff --git a/packages/forms/src/util/base64.ts b/packages/forms/src/util/base64.ts index 859a57466..221de18b2 100644 --- a/packages/forms/src/util/base64.ts +++ b/packages/forms/src/util/base64.ts @@ -1,3 +1,10 @@ +/** + * Converts a given string input into its Base64 encoded representation. + * + * This function uses different methods depending on the environment: + * - In Node.js environments, it uses the Buffer API. + * - In browser environments, it utilizes the TextEncoder API. + */ export const stringToBase64 = (input: string): string => { if (typeof Buffer !== 'undefined') { return Buffer.from(input, 'utf-8').toString('base64'); @@ -12,6 +19,13 @@ export const stringToBase64 = (input: string): string => { } }; +/** + * Converts a Uint8Array instance into a Base64-encoded string. + * + * This function uses different methods depending on the environment: + * - In Node.js environments, it uses the Buffer API. + * - In browser environments, it utilizes the FileReader API. + */ export const uint8ArrayToBase64 = async (uint8Array: Uint8Array) => { if (typeof Buffer !== 'undefined') { return Buffer.from(uint8Array).toString('base64'); @@ -29,6 +43,9 @@ export const uint8ArrayToBase64 = async (uint8Array: Uint8Array) => { }); }; +/** + * Converts a base64 encoded string to a Uint8Array. + */ export const base64ToUint8Array = (base64: string) => { const binaryString = atob(base64); const len = binaryString.length; diff --git a/packages/forms/src/util/zod.ts b/packages/forms/src/util/zod.ts index 097b04373..b605e2369 100644 --- a/packages/forms/src/util/zod.ts +++ b/packages/forms/src/util/zod.ts @@ -4,6 +4,9 @@ import * as r from '@atj/common'; import { type FormError, type FormErrors, type Pattern } from '../index.js'; +/** + * Safely parses an unknown object using the provided Zod schema. + */ export const safeZodParse = ( schema: z.Schema, obj: unknown @@ -16,6 +19,9 @@ export const safeZodParse = ( } }; +/** + * Safely parses an object against a given Zod schema and converts potential parsing errors into a FormError. + */ export const safeZodParseToFormError = ( schema: z.Schema, obj: unknown @@ -29,6 +35,10 @@ export const safeZodParseToFormError = ( } }; +/** + * Parses and validates an object against a given Zod schema, ensuring safe handling of errors, + * and converts validation errors into a form-friendly error structure. + */ export const safeZodParseFormErrors = ( schema: Schema, obj: unknown @@ -42,6 +52,9 @@ export const safeZodParseFormErrors = ( } }; +/** + * Converts a ZodError into a structured set of form errors. + */ const convertZodErrorToFormErrors = (zodError: z.ZodError): FormErrors => { const formErrors: FormErrors = {}; zodError.errors.forEach(error => { @@ -61,6 +74,9 @@ const convertZodErrorToFormErrors = (zodError: z.ZodError): FormErrors => { return formErrors; }; +/** + * Converts a ZodError into a FormError object. + */ const convertZodErrorToFormError = (zodError: z.ZodError): FormError => { return { type: 'custom', From 6f5c6286e13fa84815ce13196e25c945699c5776 Mon Sep 17 00:00:00 2001 From: Ethan Gardner Date: Fri, 10 Jan 2025 11:44:07 -0500 Subject: [PATCH 2/4] update class name in comment (#435) --- packages/forms/src/builder/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/forms/src/builder/index.ts b/packages/forms/src/builder/index.ts index b6462d402..b74f8203b 100644 --- a/packages/forms/src/builder/index.ts +++ b/packages/forms/src/builder/index.ts @@ -27,7 +27,7 @@ import type { ParsedPdf } from '../documents/pdf/parsing-api.js'; /** * Constructs and manipulates a Blueprint object for forms. A Blueprint - * defines the structure of a form. The `BuildprintBuilder` provides methods to dynamically + * defines the structure of a form. The `BlueprintBuilder` provides methods to dynamically * modify pages, patterns, field sets, and documents within a hierarchical form structure. */ export class BlueprintBuilder { From c3bbc0bfe71cdb5d363a7289a09fc8ac3f38f34b Mon Sep 17 00:00:00 2001 From: Ethan Gardner Date: Fri, 10 Jan 2025 11:51:29 -0500 Subject: [PATCH 3/4] add jsdoc comments for database package (#425) * add jsdoc comments for database package * formatting --- packages/database/src/clients/knex.ts | 18 ++++++++----- .../database/src/clients/kysely/postgres.ts | 7 +++++ .../database/src/clients/kysely/sqlite3.ts | 26 +++++-------------- packages/database/src/context/file-system.ts | 3 +++ packages/database/src/context/in-memory.ts | 5 ++++ packages/database/src/context/postgres.ts | 3 +++ .../src/management/migrate-database.ts | 11 ++++++++ 7 files changed, 47 insertions(+), 26 deletions(-) diff --git a/packages/database/src/clients/knex.ts b/packages/database/src/clients/knex.ts index 71f393fc7..bf2211581 100644 --- a/packages/database/src/clients/knex.ts +++ b/packages/database/src/clients/knex.ts @@ -9,8 +9,13 @@ const migrationsDirectory = path.resolve( '../../migrations' ); -export const createKnex = (config: Knex.Config): Knex => knex(config); - +/** + * Creates and configures a query builder instance configured for a PostgreSQL database. + * + * @param {string} connectionString - The connection string for the PostgreSQL database. + * @param {boolean} [ssl=false] - Indicates whether SSL should be enabled for the connection. + * If enabled, `rejectUnauthorized` will be set to `false` to allow self-signed certificates. + */ export const getPostgresKnex = ( connectionString: string, ssl: boolean = false @@ -33,10 +38,11 @@ export const getInMemoryKnex = (): Knex => { return getSqlite3Knex(':memory:'); }; -export const getFileSystemKnex = (path: string): Knex => { - return getSqlite3Knex(path); -}; - +/** + * Creates and configures a query builder instance configured for a SQLite database. + * + * @param {string} filename - The path to the SQLite database file. + */ const getSqlite3Knex = (filename: string): Knex => { return knex({ client: 'better-sqlite3', diff --git a/packages/database/src/clients/kysely/postgres.ts b/packages/database/src/clients/kysely/postgres.ts index c6bcc5972..0a11af709 100644 --- a/packages/database/src/clients/kysely/postgres.ts +++ b/packages/database/src/clients/kysely/postgres.ts @@ -3,6 +3,13 @@ import pg from 'pg'; import { type Database } from './types.js'; +/** + * Creates a new Postgres database connection. + * + * @param {string} connectionString - The connection string to connect to the Postgres database. + * @param {boolean} ssl - A boolean indicating whether SSL should be used for the connection. + * If true, SSL is enabled with the option to not reject unauthorized certificates. + */ export const createPostgresDatabase = ( connectionString: string, ssl: boolean diff --git a/packages/database/src/clients/kysely/sqlite3.ts b/packages/database/src/clients/kysely/sqlite3.ts index 88e70077e..75e3f9add 100644 --- a/packages/database/src/clients/kysely/sqlite3.ts +++ b/packages/database/src/clients/kysely/sqlite3.ts @@ -1,27 +1,13 @@ import { Kysely, SqliteDialect } from 'kysely'; -import BetterSqliteDatabase, { - type Database as SqliteDatabase, -} from 'better-sqlite3'; +import { type Database as SqliteDatabase } from 'better-sqlite3'; import { type Database } from './types.js'; -type TestDatabase = { - kysely: Kysely; - sqlite: SqliteDatabase; -}; - -export const createInMemoryDatabase = (): TestDatabase => { - const database = new BetterSqliteDatabase(':memory:'); - return { - kysely: new Kysely({ - dialect: new SqliteDialect({ - database, - }), - }), - sqlite: database, - }; -}; - +/** + * Creates a query builder instance configured to use SQLite as the database dialect. + * + * @param {SqliteDatabase} database - The SQLite database connection or configuration object. + */ export const createSqliteDatabase = (database: SqliteDatabase) => { return new Kysely({ dialect: new SqliteDialect({ diff --git a/packages/database/src/context/file-system.ts b/packages/database/src/context/file-system.ts index 8d7833dc3..52f8169e6 100644 --- a/packages/database/src/context/file-system.ts +++ b/packages/database/src/context/file-system.ts @@ -16,6 +16,9 @@ const migrationsDirectory = path.resolve( '../../migrations' ); +/** + * Provides a context for accessing and managing a SQLite database stored on the filesystem. + */ export class FilesystemDatabaseContext implements DatabaseContext { public readonly engine = 'sqlite'; knex?: Knex; diff --git a/packages/database/src/context/in-memory.ts b/packages/database/src/context/in-memory.ts index 62c85f880..b0dc7ffb5 100644 --- a/packages/database/src/context/in-memory.ts +++ b/packages/database/src/context/in-memory.ts @@ -9,6 +9,11 @@ import { migrateDatabase } from '../management/migrate-database.js'; import { type DatabaseContext } from './types.js'; +/** + * Provides a context for accessing and managing a SQLite database stored in memory. + * + * This context is implemented for testing or temporary use cases where persistence is not required. + */ export class InMemoryDatabaseContext implements DatabaseContext { public readonly engine = 'sqlite'; knex?: Knex; diff --git a/packages/database/src/context/postgres.ts b/packages/database/src/context/postgres.ts index c6658a4bb..02983298c 100644 --- a/packages/database/src/context/postgres.ts +++ b/packages/database/src/context/postgres.ts @@ -9,6 +9,9 @@ import { migrateDatabase } from '../management/migrate-database.js'; import { type DatabaseContext } from './types.js'; import { Pool } from 'pg'; +/** + * Provides a context for accessing and managing a PostgreSQL database. + */ export class PostgresDatabaseContext implements DatabaseContext { public readonly engine = 'postgres'; knex?: Knex; diff --git a/packages/database/src/management/migrate-database.ts b/packages/database/src/management/migrate-database.ts index 0c26637c8..e3fb3f6c3 100644 --- a/packages/database/src/management/migrate-database.ts +++ b/packages/database/src/management/migrate-database.ts @@ -1,5 +1,16 @@ import { type DatabaseContext } from '../context/types.js'; +/** + * Handles database migration operations. + * + * Executes the latest database migrations for the given context and + * returns a function to roll back these migrations if needed. + * + * @param {DatabaseContext} ctx - The database context providing access to + * the database instance and migration utilities. + * + * @returns {Function} A function to roll back the last applied migrations. + */ export const migrateDatabase = async (ctx: DatabaseContext) => { const db = await ctx.getKnex(); await db.migrate.latest(); From 867e209d7223d4138e45a06d0825bba99203976d Mon Sep 17 00:00:00 2001 From: Ethan Gardner Date: Fri, 10 Jan 2025 11:59:08 -0500 Subject: [PATCH 4/4] add jsdoc comments to the auth package (#424) --- packages/auth/src/context/base.ts | 6 ++++++ packages/auth/src/lucia.ts | 16 ++++++++++++---- packages/auth/src/provider.ts | 5 +++++ packages/auth/src/repository/create-session.ts | 7 ++++++- packages/auth/src/repository/create-user.ts | 6 ++++++ packages/auth/src/repository/get-user-id.ts | 6 ++++++ packages/auth/src/repository/index.ts | 11 +++++++++++ .../auth/src/services/get-provider-redirect.ts | 8 ++++++++ packages/auth/src/services/index.ts | 5 +++++ packages/auth/src/services/logout.ts | 9 +++++++-- .../src/services/process-provider-callback.ts | 14 ++++++++++++++ .../auth/src/services/process-session-cookie.ts | 10 ++++++++++ 12 files changed, 96 insertions(+), 7 deletions(-) diff --git a/packages/auth/src/context/base.ts b/packages/auth/src/context/base.ts index e4181e4f3..9a0c7f222 100644 --- a/packages/auth/src/context/base.ts +++ b/packages/auth/src/context/base.ts @@ -8,6 +8,12 @@ import { import { LoginGov } from '../provider.js'; import { type AuthRepository } from '../repository/index.js'; +/** + * The `BaseAuthContext` class implements the `AuthServiceContext` interface, + * providing an authentication context for user sessions and database interactions. + * It integrates with a repository for database operations, a third-party login provider, + * and various utilities for managing cookies and user sessions. + */ export class BaseAuthContext implements AuthServiceContext { private lucia?: Lucia; diff --git a/packages/auth/src/lucia.ts b/packages/auth/src/lucia.ts index 4761306d2..44a377462 100644 --- a/packages/auth/src/lucia.ts +++ b/packages/auth/src/lucia.ts @@ -5,20 +5,28 @@ import { Lucia } from 'lucia'; import { type Database } from '@atj/database'; +/** + * Factory function to create a SQLite Lucia adapter. + * + * @param {Sqlite3Database} db - The SQLite3 database instance used to initialize the adapter. + */ export const createSqliteLuciaAdapter = (db: Sqlite3Database) => { - const adapter = new BetterSqlite3Adapter(db, { + return new BetterSqlite3Adapter(db, { user: 'users', session: 'sessions', }); - return adapter; }; +/** + * Factory function to create a Postgres Lucia adapter. + * + * @param {Sqlite3Database} pgPool - The SQLite3 database instance used to initialize the adapter. + */ export const createPostgresLuciaAdapter = (pgPool: any) => { - const adapter = new NodePostgresAdapter(pgPool, { + return new NodePostgresAdapter(pgPool, { user: 'users', session: 'sessions', }); - return adapter; }; declare module 'lucia' { diff --git a/packages/auth/src/provider.ts b/packages/auth/src/provider.ts index 51ae383a4..e92825436 100644 --- a/packages/auth/src/provider.ts +++ b/packages/auth/src/provider.ts @@ -19,6 +19,11 @@ export type LoginGovOptions = { redirectURI?: string; }; +/** + * The LoginGov class implements the OAuth2ProviderWithPKCE interface + * and provides functionality to authenticate users using Login.gov's + * OAuth 2.0 with PKCE flow. + */ export class LoginGov implements OAuth2ProviderWithPKCE { private client: OAuth2Client; //private clientSecret: string; diff --git a/packages/auth/src/repository/create-session.ts b/packages/auth/src/repository/create-session.ts index 752c2a0af..5e39929aa 100644 --- a/packages/auth/src/repository/create-session.ts +++ b/packages/auth/src/repository/create-session.ts @@ -7,6 +7,12 @@ type Session = { userId: string; }; +/** + * Asynchronously creates a new session in the database. + * + * @param {DatabaseContext} ctx - The database context used to manage the connection and provide access to the database engine. + * @param {Session} session - The session data to be inserted, containing properties such as id, expiration time, session token, and user id. + */ export const createSession = async (ctx: DatabaseContext, session: Session) => { const db = await ctx.getKysely(); const result = await db.transaction().execute(async trx => { @@ -17,7 +23,6 @@ export const createSession = async (ctx: DatabaseContext, session: Session) => { expires_at: dateValue(ctx.engine, session.expiresAt), session_token: session.sessionToken, user_id: session.userId, - //...session.attributes, }) .execute(); }); diff --git a/packages/auth/src/repository/create-user.ts b/packages/auth/src/repository/create-user.ts index 8f618538e..8a9edded7 100644 --- a/packages/auth/src/repository/create-user.ts +++ b/packages/auth/src/repository/create-user.ts @@ -2,6 +2,12 @@ import { randomUUID } from 'crypto'; import { type DatabaseContext } from '@atj/database'; +/** + * Asynchronously creates a new user record in the database. + * + * @param {DatabaseContext} ctx - The database context used to interact with the database. + * @param {string} email - The email address of the user to be created. + */ export const createUser = async (ctx: DatabaseContext, email: string) => { const id = randomUUID(); diff --git a/packages/auth/src/repository/get-user-id.ts b/packages/auth/src/repository/get-user-id.ts index 4d4af6f3a..eab207304 100644 --- a/packages/auth/src/repository/get-user-id.ts +++ b/packages/auth/src/repository/get-user-id.ts @@ -1,5 +1,11 @@ import { type DatabaseContext } from '@atj/database'; +/** + * Retrieves the unique identifier (ID) of a user based on their email address. + * + * @param {DatabaseContext} ctx - The database context used to establish a connection and perform the query. + * @param {string} email - The email address of the user whose ID is to be retrieved. + */ export const getUserId = async (ctx: DatabaseContext, email: string) => { const db = await ctx.getKysely(); const user = await db.transaction().execute(trx => { diff --git a/packages/auth/src/repository/index.ts b/packages/auth/src/repository/index.ts index 84b6c3238..1a312478e 100644 --- a/packages/auth/src/repository/index.ts +++ b/packages/auth/src/repository/index.ts @@ -5,6 +5,17 @@ import { createSession } from './create-session.js'; import { createUser } from './create-user.js'; import { getUserId } from './get-user-id.js'; +/** + * Factory function to create an authentication repository. + * + * @param {DatabaseContext} ctx - The database context used for initializing the repository. + * @returns Returns an authentication service object with methods to handle user authentication and management. + * + * The returned service object provides the following methods: + * - `createSession` + * - `createUser` + * - `getUserId` + */ export const createAuthRepository = (ctx: DatabaseContext) => createService(ctx, { createSession, diff --git a/packages/auth/src/services/get-provider-redirect.ts b/packages/auth/src/services/get-provider-redirect.ts index 3988664dd..99cc0e958 100644 --- a/packages/auth/src/services/get-provider-redirect.ts +++ b/packages/auth/src/services/get-provider-redirect.ts @@ -1,6 +1,14 @@ import { generateCodeVerifier, generateState } from 'arctic'; import { type AuthServiceContext } from './index.js'; +/** + * Asynchronously generates a redirection URL for an OAuth authorization request and associated cookies. + * + * This function interacts with the provided authentication service context to create an authorization + * URL, including necessary state and verification parameters for security measures. + * + * @param {AuthServiceContext} ctx - The authentication service context used to interact with the provider. + */ export const getProviderRedirect = async (ctx: AuthServiceContext) => { const state = generateState(); const codeVerifier = generateCodeVerifier(); diff --git a/packages/auth/src/services/index.ts b/packages/auth/src/services/index.ts index d791ab9ea..7e60f93f6 100644 --- a/packages/auth/src/services/index.ts +++ b/packages/auth/src/services/index.ts @@ -22,6 +22,11 @@ export type AuthServiceContext = { isUserAuthorized: (email: string) => Promise; }; +/** + * Factory function to create an authentication service. + * + * @param {AuthServiceContext} ctx - The context required to initialize the authentication service. + */ export const createAuthService = (ctx: AuthServiceContext) => createService(ctx, { getProviderRedirect, diff --git a/packages/auth/src/services/logout.ts b/packages/auth/src/services/logout.ts index 00179c702..ddc816890 100644 --- a/packages/auth/src/services/logout.ts +++ b/packages/auth/src/services/logout.ts @@ -1,9 +1,14 @@ import { type Session } from 'lucia'; import { type AuthServiceContext } from './index.js'; +/** + * Logs out a user by invalidating their existing session and creating a blank session cookie. + * + * @param {AuthServiceContext} ctx - The authentication service context. + * @param {Session} session - The session object to be invalidated. + */ export const logOut = async (ctx: AuthServiceContext, session: Session) => { const lucia = await ctx.getLucia(); await lucia.invalidateSession(session.id); - const sessionCookie = lucia.createBlankSessionCookie(); - return sessionCookie; + return lucia.createBlankSessionCookie(); }; diff --git a/packages/auth/src/services/process-provider-callback.ts b/packages/auth/src/services/process-provider-callback.ts index 4d5ac9b2b..88a7e6f8b 100644 --- a/packages/auth/src/services/process-provider-callback.ts +++ b/packages/auth/src/services/process-provider-callback.ts @@ -18,6 +18,15 @@ type Params = { state?: string | null; }; +/** + * Processes the provider callback for an OAuth-based authentication flow. Ensures data integrity and security through checks like nonce matching, + * state validation, and proper error handling. + * + * @param {AuthServiceContext} ctx - The context object containing authentication services, database access, and related utilities. + * @param {Params} params - The parameters received from the provider as part of the callback request. + * @param {Params & { nonce: string | null }} storedParams - Locally stored parameters including the nonce for verification and validation. + * @param {function} [fetchUserData=fetchUserDataImpl] - A function to fetch user data from the external provider using the access token. + */ export const processProviderCallback = async ( ctx: AuthServiceContext, params: Params, @@ -91,6 +100,11 @@ export const processProviderCallback = async ( }); }; +/** + * Fetches user data from the login-provider endpoint using the provided access token with bearer token auth. + * + * @param {string} accessToken - The access token to authorize the request. + */ const fetchUserDataImpl = (accessToken: string) => fetch('https://idp.int.identitysandbox.gov/api/openid_connect/userinfo', { headers: { diff --git a/packages/auth/src/services/process-session-cookie.ts b/packages/auth/src/services/process-session-cookie.ts index 401a7122d..209cf2465 100644 --- a/packages/auth/src/services/process-session-cookie.ts +++ b/packages/auth/src/services/process-session-cookie.ts @@ -4,6 +4,16 @@ import { type VoidResult } from '@atj/common'; import { type AuthServiceContext } from './index.js'; +/** + * Processes the session cookie in the context of an authentication request. + * This function validates the session cookie from the incoming request and + * sets the appropriate user session in the given context. It checks the + * request's origin for security and handles session expiration or invalidation + * by creating blank session cookies when necessary. + * + * @param {AuthServiceContext} ctx - The authentication service context used to manage sessions and cookies. + * @param {Request} request - The incoming HTTP request object containing session and origin information. + */ export const processSessionCookie = async ( ctx: AuthServiceContext, request: Request