solid-logic 6.0.0-0 → 6.0.0-1

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,2 +1,2 @@
1
- const e=require("../util/ns.cjs.js"),t=require("../acl/aclLogic.cjs.js"),n=require("./resourceHttp.cjs.js"),r=require("./resourceMetadata.cjs.js");let i=require("rdflib");function a(a,o,s,c){function l(e){return s.createContainer(e)}function u(e){return s.isContainer(e)}function d(e){return s.getContainerMemberCount(e)}function f(n,i){let o,s=!1,c=!1,l,u;if(i.headers){o=i.headers.get(`content-type`)?.split(`;`)[0]??void 0;let t=r.readWacAccessInfo(i.headers.get(`wac-allow`));s=t.canEdit,c=t.isPublic,l=i.headers.get(`etag`)??void 0,u=a.anyValue(n,e.ns.dct(`modified`))||a.anyValue(n,e.ns.dc(`modified`))||void 0}(!i.headers||!i.headers.get(`content-type`))&&(!i.headers||!i.headers.get(`wac-allow`)||!i.headers.get(`etag`))&&a.each(null,a.sym(`http://www.w3.org/2007/ont/link#requestedURI`),n).map(t=>{let i=a.any(t,a.sym(`http://www.w3.org/2007/ont/link#response`));if(i&&i.termType===`NamedNode`){let t=a.anyValue(i,e.ns.httph(`content-type`))||void 0;o===void 0&&(o=t);let d=r.readWacAccessInfo(a.anyValue(i,e.ns.httph(`wac-allow`))||a.anyValue(i,e.ns.httph(`WAC-Allow`)));s||=d.canEdit,c||=d.isPublic;let f=a.anyValue(i,e.ns.httph(`etag`))||void 0;l===void 0&&(l=f),u=a.anyValue(n,e.ns.dct(`modified`))||a.anyValue(n,e.ns.dc(`modified`))||void 0}});let d=a.any(n,t.ACL_LINK)?.value||void 0;return{contentType:o,access:{canEdit:s,isPublic:c},aclUri:d,eTag:l,modified:u}}async function p(e){let t=await a.fetcher.webOperation(`HEAD`,e.uri);return n.assertSuccessfulHttpResponse(t,`HEAD`),f(e,t)}async function m(t){let n=a.any(t,e.ns.ldp(`contains`))||t.dir();if(!n||n.termType!==`NamedNode`)return!1;try{return(await p(n)).access.canEdit}catch{return!1}}async function h(e){return m(e)}async function g(e){return p(e)}async function _(e){let t;try{t=await p(e)}catch{t={contentType:void 0,access:{canEdit:!1,isPublic:!1},aclUri:void 0,eTag:void 0,modified:void 0}}let n=await h(e),r={canEdit:t.access?.canEdit??!1,isPublic:t.access?.isPublic??!1,canDelete:n};return{...t,access:r}}async function v(e,t){if(t)try{await c.deleteTypeIndexRegistrationForResource(e,t)}catch{}}async function y(t,r={}){let o=t.dir();if(u(t)){let e=await s.getContainerMembers(t);await Promise.all(e.map(e=>y((0,i.sym)(e),r)))}let c;try{c=await a.fetcher._fetch(t.value,{method:`DELETE`}),n.assertSuccessfulHttpResponse(c,`DELETE`,{allowNotFound:!0})}catch(e){if(!n.isMissingError(e))throw e}return r.deleteTypeIndexes&&await v(t,r.user),o&&a.removeMatches(o,e.ns.ldp(`contains`),t,o.doc()),a.removeDocument(t),a.fetcher.unload(t.doc()),c}async function b(e,t){await y(e,{deleteTypeIndexes:!0,user:t})}return{recursiveDelete:y,deleteResourceAndTypeIndexIfExists:b,fetchMetadata:g,fetchMetadataWithDelete:_,createContainer:l,isContainer:u,getContainerMemberCount:d}}exports.createResourceLogic=a;
1
+ const e=require("../util/ns.cjs.js"),t=require("../acl/aclLogic.cjs.js"),n=require("./resourceHttp.cjs.js"),r=require("./resourceMetadata.cjs.js");let i=require("rdflib");function a(a,o,s,c){function l(e){return s.createContainer(e)}function u(e){return s.isContainer(e)}function d(e){return s.getContainerMemberCount(e)}function f(n,i){let o,s=!1,c=!1,l,u;if(i.headers){o=i.headers.get(`content-type`)?.split(`;`)[0]??void 0;let t=r.readWacAccessInfo(i.headers.get(`wac-allow`));s=t.canEdit,c=t.isPublic,l=i.headers.get(`etag`)??void 0,u=a.anyValue(n,e.ns.dct(`modified`))||a.anyValue(n,e.ns.dc(`modified`))||void 0}(!i.headers||!i.headers.get(`content-type`))&&(!i.headers||!i.headers.get(`wac-allow`)||!i.headers.get(`etag`))&&a.each(null,a.sym(`http://www.w3.org/2007/ont/link#requestedURI`),n).map(t=>{let i=a.any(t,a.sym(`http://www.w3.org/2007/ont/link#response`));if(i&&i.termType===`NamedNode`){let t=a.anyValue(i,e.ns.httph(`content-type`))||void 0;o===void 0&&(o=t);let d=r.readWacAccessInfo(a.anyValue(i,e.ns.httph(`wac-allow`))||a.anyValue(i,e.ns.httph(`WAC-Allow`)));s||=d.canEdit,c||=d.isPublic;let f=a.anyValue(i,e.ns.httph(`etag`))||void 0;l===void 0&&(l=f),u=a.anyValue(n,e.ns.dct(`modified`))||a.anyValue(n,e.ns.dc(`modified`))||void 0}});let d=a.any(n,t.ACL_LINK)?.value||void 0;return{contentType:o,access:{canEdit:s,isPublic:c},aclUri:d,eTag:l,modified:u}}async function p(e){let t=await a.fetcher.webOperation(`HEAD`,e.uri);return n.assertSuccessfulHttpResponse(t,`HEAD`),f(e,t)}async function m(t){let n=a.any(t,e.ns.ldp(`contains`))||t.dir();if(!n||n.termType!==`NamedNode`)return!1;try{return(await p(n)).access.canEdit}catch{return!1}}async function h(e){return m(e)}async function g(e){return p(e)}async function _(e){let t;try{t=await p(e)}catch{t={contentType:void 0,access:{canEdit:!1,isPublic:!1},aclUri:void 0,eTag:void 0,modified:void 0}}let n=await h(e),r={canEdit:t.access?.canEdit??!1,isPublic:t.access?.isPublic??!1,canDelete:n};return{...t,access:r}}async function v(e,t){if(t)try{await c.deleteTypeIndexRegistrationForResource(e,t)}catch{}}async function y(t,r={}){let o=t.dir();if(u(t)){let e=await s.getContainerMembers(t);await Promise.all(e.map(e=>y((0,i.sym)(e),r)))}let c;try{c=await a.fetcher._fetch(t.value,{method:`DELETE`}),n.assertSuccessfulHttpResponse(c,`DELETE`,{allowNotFound:!0})}catch(e){if(!n.isMissingError(e))throw e}return r.deleteTypeIndexes&&await v(t,r.user),o&&a.removeMatches(o,e.ns.ldp(`contains`),t,o.doc()),a.removeDocument(t),a.fetcher.unload(t.doc()),c}async function b(e,t){await y(e,{deleteTypeIndexes:!0,user:t})}async function x(e){if(!e||!a.updater||!a.fetcher||typeof a.fetcher.refresh!=`function`)return!1;let t=e.uri||e.value||``;if(!t)return!1;let n=a.updater.editable(t,a);if(n!==!1&&n!==void 0)return!0;try{await a.fetcher.refresh(e)}catch(e){throw e instanceof Error?e:Error(`Failed to refresh <${t}>`)}let r=a.updater.editable(t,a);return r!==!1&&r!==void 0}return{recursiveDelete:y,deleteResourceAndTypeIndexIfExists:b,fetchMetadata:g,fetchMetadataWithDelete:_,checkAndRefreshEditable:x,createContainer:l,isContainer:u,getContainerMemberCount:d}}exports.createResourceLogic=a;
2
2
  //# sourceMappingURL=resourceLogic.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resourceLogic.cjs.js","names":[],"sources":["../../src/resource/resourceLogic.ts"],"sourcesContent":["import { NamedNode, sym } from 'rdflib'\nimport { ACL_LINK } from '../acl/aclLogic'\nimport { ns } from '../util/ns'\nimport { assertSuccessfulHttpResponse, isMissingError } from './resourceHttp'\nimport { readWacAccessInfo } from './resourceMetadata'\nimport { type AclLogic, type ResourceAccess, type ResourceAccessWithDelete, type ResourceDeleteOptions, type ResourceLogic, type ResourceMetadata, type ResourceMetadataWithDelete, type TypeIndexLogic } from '../types'\n\nexport function createResourceLogic(store, aclLogic: AclLogic, containerLogic, typeIndexLogic: TypeIndexLogic): ResourceLogic {\n function createContainer(url: string) {\n return containerLogic.createContainer(url)\n }\n\n function isContainer(resourceNode: NamedNode) {\n return containerLogic.isContainer(resourceNode)\n }\n\n function getContainerMemberCount(resourceNode: NamedNode) {\n return containerLogic.getContainerMemberCount(resourceNode)\n }\n\n function readMetadata(subject: NamedNode, response: Response): ResourceMetadata {\n let contentType: string | undefined\n let canEdit = false\n let isPublic = false\n let eTag: string | undefined\n let modified: string | undefined\n\n if (response.headers) {\n const contentTypeHeader = response.headers.get('content-type')\n contentType = contentTypeHeader?.split(';')[0] ?? undefined\n\n const accessFlags = readWacAccessInfo(response.headers.get('wac-allow'))\n canEdit = accessFlags.canEdit\n isPublic = accessFlags.isPublic\n eTag = response.headers.get('etag') ?? undefined\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n\n if ((!response.headers || !response.headers.get('content-type')) && (!response.headers || !response.headers.get('wac-allow') || !response.headers.get('etag'))) {\n const reqs = store.each(\n null,\n store.sym('http://www.w3.org/2007/ont/link#requestedURI'),\n subject\n )\n reqs.map((req: any) => {\n const responseNode = store.any(\n req as any,\n store.sym('http://www.w3.org/2007/ont/link#response')\n )\n if (responseNode && responseNode.termType === 'NamedNode') {\n const responseContentType = store.anyValue(responseNode as any, ns.httph('content-type')) || undefined\n if (contentType === undefined) {\n contentType = responseContentType\n }\n const wacAllow = (store.anyValue(responseNode as any, ns.httph('wac-allow')) as string | undefined) ||\n (store.anyValue(responseNode as any, ns.httph('WAC-Allow')) as string | undefined)\n const accessFlags = readWacAccessInfo(wacAllow)\n canEdit = canEdit || accessFlags.canEdit\n isPublic = isPublic || accessFlags.isPublic\n const responseETag = store.anyValue(responseNode as any, ns.httph('etag')) || undefined\n if (eTag === undefined) {\n eTag = responseETag\n }\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n })\n }\n\n const aclUri = store.any(subject, ACL_LINK)?.value || undefined\n const access: ResourceAccess = { canEdit, isPublic }\n return { contentType, access, aclUri, eTag, modified }\n }\n\n async function fetchHeadMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n const response = await store.fetcher.webOperation('HEAD', subject.uri)\n assertSuccessfulHttpResponse(response, 'HEAD')\n return readMetadata(subject, response)\n }\n\n async function userCanWriteToContainingContainer(resourceNode: NamedNode): Promise<boolean> {\n const containerNode = store.any(resourceNode, ns.ldp('contains')) || resourceNode.dir()\n if (!containerNode || containerNode.termType !== 'NamedNode') {\n return false\n }\n\n try {\n const containerMetadata = await fetchHeadMetadata(containerNode as NamedNode)\n return containerMetadata.access.canEdit\n } catch (_error) {\n return false\n }\n }\n\n async function userCanDeleteResource(resourceNode: NamedNode): Promise<boolean> {\n return userCanWriteToContainingContainer(resourceNode)\n }\n\n async function fetchMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n return fetchHeadMetadata(subject)\n }\n\n async function fetchMetadataWithDelete(subject: NamedNode): Promise<ResourceMetadataWithDelete> {\n let resourceMetadata: ResourceMetadata\n\n try {\n resourceMetadata = await fetchHeadMetadata(subject)\n } catch (_error) {\n resourceMetadata = {\n contentType: undefined,\n access: { canEdit: false, isPublic: false },\n aclUri: undefined,\n eTag: undefined,\n modified: undefined\n }\n }\n\n const canDelete = await userCanDeleteResource(subject)\n const access: ResourceAccessWithDelete = {\n canEdit: resourceMetadata.access?.canEdit ?? false,\n isPublic: resourceMetadata.access?.isPublic ?? false,\n canDelete\n }\n return { ...resourceMetadata, access }\n }\n\n async function deleteTypeIndexesForResource(resourceNode: NamedNode, user?: NamedNode | null) {\n if (!user) return\n\n try {\n await typeIndexLogic.deleteTypeIndexRegistrationForResource(resourceNode, user)\n } catch (_error) {\n // Keep resource deletion best-effort even if type-index cleanup fails.\n }\n }\n\n async function recursiveDelete(resourceNode: NamedNode, options: ResourceDeleteOptions = {}) {\n const resourceParent = resourceNode.dir()\n\n if (isContainer(resourceNode)) {\n const containerMembers = await containerLogic.getContainerMembers(resourceNode)\n await Promise.all(containerMembers.map((url) => recursiveDelete(sym(url), options)))\n }\n\n let deleted\n try {\n deleted = await store.fetcher._fetch(resourceNode.value, { method: 'DELETE' })\n assertSuccessfulHttpResponse(deleted, 'DELETE', { allowNotFound: true })\n } catch (error) {\n if (!isMissingError(error)) {\n throw error\n }\n }\n\n if (options.deleteTypeIndexes) {\n await deleteTypeIndexesForResource(resourceNode, options.user)\n }\n\n if (resourceParent) {\n store.removeMatches(resourceParent, ns.ldp('contains'), resourceNode, resourceParent.doc())\n }\n\n store.removeDocument(resourceNode)\n store.fetcher.unload(resourceNode.doc())\n return deleted\n }\n\n async function deleteResourceAndTypeIndexIfExists(resourceNode: NamedNode, user?: NamedNode | null) {\n await recursiveDelete(resourceNode, { deleteTypeIndexes: true, user })\n }\n\n return {\n recursiveDelete,\n deleteResourceAndTypeIndexIfExists,\n fetchMetadata,\n fetchMetadataWithDelete,\n createContainer,\n isContainer,\n getContainerMemberCount\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resourceLogic.cjs.js","names":[],"sources":["../../src/resource/resourceLogic.ts"],"sourcesContent":["import { NamedNode, sym, LiveStore } from 'rdflib'\nimport { ACL_LINK } from '../acl/aclLogic'\nimport { ns } from '../util/ns'\nimport { assertSuccessfulHttpResponse, isMissingError } from './resourceHttp'\nimport { readWacAccessInfo } from './resourceMetadata'\nimport { type AclLogic, type ResourceAccess, type ResourceAccessWithDelete, type ResourceDeleteOptions, type ResourceLogic, type ResourceMetadata, type ResourceMetadataWithDelete, type TypeIndexLogic } from '../types'\n\nexport function createResourceLogic(store: LiveStore, aclLogic: AclLogic, containerLogic, typeIndexLogic: TypeIndexLogic): ResourceLogic {\n function createContainer(url: string) {\n return containerLogic.createContainer(url)\n }\n\n function isContainer(resourceNode: NamedNode) {\n return containerLogic.isContainer(resourceNode)\n }\n\n function getContainerMemberCount(resourceNode: NamedNode) {\n return containerLogic.getContainerMemberCount(resourceNode)\n }\n\n function readMetadata(subject: NamedNode, response: Response): ResourceMetadata {\n let contentType: string | undefined\n let canEdit = false\n let isPublic = false\n let eTag: string | undefined\n let modified: string | undefined\n\n if (response.headers) {\n const contentTypeHeader = response.headers.get('content-type')\n contentType = contentTypeHeader?.split(';')[0] ?? undefined\n\n const accessFlags = readWacAccessInfo(response.headers.get('wac-allow'))\n canEdit = accessFlags.canEdit\n isPublic = accessFlags.isPublic\n eTag = response.headers.get('etag') ?? undefined\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n\n if ((!response.headers || !response.headers.get('content-type')) && (!response.headers || !response.headers.get('wac-allow') || !response.headers.get('etag'))) {\n const reqs = store.each(\n null,\n store.sym('http://www.w3.org/2007/ont/link#requestedURI'),\n subject\n )\n reqs.map((req: any) => {\n const responseNode = store.any(\n req as any,\n store.sym('http://www.w3.org/2007/ont/link#response')\n )\n if (responseNode && responseNode.termType === 'NamedNode') {\n const responseContentType = store.anyValue(responseNode as any, ns.httph('content-type')) || undefined\n if (contentType === undefined) {\n contentType = responseContentType\n }\n const wacAllow = (store.anyValue(responseNode as any, ns.httph('wac-allow')) as string | undefined) ||\n (store.anyValue(responseNode as any, ns.httph('WAC-Allow')) as string | undefined)\n const accessFlags = readWacAccessInfo(wacAllow)\n canEdit = canEdit || accessFlags.canEdit\n isPublic = isPublic || accessFlags.isPublic\n const responseETag = store.anyValue(responseNode as any, ns.httph('etag')) || undefined\n if (eTag === undefined) {\n eTag = responseETag\n }\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n })\n }\n\n const aclUri = store.any(subject, ACL_LINK)?.value || undefined\n const access: ResourceAccess = { canEdit, isPublic }\n return { contentType, access, aclUri, eTag, modified }\n }\n\n async function fetchHeadMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n const response = await store.fetcher.webOperation('HEAD', subject.uri)\n assertSuccessfulHttpResponse(response, 'HEAD')\n return readMetadata(subject, response)\n }\n\n async function userCanWriteToContainingContainer(resourceNode: NamedNode): Promise<boolean> {\n const containerNode = store.any(resourceNode, ns.ldp('contains')) || resourceNode.dir()\n if (!containerNode || containerNode.termType !== 'NamedNode') {\n return false\n }\n\n try {\n const containerMetadata = await fetchHeadMetadata(containerNode as NamedNode)\n return containerMetadata.access.canEdit\n } catch (_error) {\n return false\n }\n }\n\n async function userCanDeleteResource(resourceNode: NamedNode): Promise<boolean> {\n return userCanWriteToContainingContainer(resourceNode)\n }\n\n async function fetchMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n return fetchHeadMetadata(subject)\n }\n\n async function fetchMetadataWithDelete(subject: NamedNode): Promise<ResourceMetadataWithDelete> {\n let resourceMetadata: ResourceMetadata\n\n try {\n resourceMetadata = await fetchHeadMetadata(subject)\n } catch (_error) {\n resourceMetadata = {\n contentType: undefined,\n access: { canEdit: false, isPublic: false },\n aclUri: undefined,\n eTag: undefined,\n modified: undefined\n }\n }\n\n const canDelete = await userCanDeleteResource(subject)\n const access: ResourceAccessWithDelete = {\n canEdit: resourceMetadata.access?.canEdit ?? false,\n isPublic: resourceMetadata.access?.isPublic ?? false,\n canDelete\n }\n return { ...resourceMetadata, access }\n }\n\n async function deleteTypeIndexesForResource(resourceNode: NamedNode, user?: NamedNode | null) {\n if (!user) return\n\n try {\n await typeIndexLogic.deleteTypeIndexRegistrationForResource(resourceNode, user)\n } catch (_error) {\n // Keep resource deletion best-effort even if type-index cleanup fails.\n }\n }\n\n async function recursiveDelete(resourceNode: NamedNode, options: ResourceDeleteOptions = {}) {\n const resourceParent = resourceNode.dir()\n\n if (isContainer(resourceNode)) {\n const containerMembers = await containerLogic.getContainerMembers(resourceNode)\n await Promise.all(containerMembers.map((url) => recursiveDelete(sym(url), options)))\n }\n\n let deleted\n try {\n deleted = await store.fetcher._fetch(resourceNode.value, { method: 'DELETE' })\n assertSuccessfulHttpResponse(deleted, 'DELETE', { allowNotFound: true })\n } catch (error) {\n if (!isMissingError(error)) {\n throw error\n }\n }\n\n if (options.deleteTypeIndexes) {\n await deleteTypeIndexesForResource(resourceNode, options.user)\n }\n\n if (resourceParent) {\n store.removeMatches(resourceParent, ns.ldp('contains'), resourceNode, resourceParent.doc())\n }\n\n store.removeDocument(resourceNode)\n store.fetcher.unload(resourceNode.doc())\n return deleted\n }\n\n async function deleteResourceAndTypeIndexIfExists(resourceNode: NamedNode, user?: NamedNode | null) {\n await recursiveDelete(resourceNode, { deleteTypeIndexes: true, user })\n }\n\n async function checkAndRefreshEditable(resourceNode: NamedNode | null | undefined): Promise<boolean> {\n if (!resourceNode || !store.updater || !store.fetcher || typeof store.fetcher.refresh !== 'function') return false\n\n const resourceUri = resourceNode.uri || resourceNode.value || ''\n if (!resourceUri) return false\n\n const editable = store.updater.editable(resourceUri, store)\n if (editable !== false && editable !== undefined) {\n return true\n }\n\n try {\n await store.fetcher.refresh(resourceNode)\n } catch (error) {\n throw error instanceof Error ? error : new Error(`Failed to refresh <${resourceUri}>`)\n }\n\n const editableAfterRefresh = store.updater.editable(resourceUri, store)\n return editableAfterRefresh !== false && editableAfterRefresh !== undefined\n }\n\n return {\n recursiveDelete,\n deleteResourceAndTypeIndexIfExists,\n fetchMetadata,\n fetchMetadataWithDelete,\n checkAndRefreshEditable,\n createContainer,\n isContainer,\n getContainerMemberCount\n }\n}\n"],"mappings":"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"}
