@undefineds.co/xpod 0.3.22 → 0.3.24

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ScopedPickWebIdHandler.js","sourceRoot":"","sources":["../../../src/identity/oidc/ScopedPickWebIdHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { boolean, object, string } from 'yup';\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n BadRequestHttpError,\n FoundHttpError,\n JsonInteractionHandler,\n assertAccountId,\n assertOidcInteraction,\n finishInteraction,\n forgetWebId,\n parseSchema,\n validateWithError,\n} from '@solid/community-server';\nimport type {\n Json,\n JsonInteractionHandlerInput,\n JsonRepresentation,\n JsonView,\n ProviderFactory,\n WebIdStore,\n} from '@solid/community-server';\nimport { getIdentityDatabase } from '../drizzle/db';\nimport { PodLookupRepository, type PodLookupResult } from '../drizzle/PodLookupRepository';\nimport { ProvisionCodeCodec } from '../../provision/ProvisionCodeCodec';\n\ntype FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nconst inSchema = object({\n webId: string().trim().required(),\n remember: boolean().default(false),\n});\n\nexport interface ScopedPickWebIdHandlerOptions {\n webIdStore: WebIdStore;\n providerFactory: ProviderFactory;\n identityDbUrl?: string;\n podLookupRepository?: PodWebIdLookupRepository;\n fetch?: FetchLike;\n}\n\nexport interface PodWebIdLookupRepository {\n findByWebId: (webId: string) => Promise<PodLookupResult | undefined>;\n}\n\ninterface WebIdEntry extends Record<string, Json | undefined> {\n webId: string;\n storageUrl?: string;\n storageMode?: 'cloud' | 'local' | 'custom';\n}\n\n/**\n * CSS-compatible WebID picker scoped to the current storage provider.\n *\n * The upstream handler lists every WebID linked to the IdP account. In an\n * IDP/SP split flow that lets a Local SP login pick a Cloud Pod again, so this\n * replacement keeps consent choices constrained by the selected SP's Pod facts.\n */\nexport class ScopedPickWebIdHandler extends JsonInteractionHandler implements JsonView {\n private readonly logger = getLoggerFor(this);\n private readonly webIdStore: WebIdStore;\n private readonly providerFactory: ProviderFactory;\n private readonly podLookupRepository?: PodWebIdLookupRepository;\n private readonly fetch: FetchLike;\n\n public constructor(options: ScopedPickWebIdHandlerOptions) {\n super();\n this.webIdStore = options.webIdStore;\n this.providerFactory = options.providerFactory;\n this.podLookupRepository = options.podLookupRepository ??\n (options.identityDbUrl ? new PodLookupRepository(getIdentityDatabase(options.identityDbUrl)) : undefined);\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n public async getView({ accountId, oidcInteraction }: JsonInteractionHandlerInput): Promise<JsonRepresentation> {\n assertAccountId(accountId);\n const provider = await this.providerFactory.getProvider();\n const description = parseSchema(inSchema);\n const target = await this.resolveTargetStorage(provider, oidcInteraction);\n const entries = await this.resolveScopedEntries(accountId, target);\n\n return {\n json: {\n ...description,\n webIds: entries.map((entry) => entry.webId),\n entries,\n },\n };\n }\n\n public async handle({ oidcInteraction, accountId, json }: JsonInteractionHandlerInput): Promise<never> {\n assertOidcInteraction(oidcInteraction);\n assertAccountId(accountId);\n const { webId, remember } = await validateWithError(inSchema, json);\n const provider = await this.providerFactory.getProvider();\n const target = await this.resolveTargetStorage(provider, oidcInteraction);\n\n if (!await this.webIdStore.isLinked(webId, accountId)) {\n this.logger.warn(`Trying to pick WebID ${webId} which does not belong to account ${accountId}`);\n throw new BadRequestHttpError('WebID does not belong to this account.');\n }\n\n if (!await this.isResolvableByCurrentSp(webId, target)) {\n this.logger.warn(`Trying to pick WebID ${webId} which does not belong to this storage provider`);\n throw new BadRequestHttpError('WebID does not belong to this storage provider.');\n }\n\n await forgetWebId(provider, oidcInteraction);\n const location = await finishInteraction(oidcInteraction, {\n login: {\n accountId: webId,\n remember,\n },\n }, true);\n throw new FoundHttpError(location);\n }\n\n private async resolveScopedEntries(accountId: string, target: TargetStorage): Promise<WebIdEntry[]> {\n const webIds = (await this.webIdStore.findLinks(accountId)).map((link) => link.webId);\n if (target.serviceToken) {\n return this.resolveRemoteSpEntries(webIds, target);\n }\n\n const entries: WebIdEntry[] = [];\n for (const webId of webIds) {\n const pod = await this.findSpPod(webId, target.storageUrl);\n if (!pod) {\n continue;\n }\n const storageUrl = ensureTrailingSlash(pod.storageUrl ?? pod.baseUrl);\n entries.push({\n webId,\n storageUrl,\n storageMode: deriveStorageMode(webId, storageUrl),\n });\n }\n return entries;\n }\n\n private async isResolvableByCurrentSp(webId: string, target: TargetStorage): Promise<boolean> {\n if (target.serviceToken) {\n return (await this.resolveRemoteSpEntries([webId], target)).some((entry) => entry.webId === webId);\n }\n return Boolean(await this.findSpPod(webId, target.storageUrl));\n }\n\n private async findSpPod(webId: string, targetStorageUrl: string): Promise<PodLookupResult | undefined> {\n if (!this.podLookupRepository) {\n this.logger.warn('No PodLookupRepository configured; refusing to expose unscoped WebID choices');\n return undefined;\n }\n\n try {\n const pod = await this.podLookupRepository.findByWebId(webId);\n return pod && matchesTargetStorage(pod, targetStorageUrl) ? pod : undefined;\n } catch (error) {\n this.logger.warn(`Pod lookup unavailable for WebID ${webId}: ${error}`);\n return undefined;\n }\n }\n\n private async resolveTargetStorage(\n provider: { issuer: string },\n oidcInteraction?: JsonInteractionHandlerInput['oidcInteraction'],\n ): Promise<TargetStorage> {\n const provisionCode = extractProvisionCode(oidcInteraction);\n if (!provisionCode) {\n return { storageUrl: ensureTrailingSlash(provider.issuer) };\n }\n\n const payload = new ProvisionCodeCodec(provider.issuer).decode(provisionCode);\n if (!payload) {\n throw new BadRequestHttpError('Invalid or expired provisionCode.');\n }\n\n const targetUrl = payload.spDomain\n ? `https://${payload.spDomain}`\n : payload.spUrl;\n return {\n storageUrl: ensureTrailingSlash(targetUrl),\n lookupUrl: ensureTrailingSlash(payload.spUrl),\n serviceToken: payload.serviceToken,\n };\n }\n\n private async resolveRemoteSpEntries(webIds: string[], target: TargetStorage): Promise<WebIdEntry[]> {\n if (!target.lookupUrl || !target.serviceToken || webIds.length === 0) {\n return [];\n }\n\n const response = await this.fetch(new URL('/provision/webids', target.lookupUrl).toString(), {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${target.serviceToken}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify({ webIds }),\n });\n\n if (!response.ok) {\n this.logger.warn(`Remote SP WebID lookup failed: HTTP ${response.status}`);\n return [];\n }\n\n const body = await response.json().catch(() => null) as { entries?: RemoteSpWebIdEntry[] } | null;\n if (!Array.isArray(body?.entries)) {\n return [];\n }\n\n const allowedWebIds = new Set(webIds);\n return body.entries\n .filter((entry) => typeof entry.webId === 'string' && allowedWebIds.has(entry.webId))\n .filter((entry) => typeof entry.storageUrl === 'string' && matchesTargetStorage(\n {\n podId: '',\n accountId: '',\n baseUrl: entry.podUrl ?? entry.storageUrl,\n storageUrl: entry.storageUrl,\n },\n target.storageUrl,\n ))\n .map((entry) => ({\n webId: entry.webId,\n storageUrl: ensureTrailingSlash(entry.storageUrl),\n storageMode: deriveStorageMode(entry.webId, entry.storageUrl),\n }));\n }\n}\n\ninterface TargetStorage {\n storageUrl: string;\n lookupUrl?: string;\n serviceToken?: string;\n}\n\ninterface RemoteSpWebIdEntry {\n webId: string;\n podUrl?: string;\n storageUrl: string;\n}\n\nfunction deriveStorageMode(webId: string, storageUrl: string): 'cloud' | 'local' | 'custom' {\n const webIdRoot = deriveStorageRoot(webId);\n const storageRoot = deriveStorageRoot(storageUrl);\n if (!webIdRoot || !storageRoot) {\n return 'custom';\n }\n return webIdRoot === storageRoot ? 'cloud' : 'local';\n}\n\nfunction deriveStorageRoot(url: string): string | undefined {\n try {\n const parsed = new URL(url);\n const segments = parsed.pathname.split('/').filter(Boolean);\n if (segments.length === 0) {\n return ensureTrailingSlash(parsed.origin);\n }\n\n return ensureTrailingSlash(new URL(`/${segments[0]}/`, parsed.origin).toString());\n } catch {\n return undefined;\n }\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.replace(/\\/+$/u, '') + '/';\n}\n\nfunction matchesTargetStorage(pod: PodLookupResult, targetStorageUrl: string): boolean {\n const candidateUrls = [pod.storageUrl, pod.baseUrl].filter((value): value is string => typeof value === 'string' && value.length > 0);\n const targetRoot = deriveStorageRoot(targetStorageUrl);\n if (!targetRoot) {\n return false;\n }\n\n for (const candidate of candidateUrls) {\n const candidateRoot = deriveStorageRoot(candidate);\n if (candidateRoot && candidateRoot === targetRoot) {\n return true;\n }\n\n const candidateUrl = ensureTrailingSlash(candidate);\n if (candidateUrl.startsWith(targetRoot) || targetRoot.startsWith(candidateUrl)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction extractProvisionCode(oidcInteraction: JsonInteractionHandlerInput['oidcInteraction']): string | undefined {\n const params = oidcInteraction?.params as Record<string, unknown> | undefined;\n const value = params?.provisionCode;\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n"]}
1
+ {"version":3,"file":"ScopedPickWebIdHandler.js","sourceRoot":"","sources":["../../../src/identity/oidc/ScopedPickWebIdHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { boolean, object, string } from 'yup';\nimport { getLoggerFor } from 'global-logger-factory';\nimport {\n BadRequestHttpError,\n FoundHttpError,\n JsonInteractionHandler,\n assertAccountId,\n assertOidcInteraction,\n finishInteraction,\n forgetWebId,\n parseSchema,\n validateWithError,\n} from '@solid/community-server';\nimport type {\n Json,\n JsonInteractionHandlerInput,\n JsonRepresentation,\n JsonView,\n ProviderFactory,\n WebIdStore,\n} from '@solid/community-server';\nimport { getIdentityDatabase } from '../drizzle/db';\nimport { PodLookupRepository, type PodLookupResult } from '../drizzle/PodLookupRepository';\nimport { ProvisionCodeCodec } from '../../provision/ProvisionCodeCodec';\n\ntype FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\n\nconst inSchema = object({\n webId: string().trim().required(),\n remember: boolean().default(false),\n});\n\nexport interface ScopedPickWebIdHandlerOptions {\n webIdStore: WebIdStore;\n providerFactory: ProviderFactory;\n identityDbUrl?: string;\n podLookupRepository?: PodWebIdLookupRepository;\n fetch?: FetchLike;\n}\n\nexport interface PodWebIdLookupRepository {\n findByWebId: (webId: string) => Promise<PodLookupResult | undefined>;\n findAllByWebId?: (webId: string) => Promise<PodLookupResult[]>;\n}\n\ninterface WebIdEntry extends Record<string, Json | undefined> {\n webId: string;\n storageUrl?: string;\n storageMode?: 'cloud' | 'local' | 'custom';\n}\n\n/**\n * CSS-compatible WebID picker scoped to the current storage provider.\n *\n * The upstream handler lists every WebID linked to the IdP account. In an\n * IDP/SP split flow that lets a Local SP login pick a Cloud Pod again, so this\n * replacement keeps consent choices constrained by the selected SP's Pod facts.\n */\nexport class ScopedPickWebIdHandler extends JsonInteractionHandler implements JsonView {\n private readonly logger = getLoggerFor(this);\n private readonly webIdStore: WebIdStore;\n private readonly providerFactory: ProviderFactory;\n private readonly podLookupRepository?: PodWebIdLookupRepository;\n private readonly fetch: FetchLike;\n\n public constructor(options: ScopedPickWebIdHandlerOptions) {\n super();\n this.webIdStore = options.webIdStore;\n this.providerFactory = options.providerFactory;\n this.podLookupRepository = options.podLookupRepository ??\n (options.identityDbUrl ? new PodLookupRepository(getIdentityDatabase(options.identityDbUrl)) : undefined);\n this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n public async getView({ accountId, oidcInteraction }: JsonInteractionHandlerInput): Promise<JsonRepresentation> {\n assertAccountId(accountId);\n const provider = await this.providerFactory.getProvider();\n const description = parseSchema(inSchema);\n const target = await this.resolveTargetStorage(provider, oidcInteraction);\n const entries = await this.resolveScopedEntries(accountId, target);\n\n return {\n json: {\n ...description,\n webIds: entries.map((entry) => entry.webId),\n entries,\n },\n };\n }\n\n public async handle({ oidcInteraction, accountId, json }: JsonInteractionHandlerInput): Promise<never> {\n assertOidcInteraction(oidcInteraction);\n assertAccountId(accountId);\n const { webId, remember } = await validateWithError(inSchema, json);\n const provider = await this.providerFactory.getProvider();\n const target = await this.resolveTargetStorage(provider, oidcInteraction);\n\n if (!await this.webIdStore.isLinked(webId, accountId)) {\n this.logger.warn(`Trying to pick WebID ${webId} which does not belong to account ${accountId}`);\n throw new BadRequestHttpError('WebID does not belong to this account.');\n }\n\n if (!await this.isResolvableByCurrentSp(webId, target)) {\n this.logger.warn(`Trying to pick WebID ${webId} which does not belong to this storage provider`);\n throw new BadRequestHttpError('WebID does not belong to this storage provider.');\n }\n\n await forgetWebId(provider, oidcInteraction);\n const location = await finishInteraction(oidcInteraction, {\n login: {\n accountId: webId,\n remember,\n },\n }, true);\n throw new FoundHttpError(location);\n }\n\n private async resolveScopedEntries(accountId: string, target: TargetStorage): Promise<WebIdEntry[]> {\n const webIds = (await this.webIdStore.findLinks(accountId)).map((link) => link.webId);\n if (target.serviceToken) {\n return this.resolveRemoteSpEntries(webIds, target);\n }\n\n const entries: WebIdEntry[] = [];\n for (const webId of webIds) {\n const pod = await this.findSpPod(webId, target.storageUrl);\n if (!pod) {\n continue;\n }\n const storageUrl = ensureTrailingSlash(pod.storageUrl ?? pod.baseUrl);\n entries.push({\n webId,\n storageUrl,\n storageMode: deriveStorageMode(webId, storageUrl),\n });\n }\n return entries;\n }\n\n private async isResolvableByCurrentSp(webId: string, target: TargetStorage): Promise<boolean> {\n if (target.serviceToken) {\n return (await this.resolveRemoteSpEntries([webId], target)).some((entry) => entry.webId === webId);\n }\n return Boolean(await this.findSpPod(webId, target.storageUrl));\n }\n\n private async findSpPod(webId: string, targetStorageUrl: string): Promise<PodLookupResult | undefined> {\n if (!this.podLookupRepository) {\n this.logger.warn('No PodLookupRepository configured; refusing to expose unscoped WebID choices');\n return undefined;\n }\n\n try {\n const pods = this.podLookupRepository.findAllByWebId\n ? await this.podLookupRepository.findAllByWebId(webId)\n : await this.podLookupRepository.findByWebId(webId).then((pod) => pod ? [pod] : []);\n return pods.find((pod) => matchesTargetStorage(pod, targetStorageUrl));\n } catch (error) {\n this.logger.warn(`Pod lookup unavailable for WebID ${webId}: ${error}`);\n return undefined;\n }\n }\n\n private async resolveTargetStorage(\n provider: { issuer: string },\n oidcInteraction?: JsonInteractionHandlerInput['oidcInteraction'],\n ): Promise<TargetStorage> {\n const provisionCode = extractProvisionCode(oidcInteraction);\n if (!provisionCode) {\n return { storageUrl: ensureTrailingSlash(provider.issuer) };\n }\n\n const payload = new ProvisionCodeCodec(provider.issuer).decode(provisionCode);\n if (!payload) {\n throw new BadRequestHttpError('Invalid or expired provisionCode.');\n }\n\n const targetUrl = payload.spDomain\n ? `https://${payload.spDomain}`\n : payload.spUrl;\n return {\n storageUrl: ensureTrailingSlash(targetUrl),\n lookupUrl: ensureTrailingSlash(payload.spUrl),\n serviceToken: payload.serviceToken,\n };\n }\n\n private async resolveRemoteSpEntries(webIds: string[], target: TargetStorage): Promise<WebIdEntry[]> {\n if (!target.lookupUrl || !target.serviceToken || webIds.length === 0) {\n return [];\n }\n\n const response = await this.fetch(new URL('/provision/webids', target.lookupUrl).toString(), {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${target.serviceToken}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify({ webIds }),\n });\n\n if (!response.ok) {\n this.logger.warn(`Remote SP WebID lookup failed: HTTP ${response.status}`);\n return [];\n }\n\n const body = await response.json().catch(() => null) as { entries?: RemoteSpWebIdEntry[] } | null;\n if (!Array.isArray(body?.entries)) {\n return [];\n }\n\n const allowedWebIds = new Set(webIds);\n return body.entries\n .filter((entry) => typeof entry.webId === 'string' && allowedWebIds.has(entry.webId))\n .filter((entry) => typeof entry.storageUrl === 'string' && matchesTargetStorage(\n {\n podId: '',\n accountId: '',\n baseUrl: entry.podUrl ?? entry.storageUrl,\n storageUrl: entry.storageUrl,\n },\n target.storageUrl,\n ))\n .map((entry) => ({\n webId: entry.webId,\n storageUrl: ensureTrailingSlash(entry.storageUrl),\n storageMode: deriveStorageMode(entry.webId, entry.storageUrl),\n }));\n }\n}\n\ninterface TargetStorage {\n storageUrl: string;\n lookupUrl?: string;\n serviceToken?: string;\n}\n\ninterface RemoteSpWebIdEntry {\n webId: string;\n podUrl?: string;\n storageUrl: string;\n}\n\nfunction deriveStorageMode(webId: string, storageUrl: string): 'cloud' | 'local' | 'custom' {\n const webIdRoot = deriveStorageRoot(webId);\n const storageRoot = deriveStorageRoot(storageUrl);\n if (!webIdRoot || !storageRoot) {\n return 'custom';\n }\n return webIdRoot === storageRoot ? 'cloud' : 'local';\n}\n\nfunction deriveStorageRoot(url: string): string | undefined {\n try {\n const parsed = new URL(url);\n const segments = parsed.pathname.split('/').filter(Boolean);\n if (segments.length === 0) {\n return ensureTrailingSlash(parsed.origin);\n }\n\n return ensureTrailingSlash(new URL(`/${segments[0]}/`, parsed.origin).toString());\n } catch {\n return undefined;\n }\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.replace(/\\/+$/u, '') + '/';\n}\n\nfunction matchesTargetStorage(pod: PodLookupResult, targetStorageUrl: string): boolean {\n const candidateUrls = [pod.storageUrl, pod.baseUrl].filter((value): value is string => typeof value === 'string' && value.length > 0);\n const targetRoot = deriveStorageRoot(targetStorageUrl);\n if (!targetRoot) {\n return false;\n }\n\n for (const candidate of candidateUrls) {\n const candidateRoot = deriveStorageRoot(candidate);\n if (candidateRoot && candidateRoot === targetRoot) {\n return true;\n }\n\n const candidateUrl = ensureTrailingSlash(candidate);\n if (candidateUrl.startsWith(targetRoot) || targetRoot.startsWith(candidateUrl)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction extractProvisionCode(oidcInteraction: JsonInteractionHandlerInput['oidcInteraction']): string | undefined {\n const params = oidcInteraction?.params as Record<string, unknown> | undefined;\n const value = params?.provisionCode;\n return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;\n}\n"]}
@@ -4,14 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LocalSolidFS = void 0;
7
- const node_crypto_1 = require("node:crypto");
8
- const node_fs_1 = require("node:fs");
9
7
  const promises_1 = require("node:fs/promises");
10
8
  const node_os_1 = __importDefault(require("node:os"));
11
9
  const node_path_1 = __importDefault(require("node:path"));
12
- const node_url_1 = require("node:url");
13
10
  const types_1 = require("./types");
14
11
  const RdfContentTypes_1 = require("../storage/rdf/RdfContentTypes");
12
+ const SolidFsPathUtils_1 = require("./SolidFsPathUtils");
15
13
  class LocalSolidFS {
16
14
  constructor(options = {}) {
17
15
  this.workRoot = options.workRoot ?? node_path_1.default.join(node_os_1.default.tmpdir(), 'xpod-solidfs');
@@ -32,13 +30,17 @@ class LocalSolidFS {
32
30
  ? (relativePath) => syncer.shouldTrackPath(relativePath)
33
31
  : isLineAddressableRdfPath
34
32
  : undefined;
35
- const entries = changeFilter ? await snapshotDirectory(sourceRoot, changeFilter) : [];
33
+ const entries = changeFilter ? await (0, SolidFsPathUtils_1.snapshotDirectory)(sourceRoot, changeFilter) : [];
34
+ const manifest = this.createManifest(input.workspace, sourceRoot, projection, entries);
35
+ if (trackChanges && syncer?.initializeWorkspace) {
36
+ await syncer.initializeWorkspace(manifest, input.context);
37
+ }
36
38
  return new LocalMaterializedWorkspace({
37
39
  sourceRoot,
38
40
  cwd: sourceRoot,
39
41
  projection,
40
42
  cleanupOnRollback: false,
41
- manifest: this.createManifest(input.workspace, sourceRoot, projection, entries),
43
+ manifest,
42
44
  changeFilter,
43
45
  context: input.context,
44
46
  syncer: this.syncer,
@@ -61,7 +63,7 @@ class LocalSolidFS {
61
63
  throw new Error(`LocalSolidFS does not support projection '${projection}' yet.`);
62
64
  }
63
65
  const cwd = await this.createCopyWorkdir(sourceRoot, input.run?.id);
64
- const entries = await snapshotDirectory(sourceRoot);
66
+ const entries = await (0, SolidFsPathUtils_1.snapshotDirectory)(sourceRoot);
65
67
  await (0, promises_1.cp)(sourceRoot, cwd, {
66
68
  recursive: true,
67
69
  force: true,
@@ -110,14 +112,14 @@ class LocalSolidFS {
110
112
  return workspaceDir;
111
113
  }
112
114
  createManifest(workspace, cwd, projection, snapshots) {
113
- const source = sourceForProjection(projection, workspace);
115
+ const source = (0, SolidFsPathUtils_1.sourceForProjection)(projection, workspace);
114
116
  return {
115
117
  workspace,
116
118
  cwd,
117
119
  projection,
118
120
  entries: snapshots.map((snapshot) => ({
119
121
  path: snapshot.relativePath,
120
- resource: resolveWorkspaceResource(workspace, snapshot.relativePath),
122
+ resource: (0, SolidFsPathUtils_1.resolveWorkspaceResource)(workspace, snapshot.relativePath),
121
123
  source,
122
124
  sourcePath: snapshot.absolutePath,
123
125
  projection,
@@ -155,7 +157,7 @@ class LocalMaterializedWorkspace {
155
157
  this.context = options.context;
156
158
  this.syncer = options.syncer;
157
159
  this.hydrator = options.hydrator;
158
- this.entrySource = sourceForProjection(this.projection, this.manifest.workspace);
160
+ this.entrySource = (0, SolidFsPathUtils_1.sourceForProjection)(this.projection, this.manifest.workspace);
159
161
  }
160
162
  async commit() {
161
163
  if (this.projection === 'hydrated-object') {
@@ -203,7 +205,7 @@ class LocalMaterializedWorkspace {
203
205
  if (!this.hydrator) {
204
206
  throw new Error('SolidFS hydrated-object projection requires a hydrator');
205
207
  }
206
- const normalized = safeRelativePath(relativePath);
208
+ const normalized = (0, SolidFsPathUtils_1.safeRelativePath)(relativePath);
207
209
  const targetPath = node_path_1.default.join(this.cwd, normalized);
208
210
  await (0, promises_1.mkdir)(node_path_1.default.dirname(targetPath), { recursive: true });
209
211
  const result = await this.hydrator.hydrate({
@@ -212,15 +214,15 @@ class LocalMaterializedWorkspace {
212
214
  workspace: this.manifest,
213
215
  context: this.context,
214
216
  });
215
- const workingVersion = await fileVersion(targetPath);
217
+ const workingVersion = await (0, SolidFsPathUtils_1.fileVersion)(targetPath);
216
218
  let entry = this.manifest.entries.find((candidate) => candidate.path === normalized);
217
219
  if (!entry) {
218
220
  entry = {
219
221
  path: normalized,
220
- resource: resolveWorkspaceResource(this.manifest.workspace, normalized),
222
+ resource: (0, SolidFsPathUtils_1.resolveWorkspaceResource)(this.manifest.workspace, normalized),
221
223
  source: this.entrySource,
222
224
  sourcePath: targetPath,
223
- contentType: result?.contentType ?? contentTypeForPath(normalized),
225
+ contentType: result?.contentType ?? (0, SolidFsPathUtils_1.contentTypeForPath)(normalized),
224
226
  projection: this.projection,
225
227
  sourceVersion: result?.sourceVersion,
226
228
  workingVersion,
@@ -232,7 +234,7 @@ class LocalMaterializedWorkspace {
232
234
  return entry;
233
235
  }
234
236
  entry.sourcePath = targetPath;
235
- entry.contentType = result?.contentType ?? entry.contentType ?? contentTypeForPath(normalized);
237
+ entry.contentType = result?.contentType ?? entry.contentType ?? (0, SolidFsPathUtils_1.contentTypeForPath)(normalized);
236
238
  entry.sourceVersion = result?.sourceVersion ?? entry.sourceVersion;
237
239
  entry.workingVersion = workingVersion;
238
240
  entry.lastAccessedAt = Date.now();
@@ -247,7 +249,7 @@ class LocalMaterializedWorkspace {
247
249
  const olderThanMs = options.olderThanMs ?? 0;
248
250
  const retained = [];
249
251
  for (const entry of this.manifest.entries) {
250
- const currentVersion = await maybeFileVersion(entry.sourcePath);
252
+ const currentVersion = await (0, SolidFsPathUtils_1.maybeFileVersion)(entry.sourcePath);
251
253
  const dirty = currentVersion !== undefined && currentVersion !== entry.workingVersion;
252
254
  if (dirty) {
253
255
  entry.state = 'dirty';
@@ -289,7 +291,7 @@ class LocalMaterializedWorkspace {
289
291
  const entry = this.manifest.entries.find((candidate) => candidate.path === change.path);
290
292
  if (entry) {
291
293
  entry.sourceVersion = result?.sourceVersion ?? entry.sourceVersion;
292
- entry.workingVersion = await fileVersion(entry.sourcePath);
294
+ entry.workingVersion = await (0, SolidFsPathUtils_1.fileVersion)(entry.sourcePath);
293
295
  entry.lastAccessedAt = Date.now();
294
296
  }
295
297
  }
@@ -301,11 +303,11 @@ class LocalMaterializedWorkspace {
301
303
  const changes = [];
302
304
  const tracked = new Set(this.manifest.entries.map((entry) => entry.path));
303
305
  for (const entry of this.manifest.entries) {
304
- const currentVersion = await maybeFileVersion(entry.sourcePath);
306
+ const currentVersion = await (0, SolidFsPathUtils_1.maybeFileVersion)(entry.sourcePath);
305
307
  if (currentVersion === undefined) {
306
308
  changes.push({
307
309
  path: entry.path,
308
- resource: entry.resource ?? resolveWorkspaceResource(this.manifest.workspace, entry.path),
310
+ resource: entry.resource ?? (0, SolidFsPathUtils_1.resolveWorkspaceResource)(this.manifest.workspace, entry.path),
309
311
  source: entry.source,
310
312
  sourcePath: entry.sourcePath,
311
313
  contentType: entry.contentType,
@@ -319,7 +321,7 @@ class LocalMaterializedWorkspace {
319
321
  if (currentVersion !== entry.workingVersion) {
320
322
  changes.push({
321
323
  path: entry.path,
322
- resource: entry.resource ?? resolveWorkspaceResource(this.manifest.workspace, entry.path),
324
+ resource: entry.resource ?? (0, SolidFsPathUtils_1.resolveWorkspaceResource)(this.manifest.workspace, entry.path),
323
325
  source: entry.source,
324
326
  sourcePath: entry.sourcePath,
325
327
  contentType: entry.contentType,
@@ -330,16 +332,16 @@ class LocalMaterializedWorkspace {
330
332
  entry.state = 'dirty';
331
333
  }
332
334
  }
333
- for (const snapshot of await snapshotDirectory(this.cwd)) {
335
+ for (const snapshot of await (0, SolidFsPathUtils_1.snapshotDirectory)(this.cwd)) {
334
336
  if (tracked.has(snapshot.relativePath)) {
335
337
  continue;
336
338
  }
337
339
  this.manifest.entries.push({
338
340
  path: snapshot.relativePath,
339
- resource: resolveWorkspaceResource(this.manifest.workspace, snapshot.relativePath),
341
+ resource: (0, SolidFsPathUtils_1.resolveWorkspaceResource)(this.manifest.workspace, snapshot.relativePath),
340
342
  source: this.entrySource,
341
343
  sourcePath: snapshot.absolutePath,
342
- contentType: contentTypeForPath(snapshot.relativePath),
344
+ contentType: (0, SolidFsPathUtils_1.contentTypeForPath)(snapshot.relativePath),
343
345
  projection: this.projection,
344
346
  workingVersion: snapshot.version,
345
347
  lastAccessedAt: Date.now(),
@@ -347,10 +349,10 @@ class LocalMaterializedWorkspace {
347
349
  });
348
350
  changes.push({
349
351
  path: snapshot.relativePath,
350
- resource: resolveWorkspaceResource(this.manifest.workspace, snapshot.relativePath),
352
+ resource: (0, SolidFsPathUtils_1.resolveWorkspaceResource)(this.manifest.workspace, snapshot.relativePath),
351
353
  source: this.entrySource,
352
354
  sourcePath: snapshot.absolutePath,
353
- contentType: contentTypeForPath(snapshot.relativePath),
355
+ contentType: (0, SolidFsPathUtils_1.contentTypeForPath)(snapshot.relativePath),
354
356
  projection: this.projection,
355
357
  type: 'created',
356
358
  });
@@ -365,7 +367,7 @@ class LocalMaterializedWorkspace {
365
367
  if (!entry.sourceVersion) {
366
368
  continue;
367
369
  }
368
- const currentVersion = await maybeFileVersion(entry.sourcePath);
370
+ const currentVersion = await (0, SolidFsPathUtils_1.maybeFileVersion)(entry.sourcePath);
369
371
  if (currentVersion !== entry.sourceVersion) {
370
372
  conflicts.push({
371
373
  path: entry.path,
@@ -376,7 +378,7 @@ class LocalMaterializedWorkspace {
376
378
  });
377
379
  }
378
380
  }
379
- const currentSourceFiles = await snapshotDirectory(this.sourceRoot);
381
+ const currentSourceFiles = await (0, SolidFsPathUtils_1.snapshotDirectory)(this.sourceRoot);
380
382
  for (const current of currentSourceFiles) {
381
383
  if (!initialPaths.has(current.relativePath)) {
382
384
  conflicts.push({
@@ -394,7 +396,7 @@ class LocalMaterializedWorkspace {
394
396
  if (before.size === 0 && this.projection === 'direct' && !this.changeFilter) {
395
397
  return [];
396
398
  }
397
- const after = new Map((await snapshotDirectory(this.cwd, this.changeFilter)).map((snapshot) => [snapshot.relativePath, snapshot]));
399
+ const after = new Map((await (0, SolidFsPathUtils_1.snapshotDirectory)(this.cwd, this.changeFilter)).map((snapshot) => [snapshot.relativePath, snapshot]));
398
400
  const changes = [];
399
401
  for (const [relativePath, snapshot] of after) {
400
402
  const entry = before.get(relativePath);
@@ -416,10 +418,10 @@ class LocalMaterializedWorkspace {
416
418
  createChange(relativePath, sourcePath, type) {
417
419
  return {
418
420
  path: relativePath,
419
- resource: resolveWorkspaceResource(this.manifest.workspace, relativePath),
421
+ resource: (0, SolidFsPathUtils_1.resolveWorkspaceResource)(this.manifest.workspace, relativePath),
420
422
  source: this.entrySource,
421
423
  sourcePath,
422
- contentType: contentTypeForPath(relativePath),
424
+ contentType: (0, SolidFsPathUtils_1.contentTypeForPath)(relativePath),
423
425
  projection: this.projection,
424
426
  type,
425
427
  };
@@ -438,102 +440,7 @@ class LocalMaterializedWorkspace {
438
440
  }
439
441
  }
440
442
  }
441
- function contentTypeForPath(filePath) {
442
- const lower = filePath.toLowerCase();
443
- const rdfContentType = (0, RdfContentTypes_1.rdfContentTypeForPath)(lower);
444
- if (rdfContentType) {
445
- return rdfContentType;
446
- }
447
- if (lower.endsWith('.md') || lower.endsWith('.markdown') || lower.endsWith('.mdown')) {
448
- return 'text/markdown';
449
- }
450
- if (lower.endsWith('.txt') || lower.endsWith('.log')) {
451
- return 'text/plain';
452
- }
453
- return undefined;
454
- }
455
- function sourceForProjection(projection, workspace) {
456
- if (projection === 'hydrated-object') {
457
- return 'object';
458
- }
459
- if (/^https?:/u.test(workspace)) {
460
- return 'pod-http';
461
- }
462
- return 'filesystem';
463
- }
464
- function resolveWorkspaceResource(workspace, relativePath) {
465
- if (node_path_1.default.isAbsolute(workspace)) {
466
- return (0, node_url_1.pathToFileURL)(node_path_1.default.join(workspace, relativePath)).href;
467
- }
468
- try {
469
- const base = new URL(workspace.endsWith('/') ? workspace : `${workspace}/`);
470
- const normalized = relativePath.split(node_path_1.default.sep).join('/');
471
- return new URL(normalized, base).href;
472
- }
473
- catch {
474
- return undefined;
475
- }
476
- }
477
443
  function isLineAddressableRdfPath(filePath) {
478
444
  return (0, RdfContentTypes_1.isLineAddressableRdfPath)(filePath);
479
445
  }
480
- function safeRelativePath(input) {
481
- const normalized = input.split(/[\\/]+/u).filter((part) => part.length > 0).join(node_path_1.default.sep);
482
- if (!normalized || node_path_1.default.isAbsolute(input) || normalized.split(node_path_1.default.sep).includes('..')) {
483
- throw new Error(`Invalid SolidFS relative path: ${input}`);
484
- }
485
- return normalized;
486
- }
487
- async function maybeFileVersion(filePath) {
488
- try {
489
- return await fileVersion(filePath);
490
- }
491
- catch {
492
- return undefined;
493
- }
494
- }
495
- async function fileVersion(filePath) {
496
- const fileStat = await (0, promises_1.stat)(filePath);
497
- const hash = (0, node_crypto_1.createHash)('sha256');
498
- await new Promise((resolve, reject) => {
499
- const stream = (0, node_fs_1.createReadStream)(filePath);
500
- stream.on('data', (chunk) => hash.update(chunk));
501
- stream.on('error', reject);
502
- stream.on('end', resolve);
503
- });
504
- return `${fileStat.size}:${fileStat.mtimeMs}:${hash.digest('hex')}`;
505
- }
506
- async function snapshotDirectory(root, filter) {
507
- const snapshots = [];
508
- async function walk(current) {
509
- let entries;
510
- try {
511
- entries = await (0, promises_1.readdir)(current, { withFileTypes: true });
512
- }
513
- catch {
514
- return;
515
- }
516
- for (const entry of entries) {
517
- const absolute = node_path_1.default.join(current, entry.name);
518
- const relative = node_path_1.default.relative(root, absolute);
519
- if (entry.isDirectory()) {
520
- await walk(absolute);
521
- continue;
522
- }
523
- if (!entry.isFile()) {
524
- continue;
525
- }
526
- if (filter && !filter(relative)) {
527
- continue;
528
- }
529
- snapshots.push({
530
- relativePath: relative,
531
- absolutePath: absolute,
532
- version: await fileVersion(absolute),
533
- });
534
- }
535
- }
536
- await walk(root);
537
- return snapshots.sort((left, right) => left.relativePath.localeCompare(right.relativePath));
538
- }
539
446
  //# sourceMappingURL=LocalSolidFS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LocalSolidFS.js","sourceRoot":"","sources":["../../src/solidfs/LocalSolidFS.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport { createReadStream } from 'node:fs';\nimport {\n cp,\n mkdir,\n mkdtemp,\n readdir,\n rm,\n stat,\n} from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport {\n MaterializedWorkspace,\n SolidFS,\n SolidFsChange,\n SolidFsConflict,\n SolidFsConflictError,\n SolidFsEntrySource,\n SolidFsHydrator,\n SolidFsManifest,\n SolidFsManifestEntry,\n SolidFsPrepareInput,\n SolidFsPruneOptions,\n SolidFsProjection,\n SolidFsSyncer,\n} from './types';\nimport {\n isLineAddressableRdfPath as isRdfPath,\n rdfContentTypeForPath,\n} from '../storage/rdf/RdfContentTypes';\n\ninterface FileSnapshot {\n relativePath: string;\n absolutePath: string;\n version: string;\n}\n\nexport interface LocalSolidFSOptions {\n workRoot?: string;\n syncer?: SolidFsSyncer;\n hydrator?: SolidFsHydrator;\n}\n\nexport class LocalSolidFS implements SolidFS {\n private readonly workRoot: string;\n private readonly syncer?: SolidFsSyncer;\n private readonly hydrator?: SolidFsHydrator;\n\n public constructor(options: LocalSolidFSOptions = {}) {\n this.workRoot = options.workRoot ?? path.join(os.tmpdir(), 'xpod-solidfs');\n this.syncer = options.syncer;\n this.hydrator = options.hydrator;\n }\n\n public async prepare(input: SolidFsPrepareInput): Promise<MaterializedWorkspace> {\n const sourceRoot = input.sourcePath\n ? path.resolve(input.sourcePath)\n : this.resolveWorkspacePath(input.workspace);\n const projection = input.projection ?? 'direct';\n\n await this.assertSourceDirectory(sourceRoot);\n\n if (projection === 'direct') {\n const trackChanges = this.syncer?.shouldTrack?.(input) ?? Boolean(this.syncer);\n const syncer = this.syncer;\n const changeFilter = trackChanges\n ? syncer?.shouldTrackPath\n ? (relativePath: string): boolean => syncer.shouldTrackPath!(relativePath)\n : isLineAddressableRdfPath\n : undefined;\n const entries = changeFilter ? await snapshotDirectory(sourceRoot, changeFilter) : [];\n return new LocalMaterializedWorkspace({\n sourceRoot,\n cwd: sourceRoot,\n projection,\n cleanupOnRollback: false,\n manifest: this.createManifest(input.workspace, sourceRoot, projection, entries),\n changeFilter,\n context: input.context,\n syncer: this.syncer,\n hydrator: this.hydrator,\n });\n }\n\n if (projection === 'hydrated-object') {\n const cwd = await this.createHydratedWorkdir(sourceRoot, input.run?.id);\n return new LocalMaterializedWorkspace({\n sourceRoot,\n cwd,\n projection,\n cleanupOnRollback: true,\n manifest: this.createManifest(input.workspace, cwd, projection, []),\n context: input.context,\n hydrator: this.hydrator,\n });\n }\n\n if (projection !== 'copy') {\n throw new Error(`LocalSolidFS does not support projection '${projection}' yet.`);\n }\n\n const cwd = await this.createCopyWorkdir(sourceRoot, input.run?.id);\n const entries = await snapshotDirectory(sourceRoot);\n await cp(sourceRoot, cwd, {\n recursive: true,\n force: true,\n errorOnExist: false,\n dereference: false,\n });\n\n return new LocalMaterializedWorkspace({\n sourceRoot,\n cwd,\n projection,\n cleanupOnRollback: true,\n manifest: this.createManifest(input.workspace, cwd, projection, entries),\n context: input.context,\n syncer: this.syncer,\n hydrator: this.hydrator,\n });\n }\n\n private resolveWorkspacePath(workspace: string): string {\n if (workspace.startsWith('file://')) {\n const url = new URL(workspace);\n const pathname = decodeURIComponent(url.pathname);\n if (process.platform === 'win32' && /^\\/[A-Za-z]:/.test(pathname)) {\n return pathname.slice(1);\n }\n return pathname;\n }\n\n if (path.isAbsolute(workspace)) {\n return workspace;\n }\n\n throw new Error(`Unsupported workspace '${workspace}'. LocalSolidFS expects file:// or absolute paths.`);\n }\n\n private async createCopyWorkdir(sourceRoot: string, runId?: string): Promise<string> {\n const safeRun = (runId ?? 'run').replace(/[^a-zA-Z0-9._-]+/gu, '_');\n const prefix = path.join(this.workRoot, `${safeRun}-`);\n await mkdir(this.workRoot, { recursive: true });\n const cwd = await mkdtemp(prefix);\n\n const sourceName = path.basename(sourceRoot.replace(/[\\\\/]+$/u, '')) || 'workspace';\n return path.join(cwd, sourceName);\n }\n\n private async createHydratedWorkdir(sourceRoot: string, runId?: string): Promise<string> {\n const safeRun = (runId ?? 'run').replace(/[^a-zA-Z0-9._-]+/gu, '_');\n await mkdir(this.workRoot, { recursive: true });\n const cwd = await mkdtemp(path.join(this.workRoot, `${safeRun}-hydrated-`));\n const workspaceDir = path.join(cwd, path.basename(sourceRoot.replace(/[\\\\/]+$/u, '')) || 'workspace');\n await mkdir(workspaceDir, { recursive: true });\n return workspaceDir;\n }\n\n private createManifest(\n workspace: string,\n cwd: string,\n projection: SolidFsProjection,\n snapshots: FileSnapshot[],\n ): SolidFsManifest {\n const source = sourceForProjection(projection, workspace);\n return {\n workspace,\n cwd,\n projection,\n entries: snapshots.map((snapshot): SolidFsManifestEntry => ({\n path: snapshot.relativePath,\n resource: resolveWorkspaceResource(workspace, snapshot.relativePath),\n source,\n sourcePath: snapshot.absolutePath,\n projection,\n sourceVersion: snapshot.version,\n workingVersion: snapshot.version,\n state: 'clean',\n })),\n };\n }\n\n private async assertSourceDirectory(sourceRoot: string): Promise<void> {\n let sourceStat;\n try {\n sourceStat = await stat(sourceRoot);\n } catch (error: any) {\n if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') {\n throw new Error(`SolidFS workspace does not exist: ${sourceRoot}`);\n }\n throw error;\n }\n\n if (!sourceStat.isDirectory()) {\n throw new Error(`SolidFS workspace is not a directory: ${sourceRoot}`);\n }\n }\n\n}\n\ninterface LocalMaterializedWorkspaceOptions {\n sourceRoot: string;\n cwd: string;\n projection: SolidFsProjection;\n cleanupOnRollback: boolean;\n manifest: SolidFsManifest;\n changeFilter?: (relativePath: string) => boolean;\n context?: unknown;\n syncer?: SolidFsSyncer;\n hydrator?: SolidFsHydrator;\n}\n\nclass LocalMaterializedWorkspace implements MaterializedWorkspace {\n public readonly cwd: string;\n public readonly manifest: SolidFsManifest;\n\n private readonly sourceRoot: string;\n private readonly projection: SolidFsProjection;\n private readonly cleanupOnRollback: boolean;\n private readonly changeFilter?: (relativePath: string) => boolean;\n private readonly context?: unknown;\n private readonly syncer?: SolidFsSyncer;\n private readonly hydrator?: SolidFsHydrator;\n private readonly entrySource: SolidFsEntrySource;\n\n public constructor(options: LocalMaterializedWorkspaceOptions) {\n this.sourceRoot = options.sourceRoot;\n this.cwd = options.cwd;\n this.projection = options.projection;\n this.cleanupOnRollback = options.cleanupOnRollback;\n this.manifest = options.manifest;\n this.changeFilter = options.changeFilter;\n this.context = options.context;\n this.syncer = options.syncer;\n this.hydrator = options.hydrator;\n this.entrySource = sourceForProjection(this.projection, this.manifest.workspace);\n }\n\n public async commit(): Promise<SolidFsManifest> {\n if (this.projection === 'hydrated-object') {\n return this.commitHydratedObjects();\n }\n\n const changes = await this.detectChanges();\n this.manifest.changes = changes;\n\n if (this.projection === 'direct') {\n await this.syncChanges(changes);\n this.markCommitted();\n return this.manifest;\n }\n\n if (this.projection !== 'copy') {\n throw new Error(`Commit is not implemented for projection '${this.projection}'.`);\n }\n\n const conflicts = await this.findConflicts();\n if (conflicts.length > 0) {\n for (const entry of this.manifest.entries) {\n if (conflicts.some((conflict) => conflict.path === entry.path)) {\n entry.state = 'conflict';\n }\n }\n throw new SolidFsConflictError(conflicts);\n }\n\n await rm(this.sourceRoot, { recursive: true, force: true });\n await cp(this.cwd, this.sourceRoot, {\n recursive: true,\n force: true,\n errorOnExist: false,\n dereference: false,\n });\n await this.syncChanges(changes);\n this.markCommitted();\n return this.manifest;\n }\n\n public async rollback(): Promise<void> {\n if (this.cleanupOnRollback) {\n await rm(path.dirname(this.cwd), { recursive: true, force: true });\n }\n }\n\n public async hydrate(relativePath: string): Promise<SolidFsManifestEntry> {\n if (this.projection !== 'hydrated-object') {\n throw new Error(`hydrate() is only supported for hydrated-object projection, not '${this.projection}'`);\n }\n if (!this.hydrator) {\n throw new Error('SolidFS hydrated-object projection requires a hydrator');\n }\n\n const normalized = safeRelativePath(relativePath);\n const targetPath = path.join(this.cwd, normalized);\n await mkdir(path.dirname(targetPath), { recursive: true });\n\n const result = await this.hydrator.hydrate({\n path: normalized,\n targetPath,\n workspace: this.manifest,\n context: this.context,\n });\n\n const workingVersion = await fileVersion(targetPath);\n let entry = this.manifest.entries.find((candidate) => candidate.path === normalized);\n if (!entry) {\n entry = {\n path: normalized,\n resource: resolveWorkspaceResource(this.manifest.workspace, normalized),\n source: this.entrySource,\n sourcePath: targetPath,\n contentType: result?.contentType ?? contentTypeForPath(normalized),\n projection: this.projection,\n sourceVersion: result?.sourceVersion,\n workingVersion,\n lastAccessedAt: Date.now(),\n state: 'clean',\n };\n this.manifest.entries.push(entry);\n this.manifest.entries.sort((left, right) => left.path.localeCompare(right.path));\n return entry;\n }\n\n entry.sourcePath = targetPath;\n entry.contentType = result?.contentType ?? entry.contentType ?? contentTypeForPath(normalized);\n entry.sourceVersion = result?.sourceVersion ?? entry.sourceVersion;\n entry.workingVersion = workingVersion;\n entry.lastAccessedAt = Date.now();\n entry.state = 'clean';\n return entry;\n }\n\n public async prune(options: SolidFsPruneOptions = {}): Promise<SolidFsManifest> {\n if (this.projection !== 'hydrated-object') {\n return this.manifest;\n }\n\n const now = options.now ?? Date.now();\n const olderThanMs = options.olderThanMs ?? 0;\n const retained: SolidFsManifestEntry[] = [];\n\n for (const entry of this.manifest.entries) {\n const currentVersion = await maybeFileVersion(entry.sourcePath);\n const dirty = currentVersion !== undefined && currentVersion !== entry.workingVersion;\n if (dirty) {\n entry.state = 'dirty';\n retained.push(entry);\n continue;\n }\n\n const age = now - (entry.lastAccessedAt ?? now);\n if (age >= olderThanMs) {\n await rm(entry.sourcePath, { force: true });\n continue;\n }\n retained.push(entry);\n }\n\n this.manifest.entries = retained;\n return this.manifest;\n }\n\n private async commitHydratedObjects(): Promise<SolidFsManifest> {\n if (!this.hydrator) {\n throw new Error('SolidFS hydrated-object projection requires a hydrator');\n }\n\n const changes = await this.detectHydratedChanges();\n this.manifest.changes = changes;\n\n for (const change of changes) {\n if (change.type === 'deleted' && this.hydrator.delete) {\n await this.hydrator.delete({\n change,\n workspace: this.manifest,\n context: this.context,\n });\n this.manifest.entries = this.manifest.entries.filter((entry) => entry.path !== change.path);\n continue;\n }\n if (change.type !== 'deleted') {\n const result = await this.hydrator.commit({\n change,\n workspace: this.manifest,\n context: this.context,\n });\n const entry = this.manifest.entries.find((candidate) => candidate.path === change.path);\n if (entry) {\n entry.sourceVersion = result?.sourceVersion ?? entry.sourceVersion;\n entry.workingVersion = await fileVersion(entry.sourcePath);\n entry.lastAccessedAt = Date.now();\n }\n }\n }\n\n this.markCommitted();\n return this.manifest;\n }\n\n private async detectHydratedChanges(): Promise<SolidFsChange[]> {\n const changes: SolidFsChange[] = [];\n const tracked = new Set(this.manifest.entries.map((entry) => entry.path));\n for (const entry of this.manifest.entries) {\n const currentVersion = await maybeFileVersion(entry.sourcePath);\n if (currentVersion === undefined) {\n changes.push({\n path: entry.path,\n resource: entry.resource ?? resolveWorkspaceResource(this.manifest.workspace, entry.path),\n source: entry.source,\n sourcePath: entry.sourcePath,\n contentType: entry.contentType,\n projection: this.projection,\n type: 'deleted',\n sourceVersion: entry.sourceVersion,\n });\n entry.state = 'dirty';\n continue;\n }\n if (currentVersion !== entry.workingVersion) {\n changes.push({\n path: entry.path,\n resource: entry.resource ?? resolveWorkspaceResource(this.manifest.workspace, entry.path),\n source: entry.source,\n sourcePath: entry.sourcePath,\n contentType: entry.contentType,\n projection: this.projection,\n type: 'updated',\n sourceVersion: entry.sourceVersion,\n });\n entry.state = 'dirty';\n }\n }\n\n for (const snapshot of await snapshotDirectory(this.cwd)) {\n if (tracked.has(snapshot.relativePath)) {\n continue;\n }\n this.manifest.entries.push({\n path: snapshot.relativePath,\n resource: resolveWorkspaceResource(this.manifest.workspace, snapshot.relativePath),\n source: this.entrySource,\n sourcePath: snapshot.absolutePath,\n contentType: contentTypeForPath(snapshot.relativePath),\n projection: this.projection,\n workingVersion: snapshot.version,\n lastAccessedAt: Date.now(),\n state: 'dirty',\n });\n changes.push({\n path: snapshot.relativePath,\n resource: resolveWorkspaceResource(this.manifest.workspace, snapshot.relativePath),\n source: this.entrySource,\n sourcePath: snapshot.absolutePath,\n contentType: contentTypeForPath(snapshot.relativePath),\n projection: this.projection,\n type: 'created',\n });\n }\n this.manifest.entries.sort((left, right) => left.path.localeCompare(right.path));\n return changes.sort((left, right) => left.path.localeCompare(right.path));\n }\n\n private async findConflicts(): Promise<SolidFsConflict[]> {\n const conflicts: SolidFsConflict[] = [];\n const initialPaths = new Set(this.manifest.entries.map((entry) => entry.path));\n\n for (const entry of this.manifest.entries) {\n if (!entry.sourceVersion) {\n continue;\n }\n const currentVersion = await maybeFileVersion(entry.sourcePath);\n if (currentVersion !== entry.sourceVersion) {\n conflicts.push({\n path: entry.path,\n sourcePath: entry.sourcePath,\n expectedVersion: entry.sourceVersion,\n actualVersion: currentVersion,\n message: 'Source file changed after workspace prepare.',\n });\n }\n }\n\n const currentSourceFiles = await snapshotDirectory(this.sourceRoot);\n for (const current of currentSourceFiles) {\n if (!initialPaths.has(current.relativePath)) {\n conflicts.push({\n path: current.relativePath,\n sourcePath: current.absolutePath,\n actualVersion: current.version,\n message: 'Source file was created after workspace prepare.',\n });\n }\n }\n return conflicts;\n }\n\n private async detectChanges(): Promise<SolidFsChange[]> {\n const before = new Map(this.manifest.entries.map((entry) => [entry.path, entry]));\n if (before.size === 0 && this.projection === 'direct' && !this.changeFilter) {\n return [];\n }\n const after = new Map((await snapshotDirectory(this.cwd, this.changeFilter)).map((snapshot) => [snapshot.relativePath, snapshot]));\n const changes: SolidFsChange[] = [];\n\n for (const [relativePath, snapshot] of after) {\n const entry = before.get(relativePath);\n if (!entry) {\n changes.push(this.createChange(relativePath, snapshot.absolutePath, 'created'));\n continue;\n }\n if (entry.sourceVersion !== snapshot.version) {\n changes.push(this.createChange(relativePath, snapshot.absolutePath, 'updated'));\n }\n }\n\n for (const [relativePath, entry] of before) {\n if (!after.has(relativePath)) {\n changes.push(this.createChange(relativePath, entry.sourcePath, 'deleted'));\n }\n }\n\n return changes.sort((left, right) => left.path.localeCompare(right.path));\n }\n\n private createChange(\n relativePath: string,\n sourcePath: string,\n type: SolidFsChange['type'],\n ): SolidFsChange {\n return {\n path: relativePath,\n resource: resolveWorkspaceResource(this.manifest.workspace, relativePath),\n source: this.entrySource,\n sourcePath,\n contentType: contentTypeForPath(relativePath),\n projection: this.projection,\n type,\n };\n }\n\n private async syncChanges(changes: SolidFsChange[]): Promise<void> {\n if (!this.syncer) {\n return;\n }\n for (const change of changes) {\n await this.syncer.sync(change, this.manifest, this.context);\n }\n }\n\n private markCommitted(): void {\n for (const entry of this.manifest.entries) {\n entry.state = 'committed';\n }\n }\n}\n\nfunction contentTypeForPath(filePath: string): string | undefined {\n const lower = filePath.toLowerCase();\n const rdfContentType = rdfContentTypeForPath(lower);\n if (rdfContentType) {\n return rdfContentType;\n }\n if (lower.endsWith('.md') || lower.endsWith('.markdown') || lower.endsWith('.mdown')) {\n return 'text/markdown';\n }\n if (lower.endsWith('.txt') || lower.endsWith('.log')) {\n return 'text/plain';\n }\n return undefined;\n}\n\nfunction sourceForProjection(projection: SolidFsProjection, workspace: string): SolidFsEntrySource {\n if (projection === 'hydrated-object') {\n return 'object';\n }\n if (/^https?:/u.test(workspace)) {\n return 'pod-http';\n }\n return 'filesystem';\n}\n\nfunction resolveWorkspaceResource(workspace: string, relativePath: string): string | undefined {\n if (path.isAbsolute(workspace)) {\n return pathToFileURL(path.join(workspace, relativePath)).href;\n }\n\n try {\n const base = new URL(workspace.endsWith('/') ? workspace : `${workspace}/`);\n const normalized = relativePath.split(path.sep).join('/');\n return new URL(normalized, base).href;\n } catch {\n return undefined;\n }\n}\n\nfunction isLineAddressableRdfPath(filePath: string): boolean {\n return isRdfPath(filePath);\n}\n\nfunction safeRelativePath(input: string): string {\n const normalized = input.split(/[\\\\/]+/u).filter((part) => part.length > 0).join(path.sep);\n if (!normalized || path.isAbsolute(input) || normalized.split(path.sep).includes('..')) {\n throw new Error(`Invalid SolidFS relative path: ${input}`);\n }\n return normalized;\n}\n\nasync function maybeFileVersion(filePath: string): Promise<string | undefined> {\n try {\n return await fileVersion(filePath);\n } catch {\n return undefined;\n }\n}\n\nasync function fileVersion(filePath: string): Promise<string> {\n const fileStat = await stat(filePath);\n const hash = createHash('sha256');\n await new Promise<void>((resolve, reject) => {\n const stream = createReadStream(filePath);\n stream.on('data', (chunk) => hash.update(chunk));\n stream.on('error', reject);\n stream.on('end', resolve);\n });\n return `${fileStat.size}:${fileStat.mtimeMs}:${hash.digest('hex')}`;\n}\n\nasync function snapshotDirectory(\n root: string,\n filter?: (relativePath: string) => boolean,\n): Promise<FileSnapshot[]> {\n const snapshots: FileSnapshot[] = [];\n\n async function walk(current: string): Promise<void> {\n let entries;\n try {\n entries = await readdir(current, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const absolute = path.join(current, entry.name);\n const relative = path.relative(root, absolute);\n if (entry.isDirectory()) {\n await walk(absolute);\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n if (filter && !filter(relative)) {\n continue;\n }\n snapshots.push({\n relativePath: relative,\n absolutePath: absolute,\n version: await fileVersion(absolute),\n });\n }\n }\n\n await walk(root);\n return snapshots.sort((left, right) => left.relativePath.localeCompare(right.relativePath));\n}\n"]}
1
+ {"version":3,"file":"LocalSolidFS.js","sourceRoot":"","sources":["../../src/solidfs/LocalSolidFS.ts"],"names":[],"mappings":";;;;;;AAAA,+CAM0B;AAC1B,sDAAyB;AACzB,0DAA6B;AAE7B,mCAciB;AACjB,oEAEwC;AACxC,yDAS4B;AAQ5B,MAAa,YAAY;IAKvB,YAAmB,UAA+B,EAAE;QAClD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,mBAAI,CAAC,IAAI,CAAC,iBAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACnC,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,KAA0B;QAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU;YACjC,CAAC,CAAC,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,QAAQ,CAAC;QAEhD,MAAM,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;QAE7C,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,MAAM,YAAY,GAAG,YAAY;gBAC/B,CAAC,CAAC,MAAM,EAAE,eAAe;oBACvB,CAAC,CAAC,CAAC,YAAoB,EAAW,EAAE,CAAC,MAAM,CAAC,eAAgB,CAAC,YAAY,CAAC;oBAC1E,CAAC,CAAC,wBAAwB;gBAC5B,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,IAAA,oCAAiB,EAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YACvF,IAAI,YAAY,IAAI,MAAM,EAAE,mBAAmB,EAAE,CAAC;gBAChD,MAAM,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,IAAI,0BAA0B,CAAC;gBACpC,UAAU;gBACV,GAAG,EAAE,UAAU;gBACf,UAAU;gBACV,iBAAiB,EAAE,KAAK;gBACxB,QAAQ;gBACR,YAAY;gBACZ,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,UAAU,KAAK,iBAAiB,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACxE,OAAO,IAAI,0BAA0B,CAAC;gBACpC,UAAU;gBACV,GAAG;gBACH,UAAU;gBACV,iBAAiB,EAAE,IAAI;gBACvB,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,CAAC;gBACnE,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,6CAA6C,UAAU,QAAQ,CAAC,CAAC;QACnF,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,IAAA,oCAAiB,EAAC,UAAU,CAAC,CAAC;QACpD,MAAM,IAAA,aAAE,EAAC,UAAU,EAAE,GAAG,EAAE;YACxB,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;QAEH,OAAO,IAAI,0BAA0B,CAAC;YACpC,UAAU;YACV,GAAG;YACH,UAAU;YACV,iBAAiB,EAAE,IAAI;YACvB,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC;YACxE,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;IACL,CAAC;IAEO,oBAAoB,CAAC,SAAiB;QAC5C,IAAI,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAClD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,mBAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,oDAAoD,CAAC,CAAC;IAC3G,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,UAAkB,EAAE,KAAc;QAChE,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC;QACvD,MAAM,IAAA,gBAAK,EAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,IAAA,kBAAO,EAAC,MAAM,CAAC,CAAC;QAElC,MAAM,UAAU,GAAG,mBAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC;QACpF,OAAO,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACpC,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,UAAkB,EAAE,KAAc;QACpE,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;QACpE,MAAM,IAAA,gBAAK,EAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,IAAA,kBAAO,EAAC,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,OAAO,YAAY,CAAC,CAAC,CAAC;QAC5E,MAAM,YAAY,GAAG,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC;QACtG,MAAM,IAAA,gBAAK,EAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO,YAAY,CAAC;IACtB,CAAC;IAEO,cAAc,CACpB,SAAiB,EACjB,GAAW,EACX,UAA6B,EAC7B,SAAgC;QAEhC,MAAM,MAAM,GAAG,IAAA,sCAAmB,EAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC1D,OAAO;YACL,SAAS;YACT,GAAG;YACH,UAAU;YACV,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAwB,EAAE,CAAC,CAAC;gBAC1D,IAAI,EAAE,QAAQ,CAAC,YAAY;gBAC3B,QAAQ,EAAE,IAAA,2CAAwB,EAAC,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC;gBACpE,MAAM;gBACN,UAAU,EAAE,QAAQ,CAAC,YAAY;gBACjC,UAAU;gBACV,aAAa,EAAE,QAAQ,CAAC,OAAO;gBAC/B,cAAc,EAAE,QAAQ,CAAC,OAAO;gBAChC,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,UAAkB;QACpD,IAAI,UAAU,CAAC;QACf,IAAI,CAAC;YACH,UAAU,GAAG,MAAM,IAAA,eAAI,EAAC,UAAU,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,qCAAqC,UAAU,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yCAAyC,UAAU,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;CAEF;AA/JD,oCA+JC;AAcD,MAAM,0BAA0B;IAa9B,YAAmB,OAA0C;QAC3D,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,IAAA,sCAAmB,EAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnF,CAAC;IAEM,KAAK,CAAC,MAAM;QACjB,IAAI,IAAI,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACtC,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3C,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;QAEhC,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,6CAA6C,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC7C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAC1C,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/D,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC;gBAC3B,CAAC;YACH,CAAC;YACD,MAAM,IAAI,4BAAoB,CAAC,SAAS,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,IAAA,aAAE,EAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,IAAA,aAAE,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE;YAClC,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,MAAM,IAAA,aAAE,EAAC,mBAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,YAAoB;QACvC,IAAI,IAAI,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,oEAAoE,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QAC1G,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,mCAAgB,EAAC,YAAY,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACnD,MAAM,IAAA,gBAAK,EAAC,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YACzC,IAAI,EAAE,UAAU;YAChB,UAAU;YACV,SAAS,EAAE,IAAI,CAAC,QAAQ;YACxB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,MAAM,IAAA,8BAAW,EAAC,UAAU,CAAC,CAAC;QACrD,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACrF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG;gBACN,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,IAAA,2CAAwB,EAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;gBACvE,MAAM,EAAE,IAAI,CAAC,WAAW;gBACxB,UAAU,EAAE,UAAU;gBACtB,WAAW,EAAE,MAAM,EAAE,WAAW,IAAI,IAAA,qCAAkB,EAAC,UAAU,CAAC;gBAClE,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,aAAa,EAAE,MAAM,EAAE,aAAa;gBACpC,cAAc;gBACd,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE;gBAC1B,KAAK,EAAE,OAAO;aACf,CAAC;YACF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YACjF,OAAO,KAAK,CAAC;QACf,CAAC;QAED,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;QAC9B,KAAK,CAAC,WAAW,GAAG,MAAM,EAAE,WAAW,IAAI,KAAK,CAAC,WAAW,IAAI,IAAA,qCAAkB,EAAC,UAAU,CAAC,CAAC;QAC/F,KAAK,CAAC,aAAa,GAAG,MAAM,EAAE,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC;QACnE,KAAK,CAAC,cAAc,GAAG,cAAc,CAAC;QACtC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,UAA+B,EAAE;QAClD,IAAI,IAAI,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACtC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAA2B,EAAE,CAAC;QAE5C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC1C,MAAM,cAAc,GAAG,MAAM,IAAA,mCAAgB,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAChE,MAAM,KAAK,GAAG,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,KAAK,CAAC,cAAc,CAAC;YACtF,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,SAAS;YACX,CAAC;YAED,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,IAAI,GAAG,CAAC,CAAC;YAChD,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;gBACvB,MAAM,IAAA,aAAE,EAAC,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5C,SAAS;YACX,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,qBAAqB;QACjC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACnD,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;QAEhC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACtD,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACzB,MAAM;oBACN,SAAS,EAAE,IAAI,CAAC,QAAQ;oBACxB,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC,CAAC;gBACH,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC5F,SAAS;YACX,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACxC,MAAM;oBACN,SAAS,EAAE,IAAI,CAAC,QAAQ;oBACxB,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;gBACxF,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,CAAC,aAAa,GAAG,MAAM,EAAE,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC;oBACnE,KAAK,CAAC,cAAc,GAAG,MAAM,IAAA,8BAAW,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;oBAC3D,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,qBAAqB;QACjC,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC1C,MAAM,cAAc,GAAG,MAAM,IAAA,mCAAgB,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAChE,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAA,2CAAwB,EAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC;oBACzF,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,IAAI,EAAE,SAAS;oBACf,aAAa,EAAE,KAAK,CAAC,aAAa;iBACnC,CAAC,CAAC;gBACH,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,IAAI,cAAc,KAAK,KAAK,CAAC,cAAc,EAAE,CAAC;gBAC5C,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAA,2CAAwB,EAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC;oBACzF,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,IAAI,EAAE,SAAS;oBACf,aAAa,EAAE,KAAK,CAAC,aAAa;iBACnC,CAAC,CAAC;gBACH,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;YACxB,CAAC;QACH,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,MAAM,IAAA,oCAAiB,EAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACzD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACvC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE,QAAQ,CAAC,YAAY;gBAC3B,QAAQ,EAAE,IAAA,2CAAwB,EAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC;gBAClF,MAAM,EAAE,IAAI,CAAC,WAAW;gBACxB,UAAU,EAAE,QAAQ,CAAC,YAAY;gBACjC,WAAW,EAAE,IAAA,qCAAkB,EAAC,QAAQ,CAAC,YAAY,CAAC;gBACtD,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,cAAc,EAAE,QAAQ,CAAC,OAAO;gBAChC,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE;gBAC1B,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,QAAQ,CAAC,YAAY;gBAC3B,QAAQ,EAAE,IAAA,2CAAwB,EAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC;gBAClF,MAAM,EAAE,IAAI,CAAC,WAAW;gBACxB,UAAU,EAAE,QAAQ,CAAC,YAAY;gBACjC,WAAW,EAAE,IAAA,qCAAkB,EAAC,QAAQ,CAAC,YAAY,CAAC;gBACtD,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,IAAI,EAAE,SAAS;aAChB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACjF,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,MAAM,SAAS,GAAsB,EAAE,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAE/E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,MAAM,cAAc,GAAG,MAAM,IAAA,mCAAgB,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAChE,IAAI,cAAc,KAAK,KAAK,CAAC,aAAa,EAAE,CAAC;gBAC3C,SAAS,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,eAAe,EAAE,KAAK,CAAC,aAAa;oBACpC,aAAa,EAAE,cAAc;oBAC7B,OAAO,EAAE,8CAA8C;iBACxD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,kBAAkB,GAAG,MAAM,IAAA,oCAAiB,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC5C,SAAS,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,OAAO,CAAC,YAAY;oBAC1B,UAAU,EAAE,OAAO,CAAC,YAAY;oBAChC,aAAa,EAAE,OAAO,CAAC,OAAO;oBAC9B,OAAO,EAAE,kDAAkD;iBAC5D,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAClF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC5E,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,IAAA,oCAAiB,EAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QACnI,MAAM,OAAO,GAAoB,EAAE,CAAC;QAEpC,KAAK,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;gBAChF,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,aAAa,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAC7C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;YAClF,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEO,YAAY,CAClB,YAAoB,EACpB,UAAkB,EAClB,IAA2B;QAE3B,OAAO;YACL,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,IAAA,2CAAwB,EAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;YACzE,MAAM,EAAE,IAAI,CAAC,WAAW;YACxB,UAAU;YACV,WAAW,EAAE,IAAA,qCAAkB,EAAC,YAAY,CAAC;YAC7C,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI;SACL,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,OAAwB;QAChD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC1C,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC;QAC5B,CAAC;IACH,CAAC;CACF;AAED,SAAS,wBAAwB,CAAC,QAAgB;IAChD,OAAO,IAAA,0CAAS,EAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import {\n cp,\n mkdir,\n mkdtemp,\n rm,\n stat,\n} from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport {\n MaterializedWorkspace,\n SolidFS,\n SolidFsChange,\n SolidFsConflict,\n SolidFsConflictError,\n SolidFsEntrySource,\n SolidFsHydrator,\n SolidFsManifest,\n SolidFsManifestEntry,\n SolidFsPrepareInput,\n SolidFsPruneOptions,\n SolidFsProjection,\n SolidFsSyncer,\n} from './types';\nimport {\n isLineAddressableRdfPath as isRdfPath,\n} from '../storage/rdf/RdfContentTypes';\nimport {\n contentTypeForPath,\n fileVersion,\n maybeFileVersion,\n resolveWorkspaceResource,\n safeRelativePath,\n snapshotDirectory,\n SolidFsFileSnapshot,\n sourceForProjection,\n} from './SolidFsPathUtils';\n\nexport interface LocalSolidFSOptions {\n workRoot?: string;\n syncer?: SolidFsSyncer;\n hydrator?: SolidFsHydrator;\n}\n\nexport class LocalSolidFS implements SolidFS {\n private readonly workRoot: string;\n private readonly syncer?: SolidFsSyncer;\n private readonly hydrator?: SolidFsHydrator;\n\n public constructor(options: LocalSolidFSOptions = {}) {\n this.workRoot = options.workRoot ?? path.join(os.tmpdir(), 'xpod-solidfs');\n this.syncer = options.syncer;\n this.hydrator = options.hydrator;\n }\n\n public async prepare(input: SolidFsPrepareInput): Promise<MaterializedWorkspace> {\n const sourceRoot = input.sourcePath\n ? path.resolve(input.sourcePath)\n : this.resolveWorkspacePath(input.workspace);\n const projection = input.projection ?? 'direct';\n\n await this.assertSourceDirectory(sourceRoot);\n\n if (projection === 'direct') {\n const trackChanges = this.syncer?.shouldTrack?.(input) ?? Boolean(this.syncer);\n const syncer = this.syncer;\n const changeFilter = trackChanges\n ? syncer?.shouldTrackPath\n ? (relativePath: string): boolean => syncer.shouldTrackPath!(relativePath)\n : isLineAddressableRdfPath\n : undefined;\n const entries = changeFilter ? await snapshotDirectory(sourceRoot, changeFilter) : [];\n const manifest = this.createManifest(input.workspace, sourceRoot, projection, entries);\n if (trackChanges && syncer?.initializeWorkspace) {\n await syncer.initializeWorkspace(manifest, input.context);\n }\n return new LocalMaterializedWorkspace({\n sourceRoot,\n cwd: sourceRoot,\n projection,\n cleanupOnRollback: false,\n manifest,\n changeFilter,\n context: input.context,\n syncer: this.syncer,\n hydrator: this.hydrator,\n });\n }\n\n if (projection === 'hydrated-object') {\n const cwd = await this.createHydratedWorkdir(sourceRoot, input.run?.id);\n return new LocalMaterializedWorkspace({\n sourceRoot,\n cwd,\n projection,\n cleanupOnRollback: true,\n manifest: this.createManifest(input.workspace, cwd, projection, []),\n context: input.context,\n hydrator: this.hydrator,\n });\n }\n\n if (projection !== 'copy') {\n throw new Error(`LocalSolidFS does not support projection '${projection}' yet.`);\n }\n\n const cwd = await this.createCopyWorkdir(sourceRoot, input.run?.id);\n const entries = await snapshotDirectory(sourceRoot);\n await cp(sourceRoot, cwd, {\n recursive: true,\n force: true,\n errorOnExist: false,\n dereference: false,\n });\n\n return new LocalMaterializedWorkspace({\n sourceRoot,\n cwd,\n projection,\n cleanupOnRollback: true,\n manifest: this.createManifest(input.workspace, cwd, projection, entries),\n context: input.context,\n syncer: this.syncer,\n hydrator: this.hydrator,\n });\n }\n\n private resolveWorkspacePath(workspace: string): string {\n if (workspace.startsWith('file://')) {\n const url = new URL(workspace);\n const pathname = decodeURIComponent(url.pathname);\n if (process.platform === 'win32' && /^\\/[A-Za-z]:/.test(pathname)) {\n return pathname.slice(1);\n }\n return pathname;\n }\n\n if (path.isAbsolute(workspace)) {\n return workspace;\n }\n\n throw new Error(`Unsupported workspace '${workspace}'. LocalSolidFS expects file:// or absolute paths.`);\n }\n\n private async createCopyWorkdir(sourceRoot: string, runId?: string): Promise<string> {\n const safeRun = (runId ?? 'run').replace(/[^a-zA-Z0-9._-]+/gu, '_');\n const prefix = path.join(this.workRoot, `${safeRun}-`);\n await mkdir(this.workRoot, { recursive: true });\n const cwd = await mkdtemp(prefix);\n\n const sourceName = path.basename(sourceRoot.replace(/[\\\\/]+$/u, '')) || 'workspace';\n return path.join(cwd, sourceName);\n }\n\n private async createHydratedWorkdir(sourceRoot: string, runId?: string): Promise<string> {\n const safeRun = (runId ?? 'run').replace(/[^a-zA-Z0-9._-]+/gu, '_');\n await mkdir(this.workRoot, { recursive: true });\n const cwd = await mkdtemp(path.join(this.workRoot, `${safeRun}-hydrated-`));\n const workspaceDir = path.join(cwd, path.basename(sourceRoot.replace(/[\\\\/]+$/u, '')) || 'workspace');\n await mkdir(workspaceDir, { recursive: true });\n return workspaceDir;\n }\n\n private createManifest(\n workspace: string,\n cwd: string,\n projection: SolidFsProjection,\n snapshots: SolidFsFileSnapshot[],\n ): SolidFsManifest {\n const source = sourceForProjection(projection, workspace);\n return {\n workspace,\n cwd,\n projection,\n entries: snapshots.map((snapshot): SolidFsManifestEntry => ({\n path: snapshot.relativePath,\n resource: resolveWorkspaceResource(workspace, snapshot.relativePath),\n source,\n sourcePath: snapshot.absolutePath,\n projection,\n sourceVersion: snapshot.version,\n workingVersion: snapshot.version,\n state: 'clean',\n })),\n };\n }\n\n private async assertSourceDirectory(sourceRoot: string): Promise<void> {\n let sourceStat;\n try {\n sourceStat = await stat(sourceRoot);\n } catch (error: any) {\n if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') {\n throw new Error(`SolidFS workspace does not exist: ${sourceRoot}`);\n }\n throw error;\n }\n\n if (!sourceStat.isDirectory()) {\n throw new Error(`SolidFS workspace is not a directory: ${sourceRoot}`);\n }\n }\n\n}\n\ninterface LocalMaterializedWorkspaceOptions {\n sourceRoot: string;\n cwd: string;\n projection: SolidFsProjection;\n cleanupOnRollback: boolean;\n manifest: SolidFsManifest;\n changeFilter?: (relativePath: string) => boolean;\n context?: unknown;\n syncer?: SolidFsSyncer;\n hydrator?: SolidFsHydrator;\n}\n\nclass LocalMaterializedWorkspace implements MaterializedWorkspace {\n public readonly cwd: string;\n public readonly manifest: SolidFsManifest;\n\n private readonly sourceRoot: string;\n private readonly projection: SolidFsProjection;\n private readonly cleanupOnRollback: boolean;\n private readonly changeFilter?: (relativePath: string) => boolean;\n private readonly context?: unknown;\n private readonly syncer?: SolidFsSyncer;\n private readonly hydrator?: SolidFsHydrator;\n private readonly entrySource: SolidFsEntrySource;\n\n public constructor(options: LocalMaterializedWorkspaceOptions) {\n this.sourceRoot = options.sourceRoot;\n this.cwd = options.cwd;\n this.projection = options.projection;\n this.cleanupOnRollback = options.cleanupOnRollback;\n this.manifest = options.manifest;\n this.changeFilter = options.changeFilter;\n this.context = options.context;\n this.syncer = options.syncer;\n this.hydrator = options.hydrator;\n this.entrySource = sourceForProjection(this.projection, this.manifest.workspace);\n }\n\n public async commit(): Promise<SolidFsManifest> {\n if (this.projection === 'hydrated-object') {\n return this.commitHydratedObjects();\n }\n\n const changes = await this.detectChanges();\n this.manifest.changes = changes;\n\n if (this.projection === 'direct') {\n await this.syncChanges(changes);\n this.markCommitted();\n return this.manifest;\n }\n\n if (this.projection !== 'copy') {\n throw new Error(`Commit is not implemented for projection '${this.projection}'.`);\n }\n\n const conflicts = await this.findConflicts();\n if (conflicts.length > 0) {\n for (const entry of this.manifest.entries) {\n if (conflicts.some((conflict) => conflict.path === entry.path)) {\n entry.state = 'conflict';\n }\n }\n throw new SolidFsConflictError(conflicts);\n }\n\n await rm(this.sourceRoot, { recursive: true, force: true });\n await cp(this.cwd, this.sourceRoot, {\n recursive: true,\n force: true,\n errorOnExist: false,\n dereference: false,\n });\n await this.syncChanges(changes);\n this.markCommitted();\n return this.manifest;\n }\n\n public async rollback(): Promise<void> {\n if (this.cleanupOnRollback) {\n await rm(path.dirname(this.cwd), { recursive: true, force: true });\n }\n }\n\n public async hydrate(relativePath: string): Promise<SolidFsManifestEntry> {\n if (this.projection !== 'hydrated-object') {\n throw new Error(`hydrate() is only supported for hydrated-object projection, not '${this.projection}'`);\n }\n if (!this.hydrator) {\n throw new Error('SolidFS hydrated-object projection requires a hydrator');\n }\n\n const normalized = safeRelativePath(relativePath);\n const targetPath = path.join(this.cwd, normalized);\n await mkdir(path.dirname(targetPath), { recursive: true });\n\n const result = await this.hydrator.hydrate({\n path: normalized,\n targetPath,\n workspace: this.manifest,\n context: this.context,\n });\n\n const workingVersion = await fileVersion(targetPath);\n let entry = this.manifest.entries.find((candidate) => candidate.path === normalized);\n if (!entry) {\n entry = {\n path: normalized,\n resource: resolveWorkspaceResource(this.manifest.workspace, normalized),\n source: this.entrySource,\n sourcePath: targetPath,\n contentType: result?.contentType ?? contentTypeForPath(normalized),\n projection: this.projection,\n sourceVersion: result?.sourceVersion,\n workingVersion,\n lastAccessedAt: Date.now(),\n state: 'clean',\n };\n this.manifest.entries.push(entry);\n this.manifest.entries.sort((left, right) => left.path.localeCompare(right.path));\n return entry;\n }\n\n entry.sourcePath = targetPath;\n entry.contentType = result?.contentType ?? entry.contentType ?? contentTypeForPath(normalized);\n entry.sourceVersion = result?.sourceVersion ?? entry.sourceVersion;\n entry.workingVersion = workingVersion;\n entry.lastAccessedAt = Date.now();\n entry.state = 'clean';\n return entry;\n }\n\n public async prune(options: SolidFsPruneOptions = {}): Promise<SolidFsManifest> {\n if (this.projection !== 'hydrated-object') {\n return this.manifest;\n }\n\n const now = options.now ?? Date.now();\n const olderThanMs = options.olderThanMs ?? 0;\n const retained: SolidFsManifestEntry[] = [];\n\n for (const entry of this.manifest.entries) {\n const currentVersion = await maybeFileVersion(entry.sourcePath);\n const dirty = currentVersion !== undefined && currentVersion !== entry.workingVersion;\n if (dirty) {\n entry.state = 'dirty';\n retained.push(entry);\n continue;\n }\n\n const age = now - (entry.lastAccessedAt ?? now);\n if (age >= olderThanMs) {\n await rm(entry.sourcePath, { force: true });\n continue;\n }\n retained.push(entry);\n }\n\n this.manifest.entries = retained;\n return this.manifest;\n }\n\n private async commitHydratedObjects(): Promise<SolidFsManifest> {\n if (!this.hydrator) {\n throw new Error('SolidFS hydrated-object projection requires a hydrator');\n }\n\n const changes = await this.detectHydratedChanges();\n this.manifest.changes = changes;\n\n for (const change of changes) {\n if (change.type === 'deleted' && this.hydrator.delete) {\n await this.hydrator.delete({\n change,\n workspace: this.manifest,\n context: this.context,\n });\n this.manifest.entries = this.manifest.entries.filter((entry) => entry.path !== change.path);\n continue;\n }\n if (change.type !== 'deleted') {\n const result = await this.hydrator.commit({\n change,\n workspace: this.manifest,\n context: this.context,\n });\n const entry = this.manifest.entries.find((candidate) => candidate.path === change.path);\n if (entry) {\n entry.sourceVersion = result?.sourceVersion ?? entry.sourceVersion;\n entry.workingVersion = await fileVersion(entry.sourcePath);\n entry.lastAccessedAt = Date.now();\n }\n }\n }\n\n this.markCommitted();\n return this.manifest;\n }\n\n private async detectHydratedChanges(): Promise<SolidFsChange[]> {\n const changes: SolidFsChange[] = [];\n const tracked = new Set(this.manifest.entries.map((entry) => entry.path));\n for (const entry of this.manifest.entries) {\n const currentVersion = await maybeFileVersion(entry.sourcePath);\n if (currentVersion === undefined) {\n changes.push({\n path: entry.path,\n resource: entry.resource ?? resolveWorkspaceResource(this.manifest.workspace, entry.path),\n source: entry.source,\n sourcePath: entry.sourcePath,\n contentType: entry.contentType,\n projection: this.projection,\n type: 'deleted',\n sourceVersion: entry.sourceVersion,\n });\n entry.state = 'dirty';\n continue;\n }\n if (currentVersion !== entry.workingVersion) {\n changes.push({\n path: entry.path,\n resource: entry.resource ?? resolveWorkspaceResource(this.manifest.workspace, entry.path),\n source: entry.source,\n sourcePath: entry.sourcePath,\n contentType: entry.contentType,\n projection: this.projection,\n type: 'updated',\n sourceVersion: entry.sourceVersion,\n });\n entry.state = 'dirty';\n }\n }\n\n for (const snapshot of await snapshotDirectory(this.cwd)) {\n if (tracked.has(snapshot.relativePath)) {\n continue;\n }\n this.manifest.entries.push({\n path: snapshot.relativePath,\n resource: resolveWorkspaceResource(this.manifest.workspace, snapshot.relativePath),\n source: this.entrySource,\n sourcePath: snapshot.absolutePath,\n contentType: contentTypeForPath(snapshot.relativePath),\n projection: this.projection,\n workingVersion: snapshot.version,\n lastAccessedAt: Date.now(),\n state: 'dirty',\n });\n changes.push({\n path: snapshot.relativePath,\n resource: resolveWorkspaceResource(this.manifest.workspace, snapshot.relativePath),\n source: this.entrySource,\n sourcePath: snapshot.absolutePath,\n contentType: contentTypeForPath(snapshot.relativePath),\n projection: this.projection,\n type: 'created',\n });\n }\n this.manifest.entries.sort((left, right) => left.path.localeCompare(right.path));\n return changes.sort((left, right) => left.path.localeCompare(right.path));\n }\n\n private async findConflicts(): Promise<SolidFsConflict[]> {\n const conflicts: SolidFsConflict[] = [];\n const initialPaths = new Set(this.manifest.entries.map((entry) => entry.path));\n\n for (const entry of this.manifest.entries) {\n if (!entry.sourceVersion) {\n continue;\n }\n const currentVersion = await maybeFileVersion(entry.sourcePath);\n if (currentVersion !== entry.sourceVersion) {\n conflicts.push({\n path: entry.path,\n sourcePath: entry.sourcePath,\n expectedVersion: entry.sourceVersion,\n actualVersion: currentVersion,\n message: 'Source file changed after workspace prepare.',\n });\n }\n }\n\n const currentSourceFiles = await snapshotDirectory(this.sourceRoot);\n for (const current of currentSourceFiles) {\n if (!initialPaths.has(current.relativePath)) {\n conflicts.push({\n path: current.relativePath,\n sourcePath: current.absolutePath,\n actualVersion: current.version,\n message: 'Source file was created after workspace prepare.',\n });\n }\n }\n return conflicts;\n }\n\n private async detectChanges(): Promise<SolidFsChange[]> {\n const before = new Map(this.manifest.entries.map((entry) => [entry.path, entry]));\n if (before.size === 0 && this.projection === 'direct' && !this.changeFilter) {\n return [];\n }\n const after = new Map((await snapshotDirectory(this.cwd, this.changeFilter)).map((snapshot) => [snapshot.relativePath, snapshot]));\n const changes: SolidFsChange[] = [];\n\n for (const [relativePath, snapshot] of after) {\n const entry = before.get(relativePath);\n if (!entry) {\n changes.push(this.createChange(relativePath, snapshot.absolutePath, 'created'));\n continue;\n }\n if (entry.sourceVersion !== snapshot.version) {\n changes.push(this.createChange(relativePath, snapshot.absolutePath, 'updated'));\n }\n }\n\n for (const [relativePath, entry] of before) {\n if (!after.has(relativePath)) {\n changes.push(this.createChange(relativePath, entry.sourcePath, 'deleted'));\n }\n }\n\n return changes.sort((left, right) => left.path.localeCompare(right.path));\n }\n\n private createChange(\n relativePath: string,\n sourcePath: string,\n type: SolidFsChange['type'],\n ): SolidFsChange {\n return {\n path: relativePath,\n resource: resolveWorkspaceResource(this.manifest.workspace, relativePath),\n source: this.entrySource,\n sourcePath,\n contentType: contentTypeForPath(relativePath),\n projection: this.projection,\n type,\n };\n }\n\n private async syncChanges(changes: SolidFsChange[]): Promise<void> {\n if (!this.syncer) {\n return;\n }\n for (const change of changes) {\n await this.syncer.sync(change, this.manifest, this.context);\n }\n }\n\n private markCommitted(): void {\n for (const entry of this.manifest.entries) {\n entry.state = 'committed';\n }\n }\n}\n\nfunction isLineAddressableRdfPath(filePath: string): boolean {\n return isRdfPath(filePath);\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { SolidFsEntrySource, SolidFsProjection } from './types';
2
+ export interface SolidFsFileSnapshot {
3
+ relativePath: string;
4
+ absolutePath: string;
5
+ version: string;
6
+ }
7
+ export declare function contentTypeForPath(filePath: string): string | undefined;
8
+ export declare function sourceForProjection(projection: SolidFsProjection, workspace: string): SolidFsEntrySource;
9
+ export declare function resolveWorkspaceResource(workspace: string, relativePath: string): string | undefined;
10
+ export declare function safeRelativePath(input: string): string;
11
+ export declare function maybeFileVersion(filePath: string): Promise<string | undefined>;
12
+ export declare function fileVersion(filePath: string): Promise<string>;
13
+ export declare function snapshotDirectory(root: string, filter?: (relativePath: string) => boolean): Promise<SolidFsFileSnapshot[]>;