hikoutei 0.3.4 → 0.3.6
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.
- package/README.ja.md +44 -21
- package/README.ko.md +43 -23
- package/README.md +49 -33
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmMappedTypedSheets.d.ts +3 -3
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmMappedTypedSheets.d.ts.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmMappedTypedSheets.js +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmScalarEntityRuntime.d.ts +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmScalarEntityRuntime.js +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmScalarRuntime.js +3 -3
- package/dist/adapter/persistence/providers/mikro-orm/engine/MikroOrmScalarRuntime.js.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPolling.d.ts +3 -3
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPolling.d.ts.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPolling.js +15 -15
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPolling.js.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingFastPath.d.ts +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingFastPath.d.ts.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingFastPath.js +3 -3
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingFastPath.js.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingInspection.d.ts +5 -5
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingInspection.d.ts.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingInspection.js +5 -5
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingInspection.js.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingPersistence.d.ts +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingPersistence.js +5 -5
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingPersistence.js.map +1 -1
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingSql.js +3 -3
- package/dist/adapter/persistence/providers/mikro-orm/observation/MikroOrmUserInputPollingSql.js.map +1 -1
- package/dist/adapter/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.d.ts +156 -0
- package/dist/adapter/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.js +1112 -0
- package/dist/adapter/sheets/providers/google-sheets-api/GoogleSheetsApiSyncProvider.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/constants.d.ts +87 -0
- package/dist/adapter/sheets/providers/google-sheets-api/constants.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/constants.js +97 -0
- package/dist/adapter/sheets/providers/google-sheets-api/constants.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/errors.d.ts +53 -0
- package/dist/adapter/sheets/providers/google-sheets-api/errors.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/errors.js +61 -0
- package/dist/adapter/sheets/providers/google-sheets-api/errors.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/index.d.ts +16 -0
- package/dist/adapter/sheets/providers/google-sheets-api/index.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/index.js +13 -0
- package/dist/adapter/sheets/providers/google-sheets-api/index.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/batchBuilder.d.ts +83 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/batchBuilder.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/batchBuilder.js +413 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/batchBuilder.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/observation.d.ts +86 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/observation.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/observation.js +439 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/observation.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/planner.d.ts +115 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/planner.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/planner.js +522 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/planner.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/postcondition.d.ts +17 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/postcondition.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/postcondition.js +99 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/postcondition.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/preflight.d.ts +242 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/preflight.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/preflight.js +707 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/preflight.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/sheetIdAllocator.d.ts +16 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/sheetIdAllocator.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/sheetIdAllocator.js +29 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/sheetIdAllocator.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/tableRead.d.ts +26 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/tableRead.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/tableRead.js +57 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/tableRead.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/valueNormalization.d.ts +102 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/valueNormalization.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/valueNormalization.js +375 -0
- package/dist/adapter/sheets/providers/google-sheets-api/model/valueNormalization.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.d.ts +168 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.js +247 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/googleSheetsApiTransport.js.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/rateLimiter.d.ts +47 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/rateLimiter.d.ts.map +1 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/rateLimiter.js +60 -0
- package/dist/adapter/sheets/providers/google-sheets-api/transport/rateLimiter.js.map +1 -0
- package/dist/api/Hikoutei.d.ts +1 -1
- package/dist/api/Hikoutei.js +1 -1
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.js +2 -2
- package/dist/application/orm/mapping/contracts.d.ts +2 -2
- package/dist/application/orm/mapping/contracts.d.ts.map +1 -1
- package/dist/application/orm/mapping/definition.js +5 -5
- package/dist/application/orm/mapping/definition.js.map +1 -1
- package/dist/application/orm/mapping/projection.js +7 -7
- package/dist/application/orm/mapping/projection.js.map +1 -1
- package/dist/application/orm/persistence/flush/flushCoordinator.d.ts +3 -3
- package/dist/application/orm/persistence/flush/flushCoordinator.d.ts.map +1 -1
- package/dist/application/orm/persistence/flush/flushCoordinator.js +2 -2
- package/dist/application/orm/persistence/flush/flushCoordinator.js.map +1 -1
- package/dist/application/orm/persistence/projection/projectionEffects.d.ts +1 -1
- package/dist/application/orm/persistence/projection/projectionEffects.js +6 -6
- package/dist/application/orm/persistence/projection/projectionEffects.js.map +1 -1
- package/dist/application/orm/persistence/support/contracts.d.ts +2 -2
- package/dist/application/orm/persistence/support/contracts.d.ts.map +1 -1
- package/dist/application/sync/inbound/autoSystemConflictResolution.js +7 -7
- package/dist/application/sync/inbound/autoSystemConflictResolution.js.map +1 -1
- package/dist/application/sync/inbound/polling/SimpleSheetPolling.d.ts +3 -3
- package/dist/application/sync/inbound/polling/SimpleSheetPolling.d.ts.map +1 -1
- package/dist/application/sync/inbound/polling/SimpleSheetPolling.js +1 -1
- package/dist/application/sync/inbound/polling/SimpleSheetPolling.js.map +1 -1
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.d.ts +17 -1
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.js +27 -1
- package/dist/application/sync/outbound/effects/AdaptiveEffectBatchController.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.d.ts +2 -2
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.js +26 -6
- package/dist/application/sync/outbound/effects/SyncEffectSupervisor.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorker.d.ts +24 -9
- package/dist/application/sync/outbound/effects/SyncEffectWorker.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorker.js +128 -81
- package/dist/application/sync/outbound/effects/SyncEffectWorker.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.d.ts +31 -14
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.js +32 -15
- package/dist/application/sync/outbound/effects/SyncEffectWorkerConstants.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.d.ts +13 -9
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.js +53 -37
- package/dist/application/sync/outbound/effects/SyncEffectWorkerDispatch.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerHelpers.js +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerHelpers.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.d.ts +29 -19
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.js +59 -41
- package/dist/application/sync/outbound/effects/SyncEffectWorkerRouting.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.d.ts +4 -4
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.js +3 -3
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTiming.js.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.d.ts +3 -3
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.d.ts.map +1 -1
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.js +42 -46
- package/dist/application/sync/outbound/effects/SyncEffectWorkerTransitions.js.map +1 -1
- package/dist/application/sync/outbound/projection/ProjectionEffectFactory.d.ts +8 -8
- package/dist/application/sync/outbound/projection/ProjectionEffectFactory.d.ts.map +1 -1
- package/dist/application/sync/outbound/projection/ProjectionEffectFactory.js +15 -15
- package/dist/application/sync/outbound/projection/ProjectionEffectFactory.js.map +1 -1
- package/dist/application/sync/outbound/reconciliation/ReconciliationScanner.d.ts +3 -3
- package/dist/application/sync/outbound/reconciliation/ReconciliationScanner.d.ts.map +1 -1
- package/dist/application/sync/outbound/reconciliation/ReconciliationScanner.js +10 -10
- package/dist/application/sync/outbound/reconciliation/ReconciliationScanner.js.map +1 -1
- package/dist/application/sync/service/SyncPollingSupervisor.d.ts +1 -1
- package/dist/application/sync/service/SyncPollingSupervisor.js +1 -1
- package/dist/application/sync/service/SyncServiceBootstrap.d.ts +29 -19
- package/dist/application/sync/service/SyncServiceBootstrap.d.ts.map +1 -1
- package/dist/application/sync/service/SyncServiceBootstrap.js +103 -78
- package/dist/application/sync/service/SyncServiceBootstrap.js.map +1 -1
- package/dist/application/sync/service/errors.d.ts +1 -1
- package/dist/application/sync/service/errors.js +1 -1
- package/dist/application/sync/service/errors.js.map +1 -1
- package/dist/application/sync/sheets/conflictProjection.d.ts.map +1 -0
- package/dist/application/sync/sheets/conflictProjection.js.map +1 -0
- package/dist/application/sync/{gateway → sheets}/conflictProjectionRegistration.d.ts +1 -1
- package/dist/application/sync/sheets/conflictProjectionRegistration.d.ts.map +1 -0
- package/dist/application/sync/{gateway → sheets}/conflictProjectionRegistration.js +3 -3
- package/dist/application/sync/sheets/conflictProjectionRegistration.js.map +1 -0
- package/dist/application/sync/sheets/constants.d.ts +66 -0
- package/dist/application/sync/sheets/constants.d.ts.map +1 -0
- package/dist/application/sync/{gateway → sheets}/constants.js +15 -15
- package/dist/application/sync/sheets/constants.js.map +1 -0
- package/dist/application/sync/sheets/errors.d.ts +15 -0
- package/dist/application/sync/sheets/errors.d.ts.map +1 -0
- package/dist/application/sync/sheets/errors.js +16 -0
- package/dist/application/sync/sheets/errors.js.map +1 -0
- package/dist/application/sync/{gateway/coordinator/CoordinatedSyncGateway.d.ts → sheets/mutationCoordinator/CoordinatedSheetsProvider.d.ts} +29 -28
- package/dist/application/sync/sheets/mutationCoordinator/CoordinatedSheetsProvider.d.ts.map +1 -0
- package/dist/application/sync/{gateway/coordinator/CoordinatedSyncGateway.js → sheets/mutationCoordinator/CoordinatedSheetsProvider.js} +27 -26
- package/dist/application/sync/sheets/mutationCoordinator/CoordinatedSheetsProvider.js.map +1 -0
- package/dist/application/sync/{gateway/coordinator → sheets/mutationCoordinator}/asyncMutex.d.ts +2 -3
- package/dist/application/sync/sheets/mutationCoordinator/asyncMutex.d.ts.map +1 -0
- package/dist/application/sync/sheets/mutationCoordinator/asyncMutex.js.map +1 -0
- package/dist/application/sync/{gateway/coordinator/coordinatorTelemetry.d.ts → sheets/mutationCoordinator/laneTelemetry.d.ts} +4 -4
- package/dist/application/sync/sheets/mutationCoordinator/laneTelemetry.d.ts.map +1 -0
- package/dist/application/sync/{gateway/coordinator/coordinatorTelemetry.js → sheets/mutationCoordinator/laneTelemetry.js} +5 -5
- package/dist/application/sync/sheets/mutationCoordinator/laneTelemetry.js.map +1 -0
- package/dist/application/sync/{gateway/SyncGatewayBootstrap.d.ts → sheets/sheetsProvisioning.d.ts} +14 -14
- package/dist/application/sync/sheets/sheetsProvisioning.d.ts.map +1 -0
- package/dist/application/sync/sheets/sheetsProvisioning.js +95 -0
- package/dist/application/sync/sheets/sheetsProvisioning.js.map +1 -0
- package/dist/application/sync/{gateway/syncGateway.d.ts → sheets/syncSheets.d.ts} +61 -117
- package/dist/application/sync/sheets/syncSheets.d.ts.map +1 -0
- package/dist/application/sync/sheets/syncSheets.js +144 -0
- package/dist/application/sync/sheets/syncSheets.js.map +1 -0
- package/dist/application/sync/{gateway/transportClassification.d.ts → sheets/transportOutcome.d.ts} +23 -22
- package/dist/application/sync/sheets/transportOutcome.d.ts.map +1 -0
- package/dist/application/sync/sheets/transportOutcome.js +97 -0
- package/dist/application/sync/sheets/transportOutcome.js.map +1 -0
- package/dist/application/sync/sheets/validation.d.ts +22 -0
- package/dist/application/sync/sheets/validation.d.ts.map +1 -0
- package/dist/application/sync/sheets/validation.js +79 -0
- package/dist/application/sync/sheets/validation.js.map +1 -0
- package/dist/application/sync/telemetry/syncTiming.d.ts +7 -7
- package/dist/application/sync/telemetry/syncTiming.d.ts.map +1 -1
- package/dist/application/sync/telemetry/syncTiming.js +2 -2
- package/dist/application/sync/telemetry/syncTiming.js.map +1 -1
- package/dist/domain/evaluate/contracts.d.ts +1 -1
- package/dist/domain/evaluate/contracts.js +1 -1
- package/dist/domain/model/constants.d.ts +1 -1
- package/dist/domain/model/constants.d.ts.map +1 -1
- package/dist/domain/model/types.d.ts +1 -1
- package/dist/domain/model/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/storage/index.d.ts +1 -1
- package/dist/infrastructure/storage/index.d.ts.map +1 -1
- package/dist/infrastructure/storage/index.js +1 -1
- package/dist/infrastructure/storage/index.js.map +1 -1
- package/dist/infrastructure/storage/state/observation/observationAudit.d.ts +1 -1
- package/dist/infrastructure/storage/state/observation/observationAudit.js +1 -1
- package/dist/infrastructure/storage/state/observation/observationTypes.d.ts +3 -3
- package/dist/infrastructure/storage/state/observation/observationTypes.d.ts.map +1 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.d.ts +13 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.d.ts.map +1 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.js +23 -2
- package/dist/infrastructure/storage/sync/outbound/effectOutbox.js.map +1 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.d.ts +9 -3
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.d.ts.map +1 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.js +7 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxContracts.js.map +1 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.d.ts +11 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.d.ts.map +1 -1
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.js +44 -3
- package/dist/infrastructure/storage/sync/outbound/effectOutboxSql.js.map +1 -1
- package/dist/infrastructure/storage/sync/shared/syncRegistry.d.ts +4 -4
- package/dist/infrastructure/storage/sync/shared/syncRegistry.d.ts.map +1 -1
- package/dist/infrastructure/storage/sync/shared/syncRegistry.js +4 -4
- package/dist/infrastructure/storage/sync/shared/syncRegistry.js.map +1 -1
- package/dist/shared/encoding/types.d.ts +1 -1
- package/docs/architecture.md +52 -23
- package/docs/ci.md +31 -23
- package/docs/code-guidelines.md +10 -18
- package/docs/development.md +37 -11
- package/docs/gateway-removal-inventory.md +147 -0
- package/docs/quick-start.md +36 -26
- package/docs/sync-bulk-write-benchmark.md +561 -0
- package/docs/sync-observability.md +38 -45
- package/docs/write-and-synchronization-flow.md +56 -39
- package/package.json +5 -4
- package/apps-script/gateway/Code.gs +0 -447
- package/dist/adapter/sheets/providers/apps-script-gateway/errors.d.ts +0 -43
- package/dist/adapter/sheets/providers/apps-script-gateway/errors.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/errors.js +0 -52
- package/dist/adapter/sheets/providers/apps-script-gateway/errors.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/index.d.ts +0 -24
- package/dist/adapter/sheets/providers/apps-script-gateway/index.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/index.js +0 -13
- package/dist/adapter/sheets/providers/apps-script-gateway/index.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperation.d.ts +0 -44
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperation.js +0 -181
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperation.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperationScript.d.ts +0 -3
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperationScript.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperationScript.js +0 -810
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/effect/effectOperationScript.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/observation/observationOperation.d.ts +0 -31
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/observation/observationOperation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/observation/observationOperation.js +0 -560
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/observation/observationOperation.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/read/tableReadOperation.d.ts +0 -12
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/read/tableReadOperation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/read/tableReadOperation.js +0 -166
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/read/tableReadOperation.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/shared/appsScriptStableCodecSource.d.ts +0 -8
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/shared/appsScriptStableCodecSource.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/shared/appsScriptStableCodecSource.js +0 -122
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/shared/appsScriptStableCodecSource.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/batchAppendOperation.d.ts +0 -31
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/batchAppendOperation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/batchAppendOperation.js +0 -567
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/batchAppendOperation.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/fastAppendOperation.d.ts +0 -19
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/fastAppendOperation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/fastAppendOperation.js +0 -37
- package/dist/adapter/sheets/providers/apps-script-gateway/operations/write/fastAppendOperation.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/codeGsProtocol.d.ts +0 -51
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/codeGsProtocol.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/codeGsProtocol.js +0 -60
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/codeGsProtocol.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/constants.d.ts +0 -44
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/constants.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/constants.js +0 -40
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/constants.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/syncProtocol.d.ts +0 -12
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/syncProtocol.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/syncProtocol.js +0 -41
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/syncProtocol.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/timing.d.ts +0 -5
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/timing.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/timing.js +0 -53
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/timing.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/types.d.ts +0 -4
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/types.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/types.js +0 -2
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/types.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/validation.d.ts +0 -11
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/validation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/validation.js +0 -36
- package/dist/adapter/sheets/providers/apps-script-gateway/protocol/validation.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationClient.d.ts +0 -68
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationClient.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationClient.js +0 -273
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationClient.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationSyncGateway.d.ts +0 -73
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationSyncGateway.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationSyncGateway.js +0 -363
- package/dist/adapter/sheets/providers/apps-script-gateway/transport/operationSyncGateway.js.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/validation.d.ts +0 -3
- package/dist/adapter/sheets/providers/apps-script-gateway/validation.d.ts.map +0 -1
- package/dist/adapter/sheets/providers/apps-script-gateway/validation.js +0 -10
- package/dist/adapter/sheets/providers/apps-script-gateway/validation.js.map +0 -1
- package/dist/application/sync/gateway/SyncGatewayBootstrap.d.ts.map +0 -1
- package/dist/application/sync/gateway/SyncGatewayBootstrap.js +0 -95
- package/dist/application/sync/gateway/SyncGatewayBootstrap.js.map +0 -1
- package/dist/application/sync/gateway/conflictProjection.d.ts.map +0 -1
- package/dist/application/sync/gateway/conflictProjection.js.map +0 -1
- package/dist/application/sync/gateway/conflictProjectionRegistration.d.ts.map +0 -1
- package/dist/application/sync/gateway/conflictProjectionRegistration.js.map +0 -1
- package/dist/application/sync/gateway/constants.d.ts +0 -66
- package/dist/application/sync/gateway/constants.d.ts.map +0 -1
- package/dist/application/sync/gateway/constants.js.map +0 -1
- package/dist/application/sync/gateway/coordinator/CoordinatedSyncGateway.d.ts.map +0 -1
- package/dist/application/sync/gateway/coordinator/CoordinatedSyncGateway.js.map +0 -1
- package/dist/application/sync/gateway/coordinator/asyncMutex.d.ts.map +0 -1
- package/dist/application/sync/gateway/coordinator/asyncMutex.js.map +0 -1
- package/dist/application/sync/gateway/coordinator/coordinatorTelemetry.d.ts.map +0 -1
- package/dist/application/sync/gateway/coordinator/coordinatorTelemetry.js.map +0 -1
- package/dist/application/sync/gateway/errors.d.ts +0 -15
- package/dist/application/sync/gateway/errors.d.ts.map +0 -1
- package/dist/application/sync/gateway/errors.js +0 -16
- package/dist/application/sync/gateway/errors.js.map +0 -1
- package/dist/application/sync/gateway/syncGateway.d.ts.map +0 -1
- package/dist/application/sync/gateway/syncGateway.js +0 -191
- package/dist/application/sync/gateway/syncGateway.js.map +0 -1
- package/dist/application/sync/gateway/transportClassification.d.ts.map +0 -1
- package/dist/application/sync/gateway/transportClassification.js +0 -133
- package/dist/application/sync/gateway/transportClassification.js.map +0 -1
- package/dist/application/sync/gateway/validation.d.ts +0 -22
- package/dist/application/sync/gateway/validation.d.ts.map +0 -1
- package/dist/application/sync/gateway/validation.js +0 -79
- package/dist/application/sync/gateway/validation.js.map +0 -1
- /package/dist/application/sync/{gateway → sheets}/conflictProjection.d.ts +0 -0
- /package/dist/application/sync/{gateway → sheets}/conflictProjection.js +0 -0
- /package/dist/application/sync/{gateway/coordinator → sheets/mutationCoordinator}/asyncMutex.js +0 -0
|
@@ -0,0 +1,707 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bulk preflight: a sheet enumeration call plus one bounded data read of the
|
|
3
|
+
* target tab and receipt tab.
|
|
4
|
+
*
|
|
5
|
+
* The provider first enumerates every tab (no ranges, so hidden sheets are
|
|
6
|
+
* returned), then reads the target grid (values, date formats, row-level
|
|
7
|
+
* developer-metadata anchors) and the hidden receipt tab through the narrow
|
|
8
|
+
* transport. Every untrusted SDK payload is validated with runtime guards
|
|
9
|
+
* and promoted into a typed context the planner can mutate. Any drift —
|
|
10
|
+
* header changes, duplicate anchors or identities, malformed receipts,
|
|
11
|
+
* invalid cells — fails closed before a single mutation request is built.
|
|
12
|
+
*
|
|
13
|
+
* The enumeration and the data read are separate functions so the provider
|
|
14
|
+
* can pace and report each transport request individually; the composite
|
|
15
|
+
* `readPreflightContext` keeps the two-call sequence for non-pacing callers.
|
|
16
|
+
*/
|
|
17
|
+
import { presentValue, absentValue } from "../../../../../shared/state/index.js";
|
|
18
|
+
import { GOOGLE_SHEETS_API_ANCHOR_KEY, GOOGLE_SHEETS_API_RECEIPT_HEADERS, GOOGLE_SHEETS_API_RECEIPT_SHEET_NAME, } from "../constants.js";
|
|
19
|
+
import { invalidProviderState } from "../errors.js";
|
|
20
|
+
import { columnLetters, identityFromNormalizedCell, isBlankApiCell, normalizedCellFromApiValue, parseRegisteredRange, quoteA1SheetName, } from "./valueNormalization.js";
|
|
21
|
+
/**
|
|
22
|
+
* Preflight field mask: sheet identity plus grid values, formats, anchors.
|
|
23
|
+
*
|
|
24
|
+
* GridData has no `sheetId` of its own; the parent sheet's
|
|
25
|
+
* `sheets.properties.sheetId` identifies the grid, and developer metadata
|
|
26
|
+
* uses the REST `metadataKey`/`metadataValue` field names.
|
|
27
|
+
*/
|
|
28
|
+
export const GOOGLE_SHEETS_API_PREFLIGHT_FIELDS = [
|
|
29
|
+
"sheets.properties(sheetId,title,hidden),",
|
|
30
|
+
"sheets.data(startRow,startColumn,",
|
|
31
|
+
"rowMetadata.developerMetadata(metadataId,metadataKey,metadataValue),",
|
|
32
|
+
"rowData.values(userEnteredValue,userEnteredFormat.numberFormat,effectiveFormat.numberFormat))",
|
|
33
|
+
].join("");
|
|
34
|
+
/**
|
|
35
|
+
* Enumeration field mask: sheet identity only.
|
|
36
|
+
*
|
|
37
|
+
* The enumeration call requests no ranges because a ranged
|
|
38
|
+
* `spreadsheets.get` response only carries sheets intersecting the requested
|
|
39
|
+
* ranges (hidden tabs included only when no ranges are given); the receipt
|
|
40
|
+
* tab can therefore never be discovered from the ranged data call alone.
|
|
41
|
+
*/
|
|
42
|
+
export const GOOGLE_SHEETS_API_ENUMERATION_FIELDS = "sheets.properties(sheetId,title,hidden)";
|
|
43
|
+
/**
|
|
44
|
+
* Provisioning enumeration mask: sheet identity plus grid dimensions.
|
|
45
|
+
*
|
|
46
|
+
* The grid dimensions let provisioning request the full used grid of an
|
|
47
|
+
* existing tab (up to the sheet's actual last column) so "truly empty" is
|
|
48
|
+
* judged against the whole tab, not just the registered range.
|
|
49
|
+
*/
|
|
50
|
+
export const GOOGLE_SHEETS_API_PROVISION_ENUMERATION_FIELDS = "sheets.properties(sheetId,title,hidden,gridProperties(rowCount,columnCount))";
|
|
51
|
+
/**
|
|
52
|
+
* Provisioning data mask: values plus number formats for header checks.
|
|
53
|
+
*
|
|
54
|
+
* Anchors, merged ranges, and computed values are not needed to decide
|
|
55
|
+
* whether an existing tab is empty or whether its header row matches.
|
|
56
|
+
*/
|
|
57
|
+
export const GOOGLE_SHEETS_API_PROVISION_FIELDS = [
|
|
58
|
+
"sheets.properties(sheetId,title,hidden),",
|
|
59
|
+
"sheets.data(startRow,startColumn,",
|
|
60
|
+
"rowData.values(userEnteredValue,userEnteredFormat.numberFormat,effectiveFormat.numberFormat))",
|
|
61
|
+
].join("");
|
|
62
|
+
/**
|
|
63
|
+
* Values-only table-read mask (getValues semantics).
|
|
64
|
+
*
|
|
65
|
+
* Includes computed values, formatted error strings, number formats, and
|
|
66
|
+
* data-validation rules so formula cells resolve to their computed value,
|
|
67
|
+
* error cells to their display string, and checkbox columns to their
|
|
68
|
+
* blank/false rule.
|
|
69
|
+
*/
|
|
70
|
+
export const GOOGLE_SHEETS_API_VALUES_FIELDS = [
|
|
71
|
+
"sheets.properties(sheetId,title,hidden),",
|
|
72
|
+
"sheets.data(startRow,startColumn,",
|
|
73
|
+
"rowData.values(userEnteredValue,effectiveValue,formattedValue,",
|
|
74
|
+
"userEnteredFormat.numberFormat,effectiveFormat.numberFormat,dataValidation))",
|
|
75
|
+
].join("");
|
|
76
|
+
/**
|
|
77
|
+
* Full observation mask: values, computed values, merged ranges, anchors.
|
|
78
|
+
*
|
|
79
|
+
* This is the metadata-preserving read used by snapshots and anchor
|
|
80
|
+
* assignment. Merged regions live on the SHEET object as `sheets.merges`
|
|
81
|
+
* (GridRange entries), NOT on GridData, and `rowMetadata.developerMetadata`
|
|
82
|
+
* returns the row anchor evidence under the REST `metadataKey`/
|
|
83
|
+
* `metadataValue` names.
|
|
84
|
+
*/
|
|
85
|
+
export const GOOGLE_SHEETS_API_OBSERVATION_FIELDS = [
|
|
86
|
+
"sheets.properties(sheetId,title,hidden),",
|
|
87
|
+
"sheets.merges,",
|
|
88
|
+
"sheets.data(startRow,startColumn,",
|
|
89
|
+
"rowMetadata.developerMetadata(metadataId,metadataKey,metadataValue),",
|
|
90
|
+
"rowData.values(userEnteredValue,effectiveValue,formattedValue,",
|
|
91
|
+
"userEnteredFormat.numberFormat,effectiveFormat.numberFormat,dataValidation))",
|
|
92
|
+
].join("");
|
|
93
|
+
/**
|
|
94
|
+
* Lightweight observation mask: values and computed values only.
|
|
95
|
+
*
|
|
96
|
+
* Used by user_input polling reads, which never consult merged regions (the
|
|
97
|
+
* lightweight branch has no merged map) or data-validation rules (the
|
|
98
|
+
* checkbox-false blank rule comes from the checkboxHeaders config, not from
|
|
99
|
+
* dataValidation). Keeping `sheets.merges` and `dataValidation` out of the
|
|
100
|
+
* request makes the polling read cheaper.
|
|
101
|
+
*/
|
|
102
|
+
export const GOOGLE_SHEETS_API_LIGHTWEIGHT_OBSERVATION_FIELDS = [
|
|
103
|
+
"sheets.properties(sheetId,title,hidden),",
|
|
104
|
+
"sheets.data(startRow,startColumn,",
|
|
105
|
+
"rowMetadata.developerMetadata(metadataId,metadataKey,metadataValue),",
|
|
106
|
+
"rowData.values(userEnteredValue,effectiveValue,formattedValue,",
|
|
107
|
+
"userEnteredFormat.numberFormat,effectiveFormat.numberFormat))",
|
|
108
|
+
].join("");
|
|
109
|
+
/**
|
|
110
|
+
* Enumerates every tab of the spreadsheet (no ranges, so hidden tabs are
|
|
111
|
+
* returned). The enumeration supplies the sheetIds the data call's grid
|
|
112
|
+
* data is keyed by and the receipt tab's presence.
|
|
113
|
+
*/
|
|
114
|
+
export async function enumerateSheetProperties(transport, spreadsheetId, timeoutMs) {
|
|
115
|
+
const enumerationRequest = {
|
|
116
|
+
spreadsheetId,
|
|
117
|
+
ranges: [],
|
|
118
|
+
fields: GOOGLE_SHEETS_API_ENUMERATION_FIELDS,
|
|
119
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
120
|
+
};
|
|
121
|
+
const enumerationRaw = await transport.getSpreadsheet(enumerationRequest);
|
|
122
|
+
return parseSheetPropertiesDocument(enumerationRaw, "sheet enumeration");
|
|
123
|
+
}
|
|
124
|
+
/** Reads and validates the target and receipt tabs for one route. */
|
|
125
|
+
export async function readPreflightContext(transport, route, timeoutMs) {
|
|
126
|
+
const sheets = await enumerateSheetProperties(transport, route.spreadsheetId, timeoutMs);
|
|
127
|
+
return readPreflightData(transport, route, sheets, timeoutMs);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Reads the bounded target/receipt grid data for one route, given the sheet
|
|
131
|
+
* enumeration. The target range starts at A1 and extends to the registered
|
|
132
|
+
* range's end column (whole-column ranges can legitimately exceed ZZ),
|
|
133
|
+
* keeping the 1,048,576-row limit of the grid.
|
|
134
|
+
*/
|
|
135
|
+
export async function readPreflightData(transport, route, sheets, timeoutMs) {
|
|
136
|
+
const targetSheet = requireSheetByTitle(sheets, route.sheetName);
|
|
137
|
+
const receiptSheet = findSheetByTitle(sheets, GOOGLE_SHEETS_API_RECEIPT_SHEET_NAME);
|
|
138
|
+
// Call 2: the bounded data read, covering exactly the tabs that exist.
|
|
139
|
+
// The target range starts at A1 and extends to the registered range's end
|
|
140
|
+
// column (whole-column ranges can legitimately exceed ZZ), keeping the
|
|
141
|
+
// 1,048,576-row limit of the grid. The receipt range is requested only
|
|
142
|
+
// when the enumeration found the receipt tab.
|
|
143
|
+
const parsedRange = parseRegisteredRange(route.registeredRange);
|
|
144
|
+
const endColumnLetters = columnLetters(parsedRange.startColumn + parsedRange.columnCount - 1);
|
|
145
|
+
const ranges = [
|
|
146
|
+
`${quoteA1SheetName(route.sheetName)}!A1:${endColumnLetters}1048576`,
|
|
147
|
+
];
|
|
148
|
+
if (receiptSheet !== undefined) {
|
|
149
|
+
ranges.push(`${quoteA1SheetName(GOOGLE_SHEETS_API_RECEIPT_SHEET_NAME)}!A1:F1048576`);
|
|
150
|
+
}
|
|
151
|
+
const dataRequest = {
|
|
152
|
+
spreadsheetId: route.spreadsheetId,
|
|
153
|
+
ranges,
|
|
154
|
+
fields: GOOGLE_SHEETS_API_PREFLIGHT_FIELDS,
|
|
155
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
156
|
+
};
|
|
157
|
+
const dataRaw = await transport.getSpreadsheet(dataRequest);
|
|
158
|
+
const dataDocument = parseSpreadsheetDocument(dataRaw, "grid data");
|
|
159
|
+
const targetData = requireGridDataForSheet(dataDocument, targetSheet.sheetId);
|
|
160
|
+
const headers = readRegisteredHeaders(targetData, parsedRange, route.headers);
|
|
161
|
+
const positions = new Map();
|
|
162
|
+
headers.forEach((header, index) => positions.set(header, index));
|
|
163
|
+
const identityField = route.identityField;
|
|
164
|
+
const rows = readRows(targetData, parsedRange, headers, identityField);
|
|
165
|
+
const { byAnchor, byIdentity, nextAppendRow } = indexRows(rows, targetData);
|
|
166
|
+
const checkboxHeaders = validateCheckboxHeaders(route.checkboxHeaders, headers);
|
|
167
|
+
let receipts = new Map();
|
|
168
|
+
let receiptLastRow = 0;
|
|
169
|
+
let receiptSheetId = absentValue();
|
|
170
|
+
if (receiptSheet !== undefined) {
|
|
171
|
+
receiptSheetId = presentValue(receiptSheet.sheetId);
|
|
172
|
+
const receiptData = requireGridDataForSheet(dataDocument, receiptSheet.sheetId);
|
|
173
|
+
const parsedReceipts = readReceipts(receiptData);
|
|
174
|
+
receipts = parsedReceipts.receipts;
|
|
175
|
+
receiptLastRow = parsedReceipts.lastRow;
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
sheetId: targetSheet.sheetId,
|
|
179
|
+
title: targetSheet.title,
|
|
180
|
+
startColumn: parsedRange.startColumn,
|
|
181
|
+
headers,
|
|
182
|
+
positions,
|
|
183
|
+
rows,
|
|
184
|
+
byAnchor,
|
|
185
|
+
byIdentity,
|
|
186
|
+
nextAppendRow,
|
|
187
|
+
identityField,
|
|
188
|
+
checkboxHeaders,
|
|
189
|
+
receiptSheetId,
|
|
190
|
+
receiptLastRow,
|
|
191
|
+
receipts,
|
|
192
|
+
existingSheetIds: sheets.map((sheet) => sheet.sheetId),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/** Promotes an untrusted `spreadsheets.get` body with runtime guards. */
|
|
196
|
+
export function parseSpreadsheetDocument(value, label) {
|
|
197
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
198
|
+
invalidProviderState(`${label} response must be an object`);
|
|
199
|
+
}
|
|
200
|
+
const record = value;
|
|
201
|
+
if (!Array.isArray(record.sheets)) {
|
|
202
|
+
invalidProviderState(`${label} response must contain a sheets array`);
|
|
203
|
+
}
|
|
204
|
+
const grids = new Map();
|
|
205
|
+
const sheets = record.sheets.map((entry, index) => {
|
|
206
|
+
const sheet = parseSheetEntry(entry, `${label} sheets[${index}]`);
|
|
207
|
+
// Grid data is nested under each sheet entry in the API response and is
|
|
208
|
+
// identified by the parent sheet's properties.sheetId (GridData itself
|
|
209
|
+
// carries no sheetId).
|
|
210
|
+
if (entry !== null && typeof entry === "object" && !Array.isArray(entry) &&
|
|
211
|
+
entry.data !== undefined) {
|
|
212
|
+
parseGridDataArray(entry.data, sheet.sheetId, `${label} sheets[${index}].data`, grids);
|
|
213
|
+
}
|
|
214
|
+
return sheet;
|
|
215
|
+
});
|
|
216
|
+
return { sheets, grids };
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Promotes an enumeration-only `spreadsheets.get` body (sheet properties,
|
|
220
|
+
* no grid data) with runtime guards.
|
|
221
|
+
*/
|
|
222
|
+
export function parseSheetPropertiesDocument(value, label) {
|
|
223
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
224
|
+
invalidProviderState(`${label} response must be an object`);
|
|
225
|
+
}
|
|
226
|
+
const record = value;
|
|
227
|
+
if (!Array.isArray(record.sheets)) {
|
|
228
|
+
invalidProviderState(`${label} response must contain a sheets array`);
|
|
229
|
+
}
|
|
230
|
+
return record.sheets.map((entry, index) => parseSheetEntry(entry, `${label} sheets[${index}]`));
|
|
231
|
+
}
|
|
232
|
+
/** Validates one REST sheet entry's properties (sheetId, title, hidden). */
|
|
233
|
+
function parseSheetEntry(value, label) {
|
|
234
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
235
|
+
invalidProviderState(`${label} must be an object`);
|
|
236
|
+
}
|
|
237
|
+
const sheet = value;
|
|
238
|
+
const properties = sheet.properties;
|
|
239
|
+
if (properties === null || typeof properties !== "object" || Array.isArray(properties)) {
|
|
240
|
+
invalidProviderState(`${label}.properties must be an object`);
|
|
241
|
+
}
|
|
242
|
+
const propertyRecord = properties;
|
|
243
|
+
const sheetId = propertyRecord.sheetId;
|
|
244
|
+
const title = propertyRecord.title;
|
|
245
|
+
if (typeof sheetId !== "number" || !Number.isSafeInteger(sheetId)) {
|
|
246
|
+
invalidProviderState(`${label}.properties.sheetId is invalid`);
|
|
247
|
+
}
|
|
248
|
+
if (typeof title !== "string" || title.length === 0) {
|
|
249
|
+
invalidProviderState(`${label}.properties.title is invalid`);
|
|
250
|
+
}
|
|
251
|
+
const hidden = propertyRecord.hidden;
|
|
252
|
+
if (hidden !== undefined && typeof hidden !== "boolean") {
|
|
253
|
+
invalidProviderState(`${label}.properties.hidden is invalid`);
|
|
254
|
+
}
|
|
255
|
+
const gridProperties = propertyRecord.gridProperties;
|
|
256
|
+
const grid = gridProperties === undefined
|
|
257
|
+
? undefined
|
|
258
|
+
: (() => {
|
|
259
|
+
if (gridProperties === null || typeof gridProperties !== "object" || Array.isArray(gridProperties)) {
|
|
260
|
+
invalidProviderState(`${label}.properties.gridProperties is invalid`);
|
|
261
|
+
}
|
|
262
|
+
const gridRecord = gridProperties;
|
|
263
|
+
return {
|
|
264
|
+
rowCount: optionalPositiveInteger(gridRecord.rowCount, `${label}.properties.gridProperties.rowCount`),
|
|
265
|
+
columnCount: optionalPositiveInteger(gridRecord.columnCount, `${label}.properties.gridProperties.columnCount`),
|
|
266
|
+
};
|
|
267
|
+
})();
|
|
268
|
+
// Merged regions are a sheet-level `merges` GridRange array in the API
|
|
269
|
+
// response (GridData carries no mergedCells field), requested only by the
|
|
270
|
+
// observation mask; other masks omit the field entirely.
|
|
271
|
+
const merges = parseMergedCells(sheet.merges, `${label}.merges`);
|
|
272
|
+
return {
|
|
273
|
+
sheetId,
|
|
274
|
+
title,
|
|
275
|
+
hidden: hidden === true,
|
|
276
|
+
...(grid === undefined ? {} : { gridProperties: grid }),
|
|
277
|
+
...(merges === undefined ? {} : { merges }),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function optionalPositiveInteger(value, label) {
|
|
281
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1) {
|
|
282
|
+
invalidProviderState(`${label} is invalid`);
|
|
283
|
+
}
|
|
284
|
+
return value;
|
|
285
|
+
}
|
|
286
|
+
function parseGridDataArray(value, sheetId, label, grids) {
|
|
287
|
+
if (!Array.isArray(value)) {
|
|
288
|
+
invalidProviderState(`${label} must be an array`);
|
|
289
|
+
}
|
|
290
|
+
if (grids.has(sheetId)) {
|
|
291
|
+
invalidProviderState(`${label} contains a duplicate grid for one sheet`);
|
|
292
|
+
}
|
|
293
|
+
value.forEach((entry, index) => {
|
|
294
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
295
|
+
invalidProviderState(`${label}[${index}] must be an object`);
|
|
296
|
+
}
|
|
297
|
+
const data = entry;
|
|
298
|
+
const startRow = optionalNonNegativeInteger(data.startRow, `${label}[${index}].startRow`);
|
|
299
|
+
const startColumn = optionalNonNegativeInteger(data.startColumn, `${label}[${index}].startColumn`);
|
|
300
|
+
const rowData = parseRowData(data.rowData, `${label}[${index}].rowData`);
|
|
301
|
+
const rowMetadata = parseRowMetadata(data.rowMetadata, `${label}[${index}].rowMetadata`);
|
|
302
|
+
grids.set(sheetId, { startRow, startColumn, rowData, rowMetadata });
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
/** Parses one sheet-level `merges` GridRange array with runtime guards. */
|
|
306
|
+
function parseMergedCells(value, label) {
|
|
307
|
+
if (value === undefined)
|
|
308
|
+
return undefined;
|
|
309
|
+
if (!Array.isArray(value))
|
|
310
|
+
invalidProviderState(`${label} must be an array`);
|
|
311
|
+
return value.map((entry, index) => {
|
|
312
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
313
|
+
invalidProviderState(`${label}[${index}] must be an object`);
|
|
314
|
+
}
|
|
315
|
+
const range = entry;
|
|
316
|
+
const startRowIndex = optionalNonNegativeInteger(range.startRowIndex, `${label}[${index}].startRowIndex`);
|
|
317
|
+
const endRowIndex = optionalNonNegativeInteger(range.endRowIndex, `${label}[${index}].endRowIndex`);
|
|
318
|
+
const startColumnIndex = optionalNonNegativeInteger(range.startColumnIndex, `${label}[${index}].startColumnIndex`);
|
|
319
|
+
const endColumnIndex = optionalNonNegativeInteger(range.endColumnIndex, `${label}[${index}].endColumnIndex`);
|
|
320
|
+
if (endRowIndex <= startRowIndex || endColumnIndex <= startColumnIndex) {
|
|
321
|
+
invalidProviderState(`${label}[${index}] is not a valid cell range`);
|
|
322
|
+
}
|
|
323
|
+
const sheetIdValue = range.sheetId;
|
|
324
|
+
if (sheetIdValue !== undefined &&
|
|
325
|
+
(typeof sheetIdValue !== "number" || !Number.isSafeInteger(sheetIdValue))) {
|
|
326
|
+
invalidProviderState(`${label}[${index}].sheetId is invalid`);
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
...(sheetIdValue === undefined ? {} : { sheetId: sheetIdValue }),
|
|
330
|
+
startRowIndex,
|
|
331
|
+
endRowIndex,
|
|
332
|
+
startColumnIndex,
|
|
333
|
+
endColumnIndex,
|
|
334
|
+
};
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
function parseRowData(value, label) {
|
|
338
|
+
if (value === undefined)
|
|
339
|
+
return [];
|
|
340
|
+
if (!Array.isArray(value))
|
|
341
|
+
invalidProviderState(`${label} must be an array`);
|
|
342
|
+
return value.map((entry, index) => {
|
|
343
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
344
|
+
invalidProviderState(`${label}[${index}] must be an object`);
|
|
345
|
+
}
|
|
346
|
+
const row = entry;
|
|
347
|
+
if (row.values === undefined)
|
|
348
|
+
return { values: [] };
|
|
349
|
+
if (!Array.isArray(row.values)) {
|
|
350
|
+
invalidProviderState(`${label}[${index}].values must be an array`);
|
|
351
|
+
}
|
|
352
|
+
return { values: row.values };
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
function parseRowMetadata(value, label) {
|
|
356
|
+
if (value === undefined)
|
|
357
|
+
return [];
|
|
358
|
+
if (!Array.isArray(value))
|
|
359
|
+
invalidProviderState(`${label} must be an array`);
|
|
360
|
+
return value.map((entry, index) => {
|
|
361
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
362
|
+
invalidProviderState(`${label}[${index}] must be an object`);
|
|
363
|
+
}
|
|
364
|
+
const metadata = entry;
|
|
365
|
+
if (metadata.developerMetadata === undefined)
|
|
366
|
+
return { developerMetadata: [] };
|
|
367
|
+
if (!Array.isArray(metadata.developerMetadata)) {
|
|
368
|
+
invalidProviderState(`${label}[${index}].developerMetadata must be an array`);
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
developerMetadata: metadata.developerMetadata.map((item, itemIndex) => {
|
|
372
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
373
|
+
invalidProviderState(`${label}[${index}].developerMetadata[${itemIndex}] must be an object`);
|
|
374
|
+
}
|
|
375
|
+
const itemRecord = item;
|
|
376
|
+
if (typeof itemRecord.metadataKey !== "string" ||
|
|
377
|
+
itemRecord.metadataKey.length === 0) {
|
|
378
|
+
invalidProviderState(`${label}[${index}].developerMetadata[${itemIndex}].metadataKey is invalid`);
|
|
379
|
+
}
|
|
380
|
+
if (itemRecord.metadataValue !== undefined &&
|
|
381
|
+
typeof itemRecord.metadataValue !== "string") {
|
|
382
|
+
invalidProviderState(`${label}[${index}].developerMetadata[${itemIndex}].metadataValue is invalid`);
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
metadataKey: itemRecord.metadataKey,
|
|
386
|
+
metadataValue: itemRecord.metadataValue === undefined ? "" : itemRecord.metadataValue,
|
|
387
|
+
};
|
|
388
|
+
}),
|
|
389
|
+
};
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function optionalNonNegativeInteger(value, label) {
|
|
393
|
+
if (value === undefined)
|
|
394
|
+
return 0;
|
|
395
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
396
|
+
invalidProviderState(`${label} is invalid`);
|
|
397
|
+
}
|
|
398
|
+
return value;
|
|
399
|
+
}
|
|
400
|
+
function requireSheetByTitle(sheets, title) {
|
|
401
|
+
const sheet = findSheetByTitle(sheets, title);
|
|
402
|
+
if (sheet === undefined) {
|
|
403
|
+
invalidProviderState(`Registered sync sheet does not exist: ${title}`);
|
|
404
|
+
}
|
|
405
|
+
return sheet;
|
|
406
|
+
}
|
|
407
|
+
function findSheetByTitle(sheets, title) {
|
|
408
|
+
return sheets.find((sheet) => sheet.title === title);
|
|
409
|
+
}
|
|
410
|
+
function requireGridDataForSheet(document, sheetId) {
|
|
411
|
+
const grid = document.grids.get(sheetId);
|
|
412
|
+
if (grid === undefined) {
|
|
413
|
+
invalidProviderState(`grid data is missing for sheet ${sheetId}`);
|
|
414
|
+
}
|
|
415
|
+
return grid;
|
|
416
|
+
}
|
|
417
|
+
/** Returns the parsed grid for one sheet by title, failing closed when absent. */
|
|
418
|
+
export function requireGridDataByTitle(document, sheets, title) {
|
|
419
|
+
const sheet = findSheetByTitle(sheets, title);
|
|
420
|
+
if (sheet === undefined) {
|
|
421
|
+
invalidProviderState(`Registered sync sheet does not exist: ${title}`);
|
|
422
|
+
}
|
|
423
|
+
const grid = document.grids.get(sheet.sheetId);
|
|
424
|
+
if (grid === undefined) {
|
|
425
|
+
invalidProviderState(`grid data is missing for sheet ${sheet.sheetId}`);
|
|
426
|
+
}
|
|
427
|
+
return { sheet, grid };
|
|
428
|
+
}
|
|
429
|
+
// ---------------------------------------------------------------------------
|
|
430
|
+
// Context construction
|
|
431
|
+
// ---------------------------------------------------------------------------
|
|
432
|
+
/**
|
|
433
|
+
* Validates the header row against the registered definition and layout:
|
|
434
|
+
* every cell must be a non-empty string, duplicates fail closed, and the
|
|
435
|
+
* row must match the expected headers exactly.
|
|
436
|
+
*/
|
|
437
|
+
export function readRegisteredHeaders(data, range, expectedHeaders) {
|
|
438
|
+
const headerValues = gridRowCells(data, 1, range.startColumn, range.columnCount);
|
|
439
|
+
const actual = headerValues.map((value, index) => {
|
|
440
|
+
if (value === null) {
|
|
441
|
+
invalidProviderState(`registered header is missing at column ${index + 1}`);
|
|
442
|
+
}
|
|
443
|
+
const raw = apiStringValue(value);
|
|
444
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
445
|
+
invalidProviderState(`registered header is invalid at column ${index + 1}`);
|
|
446
|
+
}
|
|
447
|
+
return raw;
|
|
448
|
+
});
|
|
449
|
+
if (new Set(actual).size !== actual.length) {
|
|
450
|
+
invalidProviderState("registered headers contain a duplicate");
|
|
451
|
+
}
|
|
452
|
+
if (actual.length !== expectedHeaders.length ||
|
|
453
|
+
actual.some((header, index) => header !== expectedHeaders[index])) {
|
|
454
|
+
invalidProviderState("registered headers do not match the projected schema");
|
|
455
|
+
}
|
|
456
|
+
return actual;
|
|
457
|
+
}
|
|
458
|
+
/** Returns the header cells of one grid as raw API values (no validation). */
|
|
459
|
+
export function gridHeaderCells(data, range) {
|
|
460
|
+
return gridRowCells(data, 1, range.startColumn, range.columnCount);
|
|
461
|
+
}
|
|
462
|
+
function validateCheckboxHeaders(checkboxHeaders, headers) {
|
|
463
|
+
if (checkboxHeaders === undefined || checkboxHeaders.length === 0)
|
|
464
|
+
return [];
|
|
465
|
+
const headerSet = new Set(headers);
|
|
466
|
+
for (const header of checkboxHeaders) {
|
|
467
|
+
if (!headerSet.has(header)) {
|
|
468
|
+
invalidProviderState(`checkbox header is not registered: ${header}`);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return [...checkboxHeaders];
|
|
472
|
+
}
|
|
473
|
+
/** Normalizes nonblank grid rows into typed preflight rows. */
|
|
474
|
+
function readRows(data, range, headers, identityField) {
|
|
475
|
+
const anchorsByRow = readAnchorIndex(data);
|
|
476
|
+
const rows = [];
|
|
477
|
+
for (let rowIndex = 0; rowIndex < data.rowData.length; rowIndex += 1) {
|
|
478
|
+
const rowNumber = data.startRow + 1 + rowIndex;
|
|
479
|
+
if (rowNumber < 2)
|
|
480
|
+
continue;
|
|
481
|
+
const rawRow = data.rowData[rowIndex];
|
|
482
|
+
if (rawRow === undefined)
|
|
483
|
+
continue;
|
|
484
|
+
const values = gridRowCells(data, rowNumber, range.startColumn, range.columnCount);
|
|
485
|
+
if (values.every((value) => isBlankApiCell(value)))
|
|
486
|
+
continue;
|
|
487
|
+
const cells = {};
|
|
488
|
+
headers.forEach((header, columnIndex) => {
|
|
489
|
+
const value = values[columnIndex];
|
|
490
|
+
const numberFormat = apiCellNumberFormat(value);
|
|
491
|
+
cells[header] = normalizedCellFromApiValue(value === null || value === undefined
|
|
492
|
+
? undefined
|
|
493
|
+
: value.userEnteredValue, numberFormat);
|
|
494
|
+
});
|
|
495
|
+
const anchors = anchorsByRow.get(rowNumber);
|
|
496
|
+
if (anchors !== undefined && anchors.length > 1) {
|
|
497
|
+
invalidProviderState(`row has multiple sync anchors: ${rowNumber}`);
|
|
498
|
+
}
|
|
499
|
+
const firstAnchor = anchors === undefined || anchors.length === 0
|
|
500
|
+
? undefined
|
|
501
|
+
: (anchors[0] ?? undefined);
|
|
502
|
+
const physicalAnchor = firstAnchor === undefined
|
|
503
|
+
? absentValue()
|
|
504
|
+
: presentValue(firstAnchor);
|
|
505
|
+
let identity = absentValue();
|
|
506
|
+
if (identityField.kind === "present") {
|
|
507
|
+
const identityCell = cells[identityField.value];
|
|
508
|
+
const value = identityFromNormalizedCell(identityCell ?? null);
|
|
509
|
+
if (value !== null)
|
|
510
|
+
identity = presentValue(value);
|
|
511
|
+
}
|
|
512
|
+
rows.push({ rowNumber, physicalAnchor, cells, identity });
|
|
513
|
+
}
|
|
514
|
+
return rows;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Builds the row -> anchor-list index from one grid's row metadata.
|
|
518
|
+
*
|
|
519
|
+
* Row metadata is index-aligned with rowData; only the shared anchor key
|
|
520
|
+
* counts, and a row may legitimately carry several metadata entries (the
|
|
521
|
+
* caller decides whether multiple anchors are an error).
|
|
522
|
+
*/
|
|
523
|
+
export function readAnchorIndex(data) {
|
|
524
|
+
const byRow = new Map();
|
|
525
|
+
data.rowMetadata.forEach((metadata, index) => {
|
|
526
|
+
const rowNumber = data.startRow + 1 + index;
|
|
527
|
+
const anchors = metadata.developerMetadata
|
|
528
|
+
.filter((item) => item.metadataKey === GOOGLE_SHEETS_API_ANCHOR_KEY)
|
|
529
|
+
.map((item) => item.metadataValue);
|
|
530
|
+
if (anchors.length > 0)
|
|
531
|
+
byRow.set(rowNumber, anchors);
|
|
532
|
+
});
|
|
533
|
+
return byRow;
|
|
534
|
+
}
|
|
535
|
+
function indexRows(rows, data) {
|
|
536
|
+
const byAnchor = new Map();
|
|
537
|
+
const byIdentity = new Map();
|
|
538
|
+
for (const row of rows) {
|
|
539
|
+
if (row.physicalAnchor.kind === "present") {
|
|
540
|
+
const existing = byAnchor.get(row.physicalAnchor.value);
|
|
541
|
+
if (existing !== undefined) {
|
|
542
|
+
invalidProviderState(`sync anchor is duplicated: ${row.physicalAnchor.value} at rows ${existing.rowNumber} and ${row.rowNumber}`);
|
|
543
|
+
}
|
|
544
|
+
byAnchor.set(row.physicalAnchor.value, row);
|
|
545
|
+
}
|
|
546
|
+
if (row.identity.kind === "present") {
|
|
547
|
+
const existing = byIdentity.get(row.identity.value);
|
|
548
|
+
if (existing !== undefined) {
|
|
549
|
+
invalidProviderState(`sync identity is duplicated: ${row.identity.value} at rows ${existing.rowNumber} and ${row.rowNumber}`);
|
|
550
|
+
}
|
|
551
|
+
byIdentity.set(row.identity.value, row);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// The API omits trailing empty rows from grid data, so the last data row is
|
|
555
|
+
// the sheet's last content row; appends start one row below it (min row 2,
|
|
556
|
+
// matching the Apps Script nextAppendRow = max(lastRow + 1, 2)).
|
|
557
|
+
const lastContentRow = data.startRow + data.rowData.length;
|
|
558
|
+
return {
|
|
559
|
+
byAnchor,
|
|
560
|
+
byIdentity,
|
|
561
|
+
nextAppendRow: Math.max(lastContentRow + 1, 2),
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Reads the visible cells of one 1-based row over the registered range.
|
|
566
|
+
*
|
|
567
|
+
* `null` entries mark blank cells, matching the sparse values arrays the API
|
|
568
|
+
* returns (a row's values array may be narrower than the requested range).
|
|
569
|
+
*/
|
|
570
|
+
export function gridRowCells(data, rowNumber, startColumn, columnCount) {
|
|
571
|
+
const rowIndex = rowNumber - data.startRow - 1;
|
|
572
|
+
const rawRow = data.rowData[rowIndex];
|
|
573
|
+
if (rawRow === undefined) {
|
|
574
|
+
return Array.from({ length: columnCount }, () => null);
|
|
575
|
+
}
|
|
576
|
+
const values = rawRow.values;
|
|
577
|
+
const cells = [];
|
|
578
|
+
for (let offset = 0; offset < columnCount; offset += 1) {
|
|
579
|
+
const column = startColumn - 1 + offset - data.startColumn;
|
|
580
|
+
const value = values[column];
|
|
581
|
+
cells.push(value === undefined ? null : value);
|
|
582
|
+
}
|
|
583
|
+
return cells;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Extracts the number format of one API cell, if any.
|
|
587
|
+
*
|
|
588
|
+
* The REST API models `CellFormat.numberFormat` as a `{ type, pattern }`
|
|
589
|
+
* object, never a bare string; the user-entered format wins over the
|
|
590
|
+
* effective format when both are present.
|
|
591
|
+
*/
|
|
592
|
+
export function apiCellNumberFormat(value) {
|
|
593
|
+
if (value === null || typeof value !== "object")
|
|
594
|
+
return undefined;
|
|
595
|
+
const cell = value;
|
|
596
|
+
const entered = cell.userEnteredFormat;
|
|
597
|
+
if (entered !== null && typeof entered === "object") {
|
|
598
|
+
const format = parseCellNumberFormat(entered.numberFormat);
|
|
599
|
+
if (format !== undefined)
|
|
600
|
+
return format;
|
|
601
|
+
}
|
|
602
|
+
const effective = cell.effectiveFormat;
|
|
603
|
+
if (effective !== null && typeof effective === "object") {
|
|
604
|
+
const format = parseCellNumberFormat(effective.numberFormat);
|
|
605
|
+
if (format !== undefined)
|
|
606
|
+
return format;
|
|
607
|
+
}
|
|
608
|
+
return undefined;
|
|
609
|
+
}
|
|
610
|
+
/** Validates one SDK `numberFormat` object (type plus optional pattern). */
|
|
611
|
+
function parseCellNumberFormat(value) {
|
|
612
|
+
if (value === null || value === undefined)
|
|
613
|
+
return undefined;
|
|
614
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
615
|
+
invalidProviderState("cell numberFormat must be an object");
|
|
616
|
+
}
|
|
617
|
+
const record = value;
|
|
618
|
+
const type = record.type;
|
|
619
|
+
if (typeof type !== "string" || type.length === 0) {
|
|
620
|
+
invalidProviderState("cell numberFormat.type is invalid");
|
|
621
|
+
}
|
|
622
|
+
const pattern = record.pattern;
|
|
623
|
+
if (pattern !== undefined && typeof pattern !== "string") {
|
|
624
|
+
invalidProviderState("cell numberFormat.pattern is invalid");
|
|
625
|
+
}
|
|
626
|
+
return { type, pattern };
|
|
627
|
+
}
|
|
628
|
+
// ---------------------------------------------------------------------------
|
|
629
|
+
// Receipt parsing
|
|
630
|
+
// ---------------------------------------------------------------------------
|
|
631
|
+
/** Parses and validates the hidden receipt tab grid. */
|
|
632
|
+
export function readReceipts(data) {
|
|
633
|
+
const headerValues = gridRowCells(data, 1, 1, GOOGLE_SHEETS_API_RECEIPT_HEADERS.length);
|
|
634
|
+
const actualHeaders = headerValues.map((value) => {
|
|
635
|
+
if (value === null)
|
|
636
|
+
return "";
|
|
637
|
+
const raw = apiStringValue(value);
|
|
638
|
+
return typeof raw === "string" ? raw : "";
|
|
639
|
+
});
|
|
640
|
+
if (actualHeaders.length !== GOOGLE_SHEETS_API_RECEIPT_HEADERS.length ||
|
|
641
|
+
actualHeaders.some((header, index) => header !== GOOGLE_SHEETS_API_RECEIPT_HEADERS[index])) {
|
|
642
|
+
invalidProviderState("receipt sheet headers do not match");
|
|
643
|
+
}
|
|
644
|
+
const receipts = new Map();
|
|
645
|
+
let lastRow = Math.max(1, data.startRow + data.rowData.length);
|
|
646
|
+
for (let rowIndex = 1; rowIndex < data.rowData.length; rowIndex += 1) {
|
|
647
|
+
const rawRow = data.rowData[rowIndex];
|
|
648
|
+
if (rawRow === undefined)
|
|
649
|
+
continue;
|
|
650
|
+
const values = gridRowCells(data, data.startRow + 1 + rowIndex, 1, GOOGLE_SHEETS_API_RECEIPT_HEADERS.length);
|
|
651
|
+
const first = stringCellValue(values[0]);
|
|
652
|
+
if (first === null)
|
|
653
|
+
continue;
|
|
654
|
+
const effectId = first;
|
|
655
|
+
const payloadHash = stringCellValue(values[1]);
|
|
656
|
+
const status = stringCellValue(values[2]);
|
|
657
|
+
const visibleHash = stringCellValue(values[3]);
|
|
658
|
+
const visibleRevision = numberCellValue(values[4]);
|
|
659
|
+
if (payloadHash === null || visibleHash === null || status !== "applied" ||
|
|
660
|
+
visibleRevision === null || !Number.isSafeInteger(visibleRevision) ||
|
|
661
|
+
visibleRevision < 0) {
|
|
662
|
+
invalidProviderState(`receipt sheet contains an invalid receipt for effectId: ${effectId}`);
|
|
663
|
+
}
|
|
664
|
+
if (receipts.has(effectId)) {
|
|
665
|
+
invalidProviderState(`receipt sheet contains duplicate effectId: ${effectId}`);
|
|
666
|
+
}
|
|
667
|
+
receipts.set(effectId, {
|
|
668
|
+
effectId,
|
|
669
|
+
payloadHash,
|
|
670
|
+
status,
|
|
671
|
+
visibleHash,
|
|
672
|
+
visibleRevision,
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
return { receipts, lastRow };
|
|
676
|
+
}
|
|
677
|
+
function stringCellValue(value) {
|
|
678
|
+
const raw = apiStringValue(value);
|
|
679
|
+
return raw === undefined ? null : raw;
|
|
680
|
+
}
|
|
681
|
+
function numberCellValue(value) {
|
|
682
|
+
const raw = apiNumberValue(value);
|
|
683
|
+
return raw === undefined ? null : raw;
|
|
684
|
+
}
|
|
685
|
+
/** Reads the userEnteredValue.stringValue of one API cell with guards. */
|
|
686
|
+
function apiStringValue(value) {
|
|
687
|
+
if (value === null || typeof value !== "object")
|
|
688
|
+
return undefined;
|
|
689
|
+
const record = value;
|
|
690
|
+
const entered = record.userEnteredValue;
|
|
691
|
+
if (entered === null || typeof entered !== "object")
|
|
692
|
+
return undefined;
|
|
693
|
+
const raw = entered.stringValue;
|
|
694
|
+
return typeof raw === "string" ? raw : undefined;
|
|
695
|
+
}
|
|
696
|
+
/** Reads the userEnteredValue.numberValue of one API cell with guards. */
|
|
697
|
+
function apiNumberValue(value) {
|
|
698
|
+
if (value === null || typeof value !== "object")
|
|
699
|
+
return undefined;
|
|
700
|
+
const record = value;
|
|
701
|
+
const entered = record.userEnteredValue;
|
|
702
|
+
if (entered === null || typeof entered !== "object")
|
|
703
|
+
return undefined;
|
|
704
|
+
const raw = entered.numberValue;
|
|
705
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined;
|
|
706
|
+
}
|
|
707
|
+
//# sourceMappingURL=preflight.js.map
|