@@ -114,11 +114,26 @@ function o(o, s, c, l) {
114
114
  user: t
115
115
  });
116
116
  }
117
+ async function S(e) {
118
+ if (!e || !o.updater || !o.fetcher || typeof o.fetcher.refresh != "function") return !1;
119
+ let t = e.uri || e.value || "";
120
+ if (!t) return !1;
121
+ let n = o.updater.editable(t, o);
122
+ if (n !== !1 && n !== void 0) return !0;
123
+ try {
124
+ await o.fetcher.refresh(e);
125
+ } catch (e) {
126
+ throw e instanceof Error ? e : /* @__PURE__ */ Error(`Failed to refresh <${t}>`);
127
+ }
128
+ let r = o.updater.editable(t, o);
129
+ return r !== !1 && r !== void 0;
130
+ }
117
131
  return {
118
132
  recursiveDelete: b,
119
133
  deleteResourceAndTypeIndexIfExists: x,
120
134
  fetchMetadata: _,
121
135
  fetchMetadataWithDelete: v,
136
+ checkAndRefreshEditable: S,
122
137
  createContainer: u,
123
138
  isContainer: d,
124
139
  getContainerMemberCount: f
@@ -1 +1 @@
1
- {"version":3,"file":"resourceLogic.esm.js","names":[],"sources":["../../src/resource/resourceLogic.ts"],"sourcesContent":["import { NamedNode, sym } from 'rdflib'\nimport { ACL_LINK } from '../acl/aclLogic'\nimport { ns } from '../util/ns'\nimport { assertSuccessfulHttpResponse, isMissingError } from './resourceHttp'\nimport { readWacAccessInfo } from './resourceMetadata'\nimport { type AclLogic, type ResourceAccess, type ResourceAccessWithDelete, type ResourceDeleteOptions, type ResourceLogic, type ResourceMetadata, type ResourceMetadataWithDelete, type TypeIndexLogic } from '../types'\n\nexport function createResourceLogic(store, aclLogic: AclLogic, containerLogic, typeIndexLogic: TypeIndexLogic): ResourceLogic {\n function createContainer(url: string) {\n return containerLogic.createContainer(url)\n }\n\n function isContainer(resourceNode: NamedNode) {\n return containerLogic.isContainer(resourceNode)\n }\n\n function getContainerMemberCount(resourceNode: NamedNode) {\n return containerLogic.getContainerMemberCount(resourceNode)\n }\n\n function readMetadata(subject: NamedNode, response: Response): ResourceMetadata {\n let contentType: string | undefined\n let canEdit = false\n let isPublic = false\n let eTag: string | undefined\n let modified: string | undefined\n\n if (response.headers) {\n const contentTypeHeader = response.headers.get('content-type')\n contentType = contentTypeHeader?.split(';')[0] ?? undefined\n\n const accessFlags = readWacAccessInfo(response.headers.get('wac-allow'))\n canEdit = accessFlags.canEdit\n isPublic = accessFlags.isPublic\n eTag = response.headers.get('etag') ?? undefined\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n\n if ((!response.headers || !response.headers.get('content-type')) && (!response.headers || !response.headers.get('wac-allow') || !response.headers.get('etag'))) {\n const reqs = store.each(\n null,\n store.sym('http://www.w3.org/2007/ont/link#requestedURI'),\n subject\n )\n reqs.map((req: any) => {\n const responseNode = store.any(\n req as any,\n store.sym('http://www.w3.org/2007/ont/link#response')\n )\n if (responseNode && responseNode.termType === 'NamedNode') {\n const responseContentType = store.anyValue(responseNode as any, ns.httph('content-type')) || undefined\n if (contentType === undefined) {\n contentType = responseContentType\n }\n const wacAllow = (store.anyValue(responseNode as any, ns.httph('wac-allow')) as string | undefined) ||\n (store.anyValue(responseNode as any, ns.httph('WAC-Allow')) as string | undefined)\n const accessFlags = readWacAccessInfo(wacAllow)\n canEdit = canEdit || accessFlags.canEdit\n isPublic = isPublic || accessFlags.isPublic\n const responseETag = store.anyValue(responseNode as any, ns.httph('etag')) || undefined\n if (eTag === undefined) {\n eTag = responseETag\n }\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n })\n }\n\n const aclUri = store.any(subject, ACL_LINK)?.value || undefined\n const access: ResourceAccess = { canEdit, isPublic }\n return { contentType, access, aclUri, eTag, modified }\n }\n\n async function fetchHeadMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n const response = await store.fetcher.webOperation('HEAD', subject.uri)\n assertSuccessfulHttpResponse(response, 'HEAD')\n return readMetadata(subject, response)\n }\n\n async function userCanWriteToContainingContainer(resourceNode: NamedNode): Promise<boolean> {\n const containerNode = store.any(resourceNode, ns.ldp('contains')) || resourceNode.dir()\n if (!containerNode || containerNode.termType !== 'NamedNode') {\n return false\n }\n\n try {\n const containerMetadata = await fetchHeadMetadata(containerNode as NamedNode)\n return containerMetadata.access.canEdit\n } catch (_error) {\n return false\n }\n }\n\n async function userCanDeleteResource(resourceNode: NamedNode): Promise<boolean> {\n return userCanWriteToContainingContainer(resourceNode)\n }\n\n async function fetchMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n return fetchHeadMetadata(subject)\n }\n\n async function fetchMetadataWithDelete(subject: NamedNode): Promise<ResourceMetadataWithDelete> {\n let resourceMetadata: ResourceMetadata\n\n try {\n resourceMetadata = await fetchHeadMetadata(subject)\n } catch (_error) {\n resourceMetadata = {\n contentType: undefined,\n access: { canEdit: false, isPublic: false },\n aclUri: undefined,\n eTag: undefined,\n modified: undefined\n }\n }\n\n const canDelete = await userCanDeleteResource(subject)\n const access: ResourceAccessWithDelete = {\n canEdit: resourceMetadata.access?.canEdit ?? false,\n isPublic: resourceMetadata.access?.isPublic ?? false,\n canDelete\n }\n return { ...resourceMetadata, access }\n }\n\n async function deleteTypeIndexesForResource(resourceNode: NamedNode, user?: NamedNode | null) {\n if (!user) return\n\n try {\n await typeIndexLogic.deleteTypeIndexRegistrationForResource(resourceNode, user)\n } catch (_error) {\n // Keep resource deletion best-effort even if type-index cleanup fails.\n }\n }\n\n async function recursiveDelete(resourceNode: NamedNode, options: ResourceDeleteOptions = {}) {\n const resourceParent = resourceNode.dir()\n\n if (isContainer(resourceNode)) {\n const containerMembers = await containerLogic.getContainerMembers(resourceNode)\n await Promise.all(containerMembers.map((url) => recursiveDelete(sym(url), options)))\n }\n\n let deleted\n try {\n deleted = await store.fetcher._fetch(resourceNode.value, { method: 'DELETE' })\n assertSuccessfulHttpResponse(deleted, 'DELETE', { allowNotFound: true })\n } catch (error) {\n if (!isMissingError(error)) {\n throw error\n }\n }\n\n if (options.deleteTypeIndexes) {\n await deleteTypeIndexesForResource(resourceNode, options.user)\n }\n\n if (resourceParent) {\n store.removeMatches(resourceParent, ns.ldp('contains'), resourceNode, resourceParent.doc())\n }\n\n store.removeDocument(resourceNode)\n store.fetcher.unload(resourceNode.doc())\n return deleted\n }\n\n async function deleteResourceAndTypeIndexIfExists(resourceNode: NamedNode, user?: NamedNode | null) {\n await recursiveDelete(resourceNode, { deleteTypeIndexes: true, user })\n }\n\n return {\n recursiveDelete,\n deleteResourceAndTypeIndexIfExists,\n fetchMetadata,\n fetchMetadataWithDelete,\n createContainer,\n isContainer,\n getContainerMemberCount\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resourceLogic.esm.js","names":[],"sources":["../../src/resource/resourceLogic.ts"],"sourcesContent":["import { NamedNode, sym, LiveStore } from 'rdflib'\nimport { ACL_LINK } from '../acl/aclLogic'\nimport { ns } from '../util/ns'\nimport { assertSuccessfulHttpResponse, isMissingError } from './resourceHttp'\nimport { readWacAccessInfo } from './resourceMetadata'\nimport { type AclLogic, type ResourceAccess, type ResourceAccessWithDelete, type ResourceDeleteOptions, type ResourceLogic, type ResourceMetadata, type ResourceMetadataWithDelete, type TypeIndexLogic } from '../types'\n\nexport function createResourceLogic(store: LiveStore, aclLogic: AclLogic, containerLogic, typeIndexLogic: TypeIndexLogic): ResourceLogic {\n function createContainer(url: string) {\n return containerLogic.createContainer(url)\n }\n\n function isContainer(resourceNode: NamedNode) {\n return containerLogic.isContainer(resourceNode)\n }\n\n function getContainerMemberCount(resourceNode: NamedNode) {\n return containerLogic.getContainerMemberCount(resourceNode)\n }\n\n function readMetadata(subject: NamedNode, response: Response): ResourceMetadata {\n let contentType: string | undefined\n let canEdit = false\n let isPublic = false\n let eTag: string | undefined\n let modified: string | undefined\n\n if (response.headers) {\n const contentTypeHeader = response.headers.get('content-type')\n contentType = contentTypeHeader?.split(';')[0] ?? undefined\n\n const accessFlags = readWacAccessInfo(response.headers.get('wac-allow'))\n canEdit = accessFlags.canEdit\n isPublic = accessFlags.isPublic\n eTag = response.headers.get('etag') ?? undefined\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n\n if ((!response.headers || !response.headers.get('content-type')) && (!response.headers || !response.headers.get('wac-allow') || !response.headers.get('etag'))) {\n const reqs = store.each(\n null,\n store.sym('http://www.w3.org/2007/ont/link#requestedURI'),\n subject\n )\n reqs.map((req: any) => {\n const responseNode = store.any(\n req as any,\n store.sym('http://www.w3.org/2007/ont/link#response')\n )\n if (responseNode && responseNode.termType === 'NamedNode') {\n const responseContentType = store.anyValue(responseNode as any, ns.httph('content-type')) || undefined\n if (contentType === undefined) {\n contentType = responseContentType\n }\n const wacAllow = (store.anyValue(responseNode as any, ns.httph('wac-allow')) as string | undefined) ||\n (store.anyValue(responseNode as any, ns.httph('WAC-Allow')) as string | undefined)\n const accessFlags = readWacAccessInfo(wacAllow)\n canEdit = canEdit || accessFlags.canEdit\n isPublic = isPublic || accessFlags.isPublic\n const responseETag = store.anyValue(responseNode as any, ns.httph('etag')) || undefined\n if (eTag === undefined) {\n eTag = responseETag\n }\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n })\n }\n\n const aclUri = store.any(subject, ACL_LINK)?.value || undefined\n const access: ResourceAccess = { canEdit, isPublic }\n return { contentType, access, aclUri, eTag, modified }\n }\n\n async function fetchHeadMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n const response = await store.fetcher.webOperation('HEAD', subject.uri)\n assertSuccessfulHttpResponse(response, 'HEAD')\n return readMetadata(subject, response)\n }\n\n async function userCanWriteToContainingContainer(resourceNode: NamedNode): Promise<boolean> {\n const containerNode = store.any(resourceNode, ns.ldp('contains')) || resourceNode.dir()\n if (!containerNode || containerNode.termType !== 'NamedNode') {\n return false\n }\n\n try {\n const containerMetadata = await fetchHeadMetadata(containerNode as NamedNode)\n return containerMetadata.access.canEdit\n } catch (_error) {\n return false\n }\n }\n\n async function userCanDeleteResource(resourceNode: NamedNode): Promise<boolean> {\n return userCanWriteToContainingContainer(resourceNode)\n }\n\n async function fetchMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n return fetchHeadMetadata(subject)\n }\n\n async function fetchMetadataWithDelete(subject: NamedNode): Promise<ResourceMetadataWithDelete> {\n let resourceMetadata: ResourceMetadata\n\n try {\n resourceMetadata = await fetchHeadMetadata(subject)\n } catch (_error) {\n resourceMetadata = {\n contentType: undefined,\n access: { canEdit: false, isPublic: false },\n aclUri: undefined,\n eTag: undefined,\n modified: undefined\n }\n }\n\n const canDelete = await userCanDeleteResource(subject)\n const access: ResourceAccessWithDelete = {\n canEdit: resourceMetadata.access?.canEdit ?? false,\n isPublic: resourceMetadata.access?.isPublic ?? false,\n canDelete\n }\n return { ...resourceMetadata, access }\n }\n\n async function deleteTypeIndexesForResource(resourceNode: NamedNode, user?: NamedNode | null) {\n if (!user) return\n\n try {\n await typeIndexLogic.deleteTypeIndexRegistrationForResource(resourceNode, user)\n } catch (_error) {\n // Keep resource deletion best-effort even if type-index cleanup fails.\n }\n }\n\n async function recursiveDelete(resourceNode: NamedNode, options: ResourceDeleteOptions = {}) {\n const resourceParent = resourceNode.dir()\n\n if (isContainer(resourceNode)) {\n const containerMembers = await containerLogic.getContainerMembers(resourceNode)\n await Promise.all(containerMembers.map((url) => recursiveDelete(sym(url), options)))\n }\n\n let deleted\n try {\n deleted = await store.fetcher._fetch(resourceNode.value, { method: 'DELETE' })\n assertSuccessfulHttpResponse(deleted, 'DELETE', { allowNotFound: true })\n } catch (error) {\n if (!isMissingError(error)) {\n throw error\n }\n }\n\n if (options.deleteTypeIndexes) {\n await deleteTypeIndexesForResource(resourceNode, options.user)\n }\n\n if (resourceParent) {\n store.removeMatches(resourceParent, ns.ldp('contains'), resourceNode, resourceParent.doc())\n }\n\n store.removeDocument(resourceNode)\n store.fetcher.unload(resourceNode.doc())\n return deleted\n }\n\n async function deleteResourceAndTypeIndexIfExists(resourceNode: NamedNode, user?: NamedNode | null) {\n await recursiveDelete(resourceNode, { deleteTypeIndexes: true, user })\n }\n\n async function checkAndRefreshEditable(resourceNode: NamedNode | null | undefined): Promise<boolean> {\n if (!resourceNode || !store.updater || !store.fetcher || typeof store.fetcher.refresh !== 'function') return false\n\n const resourceUri = resourceNode.uri || resourceNode.value || ''\n if (!resourceUri) return false\n\n const editable = store.updater.editable(resourceUri, store)\n if (editable !== false && editable !== undefined) {\n return true\n }\n\n try {\n await store.fetcher.refresh(resourceNode)\n } catch (error) {\n throw error instanceof Error ? error : new Error(`Failed to refresh <${resourceUri}>`)\n }\n\n const editableAfterRefresh = store.updater.editable(resourceUri, store)\n return editableAfterRefresh !== false && editableAfterRefresh !== undefined\n }\n\n return {\n recursiveDelete,\n deleteResourceAndTypeIndexIfExists,\n fetchMetadata,\n fetchMetadataWithDelete,\n checkAndRefreshEditable,\n createContainer,\n isContainer,\n getContainerMemberCount\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-logic",
3
- "version": "6.0.0-0",
3
+ "version": "6.0.0-1",
4
4
  "description": "Core business logic of SolidOS",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",