arcane-os 0.1.0-dev.5
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/CHANGELOG.md +154 -0
- package/COMMERCIAL-LICENSE.md +13 -0
- package/LICENSE +661 -0
- package/NOTICE +70 -0
- package/README.md +448 -0
- package/bin/arcane-test.mjs +741 -0
- package/bin/arcane.mjs +5 -0
- package/docs/architecture.md +234 -0
- package/docs/compatibility.md +36 -0
- package/docs/event-manager.md +166 -0
- package/docs/platform-targets.md +108 -0
- package/docs/publishing.md +203 -0
- package/docs/reference/README.md +117 -0
- package/docs/reference/arcane-ollama.md +288 -0
- package/docs/reference/availability-and-normalization.md +123 -0
- package/docs/reference/behavioral-testing.md +86 -0
- package/docs/reference/cli.md +569 -0
- package/docs/reference/core/README.md +62 -0
- package/docs/reference/core/arcane-ai-contracts.md +873 -0
- package/docs/reference/core/arcane-api.md +601 -0
- package/docs/reference/core/arcane-entities.md +65 -0
- package/docs/reference/core/arcane-events.md +134 -0
- package/docs/reference/core/ollama-module.md +181 -0
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
- package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
- package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
- package/docs/reference/event-manager.md +957 -0
- package/docs/reference/inventory/package-api.json +2632 -0
- package/docs/reference/inventory/runtime-components.json +934 -0
- package/docs/reference/inventory/runtime-entities.json +26 -0
- package/docs/reference/inventory/runtime-modules.json +1249 -0
- package/docs/reference/protocols.md +242 -0
- package/docs/reference/runtime-components.md +1098 -0
- package/docs/reference/runtime-entities.md +303 -0
- package/docs/reference/runtime-modules.md +2010 -0
- package/docs/reference/sdk-api.md +4901 -0
- package/docs/roadmap.md +79 -0
- package/docs/work-amplification.md +124 -0
- package/node_modules/event-pubsub/CHANGELOG.md +55 -0
- package/node_modules/event-pubsub/MIGRATION.md +70 -0
- package/node_modules/event-pubsub/README.md +363 -0
- package/node_modules/event-pubsub/SECURITY.md +37 -0
- package/node_modules/event-pubsub/index.js +141 -0
- package/node_modules/event-pubsub/licence +21 -0
- package/node_modules/event-pubsub/package.json +59 -0
- package/node_modules/strong-type/README.md +408 -0
- package/node_modules/strong-type/assets/strong-type-header.png +0 -0
- package/node_modules/strong-type/index.js +1151 -0
- package/node_modules/strong-type/licence +21 -0
- package/node_modules/strong-type/node.js +125 -0
- package/node_modules/strong-type/package.json +61 -0
- package/package.json +95 -0
- package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
- package/runtime/arcane/components/app-bar.html +468 -0
- package/runtime/arcane/components/assistant-panel.html +715 -0
- package/runtime/arcane/components/calculator.html +8 -0
- package/runtime/arcane/components/chart.html +655 -0
- package/runtime/arcane/components/chat.html +1225 -0
- package/runtime/arcane/components/conversation-view.html +13 -0
- package/runtime/arcane/components/dashboard-config.html +341 -0
- package/runtime/arcane/components/data-maintenance.html +112 -0
- package/runtime/arcane/components/data-view.html +92 -0
- package/runtime/arcane/components/directory-picker.html +197 -0
- package/runtime/arcane/components/document-inspector.html +252 -0
- package/runtime/arcane/components/file-drop.html +264 -0
- package/runtime/arcane/components/file-inspector.html +293 -0
- package/runtime/arcane/components/file-manager.html +1715 -0
- package/runtime/arcane/components/header.html +142 -0
- package/runtime/arcane/components/integration-settings.html +14 -0
- package/runtime/arcane/components/local-ai-status.html +360 -0
- package/runtime/arcane/components/markdown-document.html +1048 -0
- package/runtime/arcane/components/markdown-editor.html +360 -0
- package/runtime/arcane/components/media-embed.html +8 -0
- package/runtime/arcane/components/modal.html +402 -0
- package/runtime/arcane/components/output-panel.html +259 -0
- package/runtime/arcane/components/preferences-form.html +135 -0
- package/runtime/arcane/components/record-timeline.html +105 -0
- package/runtime/arcane/components/relationship-board.html +116 -0
- package/runtime/arcane/components/screen-capture.html +8 -0
- package/runtime/arcane/components/source-code-viewer.html +441 -0
- package/runtime/arcane/components/source-explanation.html +124 -0
- package/runtime/arcane/components/speech.html +365 -0
- package/runtime/arcane/components/summary-strip.html +177 -0
- package/runtime/arcane/components/table.html +77 -0
- package/runtime/arcane/components/task-progress.html +282 -0
- package/runtime/arcane/components/terminal-workspace.html +65 -0
- package/runtime/arcane/components/theme-editor.html +41 -0
- package/runtime/arcane/components/theme-switcher.html +46 -0
- package/runtime/arcane/components/unified-inbox.html +20 -0
- package/runtime/arcane/components/voice-transcription.html +476 -0
- package/runtime/arcane/components/weather-widget.html +8 -0
- package/runtime/arcane/components/web-navigator.html +239 -0
- package/runtime/arcane/css/communications.css +1 -0
- package/runtime/arcane/css/dashboard-config.css +45 -0
- package/runtime/arcane/css/document-site.css +981 -0
- package/runtime/arcane/css/layout.css +438 -0
- package/runtime/arcane/css/primitives.css +321 -0
- package/runtime/arcane/css/theme.css +112 -0
- package/runtime/arcane/css/utility-workspace.css +1 -0
- package/runtime/arcane/entities/ApiModelRecord.js +20 -0
- package/runtime/arcane/entities/Calculation.js +13 -0
- package/runtime/arcane/entities/Chat.js +581 -0
- package/runtime/arcane/entities/CommunicationMessage.js +29 -0
- package/runtime/arcane/entities/CommunicationThread.js +21 -0
- package/runtime/arcane/entities/Document.js +10 -0
- package/runtime/arcane/entities/File.js +143 -0
- package/runtime/arcane/entities/Image.js +135 -0
- package/runtime/arcane/entities/IntentEnvelope.js +834 -0
- package/runtime/arcane/entities/Preference.js +83 -0
- package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
- package/runtime/arcane/entities/TerminalSession.js +46 -0
- package/runtime/arcane/entities/Theme.js +107 -0
- package/runtime/arcane/entities/User.js +1046 -0
- package/runtime/arcane/entities/Weather.js +23 -0
- package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
- package/runtime/arcane/img/arrow-left.png +0 -0
- package/runtime/arcane/img/arrow-right.png +0 -0
- package/runtime/arcane/img/doc.svg +5 -0
- package/runtime/arcane/img/folder.svg +4 -0
- package/runtime/arcane/img/image.svg +5 -0
- package/runtime/arcane/img/refresh.png +0 -0
- package/runtime/arcane/img/send.svg +9 -0
- package/runtime/arcane/img/trash.svg +5 -0
- package/runtime/arcane/img/upload.svg +5 -0
- package/runtime/arcane/modules/AI.js +2048 -0
- package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
- package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
- package/runtime/arcane/modules/AIResponseLength.js +42 -0
- package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
- package/runtime/arcane/modules/AnsiText.js +53 -0
- package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
- package/runtime/arcane/modules/AppDataScope.js +245 -0
- package/runtime/arcane/modules/AppearancePreferences.js +28 -0
- package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
- package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
- package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
- package/runtime/arcane/modules/AsyncBoundary.js +161 -0
- package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
- package/runtime/arcane/modules/CalculatorEngine.js +20 -0
- package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
- package/runtime/arcane/modules/ChartLibrary.js +35 -0
- package/runtime/arcane/modules/ChatRecords.js +13 -0
- package/runtime/arcane/modules/CommunicationAppController.js +43 -0
- package/runtime/arcane/modules/CommunicationHub.js +16 -0
- package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
- package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
- package/runtime/arcane/modules/ComponentContracts.js +586 -0
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
- package/runtime/arcane/modules/ConversationActionItems.js +488 -0
- package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
- package/runtime/arcane/modules/ConversationTimebox.js +527 -0
- package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
- package/runtime/arcane/modules/DBLS.js +171 -0
- package/runtime/arcane/modules/DBOPFS.js +1154 -0
- package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
- package/runtime/arcane/modules/DataMaintenance.js +91 -0
- package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
- package/runtime/arcane/modules/DirectoryPicker.js +109 -0
- package/runtime/arcane/modules/DocumentNavigation.js +223 -0
- package/runtime/arcane/modules/Errors.js +1025 -0
- package/runtime/arcane/modules/GifEncoder.js +29 -0
- package/runtime/arcane/modules/HTMLImport.js +114 -0
- package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
- package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
- package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
- package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
- package/runtime/arcane/modules/MD.js +111 -0
- package/runtime/arcane/modules/Mail.js +352 -0
- package/runtime/arcane/modules/MailTransport.mjs +180 -0
- package/runtime/arcane/modules/Marked.min.js +71 -0
- package/runtime/arcane/modules/MemoryRecords.js +44 -0
- package/runtime/arcane/modules/MessageAdvisory.js +38 -0
- package/runtime/arcane/modules/ModelDefinition.js +189 -0
- package/runtime/arcane/modules/Ollama.js +74 -0
- package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
- package/runtime/arcane/modules/OllamaSettings.js +24 -0
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
- package/runtime/arcane/modules/PreferenceStore.js +109 -0
- package/runtime/arcane/modules/QRCode.min.js +1 -0
- package/runtime/arcane/modules/Questionnaire.js +61 -0
- package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
- package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
- package/runtime/arcane/modules/RecordReviewStore.js +94 -0
- package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
- package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
- package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
- package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
- package/runtime/arcane/modules/ScreenCapture.js +20 -0
- package/runtime/arcane/modules/SpeechPlayback.js +581 -0
- package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
- package/runtime/arcane/modules/SystemAppearance.js +20 -0
- package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
- package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
- package/runtime/arcane/modules/TerminalClient.js +52 -0
- package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
- package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
- package/runtime/arcane/modules/ThemeManager.js +131 -0
- package/runtime/arcane/modules/TimeGuard.js +149 -0
- package/runtime/arcane/modules/ToolCallRouter.js +83 -0
- package/runtime/arcane/modules/WaitForComponent.js +102 -0
- package/runtime/arcane/modules/YouTubeMedia.js +16 -0
- package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
- package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
- package/runtime/arcane/modules/uPlot.min.css +1 -0
- package/runtime/arcane/security/arcane-network-policy.json +6 -0
- package/runtime/strong-type/index.js +352 -0
- package/runtime/strong-type/licence +21 -0
- package/runtime/strong-type/package.json +45 -0
- package/schemas/arcane-app-bundle.schema.json +125 -0
- package/schemas/arcane-app.schema.json +329 -0
- package/schemas/arcane-lock.schema.json +86 -0
- package/schemas/arcane-package.schema.json +224 -0
- package/schemas/cli-event.schema.json +122 -0
- package/schemas/event-stack.schema.json +152 -0
- package/schemas/native-build-plan.schema.json +176 -0
- package/schemas/target-adapter.schema.json +117 -0
- package/src/app-descriptor.mjs +500 -0
- package/src/cli/main.mjs +561 -0
- package/src/constants.mjs +31 -0
- package/src/dev-server.mjs +718 -0
- package/src/doctor.mjs +315 -0
- package/src/dom-event-instrumentation.mjs +594 -0
- package/src/errors.mjs +75 -0
- package/src/event-manager.mjs +1342 -0
- package/src/event-queue.mjs +138 -0
- package/src/events.mjs +219 -0
- package/src/index.mjs +177 -0
- package/src/integrated-provider-loader.mjs +432 -0
- package/src/native-plan.mjs +698 -0
- package/src/native-provider-loader.mjs +1126 -0
- package/src/packager/core.mjs +2691 -0
- package/src/process.mjs +353 -0
- package/src/release-bundle.mjs +2523 -0
- package/src/repository.mjs +90 -0
- package/src/runtime.mjs +452 -0
- package/src/scaffold.mjs +380 -0
- package/src/targets/index.mjs +436 -0
- package/src/templates/assets/app-icon.png +0 -0
- package/src/templates/workspace-template.mjs +388 -0
- package/src/testing-loader.mjs +9 -0
- package/src/testing.mjs +427 -0
- package/src/toolchain.mjs +1335 -0
- package/src/update-check.mjs +307 -0
- package/src/workspace.mjs +449 -0
|
@@ -0,0 +1,1623 @@
|
|
|
1
|
+
const PROJECTION_LEDGER_SCHEMA_VERSION = '1.0.0';
|
|
2
|
+
const DEFAULT_PROJECTION_LEDGER_CAPACITY = 500;
|
|
3
|
+
const MAX_PROJECTION_LEDGER_CAPACITY = 5000;
|
|
4
|
+
const MAX_PROJECTION_LEDGER_DEPTH = 24;
|
|
5
|
+
const MAX_PROJECTION_LEDGER_NODES = 5000;
|
|
6
|
+
const MAX_PROJECTION_LEDGER_ARRAY_ITEMS = 1000;
|
|
7
|
+
const MAX_PROJECTION_LEDGER_OBJECT_KEYS = 1000;
|
|
8
|
+
const MAX_PROJECTION_LEDGER_OBJECT_KEY_LENGTH = 256;
|
|
9
|
+
const MAX_PROJECTION_LEDGER_STRING_LENGTH = 16000;
|
|
10
|
+
const MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS = 64000;
|
|
11
|
+
const MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES = 128000;
|
|
12
|
+
const MAX_PROJECTION_LEDGER_KEY_LENGTH = 256;
|
|
13
|
+
const MIN_PROJECTION_LEDGER_STORED_CHARACTERS = 128000;
|
|
14
|
+
const DEFAULT_PROJECTION_LEDGER_STORED_CHARACTERS = 4000000;
|
|
15
|
+
const MAX_PROJECTION_LEDGER_STORED_CHARACTERS = 16000000;
|
|
16
|
+
const MIN_PROJECTION_LEDGER_STORED_UTF8_BYTES = 256000;
|
|
17
|
+
const DEFAULT_PROJECTION_LEDGER_STORED_UTF8_BYTES = 8000000;
|
|
18
|
+
const MAX_PROJECTION_LEDGER_STORED_UTF8_BYTES = 32000000;
|
|
19
|
+
const MIN_PROJECTION_LEDGER_STORED_NODES = 10000;
|
|
20
|
+
const DEFAULT_PROJECTION_LEDGER_STORED_NODES = 500000;
|
|
21
|
+
const MAX_PROJECTION_LEDGER_STORED_NODES = 2000000;
|
|
22
|
+
|
|
23
|
+
const PROJECTION_LEDGER_STATUSES = Object.freeze(
|
|
24
|
+
{
|
|
25
|
+
ACTIVE_TARGET_CONFLICT: 'active-target-conflict',
|
|
26
|
+
ALREADY_REVOKED: 'already-revoked',
|
|
27
|
+
CAPACITY_REACHED: 'capacity-reached',
|
|
28
|
+
EXISTS: 'exists',
|
|
29
|
+
NOT_FOUND: 'not-found',
|
|
30
|
+
REVOKED: 'revoked',
|
|
31
|
+
SOURCE_CONFLICT: 'source-conflict',
|
|
32
|
+
SOURCE_REVOKED: 'source-revoked',
|
|
33
|
+
STORED: 'stored'
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const PROJECTION_LEDGER_REASON_CODES = Object.freeze(
|
|
38
|
+
{
|
|
39
|
+
INVALID_INPUT: 'INVALID_INPUT'
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const PROJECTION_LEDGER_LIMITS = Object.freeze(
|
|
44
|
+
{
|
|
45
|
+
defaultCapacity: DEFAULT_PROJECTION_LEDGER_CAPACITY,
|
|
46
|
+
maximumCapacity: MAX_PROJECTION_LEDGER_CAPACITY,
|
|
47
|
+
maximumDepth: MAX_PROJECTION_LEDGER_DEPTH,
|
|
48
|
+
maximumNodes: MAX_PROJECTION_LEDGER_NODES,
|
|
49
|
+
maximumArrayItems: MAX_PROJECTION_LEDGER_ARRAY_ITEMS,
|
|
50
|
+
maximumObjectKeys: MAX_PROJECTION_LEDGER_OBJECT_KEYS,
|
|
51
|
+
maximumObjectKeyLength: MAX_PROJECTION_LEDGER_OBJECT_KEY_LENGTH,
|
|
52
|
+
maximumStringLength: MAX_PROJECTION_LEDGER_STRING_LENGTH,
|
|
53
|
+
maximumTotalCharacters: MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS,
|
|
54
|
+
maximumTotalUtf8Bytes: MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES,
|
|
55
|
+
maximumLedgerKeyLength: MAX_PROJECTION_LEDGER_KEY_LENGTH,
|
|
56
|
+
minimumStoredCharacters: MIN_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
57
|
+
defaultStoredCharacters: DEFAULT_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
58
|
+
maximumStoredCharacters: MAX_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
59
|
+
minimumStoredUtf8Bytes: MIN_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
60
|
+
defaultStoredUtf8Bytes: DEFAULT_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
61
|
+
maximumStoredUtf8Bytes: MAX_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
62
|
+
minimumStoredNodes: MIN_PROJECTION_LEDGER_STORED_NODES,
|
|
63
|
+
defaultStoredNodes: DEFAULT_PROJECTION_LEDGER_STORED_NODES,
|
|
64
|
+
maximumStoredNodes: MAX_PROJECTION_LEDGER_STORED_NODES
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const PROHIBITED_PROJECTION_LEDGER_KEYS = new Set(
|
|
69
|
+
[
|
|
70
|
+
'__proto__',
|
|
71
|
+
'constructor',
|
|
72
|
+
'prototype'
|
|
73
|
+
]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const PROJECTION_INPUT_KEYS = new Set(
|
|
77
|
+
[
|
|
78
|
+
'sourceKey',
|
|
79
|
+
'targetKey',
|
|
80
|
+
'identity',
|
|
81
|
+
'payload'
|
|
82
|
+
]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const REVOCATION_INPUT_KEYS = new Set(
|
|
86
|
+
[
|
|
87
|
+
'projectionId',
|
|
88
|
+
'payload'
|
|
89
|
+
]
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const OPTIONS_KEYS = new Set(
|
|
93
|
+
[
|
|
94
|
+
'capacity',
|
|
95
|
+
'maximumStoredCharacters',
|
|
96
|
+
'maximumStoredUtf8Bytes',
|
|
97
|
+
'maximumStoredNodes'
|
|
98
|
+
]
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
class ProjectionLedgerError extends TypeError {
|
|
102
|
+
constructor(reasonCode, message) {
|
|
103
|
+
super(message);
|
|
104
|
+
this.name = 'ProjectionLedgerError';
|
|
105
|
+
this.reasonCode = reasonCode;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function invalidProjectionLedgerBoundary(label, detail) {
|
|
110
|
+
return new ProjectionLedgerError(
|
|
111
|
+
PROJECTION_LEDGER_REASON_CODES.INVALID_INPUT,
|
|
112
|
+
`${label} ${detail}`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function readProjectionLedgerPrototype(value, label) {
|
|
117
|
+
try {
|
|
118
|
+
return Object.getPrototypeOf(value);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
throw invalidProjectionLedgerBoundary(
|
|
121
|
+
label,
|
|
122
|
+
'could not be inspected safely.'
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function readProjectionLedgerOwnKeys(value, label) {
|
|
128
|
+
try {
|
|
129
|
+
return Reflect.ownKeys(value);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
throw invalidProjectionLedgerBoundary(
|
|
132
|
+
label,
|
|
133
|
+
'could not be inspected safely.'
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function readProjectionLedgerOwnDescriptor(value, key, label) {
|
|
139
|
+
try {
|
|
140
|
+
return Reflect.getOwnPropertyDescriptor(value, key);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
throw invalidProjectionLedgerBoundary(
|
|
143
|
+
label,
|
|
144
|
+
'could not be inspected safely.'
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function readProjectionLedgerDescriptors(value, keys, label) {
|
|
150
|
+
const descriptors = Object.create(null);
|
|
151
|
+
|
|
152
|
+
for (const key of keys) {
|
|
153
|
+
const descriptor = readProjectionLedgerOwnDescriptor(value, key, label);
|
|
154
|
+
|
|
155
|
+
if (!descriptor) {
|
|
156
|
+
throw invalidProjectionLedgerBoundary(
|
|
157
|
+
label,
|
|
158
|
+
'changed while it was being inspected.'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Object.defineProperty(
|
|
163
|
+
descriptors,
|
|
164
|
+
key,
|
|
165
|
+
{
|
|
166
|
+
configurable: true,
|
|
167
|
+
enumerable: true,
|
|
168
|
+
value: descriptor,
|
|
169
|
+
writable: true
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return descriptors;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function inspectProjectionLedgerArray(value, label) {
|
|
178
|
+
try {
|
|
179
|
+
return Array.isArray(value);
|
|
180
|
+
} catch (error) {
|
|
181
|
+
throw invalidProjectionLedgerBoundary(
|
|
182
|
+
label,
|
|
183
|
+
'could not be inspected safely.'
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function assertProjectionLedgerDataDescriptor(descriptor, label) {
|
|
189
|
+
if (!descriptor
|
|
190
|
+
|| Object.hasOwn(descriptor, 'get')
|
|
191
|
+
|| Object.hasOwn(descriptor, 'set')) {
|
|
192
|
+
throw invalidProjectionLedgerBoundary(
|
|
193
|
+
label,
|
|
194
|
+
'contains an accessor property.'
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!descriptor.enumerable) {
|
|
199
|
+
throw invalidProjectionLedgerBoundary(
|
|
200
|
+
label,
|
|
201
|
+
'contains a hidden property.'
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function incrementProjectionLedgerNodeCount(label, state) {
|
|
207
|
+
state.nodes += 1;
|
|
208
|
+
|
|
209
|
+
if (state.nodes > MAX_PROJECTION_LEDGER_NODES) {
|
|
210
|
+
throw invalidProjectionLedgerBoundary(
|
|
211
|
+
label,
|
|
212
|
+
'contains too many values.'
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function projectionLedgerUtf8ByteLength(value) {
|
|
218
|
+
let bytes = 0;
|
|
219
|
+
|
|
220
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
221
|
+
const codeUnit = value.charCodeAt(index);
|
|
222
|
+
|
|
223
|
+
if (codeUnit <= 0x7f) {
|
|
224
|
+
bytes += 1;
|
|
225
|
+
} else if (codeUnit <= 0x7ff) {
|
|
226
|
+
bytes += 2;
|
|
227
|
+
} else if (codeUnit >= 0xd800
|
|
228
|
+
&& codeUnit <= 0xdbff
|
|
229
|
+
&& index + 1 < value.length) {
|
|
230
|
+
const nextCodeUnit = value.charCodeAt(index + 1);
|
|
231
|
+
|
|
232
|
+
if (nextCodeUnit >= 0xdc00 && nextCodeUnit <= 0xdfff) {
|
|
233
|
+
bytes += 4;
|
|
234
|
+
index += 1;
|
|
235
|
+
} else {
|
|
236
|
+
bytes += 3;
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
bytes += 3;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return bytes;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function consumeProjectionLedgerStringBudget(value, label, state) {
|
|
247
|
+
state.characters += value.length;
|
|
248
|
+
state.utf8Bytes += projectionLedgerUtf8ByteLength(value);
|
|
249
|
+
|
|
250
|
+
if (state.characters > MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS) {
|
|
251
|
+
throw invalidProjectionLedgerBoundary(
|
|
252
|
+
label,
|
|
253
|
+
'exceeds the cumulative character budget.'
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (state.utf8Bytes > MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES) {
|
|
258
|
+
throw invalidProjectionLedgerBoundary(
|
|
259
|
+
label,
|
|
260
|
+
'exceeds the cumulative UTF-8 byte budget.'
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function precheckProjectionLedgerArrayKeys(keys, length, label) {
|
|
266
|
+
if (keys.length > MAX_PROJECTION_LEDGER_ARRAY_ITEMS + 1) {
|
|
267
|
+
throw invalidProjectionLedgerBoundary(
|
|
268
|
+
label,
|
|
269
|
+
'contains too many array properties.'
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
for (const key of keys) {
|
|
274
|
+
if (typeof key !== 'string') {
|
|
275
|
+
throw invalidProjectionLedgerBoundary(
|
|
276
|
+
label,
|
|
277
|
+
'contains a symbol key.'
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (key === 'length') {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (!/^(?:0|[1-9][0-9]*)$/.test(key)
|
|
286
|
+
|| Number(key) >= length) {
|
|
287
|
+
throw invalidProjectionLedgerBoundary(
|
|
288
|
+
label,
|
|
289
|
+
'contains a non-index array property.'
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function precheckProjectionLedgerObjectKeys(keys, label) {
|
|
296
|
+
if (keys.length > MAX_PROJECTION_LEDGER_OBJECT_KEYS) {
|
|
297
|
+
throw invalidProjectionLedgerBoundary(
|
|
298
|
+
label,
|
|
299
|
+
'contains too many object keys.'
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
for (const key of keys) {
|
|
304
|
+
if (typeof key !== 'string') {
|
|
305
|
+
throw invalidProjectionLedgerBoundary(
|
|
306
|
+
label,
|
|
307
|
+
'contains a symbol key.'
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (key.length > MAX_PROJECTION_LEDGER_OBJECT_KEY_LENGTH) {
|
|
312
|
+
throw invalidProjectionLedgerBoundary(
|
|
313
|
+
label,
|
|
314
|
+
'contains an object key that is too long.'
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (PROHIBITED_PROJECTION_LEDGER_KEYS.has(key)) {
|
|
319
|
+
throw invalidProjectionLedgerBoundary(
|
|
320
|
+
label,
|
|
321
|
+
'contains a prohibited object key.'
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function assertProjectionLedgerKeysUnchanged(expectedKeys, actualKeys, label) {
|
|
328
|
+
if (expectedKeys.length !== actualKeys.length) {
|
|
329
|
+
throw invalidProjectionLedgerBoundary(
|
|
330
|
+
label,
|
|
331
|
+
'changed while it was being inspected.'
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const expectedKeySet = new Set(expectedKeys);
|
|
336
|
+
|
|
337
|
+
for (const key of actualKeys) {
|
|
338
|
+
if (!expectedKeySet.has(key)) {
|
|
339
|
+
throw invalidProjectionLedgerBoundary(
|
|
340
|
+
label,
|
|
341
|
+
'changed while it was being inspected.'
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function cloneProjectionLedgerArray(value, label, depth, state) {
|
|
348
|
+
const prototype = readProjectionLedgerPrototype(value, label);
|
|
349
|
+
|
|
350
|
+
if (prototype !== Array.prototype) {
|
|
351
|
+
throw invalidProjectionLedgerBoundary(
|
|
352
|
+
label,
|
|
353
|
+
'must contain only ordinary arrays.'
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const lengthDescriptor = readProjectionLedgerOwnDescriptor(
|
|
358
|
+
value,
|
|
359
|
+
'length',
|
|
360
|
+
label
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
if (!lengthDescriptor
|
|
364
|
+
|| Object.hasOwn(lengthDescriptor, 'get')
|
|
365
|
+
|| Object.hasOwn(lengthDescriptor, 'set')
|
|
366
|
+
|| !Number.isInteger(lengthDescriptor.value)
|
|
367
|
+
|| lengthDescriptor.value < 0) {
|
|
368
|
+
throw invalidProjectionLedgerBoundary(
|
|
369
|
+
label,
|
|
370
|
+
'contains an invalid array length.'
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const length = lengthDescriptor.value;
|
|
375
|
+
|
|
376
|
+
if (length > MAX_PROJECTION_LEDGER_ARRAY_ITEMS) {
|
|
377
|
+
throw invalidProjectionLedgerBoundary(
|
|
378
|
+
label,
|
|
379
|
+
'contains too many array items.'
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const keys = readProjectionLedgerOwnKeys(value, label);
|
|
384
|
+
precheckProjectionLedgerArrayKeys(keys, length, label);
|
|
385
|
+
const descriptors = readProjectionLedgerDescriptors(value, keys, label);
|
|
386
|
+
const verifiedKeys = readProjectionLedgerOwnKeys(value, label);
|
|
387
|
+
precheckProjectionLedgerArrayKeys(verifiedKeys, length, label);
|
|
388
|
+
assertProjectionLedgerKeysUnchanged(keys, verifiedKeys, label);
|
|
389
|
+
|
|
390
|
+
for (const key of keys) {
|
|
391
|
+
if (key === 'length') {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
assertProjectionLedgerDataDescriptor(descriptors[key], label);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const output = [];
|
|
399
|
+
|
|
400
|
+
for (let index = 0; index < length; index += 1) {
|
|
401
|
+
const descriptor = descriptors[String(index)];
|
|
402
|
+
|
|
403
|
+
if (!descriptor) {
|
|
404
|
+
throw invalidProjectionLedgerBoundary(
|
|
405
|
+
label,
|
|
406
|
+
'contains a sparse array item.'
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
output.push(
|
|
411
|
+
cloneProjectionLedgerNode(
|
|
412
|
+
descriptor.value,
|
|
413
|
+
`${label} item`,
|
|
414
|
+
depth + 1,
|
|
415
|
+
state
|
|
416
|
+
)
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return output;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function cloneProjectionLedgerRecord(value, label, depth, state) {
|
|
424
|
+
const prototype = readProjectionLedgerPrototype(value, label);
|
|
425
|
+
|
|
426
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
427
|
+
throw invalidProjectionLedgerBoundary(
|
|
428
|
+
label,
|
|
429
|
+
'must contain only plain objects.'
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const keys = readProjectionLedgerOwnKeys(value, label);
|
|
434
|
+
precheckProjectionLedgerObjectKeys(keys, label);
|
|
435
|
+
const descriptors = readProjectionLedgerDescriptors(value, keys, label);
|
|
436
|
+
const verifiedKeys = readProjectionLedgerOwnKeys(value, label);
|
|
437
|
+
precheckProjectionLedgerObjectKeys(verifiedKeys, label);
|
|
438
|
+
assertProjectionLedgerKeysUnchanged(keys, verifiedKeys, label);
|
|
439
|
+
|
|
440
|
+
const output = Object.create(null);
|
|
441
|
+
|
|
442
|
+
for (const key of keys) {
|
|
443
|
+
consumeProjectionLedgerStringBudget(key, label, state);
|
|
444
|
+
const descriptor = descriptors[key];
|
|
445
|
+
assertProjectionLedgerDataDescriptor(descriptor, label);
|
|
446
|
+
Object.defineProperty(
|
|
447
|
+
output,
|
|
448
|
+
key,
|
|
449
|
+
{
|
|
450
|
+
configurable: true,
|
|
451
|
+
enumerable: true,
|
|
452
|
+
value: cloneProjectionLedgerNode(
|
|
453
|
+
descriptor.value,
|
|
454
|
+
`${label} child`,
|
|
455
|
+
depth + 1,
|
|
456
|
+
state
|
|
457
|
+
),
|
|
458
|
+
writable: true
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return output;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function cloneProjectionLedgerNode(value, label, depth, state) {
|
|
467
|
+
incrementProjectionLedgerNodeCount(label, state);
|
|
468
|
+
|
|
469
|
+
if (depth > MAX_PROJECTION_LEDGER_DEPTH) {
|
|
470
|
+
throw invalidProjectionLedgerBoundary(
|
|
471
|
+
label,
|
|
472
|
+
'is nested too deeply.'
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (value === null || typeof value === 'boolean') {
|
|
477
|
+
return value;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (typeof value === 'string') {
|
|
481
|
+
if (value.length > MAX_PROJECTION_LEDGER_STRING_LENGTH) {
|
|
482
|
+
throw invalidProjectionLedgerBoundary(
|
|
483
|
+
label,
|
|
484
|
+
'contains a string that is too long.'
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
consumeProjectionLedgerStringBudget(value, label, state);
|
|
489
|
+
|
|
490
|
+
return value;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (typeof value === 'number') {
|
|
494
|
+
if (!Number.isFinite(value)) {
|
|
495
|
+
throw invalidProjectionLedgerBoundary(
|
|
496
|
+
label,
|
|
497
|
+
'contains a non-finite number.'
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return value;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (typeof value !== 'object') {
|
|
505
|
+
throw invalidProjectionLedgerBoundary(
|
|
506
|
+
label,
|
|
507
|
+
'contains an unsupported value type.'
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (state.ancestors.has(value)) {
|
|
512
|
+
throw invalidProjectionLedgerBoundary(
|
|
513
|
+
label,
|
|
514
|
+
'contains a cyclic reference.'
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
state.ancestors.add(value);
|
|
519
|
+
|
|
520
|
+
try {
|
|
521
|
+
if (inspectProjectionLedgerArray(value, label)) {
|
|
522
|
+
return cloneProjectionLedgerArray(value, label, depth, state);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return cloneProjectionLedgerRecord(value, label, depth, state);
|
|
526
|
+
} finally {
|
|
527
|
+
state.ancestors.delete(value);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function cloneProjectionLedgerValueWithMetrics(value, label) {
|
|
532
|
+
const state = {
|
|
533
|
+
ancestors: new WeakSet(),
|
|
534
|
+
characters: 0,
|
|
535
|
+
nodes: 0,
|
|
536
|
+
utf8Bytes: 0
|
|
537
|
+
};
|
|
538
|
+
const clonedValue = cloneProjectionLedgerNode(
|
|
539
|
+
value,
|
|
540
|
+
label,
|
|
541
|
+
0,
|
|
542
|
+
state
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
return {
|
|
546
|
+
value: clonedValue,
|
|
547
|
+
metrics: {
|
|
548
|
+
characters: state.characters,
|
|
549
|
+
nodes: state.nodes,
|
|
550
|
+
utf8Bytes: state.utf8Bytes
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function cloneProjectionLedgerValue(value, label = 'Value') {
|
|
556
|
+
return cloneProjectionLedgerValueWithMetrics(value, label).value;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function isProjectionLedgerRecord(value) {
|
|
560
|
+
if (!value || typeof value !== 'object') {
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (inspectProjectionLedgerArray(value, 'Record')) {
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const prototype = readProjectionLedgerPrototype(value, 'Record');
|
|
569
|
+
return prototype === Object.prototype || prototype === null;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
function stableProjectionLedgerValue(value) {
|
|
573
|
+
if (Array.isArray(value)) {
|
|
574
|
+
const output = [];
|
|
575
|
+
|
|
576
|
+
for (const item of value) {
|
|
577
|
+
output.push(stableProjectionLedgerValue(item));
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return output;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (value && typeof value === 'object') {
|
|
584
|
+
const output = Object.create(null);
|
|
585
|
+
const keys = Object.keys(value).sort();
|
|
586
|
+
|
|
587
|
+
for (const key of keys) {
|
|
588
|
+
output[key] = stableProjectionLedgerValue(value[key]);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return output;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return value;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function canonicalProjectionLedgerTextFromSafeValue(value) {
|
|
598
|
+
return JSON.stringify(stableProjectionLedgerValue(value));
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
function createProjectionLedgerFingerprintFromSafeValue(value) {
|
|
602
|
+
const text = canonicalProjectionLedgerTextFromSafeValue(value);
|
|
603
|
+
let hash = 2166136261;
|
|
604
|
+
|
|
605
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
606
|
+
hash ^= text.charCodeAt(index);
|
|
607
|
+
hash = Math.imul(hash, 16777619);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return `fnv1a32:${(hash >>> 0).toString(16).padStart(8, '0')}`;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function createProjectionLedgerFingerprint(value) {
|
|
614
|
+
const safeValue = cloneProjectionLedgerValue(value, 'Fingerprint value');
|
|
615
|
+
return createProjectionLedgerFingerprintFromSafeValue(safeValue);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function deepFreezeProjectionLedgerValue(value) {
|
|
619
|
+
if (!value || typeof value !== 'object' || Object.isFrozen(value)) {
|
|
620
|
+
return value;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if (Array.isArray(value)) {
|
|
624
|
+
for (const item of value) {
|
|
625
|
+
deepFreezeProjectionLedgerValue(item);
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
for (const key of Object.keys(value)) {
|
|
629
|
+
deepFreezeProjectionLedgerValue(value[key]);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return Object.freeze(value);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function immutableProjectionLedgerRecord(record, label) {
|
|
637
|
+
const cloned = cloneProjectionLedgerValueWithMetrics(record, label);
|
|
638
|
+
|
|
639
|
+
return {
|
|
640
|
+
record: deepFreezeProjectionLedgerValue(cloned.value),
|
|
641
|
+
metrics: Object.freeze(cloned.metrics)
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function cloneProjectionLedgerRecordForOutput(record, label) {
|
|
646
|
+
if (!record) {
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return cloneProjectionLedgerValue(record, label);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
function normalizeProjectionLedgerKey(value, label) {
|
|
654
|
+
if (typeof value !== 'string') {
|
|
655
|
+
throw invalidProjectionLedgerBoundary(label, 'must be a string.');
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const normalized = value.normalize('NFKC').trim();
|
|
659
|
+
|
|
660
|
+
if (!normalized) {
|
|
661
|
+
throw invalidProjectionLedgerBoundary(label, 'must not be empty.');
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (normalized.length > MAX_PROJECTION_LEDGER_KEY_LENGTH) {
|
|
665
|
+
throw invalidProjectionLedgerBoundary(label, 'is too long.');
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
if (/[\u0000-\u001f\u007f-\u009f]/.test(normalized)) {
|
|
669
|
+
throw invalidProjectionLedgerBoundary(
|
|
670
|
+
label,
|
|
671
|
+
'contains a control character.'
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return normalized;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function assertProjectionLedgerRecord(value, label) {
|
|
679
|
+
if (!isProjectionLedgerRecord(value)) {
|
|
680
|
+
throw invalidProjectionLedgerBoundary(label, 'must be a plain object.');
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function assertProjectionLedgerRecordKeys(record, allowedKeys, requiredKeys, label) {
|
|
685
|
+
for (const key of Object.keys(record)) {
|
|
686
|
+
if (!allowedKeys.has(key)) {
|
|
687
|
+
throw invalidProjectionLedgerBoundary(
|
|
688
|
+
label,
|
|
689
|
+
`contains unsupported key ${key}.`
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
for (const key of requiredKeys) {
|
|
695
|
+
if (!Object.hasOwn(record, key)) {
|
|
696
|
+
throw invalidProjectionLedgerBoundary(
|
|
697
|
+
label,
|
|
698
|
+
`requires ${key}.`
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function normalizeProjectionLedgerBudget(
|
|
705
|
+
options,
|
|
706
|
+
key,
|
|
707
|
+
defaultValue,
|
|
708
|
+
minimum,
|
|
709
|
+
maximum,
|
|
710
|
+
label
|
|
711
|
+
) {
|
|
712
|
+
const value = Object.hasOwn(options, key)
|
|
713
|
+
? options[key]
|
|
714
|
+
: defaultValue;
|
|
715
|
+
|
|
716
|
+
if (!Number.isInteger(value) || value < minimum || value > maximum) {
|
|
717
|
+
throw invalidProjectionLedgerBoundary(
|
|
718
|
+
label,
|
|
719
|
+
`must be an integer from ${minimum} through ${maximum}.`
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
return value;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function normalizeProjectionLedgerOptions(options) {
|
|
727
|
+
const safeOptions = cloneProjectionLedgerValue(options, 'Ledger options');
|
|
728
|
+
assertProjectionLedgerRecord(safeOptions, 'Ledger options');
|
|
729
|
+
assertProjectionLedgerRecordKeys(
|
|
730
|
+
safeOptions,
|
|
731
|
+
OPTIONS_KEYS,
|
|
732
|
+
[],
|
|
733
|
+
'Ledger options'
|
|
734
|
+
);
|
|
735
|
+
return {
|
|
736
|
+
capacity: normalizeProjectionLedgerBudget(
|
|
737
|
+
safeOptions,
|
|
738
|
+
'capacity',
|
|
739
|
+
DEFAULT_PROJECTION_LEDGER_CAPACITY,
|
|
740
|
+
1,
|
|
741
|
+
MAX_PROJECTION_LEDGER_CAPACITY,
|
|
742
|
+
'Ledger capacity'
|
|
743
|
+
),
|
|
744
|
+
maximumStoredCharacters: normalizeProjectionLedgerBudget(
|
|
745
|
+
safeOptions,
|
|
746
|
+
'maximumStoredCharacters',
|
|
747
|
+
DEFAULT_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
748
|
+
MIN_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
749
|
+
MAX_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
750
|
+
'Ledger maximumStoredCharacters'
|
|
751
|
+
),
|
|
752
|
+
maximumStoredUtf8Bytes: normalizeProjectionLedgerBudget(
|
|
753
|
+
safeOptions,
|
|
754
|
+
'maximumStoredUtf8Bytes',
|
|
755
|
+
DEFAULT_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
756
|
+
MIN_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
757
|
+
MAX_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
758
|
+
'Ledger maximumStoredUtf8Bytes'
|
|
759
|
+
),
|
|
760
|
+
maximumStoredNodes: normalizeProjectionLedgerBudget(
|
|
761
|
+
safeOptions,
|
|
762
|
+
'maximumStoredNodes',
|
|
763
|
+
DEFAULT_PROJECTION_LEDGER_STORED_NODES,
|
|
764
|
+
MIN_PROJECTION_LEDGER_STORED_NODES,
|
|
765
|
+
MAX_PROJECTION_LEDGER_STORED_NODES,
|
|
766
|
+
'Ledger maximumStoredNodes'
|
|
767
|
+
)
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function formatProjectionLedgerSequence(sequence) {
|
|
772
|
+
return String(sequence).padStart(6, '0');
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Keeps append-only projection and revocation events in bounded page memory.
|
|
777
|
+
*
|
|
778
|
+
* Inputs and outputs are descriptor-safe JSON-like values. The ledger does not
|
|
779
|
+
* persist, communicate, authorize, or attach domain meaning to either key.
|
|
780
|
+
* Operations are asynchronous for adapter compatibility but complete entirely
|
|
781
|
+
* in memory before their returned promise settles. Capacity counts projection
|
|
782
|
+
* slots; each slot includes one reserved revocation event, so every projection
|
|
783
|
+
* can always be revoked and total events cannot exceed twice the capacity.
|
|
784
|
+
* Ledger-wide character, UTF-8 byte, and node budgets count committed records
|
|
785
|
+
* plus worst-case reserved revocations before any new projection is accepted.
|
|
786
|
+
* Constructor options are `capacity`, `maximumStoredCharacters`,
|
|
787
|
+
* `maximumStoredUtf8Bytes`, and `maximumStoredNodes`; their defaults are 500,
|
|
788
|
+
* 4,000,000, 8,000,000, and 500,000. `remainingCapacity` reports unused
|
|
789
|
+
* projection slots, while the `remainingStored*` getters include reservations.
|
|
790
|
+
*/
|
|
791
|
+
class RevocableProjectionLedger {
|
|
792
|
+
#activeProjectionByTarget = new Map();
|
|
793
|
+
#capacity;
|
|
794
|
+
#maximumStoredCharacters;
|
|
795
|
+
#maximumStoredNodes;
|
|
796
|
+
#maximumStoredUtf8Bytes;
|
|
797
|
+
#projectionById = new Map();
|
|
798
|
+
#projectionBySource = new Map();
|
|
799
|
+
#projectionRecords = [];
|
|
800
|
+
#reservedRevocationCharacters = 0;
|
|
801
|
+
#reservedRevocationNodes = 0;
|
|
802
|
+
#reservedRevocationUtf8Bytes = 0;
|
|
803
|
+
#revocationByProjectionId = new Map();
|
|
804
|
+
#revocationRecords = [];
|
|
805
|
+
#sequence = 0;
|
|
806
|
+
#storedCharacters = 0;
|
|
807
|
+
#storedNodes = 0;
|
|
808
|
+
#storedUtf8Bytes = 0;
|
|
809
|
+
|
|
810
|
+
constructor(options = {}) {
|
|
811
|
+
const settings = normalizeProjectionLedgerOptions(options);
|
|
812
|
+
this.#capacity = settings.capacity;
|
|
813
|
+
this.#maximumStoredCharacters = settings.maximumStoredCharacters;
|
|
814
|
+
this.#maximumStoredUtf8Bytes = settings.maximumStoredUtf8Bytes;
|
|
815
|
+
this.#maximumStoredNodes = settings.maximumStoredNodes;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
get capacity() {
|
|
819
|
+
return this.#capacity;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
get eventCount() {
|
|
823
|
+
return this.#projectionRecords.length + this.#revocationRecords.length;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
get eventCapacity() {
|
|
827
|
+
return this.#capacity * 2;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
get maximumStoredCharacters() {
|
|
831
|
+
return this.#maximumStoredCharacters;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
get maximumStoredUtf8Bytes() {
|
|
835
|
+
return this.#maximumStoredUtf8Bytes;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
get maximumStoredNodes() {
|
|
839
|
+
return this.#maximumStoredNodes;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
get storedCharacters() {
|
|
843
|
+
return this.#storedCharacters;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
get storedUtf8Bytes() {
|
|
847
|
+
return this.#storedUtf8Bytes;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
get storedNodes() {
|
|
851
|
+
return this.#storedNodes;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
get reservedRevocationCharacters() {
|
|
855
|
+
return this.#reservedRevocationCharacters;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
get reservedRevocationUtf8Bytes() {
|
|
859
|
+
return this.#reservedRevocationUtf8Bytes;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
get reservedRevocationNodes() {
|
|
863
|
+
return this.#reservedRevocationNodes;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
get remainingStoredCharacters() {
|
|
867
|
+
return this.#maximumStoredCharacters
|
|
868
|
+
- this.#storedCharacters
|
|
869
|
+
- this.#reservedRevocationCharacters;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
get remainingStoredUtf8Bytes() {
|
|
873
|
+
return this.#maximumStoredUtf8Bytes
|
|
874
|
+
- this.#storedUtf8Bytes
|
|
875
|
+
- this.#reservedRevocationUtf8Bytes;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
get remainingStoredNodes() {
|
|
879
|
+
return this.#maximumStoredNodes
|
|
880
|
+
- this.#storedNodes
|
|
881
|
+
- this.#reservedRevocationNodes;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
get remainingCapacity() {
|
|
885
|
+
return this.#capacity - this.#projectionRecords.length;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
#projectionBudgetResult(metrics) {
|
|
889
|
+
if (metrics.characters + MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS
|
|
890
|
+
> this.remainingStoredCharacters) {
|
|
891
|
+
return {
|
|
892
|
+
status: PROJECTION_LEDGER_STATUSES.CAPACITY_REACHED,
|
|
893
|
+
capacity: this.#capacity,
|
|
894
|
+
capacityReason: 'stored-character-budget',
|
|
895
|
+
maximumStoredCharacters: this.#maximumStoredCharacters,
|
|
896
|
+
remainingStoredCharacters: this.remainingStoredCharacters,
|
|
897
|
+
remainingCapacity: this.remainingCapacity,
|
|
898
|
+
idempotent: false
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (metrics.utf8Bytes + MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES
|
|
903
|
+
> this.remainingStoredUtf8Bytes) {
|
|
904
|
+
return {
|
|
905
|
+
status: PROJECTION_LEDGER_STATUSES.CAPACITY_REACHED,
|
|
906
|
+
capacity: this.#capacity,
|
|
907
|
+
capacityReason: 'stored-utf8-budget',
|
|
908
|
+
maximumStoredUtf8Bytes: this.#maximumStoredUtf8Bytes,
|
|
909
|
+
remainingStoredUtf8Bytes: this.remainingStoredUtf8Bytes,
|
|
910
|
+
remainingCapacity: this.remainingCapacity,
|
|
911
|
+
idempotent: false
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
if (metrics.nodes + MAX_PROJECTION_LEDGER_NODES
|
|
916
|
+
> this.remainingStoredNodes) {
|
|
917
|
+
return {
|
|
918
|
+
status: PROJECTION_LEDGER_STATUSES.CAPACITY_REACHED,
|
|
919
|
+
capacity: this.#capacity,
|
|
920
|
+
capacityReason: 'stored-node-budget',
|
|
921
|
+
maximumStoredNodes: this.#maximumStoredNodes,
|
|
922
|
+
remainingStoredNodes: this.remainingStoredNodes,
|
|
923
|
+
remainingCapacity: this.remainingCapacity,
|
|
924
|
+
idempotent: false
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
return null;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
#assertRevocationBudget(metrics) {
|
|
932
|
+
const charactersAfter = this.#storedCharacters
|
|
933
|
+
+ metrics.characters
|
|
934
|
+
+ this.#reservedRevocationCharacters
|
|
935
|
+
- MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS;
|
|
936
|
+
const utf8BytesAfter = this.#storedUtf8Bytes
|
|
937
|
+
+ metrics.utf8Bytes
|
|
938
|
+
+ this.#reservedRevocationUtf8Bytes
|
|
939
|
+
- MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES;
|
|
940
|
+
const nodesAfter = this.#storedNodes
|
|
941
|
+
+ metrics.nodes
|
|
942
|
+
+ this.#reservedRevocationNodes
|
|
943
|
+
- MAX_PROJECTION_LEDGER_NODES;
|
|
944
|
+
|
|
945
|
+
if (this.#reservedRevocationCharacters
|
|
946
|
+
< MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS
|
|
947
|
+
|| this.#reservedRevocationUtf8Bytes
|
|
948
|
+
< MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES
|
|
949
|
+
|| this.#reservedRevocationNodes < MAX_PROJECTION_LEDGER_NODES
|
|
950
|
+
|| charactersAfter > this.#maximumStoredCharacters
|
|
951
|
+
|| utf8BytesAfter > this.#maximumStoredUtf8Bytes
|
|
952
|
+
|| nodesAfter > this.#maximumStoredNodes) {
|
|
953
|
+
throw new Error(
|
|
954
|
+
'Projection ledger revocation reservation invariant failed.'
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
async appendProjection(input) {
|
|
960
|
+
const safeInput = cloneProjectionLedgerValue(
|
|
961
|
+
input,
|
|
962
|
+
'Projection input'
|
|
963
|
+
);
|
|
964
|
+
assertProjectionLedgerRecord(safeInput, 'Projection input');
|
|
965
|
+
assertProjectionLedgerRecordKeys(
|
|
966
|
+
safeInput,
|
|
967
|
+
PROJECTION_INPUT_KEYS,
|
|
968
|
+
PROJECTION_INPUT_KEYS,
|
|
969
|
+
'Projection input'
|
|
970
|
+
);
|
|
971
|
+
|
|
972
|
+
const sourceKey = normalizeProjectionLedgerKey(
|
|
973
|
+
safeInput.sourceKey,
|
|
974
|
+
'Projection sourceKey'
|
|
975
|
+
);
|
|
976
|
+
const targetKey = normalizeProjectionLedgerKey(
|
|
977
|
+
safeInput.targetKey,
|
|
978
|
+
'Projection targetKey'
|
|
979
|
+
);
|
|
980
|
+
assertProjectionLedgerRecord(
|
|
981
|
+
safeInput.identity,
|
|
982
|
+
'Projection identity'
|
|
983
|
+
);
|
|
984
|
+
const identityText = canonicalProjectionLedgerTextFromSafeValue(
|
|
985
|
+
safeInput.identity
|
|
986
|
+
);
|
|
987
|
+
const existingForSource = this.#projectionBySource.get(sourceKey);
|
|
988
|
+
|
|
989
|
+
if (existingForSource) {
|
|
990
|
+
const revocation = this.#revocationByProjectionId.get(
|
|
991
|
+
existingForSource.id
|
|
992
|
+
);
|
|
993
|
+
|
|
994
|
+
if (revocation) {
|
|
995
|
+
return {
|
|
996
|
+
status: PROJECTION_LEDGER_STATUSES.SOURCE_REVOKED,
|
|
997
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
998
|
+
existingForSource,
|
|
999
|
+
'Projection record'
|
|
1000
|
+
),
|
|
1001
|
+
revocationRecord: cloneProjectionLedgerRecordForOutput(
|
|
1002
|
+
revocation,
|
|
1003
|
+
'Revocation record'
|
|
1004
|
+
),
|
|
1005
|
+
idempotent: false,
|
|
1006
|
+
remainingCapacity: this.remainingCapacity
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
const sameIdentity = canonicalProjectionLedgerTextFromSafeValue(
|
|
1011
|
+
existingForSource.identity
|
|
1012
|
+
) === identityText;
|
|
1013
|
+
|
|
1014
|
+
if (existingForSource.targetKey === targetKey && sameIdentity) {
|
|
1015
|
+
return {
|
|
1016
|
+
status: PROJECTION_LEDGER_STATUSES.EXISTS,
|
|
1017
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
1018
|
+
existingForSource,
|
|
1019
|
+
'Projection record'
|
|
1020
|
+
),
|
|
1021
|
+
idempotent: true,
|
|
1022
|
+
remainingCapacity: this.remainingCapacity
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
return {
|
|
1027
|
+
status: PROJECTION_LEDGER_STATUSES.SOURCE_CONFLICT,
|
|
1028
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
1029
|
+
existingForSource,
|
|
1030
|
+
'Projection record'
|
|
1031
|
+
),
|
|
1032
|
+
idempotent: false,
|
|
1033
|
+
remainingCapacity: this.remainingCapacity
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
const activeForTarget = this.#activeProjectionByTarget.get(targetKey);
|
|
1038
|
+
|
|
1039
|
+
if (activeForTarget) {
|
|
1040
|
+
return {
|
|
1041
|
+
status: PROJECTION_LEDGER_STATUSES.ACTIVE_TARGET_CONFLICT,
|
|
1042
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
1043
|
+
activeForTarget,
|
|
1044
|
+
'Projection record'
|
|
1045
|
+
),
|
|
1046
|
+
idempotent: false,
|
|
1047
|
+
remainingCapacity: this.remainingCapacity
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
if (this.remainingCapacity === 0) {
|
|
1052
|
+
return {
|
|
1053
|
+
status: PROJECTION_LEDGER_STATUSES.CAPACITY_REACHED,
|
|
1054
|
+
capacity: this.#capacity,
|
|
1055
|
+
capacityReason: 'projection-slots',
|
|
1056
|
+
remainingCapacity: 0,
|
|
1057
|
+
idempotent: false
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const sequence = this.#sequence + 1;
|
|
1062
|
+
const draft = {
|
|
1063
|
+
schemaVersion: PROJECTION_LEDGER_SCHEMA_VERSION,
|
|
1064
|
+
id: `projection-${formatProjectionLedgerSequence(sequence)}`,
|
|
1065
|
+
sequence,
|
|
1066
|
+
kind: 'projection',
|
|
1067
|
+
sourceKey,
|
|
1068
|
+
targetKey,
|
|
1069
|
+
identity: safeInput.identity,
|
|
1070
|
+
identityFingerprint: createProjectionLedgerFingerprintFromSafeValue(
|
|
1071
|
+
safeInput.identity
|
|
1072
|
+
),
|
|
1073
|
+
payload: safeInput.payload
|
|
1074
|
+
};
|
|
1075
|
+
const immutableRecord = immutableProjectionLedgerRecord(
|
|
1076
|
+
{
|
|
1077
|
+
...draft,
|
|
1078
|
+
fingerprint: createProjectionLedgerFingerprintFromSafeValue(draft)
|
|
1079
|
+
},
|
|
1080
|
+
'Projection record'
|
|
1081
|
+
);
|
|
1082
|
+
const record = immutableRecord.record;
|
|
1083
|
+
const budgetResult = this.#projectionBudgetResult(
|
|
1084
|
+
immutableRecord.metrics
|
|
1085
|
+
);
|
|
1086
|
+
|
|
1087
|
+
if (budgetResult) {
|
|
1088
|
+
return budgetResult;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
let recordAppended = false;
|
|
1092
|
+
|
|
1093
|
+
try {
|
|
1094
|
+
this.#projectionRecords.push(record);
|
|
1095
|
+
recordAppended = true;
|
|
1096
|
+
this.#projectionById.set(record.id, record);
|
|
1097
|
+
this.#projectionBySource.set(record.sourceKey, record);
|
|
1098
|
+
this.#activeProjectionByTarget.set(record.targetKey, record);
|
|
1099
|
+
} catch (error) {
|
|
1100
|
+
if (this.#projectionById.get(record.id) === record) {
|
|
1101
|
+
this.#projectionById.delete(record.id);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
if (this.#projectionBySource.get(record.sourceKey) === record) {
|
|
1105
|
+
this.#projectionBySource.delete(record.sourceKey);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
if (this.#activeProjectionByTarget.get(record.targetKey) === record) {
|
|
1109
|
+
this.#activeProjectionByTarget.delete(record.targetKey);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
if (recordAppended
|
|
1113
|
+
&& this.#projectionRecords[this.#projectionRecords.length - 1]
|
|
1114
|
+
=== record) {
|
|
1115
|
+
this.#projectionRecords.pop();
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
throw error;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
this.#storedCharacters += immutableRecord.metrics.characters;
|
|
1122
|
+
this.#storedUtf8Bytes += immutableRecord.metrics.utf8Bytes;
|
|
1123
|
+
this.#storedNodes += immutableRecord.metrics.nodes;
|
|
1124
|
+
this.#reservedRevocationCharacters
|
|
1125
|
+
+= MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS;
|
|
1126
|
+
this.#reservedRevocationUtf8Bytes
|
|
1127
|
+
+= MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES;
|
|
1128
|
+
this.#reservedRevocationNodes += MAX_PROJECTION_LEDGER_NODES;
|
|
1129
|
+
this.#sequence = sequence;
|
|
1130
|
+
|
|
1131
|
+
return {
|
|
1132
|
+
status: PROJECTION_LEDGER_STATUSES.STORED,
|
|
1133
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
1134
|
+
record,
|
|
1135
|
+
'Projection record'
|
|
1136
|
+
),
|
|
1137
|
+
idempotent: false,
|
|
1138
|
+
remainingCapacity: this.remainingCapacity
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
async appendRevocation(input) {
|
|
1143
|
+
const safeInput = cloneProjectionLedgerValue(
|
|
1144
|
+
input,
|
|
1145
|
+
'Revocation input'
|
|
1146
|
+
);
|
|
1147
|
+
assertProjectionLedgerRecord(safeInput, 'Revocation input');
|
|
1148
|
+
assertProjectionLedgerRecordKeys(
|
|
1149
|
+
safeInput,
|
|
1150
|
+
REVOCATION_INPUT_KEYS,
|
|
1151
|
+
REVOCATION_INPUT_KEYS,
|
|
1152
|
+
'Revocation input'
|
|
1153
|
+
);
|
|
1154
|
+
const projectionId = normalizeProjectionLedgerKey(
|
|
1155
|
+
safeInput.projectionId,
|
|
1156
|
+
'Revocation projectionId'
|
|
1157
|
+
);
|
|
1158
|
+
const projection = this.#projectionById.get(projectionId);
|
|
1159
|
+
|
|
1160
|
+
if (!projection) {
|
|
1161
|
+
return {
|
|
1162
|
+
status: PROJECTION_LEDGER_STATUSES.NOT_FOUND,
|
|
1163
|
+
projectionId,
|
|
1164
|
+
idempotent: false,
|
|
1165
|
+
remainingCapacity: this.remainingCapacity
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
const existingRevocation = this.#revocationByProjectionId.get(
|
|
1170
|
+
projectionId
|
|
1171
|
+
);
|
|
1172
|
+
|
|
1173
|
+
if (existingRevocation) {
|
|
1174
|
+
return {
|
|
1175
|
+
status: PROJECTION_LEDGER_STATUSES.ALREADY_REVOKED,
|
|
1176
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
1177
|
+
existingRevocation,
|
|
1178
|
+
'Revocation record'
|
|
1179
|
+
),
|
|
1180
|
+
projection: cloneProjectionLedgerRecordForOutput(
|
|
1181
|
+
projection,
|
|
1182
|
+
'Projection record'
|
|
1183
|
+
),
|
|
1184
|
+
idempotent: true,
|
|
1185
|
+
remainingCapacity: this.remainingCapacity
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
const sequence = this.#sequence + 1;
|
|
1190
|
+
const draft = {
|
|
1191
|
+
schemaVersion: PROJECTION_LEDGER_SCHEMA_VERSION,
|
|
1192
|
+
id: `projection-revocation-${formatProjectionLedgerSequence(sequence)}`,
|
|
1193
|
+
sequence,
|
|
1194
|
+
kind: 'projection-revocation',
|
|
1195
|
+
projectionId: projection.id,
|
|
1196
|
+
sourceKey: projection.sourceKey,
|
|
1197
|
+
targetKey: projection.targetKey,
|
|
1198
|
+
payload: safeInput.payload
|
|
1199
|
+
};
|
|
1200
|
+
const immutableRecord = immutableProjectionLedgerRecord(
|
|
1201
|
+
{
|
|
1202
|
+
...draft,
|
|
1203
|
+
fingerprint: createProjectionLedgerFingerprintFromSafeValue(draft)
|
|
1204
|
+
},
|
|
1205
|
+
'Revocation record'
|
|
1206
|
+
);
|
|
1207
|
+
const record = immutableRecord.record;
|
|
1208
|
+
this.#assertRevocationBudget(immutableRecord.metrics);
|
|
1209
|
+
let recordAppended = false;
|
|
1210
|
+
|
|
1211
|
+
try {
|
|
1212
|
+
this.#revocationRecords.push(record);
|
|
1213
|
+
recordAppended = true;
|
|
1214
|
+
this.#revocationByProjectionId.set(projection.id, record);
|
|
1215
|
+
this.#activeProjectionByTarget.delete(projection.targetKey);
|
|
1216
|
+
} catch (error) {
|
|
1217
|
+
if (this.#revocationByProjectionId.get(projection.id) === record) {
|
|
1218
|
+
this.#revocationByProjectionId.delete(projection.id);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
if (!this.#activeProjectionByTarget.has(projection.targetKey)) {
|
|
1222
|
+
this.#activeProjectionByTarget.set(
|
|
1223
|
+
projection.targetKey,
|
|
1224
|
+
projection
|
|
1225
|
+
);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
if (recordAppended
|
|
1229
|
+
&& this.#revocationRecords[this.#revocationRecords.length - 1]
|
|
1230
|
+
=== record) {
|
|
1231
|
+
this.#revocationRecords.pop();
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
throw error;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
this.#storedCharacters += immutableRecord.metrics.characters;
|
|
1238
|
+
this.#storedUtf8Bytes += immutableRecord.metrics.utf8Bytes;
|
|
1239
|
+
this.#storedNodes += immutableRecord.metrics.nodes;
|
|
1240
|
+
this.#reservedRevocationCharacters
|
|
1241
|
+
-= MAX_PROJECTION_LEDGER_TOTAL_CHARACTERS;
|
|
1242
|
+
this.#reservedRevocationUtf8Bytes
|
|
1243
|
+
-= MAX_PROJECTION_LEDGER_TOTAL_UTF8_BYTES;
|
|
1244
|
+
this.#reservedRevocationNodes -= MAX_PROJECTION_LEDGER_NODES;
|
|
1245
|
+
this.#sequence = sequence;
|
|
1246
|
+
|
|
1247
|
+
return {
|
|
1248
|
+
status: PROJECTION_LEDGER_STATUSES.REVOKED,
|
|
1249
|
+
record: cloneProjectionLedgerRecordForOutput(
|
|
1250
|
+
record,
|
|
1251
|
+
'Revocation record'
|
|
1252
|
+
),
|
|
1253
|
+
projection: cloneProjectionLedgerRecordForOutput(
|
|
1254
|
+
projection,
|
|
1255
|
+
'Projection record'
|
|
1256
|
+
),
|
|
1257
|
+
idempotent: false,
|
|
1258
|
+
remainingCapacity: this.remainingCapacity
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
async getProjection(id) {
|
|
1263
|
+
const normalizedId = normalizeProjectionLedgerKey(id, 'Projection id');
|
|
1264
|
+
return cloneProjectionLedgerRecordForOutput(
|
|
1265
|
+
this.#projectionById.get(normalizedId),
|
|
1266
|
+
'Projection record'
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
async getProjectionBySourceKey(sourceKey) {
|
|
1271
|
+
const normalizedSourceKey = normalizeProjectionLedgerKey(
|
|
1272
|
+
sourceKey,
|
|
1273
|
+
'Projection sourceKey'
|
|
1274
|
+
);
|
|
1275
|
+
return cloneProjectionLedgerRecordForOutput(
|
|
1276
|
+
this.#projectionBySource.get(normalizedSourceKey),
|
|
1277
|
+
'Projection record'
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
async listProjectionRecords() {
|
|
1282
|
+
const output = [];
|
|
1283
|
+
|
|
1284
|
+
for (const record of this.#projectionRecords) {
|
|
1285
|
+
output.push(
|
|
1286
|
+
cloneProjectionLedgerRecordForOutput(
|
|
1287
|
+
record,
|
|
1288
|
+
'Projection record'
|
|
1289
|
+
)
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
return output;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
async listRevocationRecords() {
|
|
1297
|
+
const output = [];
|
|
1298
|
+
|
|
1299
|
+
for (const record of this.#revocationRecords) {
|
|
1300
|
+
output.push(
|
|
1301
|
+
cloneProjectionLedgerRecordForOutput(
|
|
1302
|
+
record,
|
|
1303
|
+
'Revocation record'
|
|
1304
|
+
)
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
return output;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
async listEffectiveProjections() {
|
|
1312
|
+
const output = [];
|
|
1313
|
+
|
|
1314
|
+
for (const record of this.#projectionRecords) {
|
|
1315
|
+
if (!this.#revocationByProjectionId.has(record.id)) {
|
|
1316
|
+
output.push(
|
|
1317
|
+
cloneProjectionLedgerRecordForOutput(
|
|
1318
|
+
record,
|
|
1319
|
+
'Projection record'
|
|
1320
|
+
)
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
return output;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE =
|
|
1330
|
+
RevocableProjectionLedger.prototype;
|
|
1331
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE_KEYS = Object.freeze(
|
|
1332
|
+
Reflect.ownKeys(PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE)
|
|
1333
|
+
);
|
|
1334
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_CONSTRUCTOR_DESCRIPTOR =
|
|
1335
|
+
Reflect.getOwnPropertyDescriptor(
|
|
1336
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE,
|
|
1337
|
+
'constructor'
|
|
1338
|
+
);
|
|
1339
|
+
const REVOCABLE_PROJECTION_LEDGER_GETTER_NAMES = Object.freeze(
|
|
1340
|
+
[
|
|
1341
|
+
'capacity',
|
|
1342
|
+
'eventCount',
|
|
1343
|
+
'eventCapacity',
|
|
1344
|
+
'maximumStoredCharacters',
|
|
1345
|
+
'maximumStoredUtf8Bytes',
|
|
1346
|
+
'maximumStoredNodes',
|
|
1347
|
+
'storedCharacters',
|
|
1348
|
+
'storedUtf8Bytes',
|
|
1349
|
+
'storedNodes',
|
|
1350
|
+
'reservedRevocationCharacters',
|
|
1351
|
+
'reservedRevocationUtf8Bytes',
|
|
1352
|
+
'reservedRevocationNodes',
|
|
1353
|
+
'remainingStoredCharacters',
|
|
1354
|
+
'remainingStoredUtf8Bytes',
|
|
1355
|
+
'remainingStoredNodes',
|
|
1356
|
+
'remainingCapacity'
|
|
1357
|
+
]
|
|
1358
|
+
);
|
|
1359
|
+
const REVOCABLE_PROJECTION_LEDGER_METHOD_NAMES = Object.freeze(
|
|
1360
|
+
[
|
|
1361
|
+
'appendProjection',
|
|
1362
|
+
'appendRevocation',
|
|
1363
|
+
'getProjection',
|
|
1364
|
+
'getProjectionBySourceKey',
|
|
1365
|
+
'listProjectionRecords',
|
|
1366
|
+
'listRevocationRecords',
|
|
1367
|
+
'listEffectiveProjections'
|
|
1368
|
+
]
|
|
1369
|
+
);
|
|
1370
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_GETTER_DESCRIPTORS = Object.freeze(
|
|
1371
|
+
REVOCABLE_PROJECTION_LEDGER_GETTER_NAMES.reduce(
|
|
1372
|
+
function capturePristineLedgerGetterDescriptors(output, getterName) {
|
|
1373
|
+
output[getterName] = Reflect.getOwnPropertyDescriptor(
|
|
1374
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE,
|
|
1375
|
+
getterName
|
|
1376
|
+
);
|
|
1377
|
+
return output;
|
|
1378
|
+
},
|
|
1379
|
+
Object.create(null)
|
|
1380
|
+
)
|
|
1381
|
+
);
|
|
1382
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_EVENT_COUNT_DESCRIPTOR =
|
|
1383
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_GETTER_DESCRIPTORS.eventCount;
|
|
1384
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_EVENT_COUNT =
|
|
1385
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_EVENT_COUNT_DESCRIPTOR.get;
|
|
1386
|
+
const PRISTINE_REVOCABLE_PROJECTION_LEDGER_METHOD_DESCRIPTORS = Object.freeze(
|
|
1387
|
+
REVOCABLE_PROJECTION_LEDGER_METHOD_NAMES.reduce(
|
|
1388
|
+
function capturePristineLedgerMethodDescriptors(output, methodName) {
|
|
1389
|
+
output[methodName] = Reflect.getOwnPropertyDescriptor(
|
|
1390
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE,
|
|
1391
|
+
methodName
|
|
1392
|
+
);
|
|
1393
|
+
return output;
|
|
1394
|
+
},
|
|
1395
|
+
Object.create(null)
|
|
1396
|
+
)
|
|
1397
|
+
);
|
|
1398
|
+
|
|
1399
|
+
function sameProjectionLedgerDataDescriptor(current, pristine) {
|
|
1400
|
+
return Boolean(current)
|
|
1401
|
+
&& Boolean(pristine)
|
|
1402
|
+
&& current.value === pristine.value
|
|
1403
|
+
&& current.writable === pristine.writable
|
|
1404
|
+
&& current.enumerable === pristine.enumerable
|
|
1405
|
+
&& current.configurable === pristine.configurable;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
function sameProjectionLedgerAccessorDescriptor(current, pristine) {
|
|
1409
|
+
return Boolean(current)
|
|
1410
|
+
&& Boolean(pristine)
|
|
1411
|
+
&& current.get === pristine.get
|
|
1412
|
+
&& current.set === pristine.set
|
|
1413
|
+
&& current.enumerable === pristine.enumerable
|
|
1414
|
+
&& current.configurable === pristine.configurable;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
function sameProjectionLedgerKeyList(current, pristine) {
|
|
1418
|
+
if (!Array.isArray(current) || current.length !== pristine.length) {
|
|
1419
|
+
return false;
|
|
1420
|
+
}
|
|
1421
|
+
for (let index = 0; index < pristine.length; index += 1) {
|
|
1422
|
+
if (current[index] !== pristine[index]) {
|
|
1423
|
+
return false;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
return true;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
function invalidProjectionLedgerPort(detail) {
|
|
1430
|
+
throw invalidProjectionLedgerBoundary('Projection ledger port', detail);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
function assertPristineRevocableProjectionLedger(value) {
|
|
1434
|
+
let prototype;
|
|
1435
|
+
let ownKeys;
|
|
1436
|
+
let prototypeKeys;
|
|
1437
|
+
let constructorDescriptor;
|
|
1438
|
+
const getterDescriptors = Object.create(null);
|
|
1439
|
+
const methodDescriptors = Object.create(null);
|
|
1440
|
+
try {
|
|
1441
|
+
prototype = Object.getPrototypeOf(value);
|
|
1442
|
+
ownKeys = Reflect.ownKeys(value);
|
|
1443
|
+
prototypeKeys = Reflect.ownKeys(
|
|
1444
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE
|
|
1445
|
+
);
|
|
1446
|
+
constructorDescriptor = Reflect.getOwnPropertyDescriptor(
|
|
1447
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE,
|
|
1448
|
+
'constructor'
|
|
1449
|
+
);
|
|
1450
|
+
for (const getterName of REVOCABLE_PROJECTION_LEDGER_GETTER_NAMES) {
|
|
1451
|
+
getterDescriptors[getterName] = Reflect.getOwnPropertyDescriptor(
|
|
1452
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE,
|
|
1453
|
+
getterName
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
for (const methodName of REVOCABLE_PROJECTION_LEDGER_METHOD_NAMES) {
|
|
1457
|
+
methodDescriptors[methodName] = Reflect.getOwnPropertyDescriptor(
|
|
1458
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE,
|
|
1459
|
+
methodName
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
} catch (error) {
|
|
1463
|
+
invalidProjectionLedgerPort('could not be inspected safely.');
|
|
1464
|
+
}
|
|
1465
|
+
if (prototype !== PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE
|
|
1466
|
+
|| !Array.isArray(ownKeys)
|
|
1467
|
+
|| ownKeys.length !== 0
|
|
1468
|
+
|| typeof PRISTINE_REVOCABLE_PROJECTION_LEDGER_EVENT_COUNT !== 'function'
|
|
1469
|
+
|| !sameProjectionLedgerKeyList(
|
|
1470
|
+
prototypeKeys,
|
|
1471
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_PROTOTYPE_KEYS
|
|
1472
|
+
)
|
|
1473
|
+
|| !sameProjectionLedgerDataDescriptor(
|
|
1474
|
+
constructorDescriptor,
|
|
1475
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_CONSTRUCTOR_DESCRIPTOR
|
|
1476
|
+
)) {
|
|
1477
|
+
invalidProjectionLedgerPort('requires an unmodified concrete producer.');
|
|
1478
|
+
}
|
|
1479
|
+
for (const getterName of REVOCABLE_PROJECTION_LEDGER_GETTER_NAMES) {
|
|
1480
|
+
if (!sameProjectionLedgerAccessorDescriptor(
|
|
1481
|
+
getterDescriptors[getterName],
|
|
1482
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_GETTER_DESCRIPTORS[getterName]
|
|
1483
|
+
)) {
|
|
1484
|
+
invalidProjectionLedgerPort('requires unmodified producer getters.');
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
for (const methodName of REVOCABLE_PROJECTION_LEDGER_METHOD_NAMES) {
|
|
1488
|
+
if (!sameProjectionLedgerDataDescriptor(
|
|
1489
|
+
methodDescriptors[methodName],
|
|
1490
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_METHOD_DESCRIPTORS[methodName]
|
|
1491
|
+
)) {
|
|
1492
|
+
invalidProjectionLedgerPort('requires unmodified producer methods.');
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
function readPristineProjectionLedgerEventCount(value) {
|
|
1498
|
+
assertPristineRevocableProjectionLedger(value);
|
|
1499
|
+
const eventCount = PRISTINE_REVOCABLE_PROJECTION_LEDGER_EVENT_COUNT.call(value);
|
|
1500
|
+
if (!Number.isSafeInteger(eventCount) || eventCount < 0) {
|
|
1501
|
+
invalidProjectionLedgerPort('returned an invalid event count.');
|
|
1502
|
+
}
|
|
1503
|
+
return eventCount;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
function probePristineRevocableProjectionLedger(value) {
|
|
1507
|
+
try {
|
|
1508
|
+
return readPristineProjectionLedgerEventCount(value);
|
|
1509
|
+
} catch (error) {
|
|
1510
|
+
if (error instanceof ProjectionLedgerError) {
|
|
1511
|
+
throw error;
|
|
1512
|
+
}
|
|
1513
|
+
invalidProjectionLedgerPort('failed its private-brand probe.');
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
function callPristineProjectionLedgerMethod(value, methodName, args) {
|
|
1518
|
+
assertPristineRevocableProjectionLedger(value);
|
|
1519
|
+
return Reflect.apply(
|
|
1520
|
+
PRISTINE_REVOCABLE_PROJECTION_LEDGER_METHOD_DESCRIPTORS[methodName].value,
|
|
1521
|
+
value,
|
|
1522
|
+
args
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
function callPristineProjectionLedgerMutation(
|
|
1527
|
+
value,
|
|
1528
|
+
methodName,
|
|
1529
|
+
input,
|
|
1530
|
+
label
|
|
1531
|
+
) {
|
|
1532
|
+
const safeInput = cloneProjectionLedgerValue(input, label);
|
|
1533
|
+
return callPristineProjectionLedgerMethod(
|
|
1534
|
+
value,
|
|
1535
|
+
methodName,
|
|
1536
|
+
[safeInput]
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
function createRevocableProjectionLedgerPortAdapter(value) {
|
|
1541
|
+
probePristineRevocableProjectionLedger(value);
|
|
1542
|
+
|
|
1543
|
+
function readEventCount() {
|
|
1544
|
+
return readPristineProjectionLedgerEventCount(value);
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
function appendProjection(input) {
|
|
1548
|
+
return callPristineProjectionLedgerMutation(
|
|
1549
|
+
value,
|
|
1550
|
+
'appendProjection',
|
|
1551
|
+
input,
|
|
1552
|
+
'Projection adapter input'
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
function appendRevocation(input) {
|
|
1557
|
+
return callPristineProjectionLedgerMutation(
|
|
1558
|
+
value,
|
|
1559
|
+
'appendRevocation',
|
|
1560
|
+
input,
|
|
1561
|
+
'Revocation adapter input'
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
function getProjection(id) {
|
|
1566
|
+
return callPristineProjectionLedgerMethod(value, 'getProjection', [id]);
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
function getProjectionBySourceKey(sourceKey) {
|
|
1570
|
+
return callPristineProjectionLedgerMethod(
|
|
1571
|
+
value,
|
|
1572
|
+
'getProjectionBySourceKey',
|
|
1573
|
+
[sourceKey]
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
function listProjectionRecords() {
|
|
1578
|
+
return callPristineProjectionLedgerMethod(value, 'listProjectionRecords', []);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function listRevocationRecords() {
|
|
1582
|
+
return callPristineProjectionLedgerMethod(value, 'listRevocationRecords', []);
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
function listEffectiveProjections() {
|
|
1586
|
+
return callPristineProjectionLedgerMethod(value, 'listEffectiveProjections', []);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
return Object.freeze(
|
|
1590
|
+
{
|
|
1591
|
+
appendProjection,
|
|
1592
|
+
appendRevocation,
|
|
1593
|
+
getProjection,
|
|
1594
|
+
getProjectionBySourceKey,
|
|
1595
|
+
listProjectionRecords,
|
|
1596
|
+
listRevocationRecords,
|
|
1597
|
+
listEffectiveProjections,
|
|
1598
|
+
readEventCount
|
|
1599
|
+
}
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
export {
|
|
1604
|
+
DEFAULT_PROJECTION_LEDGER_CAPACITY,
|
|
1605
|
+
DEFAULT_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
1606
|
+
DEFAULT_PROJECTION_LEDGER_STORED_NODES,
|
|
1607
|
+
DEFAULT_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
1608
|
+
MAX_PROJECTION_LEDGER_CAPACITY,
|
|
1609
|
+
MAX_PROJECTION_LEDGER_STORED_CHARACTERS,
|
|
1610
|
+
MAX_PROJECTION_LEDGER_STORED_NODES,
|
|
1611
|
+
MAX_PROJECTION_LEDGER_STORED_UTF8_BYTES,
|
|
1612
|
+
PROJECTION_LEDGER_LIMITS,
|
|
1613
|
+
PROJECTION_LEDGER_REASON_CODES,
|
|
1614
|
+
PROJECTION_LEDGER_SCHEMA_VERSION,
|
|
1615
|
+
PROJECTION_LEDGER_STATUSES,
|
|
1616
|
+
ProjectionLedgerError,
|
|
1617
|
+
RevocableProjectionLedger,
|
|
1618
|
+
cloneProjectionLedgerValue,
|
|
1619
|
+
createRevocableProjectionLedgerPortAdapter,
|
|
1620
|
+
createProjectionLedgerFingerprint
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
export default RevocableProjectionLedger;
|