@happyvertical/smrt-timesheets 0.57.37 → 0.57.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/attendance/correction-models.d.ts +2 -2
  2. package/dist/attendance/correction-models.d.ts.map +1 -1
  3. package/dist/attendance/models.d.ts +5 -5
  4. package/dist/attendance/models.d.ts.map +1 -1
  5. package/dist/attendance.js +2 -2
  6. package/dist/chunks/{attendance-BVFIB2S4.js → attendance-AkgSOl0A.js} +5 -5
  7. package/dist/chunks/attendance-AkgSOl0A.js.map +1 -0
  8. package/dist/chunks/{attendance-2b9zn9tF.js → attendance-Y7BCWUe9.js} +3 -3
  9. package/dist/chunks/{attendance-2b9zn9tF.js.map → attendance-Y7BCWUe9.js.map} +1 -1
  10. package/dist/chunks/{models-CAELan0E.js → models-CZHyHdrZ.js} +16 -16
  11. package/dist/chunks/models-CZHyHdrZ.js.map +1 -0
  12. package/dist/chunks/{rollup-mrKeGtnv.js → rollup-HumZW4EB.js} +9 -9
  13. package/dist/chunks/rollup-HumZW4EB.js.map +1 -0
  14. package/dist/chunks/service-time-entry-DKwDyfK8.js +286 -0
  15. package/dist/chunks/service-time-entry-DKwDyfK8.js.map +1 -0
  16. package/dist/chunks/{time-entry-actions-BMX7Hi78.js → time-entry-actions-vYZoqn-M.js} +6 -6
  17. package/dist/chunks/time-entry-actions-vYZoqn-M.js.map +1 -0
  18. package/dist/index.js +5 -5
  19. package/dist/manifest.json +78 -12
  20. package/dist/models/service-snapshots.d.ts +3 -3
  21. package/dist/models/service-snapshots.d.ts.map +1 -1
  22. package/dist/models/service-time-entry.d.ts +2 -2
  23. package/dist/models/service-time-entry.d.ts.map +1 -1
  24. package/dist/rollup/models.d.ts +4 -4
  25. package/dist/rollup/models.d.ts.map +1 -1
  26. package/dist/rollup.js +1 -1
  27. package/dist/smrt-knowledge.json +36 -3
  28. package/package.json +8 -8
  29. package/dist/chunks/attendance-BVFIB2S4.js.map +0 -1
  30. package/dist/chunks/models-CAELan0E.js.map +0 -1
  31. package/dist/chunks/rollup-mrKeGtnv.js.map +0 -1
  32. package/dist/chunks/service-time-entry-DPXY5qo3.js +0 -286
  33. package/dist/chunks/service-time-entry-DPXY5qo3.js.map +0 -1
  34. package/dist/chunks/time-entry-actions-BMX7Hi78.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-entry-actions-vYZoqn-M.js","names":[],"sources":["../../src/models/service-snapshots.ts","../../src/services/action-principal.ts","../../src/services/service-evidence-service.ts","../../src/services/time-entry-actions.ts"],"sourcesContent":["import {\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n type SmrtSaveOptions,\n smrt,\n ValidationError,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\n/**\n * Refuse an amount that is not a JavaScript-safe integer number of minor\n * units. SQLite stores `19.99` in an INTEGER column without complaint and\n * PostgreSQL rejects it only at the driver, so the model boundary is the one\n * place both engines (and every writer: collections, `ServiceEvidenceService`,\n * resolvers) get the same answer. Sign is not constrained here.\n */\nexport function assertSnapshotMinorUnits(model: string, amount: unknown): void {\n if (typeof amount !== 'number' || !Number.isSafeInteger(amount)) {\n throw new ValidationError(\n `${model}.amount must be a safe integer number of minor units (cents) — ` +\n `got ${String(amount)}. $19.99 is 1999.`,\n 'VALIDATION_INVALID_VALUE',\n {\n fieldName: 'amount',\n value: amount,\n expectedType: 'safe integer minor units',\n },\n );\n }\n}\n\nconst chargeSnapshot = new WeakMap<ServiceChargeSnapshot, string>();\nconst compensationSnapshot = new WeakMap<ServiceCompensationSnapshot, string>();\n\nasync function immutableCommercialSnapshot(\n object: SmrtObject,\n fields: string[],\n): Promise<string | null> {\n if (!object.id) return null;\n try {\n const row = await object.db.get(object.tableName, { id: object.id });\n if (!row) return null;\n return JSON.stringify(\n Object.fromEntries(\n fields.map((key) => [\n key,\n row[key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`)] ?? null,\n ]),\n ),\n );\n } catch {\n return null;\n }\n}\n\nfunction commercialSnapshot(\n object: Record<string, unknown>,\n fields: string[],\n): string {\n return JSON.stringify(\n Object.fromEntries(fields.map((key) => [key, object[key] ?? null])),\n );\n}\n\nconst CHARGE_FIELDS = [\n 'timeEntryId',\n 'amount',\n 'currency',\n 'pricingVersion',\n 'strategy',\n 'rateSnapshot',\n 'sourceChargeRef',\n];\nconst COMPENSATION_FIELDS = [\n 'timeEntryId',\n 'amount',\n 'currency',\n 'termsVersion',\n 'rateSnapshot',\n];\n\n/**\n * Immutable client-charge snapshot for one approved time entry. Money is\n * integer minor units, consistent with smrt-commerce (#2401).\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_charge_snapshots',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: [\n '@happyvertical/smrt-projects:ServiceChargeSnapshot',\n ],\n conflictColumns: ['time_entry_id'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceChargeSnapshot extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @foreignKey('ServiceTimeEntry', { required: true }) timeEntryId: string = '';\n /**\n * Client charge in **integer minor units** of {@link currency} — `$19.99` is\n * `1999`. The `= 0` initializer is load-bearing: SMRT maps an integer literal\n * to INTEGER and a decimal literal to DECIMAL (#2401).\n *\n * Copied verbatim from the upstream `ClientCharge.amount`, so the two carry\n * the same unit by construction; a split would land cents in a major-units\n * column with no error anywhere.\n */\n amount: number = 0;\n @field({ type: 'text' }) currency: string = 'USD';\n @field({ type: 'text' }) pricingVersion: string = '';\n @field({ type: 'text' }) strategy: string = '';\n @field({ type: 'text' }) rateSnapshot: string = '{}';\n @field({ type: 'text' }) sourceChargeRef: string = '';\n createdAt: Date = new Date();\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved())\n chargeSnapshot.set(\n this,\n commercialSnapshot(\n this as unknown as Record<string, unknown>,\n CHARGE_FIELDS,\n ),\n );\n return this;\n }\n\n override async save(options?: SmrtSaveOptions): Promise<this> {\n assertSnapshotMinorUnits('ServiceChargeSnapshot', this.amount);\n const current = commercialSnapshot(\n this as unknown as Record<string, unknown>,\n CHARGE_FIELDS,\n );\n const prior =\n (await immutableCommercialSnapshot(this, CHARGE_FIELDS)) ??\n chargeSnapshot.get(this) ??\n null;\n if (prior && prior !== current)\n throw new Error(\n 'ServiceChargeSnapshot is immutable; append an upstream adjustment instead.',\n );\n const result = (await super.save(options)) as this;\n chargeSnapshot.set(this, current);\n return result;\n }\n}\n\n/**\n * Immutable provider-compensation snapshot for one approved time entry,\n * kept separate from the client charge so the margin is `charge - compensation`.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_compensation_snapshots',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: [\n '@happyvertical/smrt-projects:ServiceCompensationSnapshot',\n ],\n conflictColumns: ['time_entry_id'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceCompensationSnapshot extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @foreignKey('ServiceTimeEntry', { required: true }) timeEntryId: string = '';\n /**\n * Provider earning in **integer minor units** of {@link currency} (#2401).\n *\n * Converts with {@link ServiceChargeSnapshot.amount}: the delivery margin is\n * `charge - compensation`, so a mixed pair would make that subtraction\n * meaningless.\n */\n amount: number = 0;\n @field({ type: 'text' }) currency: string = 'USD';\n @field({ type: 'text' }) termsVersion: string = '';\n @field({ type: 'text' }) rateSnapshot: string = '{}';\n createdAt: Date = new Date();\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved())\n compensationSnapshot.set(\n this,\n commercialSnapshot(\n this as unknown as Record<string, unknown>,\n COMPENSATION_FIELDS,\n ),\n );\n return this;\n }\n\n override async save(options?: SmrtSaveOptions): Promise<this> {\n assertSnapshotMinorUnits('ServiceCompensationSnapshot', this.amount);\n const current = commercialSnapshot(\n this as unknown as Record<string, unknown>,\n COMPENSATION_FIELDS,\n );\n const prior =\n (await immutableCommercialSnapshot(this, COMPENSATION_FIELDS)) ??\n compensationSnapshot.get(this) ??\n null;\n if (prior && prior !== current)\n throw new Error(\n 'ServiceCompensationSnapshot is immutable; create explicit settlement evidence instead.',\n );\n const result = (await super.save(options)) as this;\n compensationSnapshot.set(this, current);\n return result;\n }\n}\n\n/** Collection over `service_charge_snapshots`. */\n// Registered collection class: without its own surface it published\n// generated create/update/delete MCP tools, and a forged snapshot would make\n// approval skip pricing (#4001). Reads only, like the model.\n@smrt({ mcp: { include: ['list', 'get'] }, cli: false })\nexport class ServiceChargeSnapshotCollection extends SmrtCollection<ServiceChargeSnapshot> { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n static readonly _itemClass = ServiceChargeSnapshot;\n}\n/** Collection over `service_compensation_snapshots`. */\n// Registered collection class: without its own surface it published\n// generated create/update/delete MCP tools, and a forged snapshot would make\n// approval skip pricing (#4001). Reads only, like the model.\n@smrt({ mcp: { include: ['list', 'get'] }, cli: false })\nexport class ServiceCompensationSnapshotCollection extends SmrtCollection<ServiceCompensationSnapshot> { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n static readonly _itemClass = ServiceCompensationSnapshot;\n}\n","/**\n * The acting principal for the generated service-backed time entry actions\n * (#4001).\n *\n * Identity always comes from the ambient request context, never from the\n * request body: the tenancy ALS (`withTenant`, the SvelteKit/Express\n * adapters) first, then the authenticated smrt-users session-permission ALS\n * (`createSessionHandler()` without `enterTenantContext`). This is the\n * smrt-fields / smrt-preferences precedent. Authorization goes through\n * smrt-users' `assertOperationPermission()` against the principal's published\n * permission snapshot, so ceilings, super-admin and catalog presence behave\n * exactly as they do for every other guarded operation.\n */\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { getCurrentTenant, withTenant } from '@happyvertical/smrt-tenancy';\nimport {\n assertOperationPermission,\n getCurrentSessionPermissionContext,\n type OperationPermissionCollectionInput,\n OperationPermissionError,\n UserCollection,\n} from '@happyvertical/smrt-users';\n\n/** A refused action with a 4xx status the generated transports serialize. */\nexport class TimesheetActionError extends Error {\n readonly status: number;\n readonly code: string;\n readonly publicMessage: string;\n\n constructor(status: number, code: string, message: string) {\n super(message);\n this.name = 'TimesheetActionError';\n this.status = status;\n this.code = code;\n this.publicMessage = message;\n }\n}\n\n/** Who is acting, resolved from the ambient context. */\nexport interface TimesheetActionPrincipal {\n tenantId: string;\n userId: string;\n permissions: ReadonlySet<string>;\n /** smrt-profiles Profile linked to the user; stamped into audit fields. */\n profileId: string;\n /** True when the tenancy ALS already carries this principal. */\n fromTenancy: boolean;\n}\n\ninterface AmbientPrincipal {\n tenantId: string | null;\n userId: string | null;\n permissions: ReadonlySet<string>;\n profileId: string | null;\n fromTenancy: boolean;\n}\n\nfunction profileIdOf(user: unknown): string | null {\n if (!user || typeof user !== 'object') return null;\n const value = (user as { profileId?: unknown }).profileId;\n return typeof value === 'string' && value ? value : null;\n}\n\nfunction ambientPrincipal(): AmbientPrincipal {\n const tenant = getCurrentTenant();\n const session = getCurrentSessionPermissionContext();\n if (tenant?.tenantId) {\n // Generated SvelteKit routes enter `{ tenantId, userId, permissions }`\n // without the user object; the same person's session still carries it.\n const sessionProfile =\n session?.userId && session.userId === tenant.userId\n ? profileIdOf(session.user)\n : null;\n return {\n tenantId: tenant.tenantId,\n userId: tenant.userId ?? null,\n permissions: tenant.permissions,\n profileId: profileIdOf(tenant.user) ?? sessionProfile,\n fromTenancy: true,\n };\n }\n return {\n tenantId: session?.tenantId ?? null,\n userId: session?.userId ?? null,\n permissions: session?.permissionSet ?? new Set<string>(),\n profileId: profileIdOf(session?.user),\n fromTenancy: false,\n };\n}\n\nasync function loadProfileId(\n userId: string,\n options: SmrtClassOptions,\n): Promise<string | null> {\n try {\n const users = await UserCollection.create({\n db: options.db ?? options.persistence,\n } as SmrtClassOptions);\n return profileIdOf(await users.get({ id: userId }));\n } catch {\n return null;\n }\n}\n\n/** True when the ambient principal holds `<collection>.<action>`. */\nexport async function principalHolds(\n collection: OperationPermissionCollectionInput,\n action: string,\n options: SmrtClassOptions,\n): Promise<boolean> {\n const ambient = ambientPrincipal();\n try {\n await assertOperationPermission({\n collection,\n action,\n db: options.db ?? options.persistence,\n tenantId: ambient.tenantId,\n userId: ambient.userId,\n permissionSet: ambient.permissions,\n allowSystemContextBypass: false,\n allowSuperAdminBypass: false,\n });\n return true;\n } catch (error) {\n if (error instanceof OperationPermissionError) return false;\n throw error;\n }\n}\n\n/**\n * Authorize `<collection>.<action>` for the ambient principal and resolve the\n * profile it acts as. Fails closed (403) without an authenticated,\n * tenant-bound principal, without the permission, or without a linked\n * profile — an action always records who took it.\n *\n * System context never bypasses: trusted server code without a person calls\n * `ServiceEvidenceService` directly. `allowSuperAdminBypass: false` is for\n * money and separation-of-duties operations that need an explicit grant.\n */\nexport async function authorizeTimesheetAction(\n collection: OperationPermissionCollectionInput,\n action: string,\n options: SmrtClassOptions,\n guard: { allowSuperAdminBypass: boolean },\n): Promise<TimesheetActionPrincipal> {\n const ambient = ambientPrincipal();\n try {\n await assertOperationPermission({\n collection,\n action,\n db: options.db ?? options.persistence,\n tenantId: ambient.tenantId,\n userId: ambient.userId,\n permissionSet: ambient.permissions,\n allowSystemContextBypass: false,\n allowSuperAdminBypass: guard.allowSuperAdminBypass,\n });\n } catch (error) {\n if (error instanceof OperationPermissionError) {\n throw new TimesheetActionError(403, 'permission_denied', error.message);\n }\n throw error;\n }\n if (!ambient.tenantId || !ambient.userId) {\n throw new TimesheetActionError(\n 403,\n 'permission_denied',\n 'Time entry actions need an authenticated tenant context.',\n );\n }\n const profileId =\n ambient.profileId ?? (await loadProfileId(ambient.userId, options));\n if (!profileId) {\n throw new TimesheetActionError(\n 403,\n 'actor_profile_required',\n 'Time entry actions need a user with a linked profile.',\n );\n }\n return {\n tenantId: ambient.tenantId,\n userId: ambient.userId,\n permissions: ambient.permissions,\n profileId,\n fromTenancy: ambient.fromTenancy,\n };\n}\n\n/**\n * Run `fn` with the tenancy ALS carrying `principal`, so the tenancy\n * interceptor scopes every read and write. A session-only principal is\n * entered with the same tenant, user and permissions; nothing is widened.\n */\nexport async function withActionPrincipal<T>(\n principal: TimesheetActionPrincipal,\n fn: () => Promise<T>,\n): Promise<T> {\n if (principal.fromTenancy) return fn();\n return withTenant(\n {\n tenantId: principal.tenantId,\n userId: principal.userId,\n permissions: new Set(principal.permissions),\n },\n fn,\n );\n}\n","import type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport {\n ServiceChargeSnapshotCollection,\n ServiceCompensationSnapshotCollection,\n} from '../models/service-snapshots.js';\nimport type { ServiceTimeEntry } from '../models/service-time-entry.js';\nimport {\n SERVICE_DURATION_HOURS_EVIDENCE,\n ServiceTimeEntryCollection,\n validateDurationHours,\n} from '../models/service-time-entry.js';\nimport type {\n ServiceEvidence,\n ServiceParticipantKind,\n ServiceTimeEntrySource,\n} from '../types.js';\n\n/**\n * Input for {@link ServiceEvidenceService.record}. The work reference is the\n * qualified class name and id of whatever the time was spent on.\n */\nexport interface RecordServiceTimeInput {\n tenantId?: string | null;\n workRefType?: string | null;\n workRefId?: string | null;\n participantKind: ServiceParticipantKind;\n participantProfileId?: string | null;\n agentRef?: string;\n source: ServiceTimeEntrySource;\n description: string;\n startedAt?: Date | null;\n endedAt?: Date | null;\n durationSeconds?: number | null;\n /** Exact positive decimal text; exclusive with seconds and timestamps. */\n durationHours?: string;\n evidence?: ServiceEvidence[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface CommercialSnapshot {\n /**\n * Integer minor units of `currency` — `$19.99` is `1999` (#2401).\n *\n * Written straight into `ServiceChargeSnapshot.amount` /\n * `ServiceCompensationSnapshot.amount`, INTEGER columns whose `save()`\n * refuses anything but a safe integer on every engine. A fractional\n * major-unit value (`19.99`) is rejected; a whole one (`150` for $150.00)\n * is not detectable and is stored 100× too small, so return minor units.\n */\n amount: number;\n currency?: string;\n version: string;\n strategy?: string;\n terms: Record<string, unknown>;\n sourceRef?: string;\n}\n\nexport interface ServiceCommercialResolver {\n /** Pure preflight: reject unsupported evidence before approval or snapshot writes. */\n validateEntry?(entry: ServiceTimeEntry): void | Promise<void>;\n priceClient(entry: ServiceTimeEntry): Promise<CommercialSnapshot>;\n compensateProvider(entry: ServiceTimeEntry): Promise<CommercialSnapshot>;\n}\n\n/**\n * Records, submits, approves, and corrects time entries. Approval writes one\n * immutable client-charge and one provider-compensation snapshot per entry;\n * a correction is a new entry pointing at the approved one, which flips to\n * `corrected` with its snapshots intact.\n */\nexport class ServiceEvidenceService {\n constructor(\n private readonly entries: ServiceTimeEntryCollection,\n private readonly charges: ServiceChargeSnapshotCollection,\n private readonly compensation: ServiceCompensationSnapshotCollection,\n private readonly commercial?: ServiceCommercialResolver,\n ) {}\n\n static async create(\n options: SmrtClassOptions = {},\n commercial?: ServiceCommercialResolver,\n ): Promise<ServiceEvidenceService> {\n const [entries, charges, compensation] = await Promise.all([\n ServiceTimeEntryCollection.create(options),\n ServiceChargeSnapshotCollection.create(options),\n ServiceCompensationSnapshotCollection.create(options),\n ]);\n return new ServiceEvidenceService(\n entries,\n charges,\n compensation,\n commercial,\n );\n }\n\n async record(input: RecordServiceTimeInput): Promise<ServiceTimeEntry> {\n if (!['timer', 'manual', 'import', 'agent'].includes(input.source))\n throw new Error('Unsupported service time source.');\n if (Boolean(input.workRefType) !== Boolean(input.workRefId))\n throw new Error('workRefType and workRefId must be provided together.');\n if (!(input.workRefType && input.workRefId))\n throw new Error('Service time requires a work reference.');\n if (input.participantKind === 'human' && !input.participantProfileId)\n throw new Error('Human service time requires participantProfileId.');\n if (input.participantKind === 'agent' && !input.agentRef)\n throw new Error('Agent service time requires agentRef.');\n if (input.source === 'timer' && (!input.startedAt || !input.endedAt))\n throw new Error('Timer service time requires startedAt and endedAt.');\n if (input.startedAt && input.endedAt && input.startedAt >= input.endedAt)\n throw new Error('Service time startedAt must be before endedAt.');\n const { durationHours, ...fields } = input;\n if (\n input.evidence?.some(\n (item) => item?.kind === SERVICE_DURATION_HOURS_EVIDENCE,\n )\n )\n throw new Error(\n 'Use durationHours to supply reserved decimal-hours evidence.',\n );\n const hours =\n durationHours === undefined ? null : validateDurationHours(durationHours);\n if (\n hours !== null &&\n (input.durationSeconds != null || input.startedAt || input.endedAt)\n )\n throw new Error(\n 'Decimal-hours-only service time cannot also supply seconds or timestamps.',\n );\n if (hours === null && input.durationSeconds === null)\n throw new Error('Null durationSeconds requires durationHours.');\n const duration =\n hours !== null\n ? null\n : (input.durationSeconds ??\n (input.startedAt && input.endedAt\n ? Math.round(\n (input.endedAt.getTime() - input.startedAt.getTime()) / 1000,\n )\n : 0));\n if (duration !== null && (!Number.isSafeInteger(duration) || duration <= 0))\n throw new Error(\n 'Service time durationSeconds must be a positive integer.',\n );\n const entry = await this.entries.create({\n ...fields,\n durationSeconds: duration,\n evidence: JSON.stringify([\n ...(input.evidence ?? []),\n ...(hours === null\n ? []\n : [{ kind: SERVICE_DURATION_HOURS_EVIDENCE, hours }]),\n ]),\n metadata: JSON.stringify(input.metadata ?? {}),\n status: 'draft',\n submittedAt: null,\n submittedByProfileId: null,\n approvedAt: null,\n approvedByProfileId: null,\n approvalPath: '',\n rejectedAt: null,\n rejectedByProfileId: null,\n rejectionReason: '',\n correctionOfId: null,\n });\n await entry.save();\n return entry;\n }\n\n async submit(\n entry: ServiceTimeEntry,\n profileId?: string,\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'draft' && entry.status !== 'rejected')\n throw new Error('Only draft or rejected service time may be submitted.');\n entry.status = 'submitted';\n entry.submittedAt = new Date();\n entry.submittedByProfileId = profileId ?? null;\n return entry.save();\n }\n\n async approve(\n entry: ServiceTimeEntry,\n options: { actorProfileId?: string; approvalPath: string },\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'submitted' && entry.status !== 'approved')\n throw new Error(\n 'Only submitted service time or an incomplete approval may be approved.',\n );\n if (!this.commercial)\n throw new Error(\n 'A ServiceCommercialResolver is required to approve service time.',\n );\n const timeEntryId = entry.id;\n if (!timeEntryId)\n throw new Error('ServiceTimeEntry must be saved before approval.');\n const existingCharge = (\n await this.charges.list({ where: { timeEntryId }, limit: 1 })\n )[0];\n const existingCompensation = (\n await this.compensation.list({ where: { timeEntryId }, limit: 1 })\n )[0];\n if (entry.status === 'approved' && existingCharge && existingCompensation)\n return entry;\n\n await this.commercial.validateEntry?.(entry);\n\n // Commit approval before either commercial resolver runs. The subscription\n // resolver creates an approved ClientCharge as part of priceClient(), so a\n // failed approval must never leave billable spend behind.\n if (entry.status === 'submitted') {\n entry.status = 'approved';\n entry.approvedAt = new Date();\n entry.approvedByProfileId = options.actorProfileId ?? null;\n entry.approvalPath = options.approvalPath;\n try {\n await entry.save();\n } catch (error) {\n const revisionConflict =\n error instanceof Error &&\n 'code' in error &&\n error.code === 'RUNTIME_REVISION_CONFLICT';\n if (!revisionConflict) throw error;\n const concurrent = await this.entries.get(timeEntryId);\n if (concurrent?.status !== 'approved') throw error;\n entry = concurrent;\n await this.commercial.validateEntry?.(entry);\n }\n }\n const provider = existingCompensation\n ? null\n : await this.commercial.compensateProvider(entry);\n if (provider) {\n const snapshotId = await deterministicSnapshotId(\n 'service-compensation-snapshot',\n timeEntryId,\n );\n try {\n await this.compensation.create({\n id: snapshotId,\n tenantId: entry.tenantId,\n timeEntryId,\n amount: provider.amount,\n currency: provider.currency ?? 'USD',\n termsVersion: provider.version,\n rateSnapshot: JSON.stringify(provider.terms),\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent =\n (await this.compensation.get(snapshotId)) ??\n (\n await this.compensation.list({\n where: { timeEntryId },\n limit: 1,\n })\n )[0];\n if (!concurrent) throw error;\n }\n }\n const client = existingCharge\n ? null\n : await this.commercial.priceClient(entry);\n if (client) {\n const snapshotId = await deterministicSnapshotId(\n 'service-charge-snapshot',\n timeEntryId,\n );\n try {\n await this.charges.create({\n id: snapshotId,\n tenantId: entry.tenantId,\n timeEntryId,\n amount: client.amount,\n currency: client.currency ?? 'USD',\n pricingVersion: client.version,\n strategy: client.strategy ?? '',\n rateSnapshot: JSON.stringify(client.terms),\n sourceChargeRef: client.sourceRef ?? '',\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent =\n (await this.charges.get(snapshotId)) ??\n (\n await this.charges.list({\n where: { timeEntryId },\n limit: 1,\n })\n )[0];\n if (!concurrent) throw error;\n }\n }\n return entry;\n }\n\n async correct(\n entry: ServiceTimeEntry,\n input: RecordServiceTimeInput,\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'approved')\n throw new Error('Only approved service time may be corrected.');\n if (input.tenantId !== undefined && input.tenantId !== entry.tenantId) {\n throw new Error(\n 'Service time corrections must remain in the original tenant.',\n );\n }\n const correction = await this.record({\n ...input,\n tenantId: entry.tenantId,\n });\n correction.correctionOfId = entry.id ?? null;\n await correction.save();\n entry.status = 'corrected';\n await entry.save();\n return correction;\n }\n}\n\nasync function deterministicSnapshotId(\n kind: string,\n timeEntryId: string,\n): Promise<string> {\n const bytes = new TextEncoder().encode(JSON.stringify([kind, timeEntryId]));\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));\n const uuid = digest.slice(0, 16);\n uuid[6] = (uuid[6] & 0x0f) | 0x50;\n uuid[8] = (uuid[8] & 0x3f) | 0x80;\n const hex = Array.from(uuid, (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('');\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20),\n ].join('-');\n}\n","/**\n * Service-backed write actions for `ServiceTimeEntry` (#4001).\n *\n * The generated CRUD writes stay closed: these are the only generated write\n * path, and each delegates to {@link ServiceEvidenceService}, so the status\n * machine, the submission/approval trail and the charge/compensation\n * snapshots are set in exactly one place. The thin collection methods in\n * `models/service-time-entry.ts` call in here.\n */\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport {\n ServiceChargeSnapshotCollection,\n ServiceCompensationSnapshotCollection,\n} from '../models/service-snapshots.js';\nimport type {\n ServiceTimeEntry,\n ServiceTimeEntryCollection,\n} from '../models/service-time-entry.js';\nimport type { ServiceEvidence } from '../types.js';\nimport {\n authorizeTimesheetAction,\n principalHolds,\n TimesheetActionError,\n type TimesheetActionPrincipal,\n withActionPrincipal,\n} from './action-principal.js';\nimport {\n type ServiceCommercialResolver,\n ServiceEvidenceService,\n} from './service-evidence-service.js';\n\n/** Approval path stamped by the generated `approve` action. */\nexport const SERVICE_TIME_ENTRY_ACTION_APPROVAL_PATH = 'operator';\n\n/**\n * What `approve` prices with: a resolver, or a factory the action calls per\n * request with the collection's options. Use the factory whenever the\n * resolver writes (e.g. smrt-projects' `SubscriptionServiceCommercialResolver`\n * records client charges): `options.db` is the request-bound executor, so\n * those writes share the request's transaction and PostgreSQL RLS state\n * instead of a connection captured at startup.\n */\nexport type ServiceTimeEntryCommercialResolverSource =\n | ServiceCommercialResolver\n | ((context: {\n options: SmrtClassOptions;\n }) => ServiceCommercialResolver | Promise<ServiceCommercialResolver>);\n\nlet actionCommercialResolver: ServiceTimeEntryCommercialResolverSource | null =\n null;\n\n/**\n * Install what the generated `approve` action prices with. Pass `null` to\n * remove it. Without one, `approve` refuses with 409\n * (`approval_not_configured`) and writes nothing.\n *\n * @example\n * ```ts\n * setServiceTimeEntryCommercialResolver(({ options }) =>\n * SubscriptionServiceCommercialResolver.create(options, provider),\n * );\n * ```\n */\nexport function setServiceTimeEntryCommercialResolver(\n resolver: ServiceTimeEntryCommercialResolverSource | null,\n): void {\n actionCommercialResolver = resolver;\n}\n\n/** The source installed by {@link setServiceTimeEntryCommercialResolver}. */\nexport function getServiceTimeEntryCommercialResolver(): ServiceTimeEntryCommercialResolverSource | null {\n return actionCommercialResolver;\n}\n\n/** Body of the `record` action. Identity and tenant come from the session. */\nexport interface RecordServiceTimeActionInput {\n workRefType: string;\n workRefId: string;\n /** Defaults to the acting user's profile; another person needs `approve`. */\n participantProfileId?: string | null;\n /** `manual` (default) or `timer`; imports and agents use the service. */\n source?: 'manual' | 'timer';\n description?: string;\n /** ISO 8601 instant. */\n startedAt?: string | null;\n /** ISO 8601 instant. */\n endedAt?: string | null;\n durationSeconds?: number | null;\n /** Exact positive decimal text; exclusive with seconds and timestamps. */\n durationHours?: string;\n evidence?: ServiceEvidence[];\n metadata?: Record<string, unknown>;\n}\n\n/** Body of the `submit` and `approve` actions. */\nexport interface ServiceTimeEntryActionTarget {\n entryId: string;\n}\n\ntype ActionOptions = SmrtClassOptions;\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n 'The action body must be a JSON object.',\n );\n }\n return value as Record<string, unknown>;\n}\n\nfunction optionalString(\n body: Record<string, unknown>,\n key: string,\n): string | undefined {\n const value = body[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n `${key} must be a string.`,\n );\n }\n return value;\n}\n\nfunction requiredString(body: Record<string, unknown>, key: string): string {\n const value = optionalString(body, key)?.trim();\n if (!value) {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n `${key} is required.`,\n );\n }\n return value;\n}\n\nfunction optionalInstant(\n body: Record<string, unknown>,\n key: string,\n): Date | null {\n const value = optionalString(body, key);\n if (value === undefined) return null;\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n `${key} must be an ISO 8601 instant.`,\n );\n }\n return date;\n}\n\n/**\n * Plain `Error`s from {@link ServiceEvidenceService} are its own input and\n * state preconditions; surface them as 400 instead of an opaque 500. Typed\n * errors (database, revision conflicts) pass through unchanged.\n */\nasync function serviceCall<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n if (error instanceof Error && error.constructor === Error) {\n throw new TimesheetActionError(400, 'invalid_request', error.message);\n }\n throw error;\n }\n}\n\nasync function evidenceService(\n entries: ServiceTimeEntryCollection,\n commercial?: ServiceCommercialResolver,\n): Promise<ServiceEvidenceService> {\n const options = entries.options;\n const [charges, compensation] = await Promise.all([\n ServiceChargeSnapshotCollection.create(options),\n ServiceCompensationSnapshotCollection.create(options),\n ]);\n return new ServiceEvidenceService(entries, charges, compensation, commercial);\n}\n\nfunction itemClass(entries: ServiceTimeEntryCollection) {\n return (entries.constructor as unknown as { _itemClass: unknown })\n ._itemClass as typeof ServiceTimeEntry;\n}\n\nasync function loadEntry(\n entries: ServiceTimeEntryCollection,\n principal: TimesheetActionPrincipal,\n body: Record<string, unknown>,\n): Promise<ServiceTimeEntry> {\n const entryId = requiredString(body, 'entryId');\n const entry = await entries.get({ id: entryId });\n // Optional tenancy also admits global (NULL-tenant) rows in a tenant\n // context; a write must land on the principal's own tenant only.\n if (!entry || (entry.tenantId ?? null) !== principal.tenantId) {\n throw new TimesheetActionError(\n 404,\n 'not_found',\n `Service time entry ${entryId} was not found.`,\n );\n }\n return entry;\n}\n\n/** `record`: create a draft entry through `ServiceEvidenceService.record()`. */\nexport async function recordServiceTimeAction(\n entries: ServiceTimeEntryCollection,\n input: unknown,\n): Promise<ServiceTimeEntry> {\n const body = asRecord(input);\n const principal = await authorizeTimesheetAction(\n itemClass(entries),\n 'record',\n entries.options as ActionOptions,\n { allowSuperAdminBypass: true },\n );\n const participantProfileId =\n optionalString(body, 'participantProfileId')?.trim() || principal.profileId;\n if (\n participantProfileId !== principal.profileId &&\n !(await principalHolds(itemClass(entries), 'approve', entries.options))\n ) {\n throw new TimesheetActionError(\n 403,\n 'permission_denied',\n \"Recording another person's time needs the approve permission.\",\n );\n }\n const source = optionalString(body, 'source') ?? 'manual';\n if (source !== 'manual' && source !== 'timer') {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n \"source must be 'manual' or 'timer'.\",\n );\n }\n const durationSeconds = body.durationSeconds;\n if (\n durationSeconds !== undefined &&\n durationSeconds !== null &&\n typeof durationSeconds !== 'number'\n ) {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n 'durationSeconds must be a number.',\n );\n }\n const evidence = body.evidence;\n if (evidence !== undefined && !Array.isArray(evidence)) {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n 'evidence must be an array.',\n );\n }\n const metadata = body.metadata;\n if (\n metadata !== undefined &&\n (metadata === null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata))\n ) {\n throw new TimesheetActionError(\n 400,\n 'invalid_request',\n 'metadata must be an object.',\n );\n }\n return withActionPrincipal(principal, async () => {\n const service = await evidenceService(entries);\n return serviceCall(() =>\n service.record({\n tenantId: principal.tenantId,\n workRefType: requiredString(body, 'workRefType'),\n workRefId: requiredString(body, 'workRefId'),\n participantKind: 'human',\n participantProfileId,\n source,\n description: optionalString(body, 'description') ?? '',\n startedAt: optionalInstant(body, 'startedAt'),\n endedAt: optionalInstant(body, 'endedAt'),\n ...(durationSeconds !== undefined\n ? { durationSeconds: durationSeconds as number | null }\n : {}),\n ...(body.durationHours !== undefined\n ? { durationHours: optionalString(body, 'durationHours') }\n : {}),\n ...(evidence ? { evidence: evidence as ServiceEvidence[] } : {}),\n ...(metadata ? { metadata: metadata as Record<string, unknown> } : {}),\n }),\n );\n });\n}\n\n/**\n * `submit`: `draft | rejected → submitted` through\n * `ServiceEvidenceService.submit()`, stamping `submittedAt` and the acting\n * profile. Only the entry's participant may submit it, unless the caller\n * holds `approve` (a supervisor submitting on someone's behalf).\n */\nexport async function submitServiceTimeAction(\n entries: ServiceTimeEntryCollection,\n input: unknown,\n): Promise<ServiceTimeEntry> {\n const body = asRecord(input);\n const principal = await authorizeTimesheetAction(\n itemClass(entries),\n 'submit',\n entries.options,\n { allowSuperAdminBypass: true },\n );\n return withActionPrincipal(principal, async () => {\n const entry = await loadEntry(entries, principal, body);\n if (\n entry.participantProfileId !== principal.profileId &&\n !(await principalHolds(itemClass(entries), 'approve', entries.options))\n ) {\n throw new TimesheetActionError(\n 403,\n 'permission_denied',\n \"Submitting another person's time needs the approve permission.\",\n );\n }\n const service = await evidenceService(entries);\n return serviceCall(() => service.submit(entry, principal.profileId));\n });\n}\n\n/**\n * `approve`: `submitted → approved` through `ServiceEvidenceService.approve()`,\n * which stamps `approvedAt`, the acting profile and the approval path, then\n * writes the immutable charge and compensation snapshots through the\n * installed {@link setServiceTimeEntryCommercialResolver resolver} (a factory\n * is called per request with the collection's options). Money:\n * super-admin bypass does not apply, the grant must be explicit.\n */\nexport async function approveServiceTimeAction(\n entries: ServiceTimeEntryCollection,\n input: unknown,\n): Promise<ServiceTimeEntry> {\n const body = asRecord(input);\n const principal = await authorizeTimesheetAction(\n itemClass(entries),\n 'approve',\n entries.options,\n { allowSuperAdminBypass: false },\n );\n const source = actionCommercialResolver;\n if (!source) {\n throw new TimesheetActionError(\n // A 4xx so generated transports return the message; the host has not\n // installed the pricing the approval needs.\n 409,\n 'approval_not_configured',\n 'No ServiceCommercialResolver is installed for time entry approval.',\n );\n }\n return withActionPrincipal(principal, async () => {\n const entry = await loadEntry(entries, principal, body);\n // Built per request inside the principal's tenancy context, on the same\n // options (and so the same request-bound executor) as the entries.\n const commercial =\n typeof source === 'function'\n ? await source({ options: entries.options })\n : source;\n const service = await evidenceService(entries, commercial);\n return serviceCall(() =>\n service.approve(entry, {\n actorProfileId: principal.profileId,\n approvalPath: SERVICE_TIME_ENTRY_ACTION_APPROVAL_PATH,\n }),\n );\n });\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { a as setServiceTimeEntryCommercialResolver, c as ServiceEvidenceService, d as ServiceChargeSnapshotCollection, f as ServiceCompensationSnapshot, i as recordServiceTimeAction, l as TimesheetActionError, n as approveServiceTimeAction, o as submitServiceTimeAction, p as ServiceCompensationSnapshotCollection, r as getServiceTimeEntryCommercialResolver, t as SERVICE_TIME_ENTRY_ACTION_APPROVAL_PATH, u as ServiceChargeSnapshot } from "./chunks/time-entry-actions-BMX7Hi78.js";
2
- import { i as ServiceTimeEntryCollection, n as SERVICE_TIME_ENTRY_FROZEN_FIELDS, r as ServiceTimeEntry, t as SERVICE_DURATION_HOURS_EVIDENCE } from "./chunks/service-time-entry-DPXY5qo3.js";
3
- import { a as AttendanceReplay, c as AttendanceSegmentCollection, i as AttendancePunchCollection, n as AttendanceBreakCollection, o as AttendanceReplayCollection, r as AttendancePunch, s as AttendanceSegment, t as AttendanceBreak } from "./chunks/models-CAELan0E.js";
4
- import { a as continueSegment, c as openSegment, d as validateAttendanceWork, f as ATTENDANCE_CORRECTION_KINDS, i as closeOpenSegment, l as replaceSegment, m as AttendanceCorrectionCollection, n as AttendanceService, o as endSegment, p as AttendanceCorrection, r as beginSegment, s as listSegments, t as AttendanceCorrectionService, u as AttendanceConflict } from "./chunks/attendance-BVFIB2S4.js";
1
+ import { a as setServiceTimeEntryCommercialResolver, c as ServiceEvidenceService, d as ServiceChargeSnapshotCollection, f as ServiceCompensationSnapshot, i as recordServiceTimeAction, l as TimesheetActionError, n as approveServiceTimeAction, o as submitServiceTimeAction, p as ServiceCompensationSnapshotCollection, r as getServiceTimeEntryCommercialResolver, t as SERVICE_TIME_ENTRY_ACTION_APPROVAL_PATH, u as ServiceChargeSnapshot } from "./chunks/time-entry-actions-vYZoqn-M.js";
2
+ import { i as ServiceTimeEntryCollection, n as SERVICE_TIME_ENTRY_FROZEN_FIELDS, r as ServiceTimeEntry, t as SERVICE_DURATION_HOURS_EVIDENCE } from "./chunks/service-time-entry-DKwDyfK8.js";
3
+ import { a as AttendanceReplay, c as AttendanceSegmentCollection, i as AttendancePunchCollection, n as AttendanceBreakCollection, o as AttendanceReplayCollection, r as AttendancePunch, s as AttendanceSegment, t as AttendanceBreak } from "./chunks/models-CZHyHdrZ.js";
4
+ import { a as continueSegment, c as openSegment, d as validateAttendanceWork, f as ATTENDANCE_CORRECTION_KINDS, i as closeOpenSegment, l as replaceSegment, m as AttendanceCorrectionCollection, n as AttendanceService, o as endSegment, p as AttendanceCorrection, r as beginSegment, s as listSegments, t as AttendanceCorrectionService, u as AttendanceConflict } from "./chunks/attendance-AkgSOl0A.js";
5
5
  import { SERVICE_TIME_ENTRY_STATUS_TRANSITIONS } from "./types.js";
6
- import { a as confirmedTimecardGuard, c as TimecardAdjustment, d as TimecardReopeningCollection, l as TimecardAdjustmentCollection, o as PeriodTimecard, s as PeriodTimecardCollection, t as PeriodRollupService, u as TimecardReopening } from "./chunks/rollup-mrKeGtnv.js";
6
+ import { a as confirmedTimecardGuard, c as TimecardAdjustment, d as TimecardReopeningCollection, l as TimecardAdjustmentCollection, o as PeriodTimecard, s as PeriodTimecardCollection, t as PeriodRollupService, u as TimecardReopening } from "./chunks/rollup-HumZW4EB.js";
7
7
  import { TIMESHEETS_MODULE_META, TIMESHEETS_UI_SLOTS } from "./ui.js";
8
8
  import { SmrtRecipe } from "@happyvertical/smrt-core";
9
9
  //#region src/recipes.ts
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-timesheets",
5
- "packageVersion": "0.57.37",
5
+ "packageVersion": "0.57.39",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-timesheets:AttendanceCorrection": {
8
8
  "name": "attendancecorrection",
@@ -107,7 +107,13 @@
107
107
  "save": {
108
108
  "name": "save",
109
109
  "async": true,
110
- "parameters": [],
110
+ "parameters": [
111
+ {
112
+ "name": "options",
113
+ "type": "SmrtSaveOptions",
114
+ "optional": true
115
+ }
116
+ ],
111
117
  "returnType": "Promise<this>",
112
118
  "isStatic": false,
113
119
  "isPublic": true
@@ -613,7 +619,13 @@
613
619
  "save": {
614
620
  "name": "save",
615
621
  "async": true,
616
- "parameters": [],
622
+ "parameters": [
623
+ {
624
+ "name": "options",
625
+ "type": "SmrtSaveOptions",
626
+ "optional": true
627
+ }
628
+ ],
617
629
  "returnType": "Promise<this>",
618
630
  "isStatic": false,
619
631
  "isPublic": true
@@ -935,7 +947,13 @@
935
947
  "save": {
936
948
  "name": "save",
937
949
  "async": true,
938
- "parameters": [],
950
+ "parameters": [
951
+ {
952
+ "name": "options",
953
+ "type": "SmrtSaveOptions",
954
+ "optional": true
955
+ }
956
+ ],
939
957
  "returnType": "Promise<this>",
940
958
  "isStatic": false,
941
959
  "isPublic": true
@@ -1210,7 +1228,13 @@
1210
1228
  "save": {
1211
1229
  "name": "save",
1212
1230
  "async": true,
1213
- "parameters": [],
1231
+ "parameters": [
1232
+ {
1233
+ "name": "options",
1234
+ "type": "SmrtSaveOptions",
1235
+ "optional": true
1236
+ }
1237
+ ],
1214
1238
  "returnType": "Promise<this>",
1215
1239
  "isStatic": false,
1216
1240
  "isPublic": true
@@ -1563,7 +1587,13 @@
1563
1587
  "save": {
1564
1588
  "name": "save",
1565
1589
  "async": true,
1566
- "parameters": [],
1590
+ "parameters": [
1591
+ {
1592
+ "name": "options",
1593
+ "type": "SmrtSaveOptions",
1594
+ "optional": true
1595
+ }
1596
+ ],
1567
1597
  "returnType": "Promise<this>",
1568
1598
  "isStatic": false,
1569
1599
  "isPublic": true
@@ -2425,7 +2455,13 @@
2425
2455
  "save": {
2426
2456
  "name": "save",
2427
2457
  "async": true,
2428
- "parameters": [],
2458
+ "parameters": [
2459
+ {
2460
+ "name": "options",
2461
+ "type": "SmrtSaveOptions",
2462
+ "optional": true
2463
+ }
2464
+ ],
2429
2465
  "returnType": "Promise<this>",
2430
2466
  "isStatic": false,
2431
2467
  "isPublic": true
@@ -2649,7 +2685,13 @@
2649
2685
  "save": {
2650
2686
  "name": "save",
2651
2687
  "async": true,
2652
- "parameters": [],
2688
+ "parameters": [
2689
+ {
2690
+ "name": "options",
2691
+ "type": "SmrtSaveOptions",
2692
+ "optional": true
2693
+ }
2694
+ ],
2653
2695
  "returnType": "Promise<this>",
2654
2696
  "isStatic": false,
2655
2697
  "isPublic": true
@@ -3299,7 +3341,13 @@
3299
3341
  "save": {
3300
3342
  "name": "save",
3301
3343
  "async": true,
3302
- "parameters": [],
3344
+ "parameters": [
3345
+ {
3346
+ "name": "options",
3347
+ "type": "SmrtSaveOptions",
3348
+ "optional": true
3349
+ }
3350
+ ],
3303
3351
  "returnType": "Promise<this>",
3304
3352
  "isStatic": false,
3305
3353
  "isPublic": true
@@ -4024,7 +4072,13 @@
4024
4072
  "save": {
4025
4073
  "name": "save",
4026
4074
  "async": true,
4027
- "parameters": [],
4075
+ "parameters": [
4076
+ {
4077
+ "name": "options",
4078
+ "type": "SmrtSaveOptions",
4079
+ "optional": true
4080
+ }
4081
+ ],
4028
4082
  "returnType": "Promise<this>",
4029
4083
  "isStatic": false,
4030
4084
  "isPublic": true
@@ -4309,7 +4363,13 @@
4309
4363
  "save": {
4310
4364
  "name": "save",
4311
4365
  "async": true,
4312
- "parameters": [],
4366
+ "parameters": [
4367
+ {
4368
+ "name": "options",
4369
+ "type": "SmrtSaveOptions",
4370
+ "optional": true
4371
+ }
4372
+ ],
4313
4373
  "returnType": "Promise<this>",
4314
4374
  "isStatic": false,
4315
4375
  "isPublic": true
@@ -4568,7 +4628,13 @@
4568
4628
  "save": {
4569
4629
  "name": "save",
4570
4630
  "async": true,
4571
- "parameters": [],
4631
+ "parameters": [
4632
+ {
4633
+ "name": "options",
4634
+ "type": "SmrtSaveOptions",
4635
+ "optional": true
4636
+ }
4637
+ ],
4572
4638
  "returnType": "Promise<this>",
4573
4639
  "isStatic": false,
4574
4640
  "isPublic": true
@@ -1,4 +1,4 @@
1
- import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
1
+ import { SmrtCollection, SmrtObject, type SmrtSaveOptions } from '@happyvertical/smrt-core';
2
2
  /**
3
3
  * Refuse an amount that is not a JavaScript-safe integer number of minor
4
4
  * units. SQLite stores `19.99` in an INTEGER column without complaint and
@@ -31,7 +31,7 @@ export declare class ServiceChargeSnapshot extends SmrtObject {
31
31
  sourceChargeRef: string;
32
32
  createdAt: Date;
33
33
  initialize(): Promise<this>;
34
- save(): Promise<this>;
34
+ save(options?: SmrtSaveOptions): Promise<this>;
35
35
  }
36
36
  /**
37
37
  * Immutable provider-compensation snapshot for one approved time entry,
@@ -53,7 +53,7 @@ export declare class ServiceCompensationSnapshot extends SmrtObject {
53
53
  rateSnapshot: string;
54
54
  createdAt: Date;
55
55
  initialize(): Promise<this>;
56
- save(): Promise<this>;
56
+ save(options?: SmrtSaveOptions): Promise<this>;
57
57
  }
58
58
  /** Collection over `service_charge_snapshots`. */
59
59
  export declare class ServiceChargeSnapshotCollection extends SmrtCollection<ServiceChargeSnapshot> {
@@ -1 +1 @@
1
- {"version":3,"file":"service-snapshots.d.ts","sourceRoot":"","sources":["../../src/models/service-snapshots.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,UAAU,EAGX,MAAM,0BAA0B,CAAC;AAGlC;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAa7E;AAoDD;;;GAGG;AACH,qBAYa,qBAAsB,SAAQ,UAAU;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACT,WAAW,EAAE,MAAM,CAAM;IAC7E;;;;;;;;OAQG;IACH,MAAM,EAAE,MAAM,CAAK;IACM,QAAQ,EAAE,MAAM,CAAS;IACzB,cAAc,EAAE,MAAM,CAAM;IAC5B,QAAQ,EAAE,MAAM,CAAM;IACtB,YAAY,EAAE,MAAM,CAAQ;IAC5B,eAAe,EAAE,MAAM,CAAM;IACtD,SAAS,EAAE,IAAI,CAAc;IAEd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAkBrC;AAED;;;GAGG;AACH,qBAYa,2BAA4B,SAAQ,UAAU;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACT,WAAW,EAAE,MAAM,CAAM;IAC7E;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAK;IACM,QAAQ,EAAE,MAAM,CAAS;IACzB,YAAY,EAAE,MAAM,CAAM;IAC1B,YAAY,EAAE,MAAM,CAAQ;IACrD,SAAS,EAAE,IAAI,CAAc;IAEd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAkBrC;AAED,kDAAkD;AAIlD,qBACa,+BAAgC,SAAQ,cAAc,CAAC,qBAAqB,CAAC;IACxF,MAAM,CAAC,QAAQ,CAAC,UAAU,+BAAyB;CACpD;AACD,wDAAwD;AAIxD,qBACa,qCAAsC,SAAQ,cAAc,CAAC,2BAA2B,CAAC;IACpG,MAAM,CAAC,QAAQ,CAAC,UAAU,qCAA+B;CAC1D"}
1
+ {"version":3,"file":"service-snapshots.d.ts","sourceRoot":"","sources":["../../src/models/service-snapshots.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,UAAU,EACV,KAAK,eAAe,EAGrB,MAAM,0BAA0B,CAAC;AAGlC;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAa7E;AAoDD;;;GAGG;AACH,qBAYa,qBAAsB,SAAQ,UAAU;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACT,WAAW,EAAE,MAAM,CAAM;IAC7E;;;;;;;;OAQG;IACH,MAAM,EAAE,MAAM,CAAK;IACM,QAAQ,EAAE,MAAM,CAAS;IACzB,cAAc,EAAE,MAAM,CAAM;IAC5B,QAAQ,EAAE,MAAM,CAAM;IACtB,YAAY,EAAE,MAAM,CAAQ;IAC5B,eAAe,EAAE,MAAM,CAAM;IACtD,SAAS,EAAE,IAAI,CAAc;IAEd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAkB9D;AAED;;;GAGG;AACH,qBAYa,2BAA4B,SAAQ,UAAU;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACT,WAAW,EAAE,MAAM,CAAM;IAC7E;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAK;IACM,QAAQ,EAAE,MAAM,CAAS;IACzB,YAAY,EAAE,MAAM,CAAM;IAC1B,YAAY,EAAE,MAAM,CAAQ;IACrD,SAAS,EAAE,IAAI,CAAc;IAEd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAkB9D;AAED,kDAAkD;AAIlD,qBACa,+BAAgC,SAAQ,cAAc,CAAC,qBAAqB,CAAC;IACxF,MAAM,CAAC,QAAQ,CAAC,UAAU,+BAAyB;CACpD;AACD,wDAAwD;AAIxD,qBACa,qCAAsC,SAAQ,cAAc,CAAC,2BAA2B,CAAC;IACpG,MAAM,CAAC,QAAQ,CAAC,UAAU,qCAA+B;CAC1D"}
@@ -1,4 +1,4 @@
1
- import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
1
+ import { SmrtCollection, SmrtObject, type SmrtSaveOptions } from '@happyvertical/smrt-core';
2
2
  import type { RecordServiceTimeActionInput, ServiceTimeEntryActionTarget } from '../services/time-entry-actions.js';
3
3
  import { type ServiceEvidence, type ServiceParticipantKind, type ServiceTimeEntrySource, type ServiceTimeEntryStatus } from '../types.js';
4
4
  /**
@@ -68,7 +68,7 @@ export declare class ServiceTimeEntry extends SmrtObject {
68
68
  */
69
69
  protected frozenFieldNames(): readonly string[];
70
70
  initialize(): Promise<this>;
71
- save(): Promise<this>;
71
+ save(options?: SmrtSaveOptions): Promise<this>;
72
72
  private readPrior;
73
73
  }
74
74
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"service-time-entry.d.ts","sourceRoot":"","sources":["../../src/models/service-time-entry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service-time-entry.d.ts","sourceRoot":"","sources":["../../src/models/service-time-entry.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
1
+ import { SmrtCollection, SmrtObject, type SmrtSaveOptions } from '@happyvertical/smrt-core';
2
2
  import type { TimecardSource } from './types.js';
3
3
  /** `open` is the draft state; `submitted` is optional (see `PeriodRollupService`). */
4
4
  export type TimecardStatus = 'open' | 'submitted' | 'confirmed';
@@ -25,7 +25,7 @@ export declare class PeriodTimecard extends SmrtObject {
25
25
  getSources(): TimecardSource[];
26
26
  /** Return the consumer policy frozen with this rollup. */
27
27
  getRules(): Record<string, unknown>;
28
- save(): Promise<this>;
28
+ save(options?: SmrtSaveOptions): Promise<this>;
29
29
  delete(): Promise<void>;
30
30
  }
31
31
  /** Attributed append-only signed seconds; the confirmed base card never changes. */
@@ -38,7 +38,7 @@ export declare class TimecardAdjustment extends SmrtObject {
38
38
  regularSeconds: number;
39
39
  overtimeSeconds: number;
40
40
  reason: string;
41
- save(): Promise<this>;
41
+ save(options?: SmrtSaveOptions): Promise<this>;
42
42
  delete(): Promise<void>;
43
43
  }
44
44
  /**
@@ -59,7 +59,7 @@ export declare class TimecardReopening extends SmrtObject {
59
59
  previousState: string;
60
60
  /** The totals and attribution the card had when it was reopened. */
61
61
  getPrevious<T = Record<string, unknown>>(): T;
62
- save(): Promise<this>;
62
+ save(options?: SmrtSaveOptions): Promise<this>;
63
63
  delete(): Promise<void>;
64
64
  }
65
65
  /** Scoped persistence collection; mutations must use PeriodRollupService. */
@@ -1 +1 @@
1
- {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/rollup/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,sFAAsF;AACtF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;AAEhE,kFAAkF;AAClF,qBAQa,cAAe,SAAQ,UAAU;IAChC,QAAQ,SAAM;IAI1B,SAAS,SAAM;IACf,QAAQ,EAAE,IAAI,CAAe;IAC7B,MAAM,EAAE,IAAI,CAAe;IAC3B,QAAQ,SAAM;IACd,YAAY,SAAM;IACO,aAAa,SAAQ;IACrB,cAAc,SAAQ;IAC/C,cAAc,SAAK;IACnB,eAAe,SAAK;IACpB,YAAY,SAAK;IACQ,MAAM,EAAE,cAAc,CAAU;IACzD,4DAA4D;IAC5D,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAKhC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3C,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAKhC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C,8EAA8E;IAC9E,UAAU,IAAI,cAAc,EAAE;IAM9B,0DAA0D;IAC1D,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAMpB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AAED,oFAAoF;AACpF,qBAQa,kBAAmB,SAAQ,UAAU;IACpC,QAAQ,SAAM;IAC4B,UAAU,SAAM;IAItE,SAAS,SAAM;IAIf,cAAc,SAAM;IACpB,WAAW,SAAM;IACjB,cAAc,SAAK;IACnB,eAAe,SAAK;IACpB,MAAM,SAAM;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AACD;;;;;GAKG;AACH,qBAca,iBAAkB,SAAQ,UAAU;IACnC,QAAQ,SAAM;IAC4B,UAAU,SAAM;IAItE,SAAS,SAAM;IAIf,cAAc,SAAM;IACpB,WAAW,SAAM;IACQ,UAAU,EAAE,cAAc,CAAe;IACzC,MAAM,SAAM;IACrC,wFAAwF;IAC/D,aAAa,SAAQ;IAC9C,oEAAoE;IACpE,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC;IAM9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IASrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AACD,6EAA6E;AAC7E,qBAAa,wBAAyB,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC1E,MAAM,CAAC,QAAQ,CAAC,UAAU,wBAAkB;CAC7C;AACD,gDAAgD;AAChD,qBAAa,4BAA6B,SAAQ,cAAc,CAAC,kBAAkB,CAAC;IAClF,MAAM,CAAC,QAAQ,CAAC,UAAU,4BAAsB;CACjD;AACD,2CAA2C;AAC3C,qBAAa,2BAA4B,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IAChF,MAAM,CAAC,QAAQ,CAAC,UAAU,2BAAqB;CAChD"}
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/rollup/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,cAAc,EACd,UAAU,EACV,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,sFAAsF;AACtF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;AAEhE,kFAAkF;AAClF,qBAQa,cAAe,SAAQ,UAAU;IAChC,QAAQ,SAAM;IAI1B,SAAS,SAAM;IACf,QAAQ,EAAE,IAAI,CAAe;IAC7B,MAAM,EAAE,IAAI,CAAe;IAC3B,QAAQ,SAAM;IACd,YAAY,SAAM;IACO,aAAa,SAAQ;IACrB,cAAc,SAAQ;IAC/C,cAAc,SAAK;IACnB,eAAe,SAAK;IACpB,YAAY,SAAK;IACQ,MAAM,EAAE,cAAc,CAAU;IACzD,4DAA4D;IAC5D,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAKhC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3C,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAKhC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3C,8EAA8E;IAC9E,UAAU,IAAI,cAAc,EAAE;IAM9B,0DAA0D;IAC1D,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAMpB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B9C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AAED,oFAAoF;AACpF,qBAQa,kBAAmB,SAAQ,UAAU;IACpC,QAAQ,SAAM;IAC4B,UAAU,SAAM;IAItE,SAAS,SAAM;IAIf,cAAc,SAAM;IACpB,WAAW,SAAM;IACjB,cAAc,SAAK;IACnB,eAAe,SAAK;IACpB,MAAM,SAAM;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AACD;;;;;GAKG;AACH,qBAca,iBAAkB,SAAQ,UAAU;IACnC,QAAQ,SAAM;IAC4B,UAAU,SAAM;IAItE,SAAS,SAAM;IAIf,cAAc,SAAM;IACpB,WAAW,SAAM;IACQ,UAAU,EAAE,cAAc,CAAe;IACzC,MAAM,SAAM;IACrC,wFAAwF;IAC/D,aAAa,SAAQ;IAC9C,oEAAoE;IACpE,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC;IAM9B,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC;AACD,6EAA6E;AAC7E,qBAAa,wBAAyB,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC1E,MAAM,CAAC,QAAQ,CAAC,UAAU,wBAAkB;CAC7C;AACD,gDAAgD;AAChD,qBAAa,4BAA6B,SAAQ,cAAc,CAAC,kBAAkB,CAAC;IAClF,MAAM,CAAC,QAAQ,CAAC,UAAU,4BAAsB;CACjD;AACD,2CAA2C;AAC3C,qBAAa,2BAA4B,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IAChF,MAAM,CAAC,QAAQ,CAAC,UAAU,2BAAqB;CAChD"}
package/dist/rollup.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as confirmedTimecardGuard, c as TimecardAdjustment, d as TimecardReopeningCollection, l as TimecardAdjustmentCollection, o as PeriodTimecard, s as PeriodTimecardCollection, t as PeriodRollupService, u as TimecardReopening } from "./chunks/rollup-mrKeGtnv.js";
1
+ import { a as confirmedTimecardGuard, c as TimecardAdjustment, d as TimecardReopeningCollection, l as TimecardAdjustmentCollection, o as PeriodTimecard, s as PeriodTimecardCollection, t as PeriodRollupService, u as TimecardReopening } from "./chunks/rollup-HumZW4EB.js";
2
2
  export { PeriodRollupService, PeriodTimecard, PeriodTimecardCollection, TimecardAdjustment, TimecardAdjustmentCollection, TimecardReopening, TimecardReopeningCollection, confirmedTimecardGuard };
@@ -3,12 +3,12 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-timesheets",
6
- "packageVersion": "0.57.37",
6
+ "packageVersion": "0.57.39",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "d17835e98429a66e1017e3716d792ccf2598f84ca9559d55fb0ab8847833947a",
11
- "packageJson": "81078a9ed41114fbc3a1a4837d3a70832974bd4ed5447da3116540e6dce5e113",
10
+ "manifest": "e113f0b3ed4286d0751188828d2914c32fd03ca0830522d54782e11317e9ecd6",
11
+ "packageJson": "24759850b8029bea3fc8ae0dda9710b4d6d65e13cab44e85edb323700bcd91b3",
12
12
  "agents": "6771f7afb9dcff79c1d649519dd85538691c0f2753df321dbc3c1c9051c9a1bd",
13
13
  "moduleDoc:agents/period-rollup.md": "68a7427e9d15815e04e8e8e77f52041224c96dd82f93712f741d471c81feada6"
14
14
  },
@@ -203,6 +203,9 @@
203
203
  {
204
204
  "name": "save",
205
205
  "async": true,
206
+ "params": [
207
+ "options?: SmrtSaveOptions"
208
+ ],
206
209
  "returns": "Promise<this>"
207
210
  }
208
211
  ],
@@ -389,6 +392,9 @@
389
392
  {
390
393
  "name": "save",
391
394
  "async": true,
395
+ "params": [
396
+ "options?: SmrtSaveOptions"
397
+ ],
392
398
  "returns": "Promise<this>"
393
399
  }
394
400
  ],
@@ -537,6 +543,9 @@
537
543
  {
538
544
  "name": "save",
539
545
  "async": true,
546
+ "params": [
547
+ "options?: SmrtSaveOptions"
548
+ ],
540
549
  "returns": "Promise<this>"
541
550
  }
542
551
  ],
@@ -742,6 +751,9 @@
742
751
  {
743
752
  "name": "save",
744
753
  "async": true,
754
+ "params": [
755
+ "options?: SmrtSaveOptions"
756
+ ],
745
757
  "returns": "Promise<this>"
746
758
  }
747
759
  ],
@@ -862,6 +874,9 @@
862
874
  {
863
875
  "name": "save",
864
876
  "async": true,
877
+ "params": [
878
+ "options?: SmrtSaveOptions"
879
+ ],
865
880
  "returns": "Promise<this>"
866
881
  },
867
882
  {
@@ -1075,6 +1090,9 @@
1075
1090
  {
1076
1091
  "name": "save",
1077
1092
  "async": true,
1093
+ "params": [
1094
+ "options?: SmrtSaveOptions"
1095
+ ],
1078
1096
  "returns": "Promise<this>"
1079
1097
  }
1080
1098
  ],
@@ -1230,6 +1248,9 @@
1230
1248
  {
1231
1249
  "name": "save",
1232
1250
  "async": true,
1251
+ "params": [
1252
+ "options?: SmrtSaveOptions"
1253
+ ],
1233
1254
  "returns": "Promise<this>"
1234
1255
  }
1235
1256
  ],
@@ -1573,6 +1594,9 @@
1573
1594
  {
1574
1595
  "name": "save",
1575
1596
  "async": true,
1597
+ "params": [
1598
+ "options?: SmrtSaveOptions"
1599
+ ],
1576
1600
  "returns": "Promise<this>"
1577
1601
  },
1578
1602
  {
@@ -1990,6 +2014,9 @@
1990
2014
  {
1991
2015
  "name": "save",
1992
2016
  "async": true,
2017
+ "params": [
2018
+ "options?: SmrtSaveOptions"
2019
+ ],
1993
2020
  "returns": "Promise<this>"
1994
2021
  }
1995
2022
  ],
@@ -2133,6 +2160,9 @@
2133
2160
  {
2134
2161
  "name": "save",
2135
2162
  "async": true,
2163
+ "params": [
2164
+ "options?: SmrtSaveOptions"
2165
+ ],
2136
2166
  "returns": "Promise<this>"
2137
2167
  }
2138
2168
  ],
@@ -2266,6 +2296,9 @@
2266
2296
  {
2267
2297
  "name": "save",
2268
2298
  "async": true,
2299
+ "params": [
2300
+ "options?: SmrtSaveOptions"
2301
+ ],
2269
2302
  "returns": "Promise<this>"
2270
2303
  }
2271
2304
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-timesheets",
3
- "version": "0.57.37",
3
+ "version": "0.57.39",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Shared time entries for the SMRT framework: who worked how long on what, approval and correction, with immutable charge and compensation snapshots",
6
6
  "type": "module",
@@ -39,12 +39,12 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
- "@happyvertical/smrt-core": "0.57.37",
43
- "@happyvertical/smrt-tenancy": "0.57.37",
44
- "@happyvertical/smrt-types": "0.57.37",
45
- "@happyvertical/smrt-ui": "0.57.37",
46
- "@happyvertical/smrt-users": "0.57.37",
47
- "@happyvertical/sql": "^0.110.0"
42
+ "@happyvertical/smrt-core": "0.57.39",
43
+ "@happyvertical/smrt-tenancy": "0.57.39",
44
+ "@happyvertical/smrt-types": "0.57.39",
45
+ "@happyvertical/smrt-ui": "0.57.39",
46
+ "@happyvertical/smrt-users": "0.57.39",
47
+ "@happyvertical/sql": "^0.111.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "svelte": "^5.57.0"
@@ -55,7 +55,7 @@
55
55
  }
56
56
  },
57
57
  "devDependencies": {
58
- "@happyvertical/smrt-vitest": "0.57.37",
58
+ "@happyvertical/smrt-vitest": "0.57.39",
59
59
  "@sveltejs/package": "^2.5.8",
60
60
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
61
61
  "@types/node": "24.13.6",