nolo-cli 0.1.30 → 0.1.31
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/agent-runtime/agentRecordConfig.ts +0 -2
- package/agent-runtime/hostAdapter.ts +0 -1
- package/agent-runtime/hostRuntimeCapabilities.ts +7 -0
- package/agent-runtime/hostRuntimeConfig.ts +86 -0
- package/agent-runtime/index.ts +13 -0
- package/agent-runtime/localToolPolicy.ts +13 -6
- package/agent-runtime/localWorkspaceTools.ts +333 -30
- package/agent-runtime/platformChatProvider.ts +4 -1
- package/agent-runtime/runtimeToolPolicy.ts +32 -47
- package/agent-runtime/shellCommandPolicy.ts +117 -0
- package/agent-runtime/toolGate.ts +38 -0
- package/agentRecordCommands.ts +1 -1
- package/agentRecordHelpers.ts +35 -20
- package/agentRunParsing.ts +18 -5
- package/agentRuntimeLocal.ts +10 -0
- package/ai/agent/agentRunDialogLineage.ts +56 -0
- package/ai/agent/agentSlice.ts +45 -10
- package/ai/agent/avatarUtils.ts +1 -1
- package/ai/agent/buildSystemPrompt.ts +1 -2
- package/ai/agent/cliExecutor.ts +330 -19
- package/ai/agent/createAgentSchema.ts +22 -0
- package/ai/agent/hooks/fetchPublicAgents.ts +14 -39
- package/ai/agent/hooks/usePublicAgents.ts +90 -192
- package/ai/agent/publicAgentCatalog.ts +359 -0
- package/ai/agent/publicAgentIdentity.ts +76 -0
- package/ai/agent/server/fetchPublicAgents.ts +21 -46
- package/ai/agent/serverOrigin.ts +7 -0
- package/ai/agent/streamAgentChatTurn.ts +23 -21
- package/ai/agent/streamAgentChatTurnUtils.ts +292 -6
- package/ai/agent/types.ts +2 -0
- package/ai/agent/web/agentDisplayUtils.ts +171 -0
- package/ai/agent/web/useAgentModelAvatarComponent.ts +32 -0
- package/ai/ai.locale.ts +8 -0
- package/ai/chat/sendOpenAICompletionsRequest.native.ts +15 -0
- package/ai/chat/sendOpenAICompletionsRequest.ts +93 -1
- package/ai/chat/sendOpenAIResponseRequest.ts +86 -9
- package/ai/chat/updateTotalUsage.ts +7 -0
- package/ai/llm/deepinfra.ts +30 -15
- package/ai/llm/mistral.ts +3 -4
- package/ai/llm/providers.ts +2 -0
- package/ai/llm/types.ts +15 -0
- package/ai/memory/capture.ts +3 -3
- package/ai/memory/consolidate.ts +2 -2
- package/ai/memory/delete.ts +4 -3
- package/ai/memory/query.ts +3 -3
- package/ai/memory/remember.ts +2 -2
- package/ai/memory/store.ts +3 -3
- package/ai/memory/storeShared.ts +3 -2
- package/ai/policy/commercialMultiplier.ts +16 -0
- package/ai/token/billingAdminAuditEvent.ts +68 -0
- package/ai/token/billingAdminAuditEventWriter.ts +41 -0
- package/ai/token/billingAnomaly.ts +90 -0
- package/ai/token/billingAnomalyLifecycle.ts +54 -0
- package/ai/token/billingAnomalyLifecycleWriter.ts +44 -0
- package/ai/token/billingAnomalyWriter.ts +41 -0
- package/ai/token/calculatePrice.ts +3 -2
- package/ai/token/deepinfraReconciliation.ts +153 -0
- package/ai/token/deepinfraRequestIdQuery.ts +92 -0
- package/ai/token/externalToolCost.ts +54 -41
- package/ai/token/missingUsageEstimate.ts +12 -3
- package/ai/token/normalizeUsage.ts +45 -5
- package/ai/token/openaiReconciliation.ts +188 -0
- package/ai/token/providerBillableEvent.ts +84 -0
- package/ai/token/providerBillableEventWriter.ts +36 -0
- package/ai/token/providerBillingAnomalyDrilldown.ts +308 -0
- package/ai/token/providerBillingDrilldown.ts +361 -0
- package/ai/token/providerBillingHealthReport.ts +366 -0
- package/ai/token/providerCall.ts +144 -0
- package/ai/token/providerCallSweeper.ts +168 -0
- package/ai/token/providerCallWriter.ts +33 -0
- package/ai/token/providerCredential.ts +89 -0
- package/ai/token/providerCredentialAnomaly.ts +154 -0
- package/ai/token/providerCredentialLifecycle.ts +59 -0
- package/ai/token/providerCredentialLifecycleWriter.ts +44 -0
- package/ai/token/providerCredentialRegistry.ts +83 -0
- package/ai/token/providerCredentialRegistryCommand.ts +97 -0
- package/ai/token/providerCredentialRegistryList.ts +124 -0
- package/ai/token/providerCredentialRegistryResolver.ts +150 -0
- package/ai/token/providerCredentialRegistryWriter.ts +41 -0
- package/ai/token/providerCredentialRotationCommand.ts +102 -0
- package/ai/token/providerCredentialRuntime.ts +56 -0
- package/ai/token/providerDispatchIntent.ts +67 -0
- package/ai/token/providerDispatchIntentWriter.ts +36 -0
- package/ai/token/providerGateway.ts +260 -0
- package/ai/token/providerReconciliation.ts +148 -0
- package/ai/token/providerReconciliationLocal.ts +97 -0
- package/ai/token/providerReconciliationRunner.ts +165 -0
- package/ai/token/providerReconciliationWriter.ts +41 -0
- package/ai/token/ratingResult.ts +202 -0
- package/ai/token/ratingResultWriter.ts +33 -0
- package/ai/token/serverDialogProjection.ts +5 -3
- package/ai/token/serverTokenWriter.ts +11 -3
- package/ai/token/types.ts +10 -0
- package/ai/tools/agent/callAgentTool.ts +3 -4
- package/ai/tools/agent/presets/appBuilderPreset.ts +5 -7
- package/ai/tools/agent/runStreamingAgentTool.ts +1 -2
- package/ai/tools/agent/streamParallelAgentsTool.ts +2 -3
- package/ai/tools/readXPostTool.ts +1 -5
- package/app/admin/adminPages.ts +9 -0
- package/app/i18n/i18n.config.ts +5 -0
- package/app/i18n/translations/pricing.locale.ts +397 -0
- package/app/utils/desktopAgentRuntimeStatusClient.ts +5 -4
- package/app/utils/desktopAgentRuntimeTurnClient.ts +4 -1
- package/app/utils/imageUtils.ts +64 -34
- package/auth/adminPermissions.ts +18 -0
- package/auth/authSlice.ts +26 -12
- package/auth/hooks/useFetchUsers.ts +3 -0
- package/auth/routes.ts +46 -0
- package/auth/server/accessActivity.ts +4 -3
- package/auth/server/adminPermissions.ts +43 -0
- package/auth/server/adminUsageReport.ts +375 -0
- package/auth/server/billingAnomalies.ts +235 -0
- package/auth/server/billingUsageReport.ts +41 -2
- package/auth/server/creatorEarningCreditConversion.ts +10 -2
- package/auth/server/deduct.ts +14 -7
- package/auth/server/delete.ts +10 -2
- package/auth/server/disable.ts +4 -3
- package/auth/server/emailAutomation.ts +7 -5
- package/auth/server/emailDbConfig.ts +4 -2
- package/auth/server/emailDelivery.ts +24 -20
- package/auth/server/emailDeliveryGuards.ts +10 -7
- package/auth/server/emailPreferences.ts +6 -4
- package/auth/server/emailReport.ts +6 -4
- package/auth/server/emailRuntimeConfig.ts +3 -3
- package/auth/server/emailScenarioNotifications.ts +9 -8
- package/auth/server/enable.ts +4 -3
- package/auth/server/getRechargeHistory.ts +3 -2
- package/auth/server/getUser.ts +3 -2
- package/auth/server/gptProAccess.ts +44 -0
- package/auth/server/inviteReward.ts +10 -7
- package/auth/server/listusers.ts +6 -4
- package/auth/server/login.ts +2 -2
- package/auth/server/productEntitlements.ts +7 -4
- package/auth/server/productPurchase.ts +10 -2
- package/auth/server/providerBillingDrilldown.ts +47 -0
- package/auth/server/providerBillingHealth.ts +71 -0
- package/auth/server/providerCredentials.ts +136 -0
- package/auth/server/recharge.ts +14 -8
- package/auth/server/revokeSessions.ts +4 -3
- package/auth/server/route.ts +77 -0
- package/auth/server/sendEmail.ts +5 -4
- package/auth/server/signup.ts +10 -3
- package/auth/server/token.ts +53 -55
- package/auth/server/tokenUsageBilling.ts +18 -7
- package/auth/server/usageManagementAccess.ts +43 -0
- package/auth/server/usageReport.ts +59 -0
- package/auth/types.ts +12 -0
- package/auth/utils.ts +24 -22
- package/authCommands.ts +36 -2
- package/buildPublish.ts +3 -1
- package/buildPublishArtifactAssembly.ts +62 -1
- package/buildPublishImportAnalysis.ts +21 -16
- package/chat/dialog/dialogLaunchScope.ts +32 -0
- package/chat/dialog/objectAssistantRegistry.ts +2 -2
- package/chat/dialog/useCreateDialog.ts +1 -1
- package/chat/hooks/useChatInput.ts +41 -10
- package/chat/messages/messageSlice.ts +5 -1
- package/chat/messages/pendingAttachmentParts.ts +28 -2
- package/chat/messages/sendFirstMessage.ts +76 -79
- package/chat/messages/types.ts +9 -0
- package/chat/messages/web/streamingMarkdownModel.ts +41 -0
- package/chat/messages/web/useStreamingReveal.ts +91 -0
- package/chat/web/messageInputAgentUi.ts +94 -6
- package/cliEnvHelpers.ts +8 -0
- package/cliRuntimeDoctorReport.ts +193 -0
- package/client/agentConfigResolver.test.ts +0 -2
- package/client/agentRun.test.ts +171 -10
- package/client/agentRun.ts +44 -637
- package/client/agentRunInput.ts +10 -0
- package/client/agentRunLocalExecutor.ts +179 -0
- package/client/agentRunServerTransport.ts +394 -0
- package/client/agentRunTaskRunRecorder.ts +176 -0
- package/client/localRuntimeAdapter.test.ts +236 -9
- package/client/localRuntimeAdapter.ts +221 -23
- package/client/localToolPolicy.test.ts +28 -4
- package/connector-experimental/daemonLauncher.ts +38 -4
- package/connectorRunArtifact.ts +34 -10
- package/connectorWebSocketTarget.ts +9 -5
- package/core/builtinAgents.ts +155 -11
- package/create/space/contentLabels.ts +1 -1
- package/create/space/contentTypeMeta.ts +3 -2
- package/create/space/sidebarVisibleTypes.ts +27 -0
- package/create/space/space.locale.ts +76 -4
- package/database/actions/agentReadResolution.ts +2 -8
- package/database/actions/read.ts +11 -9
- package/database/actions/readAndWait.ts +10 -5
- package/database/server/agentDelegation.ts +3 -2
- package/database/server/authorityStoreConformance.ts +209 -0
- package/database/server/authorityStoreTypes.ts +31 -0
- package/database/server/coreDataProxy.ts +1 -1
- package/database/server/dataHandlers.ts +13 -5
- package/database/server/db.ts +15 -34
- package/database/server/delete.ts +88 -71
- package/database/server/emailRepository.ts +11 -9
- package/database/server/fileService.ts +2 -1
- package/database/server/legacyServerDb.ts +58 -0
- package/database/server/levelAuthorityStore.ts +75 -0
- package/database/server/memoryAuthorityStore.ts +133 -0
- package/database/server/patch.ts +13 -12
- package/database/server/query.ts +3 -2
- package/database/server/read.ts +33 -30
- package/database/server/resourceAccess.ts +7 -5
- package/database/server/serverStoreFactory.ts +124 -0
- package/database/server/spaceMemberAuthority.ts +3 -2
- package/database/server/storeBatchCompat.ts +37 -0
- package/database/server/testAuthorityStore.ts +76 -0
- package/database/server/write.ts +29 -27
- package/integrations/anthropic/anthropicModels.ts +12 -12
- package/integrations/deepseek/models.ts +67 -67
- package/integrations/google/models.ts +111 -53
- package/integrations/openai/models.ts +22 -22
- package/integrations/xai/models.ts +1 -1
- package/localRuntimeDb.ts +39 -2
- package/machineCommandPrompts.ts +2 -0
- package/machineCommands.ts +193 -63
- package/machineWsRunDispatch.ts +80 -15
- package/machineWsSession.ts +39 -2
- package/noloReadBridgePrompt.ts +16 -0
- package/package.json +99 -6
- package/render/layout/mainLayoutViewMode.ts +25 -0
- package/render/page/server/createPage.ts +3 -1
- package/render/page/server/handleCreatePage.ts +2 -11
- package/runtimeDoctorCommands.ts +15 -66
- package/server/api/methods.ts +34 -12
- package/server/api/tableHandlers.ts +6 -3
- package/server/authenticateToken.ts +47 -2
- package/server/billingLedgerRoutes.ts +15 -0
- package/server/buildManifest.ts +54 -0
- package/server/coreReadiness.ts +34 -25
- package/server/coreRuntime.ts +15 -10
- package/server/handlers/activityStatsHandler.ts +5 -2
- package/server/handlers/agentEmailRegistrationE2EHandler.ts +25 -23
- package/server/handlers/agentRun/agentLookup.ts +1 -7
- package/server/handlers/agentRun/autonomousRuntime.ts +11 -10
- package/server/handlers/agentRun/builtinAgents.ts +12 -88
- package/server/handlers/agentRun/continueDialogContext.ts +15 -3
- package/server/handlers/agentRun/{inheritedDialogPrompt.ts → conversationReference.ts} +3 -3
- package/server/handlers/agentRun/dialogLookup.ts +4 -3
- package/server/handlers/agentRun/index.ts +864 -404
- package/server/handlers/agentRun/localRuntimeBootstrap.ts +17 -1
- package/server/handlers/agentRun/loop.ts +920 -508
- package/server/handlers/agentRun/machineConnector.ts +56 -8
- package/server/handlers/agentRun/machineRunAudit.ts +3 -2
- package/server/handlers/agentRun/modelUsageToolHandlers.ts +13 -10
- package/server/handlers/agentRun/requestContext.ts +12 -8
- package/server/handlers/agentRun/runtimeExecutionContext.ts +15 -3
- package/server/handlers/agentRun/runtimePreparation.ts +26 -24
- package/server/handlers/agentRun/runtimeRouting.ts +25 -40
- package/server/handlers/agentRun/runtimeSystemMessages.ts +65 -0
- package/server/handlers/agentRun/saveDialog.ts +97 -87
- package/server/handlers/agentRun/taskRunToolHandler.ts +9 -7
- package/server/handlers/agentRun/toolExecutor.ts +42 -78
- package/server/handlers/agentRun/types.ts +2 -1
- package/server/handlers/appDeployStatusStore.ts +17 -10
- package/server/handlers/appDomainHandler.ts +21 -15
- package/server/handlers/appLegacyInfraCleanup.ts +5 -2
- package/server/handlers/appSandboxHandler.ts +29 -8
- package/server/handlers/appSpaceAccess.ts +15 -8
- package/server/handlers/chatHandler.ts +22 -2
- package/server/handlers/chatUpstreamRetry.ts +225 -2
- package/server/handlers/connector/connectorConnectionRegistry.ts +55 -7
- package/server/handlers/connector/connectorWebSocket.ts +14 -10
- package/server/handlers/desktopAgentRuntimeAdapter.ts +4 -4
- package/server/handlers/desktopAgentRuntimeHostCapabilities.ts +25 -0
- package/server/handlers/desktopAgentRuntimeReadiness.ts +62 -0
- package/server/handlers/desktopAgentRuntimeStatusHandler.ts +38 -30
- package/server/handlers/desktopAgentRuntimeTurnHandler.ts +7 -3
- package/server/handlers/desktopAgentRuntimeTurnService.ts +39 -45
- package/server/handlers/desktopLlamaRuntimeHandler.ts +85 -51
- package/server/handlers/desktopUpdaterHandler.ts +132 -24
- package/server/handlers/favoriteHandlers.ts +8 -2
- package/server/handlers/getDialogBillingHandler.ts +4 -3
- package/server/handlers/getTransactionsHandler.ts +5 -2
- package/server/handlers/machines/machineBinding.ts +1 -0
- package/server/handlers/machines/machineHandlers.ts +0 -14
- package/server/handlers/machines/machineInstallAssets.ts +4 -2
- package/server/handlers/notificationEmitter.ts +5 -3
- package/server/handlers/notificationsHandler.ts +5 -2
- package/server/handlers/providerCallsRecentHandler.ts +234 -0
- package/server/handlers/providerReconciliationRunHandler.ts +180 -0
- package/server/handlers/providerRequestIdsHandler.ts +105 -0
- package/server/handlers/tableAccess.ts +6 -2
- package/server/handlers/tableToolHandlers.ts +28 -14
- package/server/handlers/userSecretsHandler.ts +17 -6
- package/server/handlers/versionHandler.ts +9 -4
- package/server/handlers/versionStore.ts +18 -10
- package/server/html/ssrPreload.ts +5 -3
- package/server/payments/crypto/cryptoUsdcBasePaymentProvider.ts +11 -8
- package/server/payments/crypto/cryptoUsdcBaseScanner.ts +12 -7
- package/server/payments/crypto/cryptoUsdtTronPaymentProvider.ts +11 -8
- package/server/payments/crypto/cryptoUsdtTronScanner.ts +9 -7
- package/server/payments/waffo/waffoPaymentProvider.ts +12 -9
- package/server/runtimeRole.ts +15 -0
- package/server/scheduler/scheduledTaskRuntime.ts +4 -2
- package/server/scheduler/schedulerService.ts +2 -2
- package/server/taskRunBridgeRoutes.ts +8 -5
- package/share/server/fetchCommunityShares.ts +1 -1
- package/share/server/helpers.ts +19 -17
- package/share/server/importShare.ts +9 -13
- package/share/server/listCommunityShares.ts +4 -4
- package/share/server/purchaseDoc.ts +8 -16
- package/share/server/readCommunityShareCover.ts +3 -2
- package/share/server/readSharedTable.ts +14 -13
- package/share/server/tableReplication.ts +42 -39
- package/spaceAttachCommands.ts +135 -0
- package/spaceInternalCommandEntries.ts +2 -0
- package/ai/agent/runtimeServerBase.ts +0 -37
- package/server/handlers/desktopAgentRuntimeHostFacts.ts +0 -40
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthorityBatchOperation,
|
|
3
|
+
AuthorityBatchWriter,
|
|
4
|
+
AuthorityIteratorOptions,
|
|
5
|
+
AuthorityStore,
|
|
6
|
+
} from "./authorityStoreTypes";
|
|
7
|
+
|
|
8
|
+
export type LegacyServerDb = {
|
|
9
|
+
readonly location?: string;
|
|
10
|
+
readonly status?: string;
|
|
11
|
+
open(): Promise<void>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
get<T = any>(key: string): Promise<T>;
|
|
14
|
+
put(key: string, value: unknown): Promise<void>;
|
|
15
|
+
del(key: string): Promise<void>;
|
|
16
|
+
batch(ops: AuthorityBatchOperation[]): Promise<void>;
|
|
17
|
+
batch(): AuthorityBatchWriter;
|
|
18
|
+
iterator(
|
|
19
|
+
options?: AuthorityIteratorOptions
|
|
20
|
+
): AsyncIterableIterator<[string, unknown]>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function createLegacyServerDb(store: AuthorityStore): LegacyServerDb {
|
|
24
|
+
const batch = (ops?: AuthorityBatchOperation[]) => {
|
|
25
|
+
if (Array.isArray(ops)) {
|
|
26
|
+
return store.batchWrite(ops);
|
|
27
|
+
}
|
|
28
|
+
return store.createBatch();
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
get location() {
|
|
33
|
+
return store.location;
|
|
34
|
+
},
|
|
35
|
+
get status() {
|
|
36
|
+
return store.status;
|
|
37
|
+
},
|
|
38
|
+
async open() {
|
|
39
|
+
await store.open();
|
|
40
|
+
},
|
|
41
|
+
async close() {
|
|
42
|
+
await store.close();
|
|
43
|
+
},
|
|
44
|
+
async get<T = any>(key: string) {
|
|
45
|
+
return store.get<T>(key);
|
|
46
|
+
},
|
|
47
|
+
async put(key: string, value: unknown) {
|
|
48
|
+
await store.put(key, value);
|
|
49
|
+
},
|
|
50
|
+
async del(key: string) {
|
|
51
|
+
await store.del(key);
|
|
52
|
+
},
|
|
53
|
+
batch: batch as LegacyServerDb["batch"],
|
|
54
|
+
iterator(options: AuthorityIteratorOptions = {}) {
|
|
55
|
+
return store.iterator(options);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthorityBatchOperation,
|
|
3
|
+
AuthorityBatchWriter,
|
|
4
|
+
AuthorityIteratorOptions,
|
|
5
|
+
AuthorityStore,
|
|
6
|
+
} from "./authorityStoreTypes";
|
|
7
|
+
|
|
8
|
+
type LevelBatchWriterLike = {
|
|
9
|
+
put(key: string, value: unknown): unknown;
|
|
10
|
+
del(key: string): unknown;
|
|
11
|
+
write(): Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type LevelLike = {
|
|
15
|
+
readonly location?: string;
|
|
16
|
+
readonly status?: string;
|
|
17
|
+
open?(): Promise<void>;
|
|
18
|
+
close?(): Promise<void>;
|
|
19
|
+
get<T = any>(key: string): Promise<T>;
|
|
20
|
+
put(key: string, value: unknown): Promise<void>;
|
|
21
|
+
del(key: string): Promise<void>;
|
|
22
|
+
batch(ops: AuthorityBatchOperation[]): Promise<void>;
|
|
23
|
+
batch(): LevelBatchWriterLike;
|
|
24
|
+
iterator(
|
|
25
|
+
options?: AuthorityIteratorOptions
|
|
26
|
+
): AsyncIterableIterator<[string, unknown]>;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function createLevelAuthorityStore(levelDb: LevelLike): AuthorityStore {
|
|
30
|
+
const createBatch = (): AuthorityBatchWriter => {
|
|
31
|
+
const batch = levelDb.batch();
|
|
32
|
+
return {
|
|
33
|
+
put(key: string, value: unknown) {
|
|
34
|
+
batch.put(key, value);
|
|
35
|
+
},
|
|
36
|
+
del(key: string) {
|
|
37
|
+
batch.del(key);
|
|
38
|
+
},
|
|
39
|
+
async write() {
|
|
40
|
+
await batch.write();
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
get location() {
|
|
47
|
+
return levelDb.location;
|
|
48
|
+
},
|
|
49
|
+
get status() {
|
|
50
|
+
return levelDb.status;
|
|
51
|
+
},
|
|
52
|
+
async open() {
|
|
53
|
+
await levelDb.open?.();
|
|
54
|
+
},
|
|
55
|
+
async close() {
|
|
56
|
+
await levelDb.close?.();
|
|
57
|
+
},
|
|
58
|
+
async get<T = any>(key: string) {
|
|
59
|
+
return levelDb.get<T>(key);
|
|
60
|
+
},
|
|
61
|
+
async put(key: string, value: unknown) {
|
|
62
|
+
await levelDb.put(key, value);
|
|
63
|
+
},
|
|
64
|
+
async del(key: string) {
|
|
65
|
+
await levelDb.del(key);
|
|
66
|
+
},
|
|
67
|
+
async batchWrite(ops: AuthorityBatchOperation[]) {
|
|
68
|
+
await levelDb.batch(ops);
|
|
69
|
+
},
|
|
70
|
+
createBatch,
|
|
71
|
+
iterator(options: AuthorityIteratorOptions = {}) {
|
|
72
|
+
return levelDb.iterator(options);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthorityBatchOperation,
|
|
3
|
+
AuthorityBatchWriter,
|
|
4
|
+
AuthorityIteratorOptions,
|
|
5
|
+
AuthorityStore,
|
|
6
|
+
} from "./authorityStoreTypes";
|
|
7
|
+
|
|
8
|
+
type MemoryEntry = {
|
|
9
|
+
key: string;
|
|
10
|
+
value: unknown;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const createNotFoundError = () => {
|
|
14
|
+
const error = new Error("NotFound") as Error & { notFound: true };
|
|
15
|
+
error.notFound = true;
|
|
16
|
+
return error;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
class MemoryAuthorityBacking {
|
|
20
|
+
readonly location: string;
|
|
21
|
+
status: "closed" | "open" = "closed";
|
|
22
|
+
private readonly data = new Map<string, unknown>();
|
|
23
|
+
|
|
24
|
+
constructor(location: string) {
|
|
25
|
+
this.location = location;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async open() {
|
|
29
|
+
this.status = "open";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async close() {
|
|
33
|
+
this.status = "closed";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async get<T = any>(key: string): Promise<T> {
|
|
37
|
+
if (!this.data.has(key)) {
|
|
38
|
+
throw createNotFoundError();
|
|
39
|
+
}
|
|
40
|
+
return this.data.get(key) as T;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async put(key: string, value: unknown) {
|
|
44
|
+
this.data.set(key, value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async del(key: string) {
|
|
48
|
+
this.data.delete(key);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async batchWrite(ops: AuthorityBatchOperation[]) {
|
|
52
|
+
for (const op of ops) {
|
|
53
|
+
if (op.type === "put") {
|
|
54
|
+
this.data.set(op.key, op.value);
|
|
55
|
+
} else {
|
|
56
|
+
this.data.delete(op.key);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
createBatch(): AuthorityBatchWriter {
|
|
62
|
+
const buffered: AuthorityBatchOperation[] = [];
|
|
63
|
+
return {
|
|
64
|
+
put(key: string, value: unknown) {
|
|
65
|
+
buffered.push({ type: "put", key, value });
|
|
66
|
+
},
|
|
67
|
+
del(key: string) {
|
|
68
|
+
buffered.push({ type: "del", key });
|
|
69
|
+
},
|
|
70
|
+
write: async () => {
|
|
71
|
+
await this.batchWrite(buffered);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async *iterator(
|
|
77
|
+
options: AuthorityIteratorOptions = {}
|
|
78
|
+
): AsyncIterableIterator<[string, unknown]> {
|
|
79
|
+
const entries: MemoryEntry[] = Array.from(this.data.entries())
|
|
80
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
81
|
+
.map(([key, value]) => ({ key, value }));
|
|
82
|
+
|
|
83
|
+
if (options.reverse) {
|
|
84
|
+
entries.reverse();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
if (options.gte && entry.key < options.gte) continue;
|
|
89
|
+
if (options.lte && entry.key > options.lte) continue;
|
|
90
|
+
if (options.lt && entry.key >= options.lt) continue;
|
|
91
|
+
yield [entry.key, entry.value];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function createMemoryAuthorityStore(
|
|
97
|
+
location = ":memory:"
|
|
98
|
+
): AuthorityStore {
|
|
99
|
+
const backing = new MemoryAuthorityBacking(location);
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
get location() {
|
|
103
|
+
return backing.location;
|
|
104
|
+
},
|
|
105
|
+
get status() {
|
|
106
|
+
return backing.status;
|
|
107
|
+
},
|
|
108
|
+
async open() {
|
|
109
|
+
await backing.open();
|
|
110
|
+
},
|
|
111
|
+
async close() {
|
|
112
|
+
await backing.close();
|
|
113
|
+
},
|
|
114
|
+
async get<T = any>(key: string) {
|
|
115
|
+
return backing.get<T>(key);
|
|
116
|
+
},
|
|
117
|
+
async put(key: string, value: unknown) {
|
|
118
|
+
await backing.put(key, value);
|
|
119
|
+
},
|
|
120
|
+
async del(key: string) {
|
|
121
|
+
await backing.del(key);
|
|
122
|
+
},
|
|
123
|
+
async batchWrite(ops: AuthorityBatchOperation[]) {
|
|
124
|
+
await backing.batchWrite(ops);
|
|
125
|
+
},
|
|
126
|
+
createBatch() {
|
|
127
|
+
return backing.createBatch();
|
|
128
|
+
},
|
|
129
|
+
iterator(options: AuthorityIteratorOptions = {}) {
|
|
130
|
+
return backing.iterator(options);
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
package/database/server/patch.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// patch.js (或你的 patch 处理文件名)
|
|
2
|
-
import { pino } from "pino";
|
|
3
|
-
import { DataType } from "../../create/types";
|
|
4
|
-
import
|
|
5
|
-
import { handleToken } from "../../auth/server/token";
|
|
2
|
+
import { pino } from "pino";
|
|
3
|
+
import { DataType } from "../../create/types";
|
|
4
|
+
import { getServerAuthorityStore } from "./db"; // 确认路径正确
|
|
5
|
+
import { handleToken } from "../../auth/server/token";
|
|
6
6
|
import {
|
|
7
7
|
CYBOT_READONLY_MESSAGE,
|
|
8
8
|
isCybotReadOnlyMutation,
|
|
@@ -63,8 +63,9 @@ const deepMerge = (target, source) => {
|
|
|
63
63
|
return output;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
export const handlePatch = async (req, res) => {
|
|
67
|
-
|
|
66
|
+
export const handlePatch = async (req, res) => {
|
|
67
|
+
const store = getServerAuthorityStore();
|
|
68
|
+
req.user = await handleToken(req, res);
|
|
68
69
|
|
|
69
70
|
// --- 修改:变量名改为 dbKey,但仍然从 req.params.id 获取值 ---
|
|
70
71
|
// (路由中仍然是 :id, 所以这里还是 req.params.id)
|
|
@@ -112,8 +113,8 @@ export const handlePatch = async (req, res) => {
|
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
try {
|
|
115
|
-
// --- 修改:使用 dbKey 变量与数据库交互 ---
|
|
116
|
-
const exist = await
|
|
116
|
+
// --- 修改:使用 dbKey 变量与数据库交互 ---
|
|
117
|
+
const exist = await store.get(dbKey);
|
|
117
118
|
if (!exist) {
|
|
118
119
|
// 使用 404 Not Found 更合适
|
|
119
120
|
return res
|
|
@@ -152,10 +153,10 @@ export const handlePatch = async (req, res) => {
|
|
|
152
153
|
});
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
// 深度合并现有数据和变更 (保持不变)
|
|
156
|
-
const final = deepMerge(exist, changes);
|
|
157
|
-
|
|
158
|
-
await
|
|
156
|
+
// 深度合并现有数据和变更 (保持不变)
|
|
157
|
+
const final = deepMerge(exist, changes);
|
|
158
|
+
|
|
159
|
+
await store.put(dbKey, final);
|
|
159
160
|
|
|
160
161
|
if (
|
|
161
162
|
(final?.type === "table" || final?.type === "table_row") &&
|
package/database/server/query.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// database/server/handler.ts
|
|
2
|
-
import
|
|
2
|
+
import { getServerAuthorityStore } from "./db";
|
|
3
3
|
import { getUserDataPrefixes } from "../queryPrefixes";
|
|
4
4
|
|
|
5
5
|
interface BaseItem {
|
|
@@ -102,6 +102,7 @@ async function fetchUserData(
|
|
|
102
102
|
userId: string,
|
|
103
103
|
options: { includeDeleted?: boolean } = {}
|
|
104
104
|
): Promise<Record<string, BaseItem[]>> {
|
|
105
|
+
const store = getServerAuthorityStore();
|
|
105
106
|
const results: Record<string, BaseItem[]> = {};
|
|
106
107
|
if (!userId || userId === "local" || userId === "undefined") return results;
|
|
107
108
|
const typeArray = Array.isArray(types) ? types : [types];
|
|
@@ -109,7 +110,7 @@ async function fetchUserData(
|
|
|
109
110
|
for (const type of typeArray) {
|
|
110
111
|
const prefixes = getUserDataPrefixes(type, userId);
|
|
111
112
|
for (const prefix of prefixes) {
|
|
112
|
-
for await (const [key, value] of
|
|
113
|
+
for await (const [key, value] of store.iterator({
|
|
113
114
|
gte: prefix,
|
|
114
115
|
lte: `${prefix}\uffff`,
|
|
115
116
|
})) {
|
package/database/server/read.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// 文件路径: packages/database/server/read.ts
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { DB_PREFIX, shareKey } from "../keys";
|
|
3
|
+
import { getServerAuthorityStore } from "./db";
|
|
4
|
+
import { DB_PREFIX, shareKey } from "../keys";
|
|
5
5
|
import { parseToken, verifyToken } from "../../auth/token";
|
|
6
6
|
import { assertSessionTokenVersion } from "../../auth/sessionTokenVersion";
|
|
7
7
|
import { hasActiveEntitlement } from "../../auth/server/productEntitlements";
|
|
@@ -11,6 +11,7 @@ import { authorizeActorRecordAccess } from "./actorAccess";
|
|
|
11
11
|
import {
|
|
12
12
|
resolveSharePaidAccess,
|
|
13
13
|
} from "../../share/paidAccess";
|
|
14
|
+
import { ensureDbOpen } from "./ensureDbOpen";
|
|
14
15
|
|
|
15
16
|
const isLevelNotFoundError = (error: any): boolean => {
|
|
16
17
|
const code = error?.code;
|
|
@@ -33,17 +34,18 @@ const isPublicAgentKey = (dbKey: string): boolean =>
|
|
|
33
34
|
const getUserIdFromProfileKey = (dbKey: string): string =>
|
|
34
35
|
dbKey.slice(0, -PROFILE_KEY_SUFFIX.length);
|
|
35
36
|
|
|
36
|
-
const getAuthorizedUserId = async (req: any): Promise<string | null> => {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
37
|
+
const getAuthorizedUserId = async (req: any): Promise<string | null> => {
|
|
38
|
+
const store = getServerAuthorityStore();
|
|
39
|
+
const authHeader = req.headers?.get?.("authorization");
|
|
40
|
+
const token = typeof authHeader === "string" ? authHeader.split(" ")[1] : "";
|
|
41
|
+
if (!token) return null;
|
|
40
42
|
|
|
41
43
|
const parsed = parseToken(token);
|
|
42
44
|
const userId = parsed?.userId;
|
|
43
45
|
if (!userId || typeof userId !== "string") return null;
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const user = await
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const user = await store.get(`${DB_PREFIX.USER}${userId}`);
|
|
47
49
|
if (!user?.publicKey || user?.isDisabled) return null;
|
|
48
50
|
|
|
49
51
|
const payload = verifyToken(token, user.publicKey);
|
|
@@ -116,8 +118,9 @@ const isAgentOwner = (agent: any, userId: string | null): boolean =>
|
|
|
116
118
|
agent?.userId === userId ||
|
|
117
119
|
agent?.tenantId === userId)
|
|
118
120
|
);
|
|
119
|
-
export const handleReadSingle = async (req: any) => {
|
|
120
|
-
const
|
|
121
|
+
export const handleReadSingle = async (req: any) => {
|
|
122
|
+
const store = getServerAuthorityStore();
|
|
123
|
+
const corsHeaders = {
|
|
121
124
|
"Access-Control-Allow-Origin": "*",
|
|
122
125
|
"Content-Type": "application/json",
|
|
123
126
|
};
|
|
@@ -132,9 +135,9 @@ export const handleReadSingle = async (req: any) => {
|
|
|
132
135
|
const dbKey = req.params.id;
|
|
133
136
|
const isShareDataKey = dbKey.startsWith("share-") || shareKey.isShareKey(dbKey);
|
|
134
137
|
|
|
135
|
-
try {
|
|
136
|
-
// ⭐ 确保 LevelDB 已打开,避免 LEVEL_DATABASE_NOT_OPEN
|
|
137
|
-
await
|
|
138
|
+
try {
|
|
139
|
+
// ⭐ 确保 LevelDB 已打开,避免 LEVEL_DATABASE_NOT_OPEN
|
|
140
|
+
await ensureDbOpen(store);
|
|
138
141
|
|
|
139
142
|
const authedUserId = await getAuthorizedUserId(req);
|
|
140
143
|
const isPublicAgentDataKey = isPublicAgentKey(dbKey);
|
|
@@ -156,19 +159,19 @@ export const handleReadSingle = async (req: any) => {
|
|
|
156
159
|
if (!authedUserId && isPublicProfileKey(dbKey)) {
|
|
157
160
|
const inviterId = getUserIdFromProfileKey(dbKey);
|
|
158
161
|
|
|
159
|
-
let profile: any = null;
|
|
160
|
-
try {
|
|
161
|
-
profile = await
|
|
162
|
-
} catch (error: any) {
|
|
163
|
-
if (!isLevelNotFoundError(error)) throw error;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
let user: any = null;
|
|
167
|
-
try {
|
|
168
|
-
user = await
|
|
169
|
-
} catch (error: any) {
|
|
170
|
-
if (!isLevelNotFoundError(error)) throw error;
|
|
171
|
-
}
|
|
162
|
+
let profile: any = null;
|
|
163
|
+
try {
|
|
164
|
+
profile = await store.get(dbKey);
|
|
165
|
+
} catch (error: any) {
|
|
166
|
+
if (!isLevelNotFoundError(error)) throw error;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let user: any = null;
|
|
170
|
+
try {
|
|
171
|
+
user = await store.get(`${DB_PREFIX.USER}${inviterId}`);
|
|
172
|
+
} catch (error: any) {
|
|
173
|
+
if (!isLevelNotFoundError(error)) throw error;
|
|
174
|
+
}
|
|
172
175
|
|
|
173
176
|
if (user?.isDisabled) {
|
|
174
177
|
return new Response(
|
|
@@ -195,8 +198,8 @@ export const handleReadSingle = async (req: any) => {
|
|
|
195
198
|
headers: corsHeaders,
|
|
196
199
|
});
|
|
197
200
|
}
|
|
198
|
-
|
|
199
|
-
const result = await
|
|
201
|
+
|
|
202
|
+
const result = await store.get(dbKey);
|
|
200
203
|
if (
|
|
201
204
|
result === null ||
|
|
202
205
|
typeof result === "undefined" ||
|
|
@@ -236,7 +239,7 @@ export const handleReadSingle = async (req: any) => {
|
|
|
236
239
|
const paidAccess = resolveSharePaidAccess(result);
|
|
237
240
|
if (paidAccess.mode === "product" && !owner) {
|
|
238
241
|
const purchased = await hasActiveEntitlement({
|
|
239
|
-
store
|
|
242
|
+
store,
|
|
240
243
|
userId: authedUserId,
|
|
241
244
|
productId: paidAccess.productId,
|
|
242
245
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isSystemAdmin } from "../../core/init";
|
|
2
2
|
import { shareKey } from "../keys";
|
|
3
|
-
import
|
|
3
|
+
import { getServerAuthorityStore } from "./db";
|
|
4
4
|
import { resolveKeyOwnerId } from "./writeAuthority";
|
|
5
5
|
|
|
6
6
|
export type AccessAction = "read" | "write" | "delete" | "manage";
|
|
@@ -73,11 +73,12 @@ const hasSpaceMembership = async (
|
|
|
73
73
|
userId: string,
|
|
74
74
|
spaceId: string | null
|
|
75
75
|
): Promise<boolean> => {
|
|
76
|
+
const store = getServerAuthorityStore();
|
|
76
77
|
const normalized = normalizeSpaceId(spaceId);
|
|
77
78
|
if (!userId || !normalized) return false;
|
|
78
79
|
|
|
79
80
|
try {
|
|
80
|
-
const membership = await
|
|
81
|
+
const membership = await store.get(
|
|
81
82
|
`${SPACE_MEMBER_PREFIX}${userId}-${normalized}`
|
|
82
83
|
);
|
|
83
84
|
if (membership) return true;
|
|
@@ -86,7 +87,7 @@ const hasSpaceMembership = async (
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
try {
|
|
89
|
-
const space = await
|
|
90
|
+
const space = await store.get(`${SPACE_PREFIX}${normalized}`);
|
|
90
91
|
return (
|
|
91
92
|
space?.ownerId === userId ||
|
|
92
93
|
(Array.isArray(space?.members) && space.members.includes(userId))
|
|
@@ -112,13 +113,14 @@ const isRecordLinkedFromMemberSpace = async (
|
|
|
112
113
|
dbKey: string,
|
|
113
114
|
record: any
|
|
114
115
|
): Promise<string | null> => {
|
|
116
|
+
const store = getServerAuthorityStore();
|
|
115
117
|
if (!userId || !dbKey) return null;
|
|
116
118
|
|
|
117
119
|
const contentKeys = getContentKeyCandidates(dbKey, record);
|
|
118
120
|
const prefix = `${SPACE_MEMBER_PREFIX}${userId}-`;
|
|
119
121
|
|
|
120
122
|
try {
|
|
121
|
-
for await (const [, membership] of
|
|
123
|
+
for await (const [, membership] of store.iterator({
|
|
122
124
|
gte: prefix,
|
|
123
125
|
lte: prefix + "\uffff",
|
|
124
126
|
})) {
|
|
@@ -126,7 +128,7 @@ const isRecordLinkedFromMemberSpace = async (
|
|
|
126
128
|
if (!spaceId) continue;
|
|
127
129
|
|
|
128
130
|
try {
|
|
129
|
-
const space = await
|
|
131
|
+
const space = await store.get(`${SPACE_PREFIX}${spaceId}`);
|
|
130
132
|
const contents = space?.contents;
|
|
131
133
|
if (!contents || typeof contents !== "object") continue;
|
|
132
134
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { Level } from "level";
|
|
4
|
+
|
|
5
|
+
import type { AuthorityStore } from "./authorityStoreTypes";
|
|
6
|
+
import { createLegacyServerDb, type LegacyServerDb } from "./legacyServerDb";
|
|
7
|
+
import { createLevelAuthorityStore } from "./levelAuthorityStore";
|
|
8
|
+
import { createMemoryAuthorityStore } from "./memoryAuthorityStore";
|
|
9
|
+
|
|
10
|
+
// Keep the storage seam local-first. Cross-process sharing stays in the
|
|
11
|
+
// existing core/proxy runtime layer; this factory is only for embedded drivers.
|
|
12
|
+
export type ServerStoreDriver = "level" | "memory";
|
|
13
|
+
|
|
14
|
+
export type ServerStoreFactoryEnv = {
|
|
15
|
+
NOLO_SERVER_AUTHORITY_DRIVER?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const safeJsonEncoding = {
|
|
19
|
+
name: "safe-json",
|
|
20
|
+
format: "utf8" as const,
|
|
21
|
+
encode: (data: any) => JSON.stringify(data),
|
|
22
|
+
decode: (data: string) => {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(data);
|
|
25
|
+
} catch {
|
|
26
|
+
console.warn("[LevelDB] Corrupted value:", data?.substring?.(0, 60));
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type ServerStoreRuntime = {
|
|
33
|
+
authorityStore: AuthorityStore;
|
|
34
|
+
serverDb: LegacyServerDb;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type ServerStoreFactoryOptions = {
|
|
38
|
+
driver?: ServerStoreDriver;
|
|
39
|
+
env?: ServerStoreFactoryEnv;
|
|
40
|
+
globalScope?: Record<string, unknown>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export function ensureServerDbDirectory(dbPath: string) {
|
|
44
|
+
const dir = path.dirname(dbPath);
|
|
45
|
+
if (!fs.existsSync(dir)) {
|
|
46
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createLevelBackedAuthorityStore(dbPath: string): AuthorityStore {
|
|
51
|
+
const levelDb = new Level<string, any>(dbPath, {
|
|
52
|
+
valueEncoding: safeJsonEncoding,
|
|
53
|
+
});
|
|
54
|
+
return createLevelAuthorityStore(levelDb);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function resolveServerStoreDriver(
|
|
58
|
+
env: ServerStoreFactoryEnv = process.env
|
|
59
|
+
): ServerStoreDriver {
|
|
60
|
+
const rawDriver = env.NOLO_SERVER_AUTHORITY_DRIVER?.trim().toLowerCase();
|
|
61
|
+
if (!rawDriver) return "level";
|
|
62
|
+
if (rawDriver === "level") return "level";
|
|
63
|
+
if (rawDriver === "memory") return "memory";
|
|
64
|
+
throw new Error(`Unsupported server authority store driver: ${rawDriver}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function createAuthorityStoreForDriver(
|
|
68
|
+
driver: ServerStoreDriver,
|
|
69
|
+
dbPath: string,
|
|
70
|
+
env: ServerStoreFactoryEnv = process.env
|
|
71
|
+
): AuthorityStore {
|
|
72
|
+
switch (driver) {
|
|
73
|
+
case "level":
|
|
74
|
+
return createLevelBackedAuthorityStore(dbPath);
|
|
75
|
+
case "memory":
|
|
76
|
+
// Test/dev-only driver that exercises the seam without changing the
|
|
77
|
+
// production single-writer runtime model.
|
|
78
|
+
return createMemoryAuthorityStore(dbPath);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getOrCreateServerStoreRuntime(
|
|
83
|
+
dbPath: string,
|
|
84
|
+
options: ServerStoreFactoryOptions = {}
|
|
85
|
+
): ServerStoreRuntime {
|
|
86
|
+
const globalScope =
|
|
87
|
+
options.globalScope ?? (globalThis as Record<string, unknown>);
|
|
88
|
+
const driver = options.driver ?? resolveServerStoreDriver(options.env);
|
|
89
|
+
const cachedDriver = globalScope.__serverAuthorityStoreDriver;
|
|
90
|
+
|
|
91
|
+
ensureServerDbDirectory(dbPath);
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
globalScope.__serverAuthorityStore &&
|
|
95
|
+
typeof cachedDriver === "string" &&
|
|
96
|
+
cachedDriver !== driver
|
|
97
|
+
) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Server authority store already initialized with driver ${cachedDriver}, cannot reuse it for ${driver}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!globalScope.__serverAuthorityStore) {
|
|
104
|
+
globalScope.__serverAuthorityStore = createAuthorityStoreForDriver(
|
|
105
|
+
driver,
|
|
106
|
+
dbPath,
|
|
107
|
+
options.env
|
|
108
|
+
);
|
|
109
|
+
globalScope.__serverAuthorityStoreDriver = driver;
|
|
110
|
+
} else if (!cachedDriver) {
|
|
111
|
+
globalScope.__serverAuthorityStoreDriver = driver;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const authorityStore = globalScope.__serverAuthorityStore as AuthorityStore;
|
|
115
|
+
|
|
116
|
+
if (!globalScope.__serverDb) {
|
|
117
|
+
globalScope.__serverDb = createLegacyServerDb(authorityStore);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
authorityStore,
|
|
122
|
+
serverDb: globalScope.__serverDb as LegacyServerDb,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getServerAuthorityStore } from "./db";
|
|
2
2
|
|
|
3
3
|
const SPACE_MEMBER_PREFIX = "space-member-";
|
|
4
4
|
const SPACE_PREFIX = "space-";
|
|
@@ -23,8 +23,9 @@ export const parseSpaceMemberKey = (
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const loadSpaceRecord = async (spaceId: string): Promise<any | null> => {
|
|
26
|
+
const store = getServerAuthorityStore();
|
|
26
27
|
try {
|
|
27
|
-
return await
|
|
28
|
+
return await store.get(`${SPACE_PREFIX}${spaceId}`);
|
|
28
29
|
} catch {
|
|
29
30
|
return null;
|
|
30
31
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthorityBatchOperation,
|
|
3
|
+
AuthorityBatchWriter,
|
|
4
|
+
} from "./authorityStoreTypes";
|
|
5
|
+
|
|
6
|
+
type BatchArrayStoreLike = {
|
|
7
|
+
batchWrite?(ops: AuthorityBatchOperation[]): Promise<void>;
|
|
8
|
+
batch?(ops: AuthorityBatchOperation[]): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type BatchBuilderStoreLike = {
|
|
12
|
+
createBatch?(): AuthorityBatchWriter;
|
|
13
|
+
batch?(): AuthorityBatchWriter;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function writeStoreOps(
|
|
17
|
+
store: BatchArrayStoreLike,
|
|
18
|
+
ops: AuthorityBatchOperation[]
|
|
19
|
+
): Promise<void> {
|
|
20
|
+
if (typeof store.batchWrite === "function") {
|
|
21
|
+
return store.batchWrite(ops);
|
|
22
|
+
}
|
|
23
|
+
if (typeof store.batch === "function") {
|
|
24
|
+
return store.batch(ops);
|
|
25
|
+
}
|
|
26
|
+
throw new Error("Store does not support batch array writes");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function createStoreBatch(store: BatchBuilderStoreLike): AuthorityBatchWriter {
|
|
30
|
+
if (typeof store.createBatch === "function") {
|
|
31
|
+
return store.createBatch();
|
|
32
|
+
}
|
|
33
|
+
if (typeof store.batch === "function") {
|
|
34
|
+
return store.batch();
|
|
35
|
+
}
|
|
36
|
+
throw new Error("Store does not support batch builder writes");
|
|
37
|
+
}
|