All files / realm/blong-access/adapter/db accessRoleMerge.ts

100% Statements 53/53
60% Branches 3/5
100% Functions 1/1
100% Lines 53/53

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 541x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 44x 44x 44x 44x 44x 44x 44x 44x 44x 44x 44x 44x 44x 8x 8x 7x  
import {type IMeta, handler} from '@feasibleone/blong';
 
import {type EnsuredRole} from './accessModel.ts';
 
/**
 * `access.role.merge` — the seed form of `access.role.ensure`: one call for the
 * list of roles a seed file declares, so `meta/db/1-accessRoleMerge.yaml` can
 * name roles without maintaining a bit table.
 *
 * This overrides the generic resource merge (`resourceType: access.role`),
 * which would insert the rows as-is and therefore needs every row to carry its
 * own `roleBit` — the column is NOT NULL and UNIQUE, so a seed could only ever
 * pick numbers by hand and collide silently.
 *
 * A row may still name a `roleBit`; when it does not, the bit is allocated
 * (`MAX(roleBit) + 1` in file order).  Roles that already exist keep the bit
 * they have, so re-running a seed never moves a bit: on a fresh database the
 * first file that seeds roles reproduces the same numbering as before, while a
 * layout change in the file cannot renumber anything.
 *
 * Wire: `access.role.merge` — the realm's own merge, called by the seed loader.
 */
export default handler(({handler: {'db/accessRoleEnsure': accessRoleEnsure}}) => ({
    async accessRoleMerge(
        params: {
            /** Declared by the seed file (`access.role`); the `role` list is the payload. */
            resourceType?: string;
            role?: Array<{name?: string; roleBit?: number; description?: string}>;
        },
        $meta: IMeta,
    ): Promise<{
        success: boolean;
        role: Array<{roleId: string; name: string; roleBit: number}>;
    }> {
        const rows = params.role ?? [];
        const result: Array<{roleId: string; name: string; roleBit: number}> = [];
        for (const row of rows) {
            if (!row.name) continue;
            const {role} = await accessRoleEnsure<EnsuredRole>(
                {
                    role: {
                        roleName: row.name,
                        roleBit: row.roleBit,
                        description: row.description,
                    },
                },
                $meta,
            );
            result.push({roleId: role.roleId, name: role.roleName, roleBit: role.roleBit});
        }
        return {success: true, role: result};
    },
}));