@paroicms/server 1.110.10 → 1.111.0

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.
Files changed (98) hide show
  1. package/ddl/main.ddl.sql +16 -1
  2. package/dist/admin-backend/account/account.queries.d.ts +2 -2
  3. package/dist/admin-backend/account/account.queries.js +5 -5
  4. package/dist/admin-backend/account/account.queries.js.map +1 -1
  5. package/dist/admin-backend/auth/auth.helper.d.ts +2 -2
  6. package/dist/admin-backend/auth/auth.helper.js.map +1 -1
  7. package/dist/admin-backend/auth/auth.types.d.ts +2 -1
  8. package/dist/admin-backend/auth/authorization.constants.d.ts +2 -0
  9. package/dist/admin-backend/auth/authorization.constants.js +11 -0
  10. package/dist/admin-backend/auth/authorization.constants.js.map +1 -0
  11. package/dist/admin-backend/auth/authorization.helper.d.ts +7 -4
  12. package/dist/admin-backend/auth/authorization.helper.js +20 -9
  13. package/dist/admin-backend/auth/authorization.helper.js.map +1 -1
  14. package/dist/admin-backend/auth/special-account.helper.js +1 -1
  15. package/dist/admin-backend/auth/special-account.helper.js.map +1 -1
  16. package/dist/admin-backend/document/load-documents.queries.js +7 -1
  17. package/dist/admin-backend/document/load-documents.queries.js.map +1 -1
  18. package/dist/admin-backend/document/save-documents.queries.js +1 -2
  19. package/dist/admin-backend/document/save-documents.queries.js.map +1 -1
  20. package/dist/admin-backend/event-log/event-log.service.js +4 -1
  21. package/dist/admin-backend/event-log/event-log.service.js.map +1 -1
  22. package/dist/admin-backend/event-log/event-log.types.d.ts +4 -4
  23. package/dist/admin-backend/lnode/lnode.queries.d.ts +1 -1
  24. package/dist/admin-backend/lnode/lnode.queries.js +2 -2
  25. package/dist/admin-backend/lnode/lnode.queries.js.map +1 -1
  26. package/dist/admin-backend/media/media-upload.controller.js +3 -2
  27. package/dist/admin-backend/media/media-upload.controller.js.map +1 -1
  28. package/dist/admin-backend/part/part.queries.js +1 -2
  29. package/dist/admin-backend/part/part.queries.js.map +1 -1
  30. package/dist/admin-backend/personal-access-token/pat.resolver.d.ts +3 -0
  31. package/dist/admin-backend/personal-access-token/pat.resolver.js +70 -0
  32. package/dist/admin-backend/personal-access-token/pat.resolver.js.map +1 -0
  33. package/dist/common/data-format.js +1 -1
  34. package/dist/common/data-format.js.map +1 -1
  35. package/dist/common/media-handles.helpers.d.ts +11 -5
  36. package/dist/common/media-handles.helpers.js +29 -12
  37. package/dist/common/media-handles.helpers.js.map +1 -1
  38. package/dist/connector/db-init/db-constants.d.ts +1 -1
  39. package/dist/connector/db-init/db-constants.js +1 -1
  40. package/dist/connector/db-init/ddl-migration.js +17 -0
  41. package/dist/connector/db-init/ddl-migration.js.map +1 -1
  42. package/dist/connector/row-types.d.ts +1 -0
  43. package/dist/express/public-api.req-handler.d.ts +1 -1
  44. package/dist/express/public-api.req-handler.js +13 -1
  45. package/dist/express/public-api.req-handler.js.map +1 -1
  46. package/dist/graphql/apollo-server-init.js +2 -0
  47. package/dist/graphql/apollo-server-init.js.map +1 -1
  48. package/dist/personal-access-token/pat-auth.helper.d.ts +6 -0
  49. package/dist/personal-access-token/pat-auth.helper.js +47 -0
  50. package/dist/personal-access-token/pat-auth.helper.js.map +1 -0
  51. package/dist/personal-access-token/pat.service.d.ts +36 -0
  52. package/dist/personal-access-token/pat.service.js +93 -0
  53. package/dist/personal-access-token/pat.service.js.map +1 -0
  54. package/dist/plugin-services/make-backend-plugin-service.js +4 -2
  55. package/dist/plugin-services/make-backend-plugin-service.js.map +1 -1
  56. package/dist/rendered-site/helpers/medias.helpers.js +1 -1
  57. package/dist/rendered-site/helpers/medias.helpers.js.map +1 -1
  58. package/dist/rendered-site/page-route/make-url.d.ts +2 -1
  59. package/dist/rendered-site/page-route/make-url.js +6 -3
  60. package/dist/rendered-site/page-route/make-url.js.map +1 -1
  61. package/dist/rendering-payload/field-values.js +4 -3
  62. package/dist/rendering-payload/field-values.js.map +1 -1
  63. package/dist/running-server/document-info.queries.d.ts +27 -0
  64. package/dist/running-server/document-info.queries.js +120 -0
  65. package/dist/running-server/document-info.queries.js.map +1 -0
  66. package/dist/running-server/get-document-api.d.ts +4 -0
  67. package/dist/running-server/get-document-api.js +121 -0
  68. package/dist/running-server/get-document-api.js.map +1 -0
  69. package/dist/running-server/markdown-content.d.ts +3 -0
  70. package/dist/running-server/markdown-content.js +25 -0
  71. package/dist/running-server/markdown-content.js.map +1 -0
  72. package/dist/running-server/media-api.d.ts +4 -0
  73. package/dist/running-server/media-api.js +43 -0
  74. package/dist/running-server/media-api.js.map +1 -0
  75. package/dist/running-server/programmatic-api-helpers.d.ts +3 -0
  76. package/dist/running-server/programmatic-api-helpers.js +6 -0
  77. package/dist/running-server/programmatic-api-helpers.js.map +1 -0
  78. package/dist/running-server/running-server-connector.d.ts +9 -1
  79. package/dist/running-server/running-server-connector.js +159 -327
  80. package/dist/running-server/running-server-connector.js.map +1 -1
  81. package/dist/running-server/search-documents-api.d.ts +11 -0
  82. package/dist/running-server/search-documents-api.js +32 -0
  83. package/dist/running-server/search-documents-api.js.map +1 -0
  84. package/dist/running-server/site-content-api.d.ts +7 -0
  85. package/dist/running-server/site-content-api.js +46 -0
  86. package/dist/running-server/site-content-api.js.map +1 -0
  87. package/dist/running-server/site-info-api.d.ts +4 -0
  88. package/dist/running-server/site-info-api.js +90 -0
  89. package/dist/running-server/site-info-api.js.map +1 -0
  90. package/dist/running-server/site-lifecycle-api.d.ts +4 -0
  91. package/dist/running-server/site-lifecycle-api.js +43 -0
  92. package/dist/running-server/site-lifecycle-api.js.map +1 -0
  93. package/dist/running-server/write-document-api.d.ts +8 -0
  94. package/dist/running-server/write-document-api.js +109 -0
  95. package/dist/running-server/write-document-api.js.map +1 -0
  96. package/dist/tsconfig.tsbuildinfo +1 -1
  97. package/package.json +17 -17
  98. package/schema.graphql +36 -0
@@ -0,0 +1,25 @@
1
+ import { getNodeTypeByName } from "@paroicms/internal-anywhere-lib";
2
+ import { createBackendPluginService } from "../plugin-services/make-backend-plugin-service.js";
3
+ export async function applyMarkdownToNativeForValues(siteContext, values, typeName, language) {
4
+ const nodeType = getNodeTypeByName(siteContext.siteSchema, typeName);
5
+ const fieldTypes = nodeType.fields ?? [];
6
+ const result = { ...values };
7
+ const list = siteContext.hooks.get("markdownToNative");
8
+ if (!list || list.length === 0)
9
+ return result;
10
+ const { handler, plugin } = list[0];
11
+ const service = createBackendPluginService(siteContext, plugin);
12
+ for (const fieldType of fieldTypes) {
13
+ const value = values[fieldType.name];
14
+ if (value === undefined || value === null)
15
+ continue;
16
+ if (typeof value !== "string")
17
+ continue;
18
+ if (fieldType.dataType !== "json" || fieldType.renderAs !== "html")
19
+ continue;
20
+ const converted = await handler({ service, value, options: { language } });
21
+ result[fieldType.name] = converted;
22
+ }
23
+ return result;
24
+ }
25
+ //# sourceMappingURL=markdown-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-content.js","sourceRoot":"","sources":["../../src/running-server/markdown-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,mDAAmD,CAAC;AAG/F,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,WAAwB,EACxB,MAAyB,EACzB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC;IACzC,MAAM,MAAM,GAAsB,EAAE,GAAG,MAAM,EAAE,CAAC;IAEhD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAE9C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,0BAA0B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEhE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QAGxC,IAAI,SAAS,CAAC,QAAQ,KAAK,MAAM,IAAI,SAAS,CAAC,QAAQ,KAAK,MAAM;YAAE,SAAS;QAE7E,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3E,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,SAA6B,CAAC;IACzD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { MSourceMedia } from "@paroicms/public-anywhere-lib";
2
+ import type { SetMediaInput } from "@paroicms/public-server-lib";
3
+ import type { SiteContext } from "../site-context/site-context.types.js";
4
+ export declare function setMediaProgrammaticApi(siteContext: SiteContext, mediaInput: SetMediaInput): Promise<MSourceMedia>;
@@ -0,0 +1,43 @@
1
+ import { getNodeTypeByName } from "@paroicms/internal-anywhere-lib";
2
+ import mime from "mime";
3
+ import { readFile } from "node:fs/promises";
4
+ import { basename } from "node:path";
5
+ import { addMediaToNode } from "../admin-backend/media/add-media-to-node.js";
6
+ import { getTypeNameOf } from "../admin-backend/node/node.queries.js";
7
+ import { getNodeIdFromHandle } from "../common/media-handles.helpers.js";
8
+ export async function setMediaProgrammaticApi(siteContext, mediaInput) {
9
+ const { handle, filePath, attachedData, replace } = mediaInput;
10
+ const nodeId = getNodeIdFromHandle(siteContext, handle);
11
+ const typeName = await getTypeNameOf(siteContext, nodeId);
12
+ const nodeType = getNodeTypeByName(siteContext.siteSchema, typeName);
13
+ return await addMediaFile(siteContext, {
14
+ nodeId,
15
+ nodeType,
16
+ handle,
17
+ path: filePath,
18
+ attachedData,
19
+ replace,
20
+ });
21
+ }
22
+ async function addMediaFile(siteContext, options) {
23
+ const { nodeId, nodeType, path, handle, attachedData, replace } = options;
24
+ const filename = basename(path);
25
+ const binaryFile = await readFile(path);
26
+ const mediaType = mime.getType(path);
27
+ if (!mediaType) {
28
+ throw new Error(`Cannot determine media type of "${path}"`);
29
+ }
30
+ return await addMediaToNode(siteContext, {
31
+ binaryFile,
32
+ originalName: filename,
33
+ weightB: binaryFile.byteLength,
34
+ mediaType,
35
+ }, {
36
+ nodeId,
37
+ nodeType,
38
+ handle,
39
+ attachedData,
40
+ replace,
41
+ });
42
+ }
43
+ //# sourceMappingURL=media-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-api.js","sourceRoot":"","sources":["../../src/running-server/media-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGpE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAGzE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,WAAwB,EACxB,UAAyB;IAEzB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAC/D,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAErE,OAAO,MAAM,YAAY,CAAC,WAAW,EAAE;QACrC,MAAM;QACN,QAAQ;QACR,MAAM;QACN,IAAI,EAAE,QAAQ;QACd,YAAY;QACZ,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,WAAwB,EACxB,OAOC;IAED,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC1E,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,GAAG,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,MAAM,cAAc,CACzB,WAAW,EACX;QACE,UAAU;QACV,YAAY,EAAE,QAAQ;QACtB,OAAO,EAAE,UAAU,CAAC,UAAU;QAC9B,SAAS;KACV,EACD;QACE,MAAM;QACN,QAAQ;QACR,MAAM;QACN,YAAY;QACZ,OAAO;KACR,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ScLabelingFieldType } from "@paroicms/public-anywhere-lib";
2
+ import type { SiteContext } from "../site-context/site-context.types.js";
3
+ export declare function getLabelingFieldTypes(siteContext: SiteContext, typeName: string): ScLabelingFieldType[];
@@ -0,0 +1,6 @@
1
+ import { getNodeTypeByName } from "@paroicms/internal-anywhere-lib";
2
+ export function getLabelingFieldTypes(siteContext, typeName) {
3
+ const docType = getNodeTypeByName(siteContext.siteSchema, typeName);
4
+ return (docType.fields ?? []).filter((f) => f.storedAs === "labeling");
5
+ }
6
+ //# sourceMappingURL=programmatic-api-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"programmatic-api-helpers.js","sourceRoot":"","sources":["../../src/running-server/programmatic-api-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAIpE,MAAM,UAAU,qBAAqB,CACnC,WAAwB,EACxB,QAAgB;IAEhB,MAAM,OAAO,GAAG,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACpE,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAA4B,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;AACnG,CAAC"}
@@ -1,2 +1,10 @@
1
- import type { RunningServerConnector } from "@paroicms/public-server-lib";
1
+ import type { RunningServerConnector, RunningSiteConnector } from "@paroicms/public-server-lib";
2
2
  export declare function createRunningServerConnector(): RunningServerConnector;
3
+ export declare function createRunningSiteConnector(input: {
4
+ authMethod: "pat";
5
+ fqdn: string;
6
+ pat: string;
7
+ } | {
8
+ authMethod: "none";
9
+ fqdn: string;
10
+ }): RunningSiteConnector;
@@ -1,22 +1,21 @@
1
- import { getDocumentTypeByName, getNodeTypeByName, getRegularDocumentTypeByName, } from "@paroicms/internal-anywhere-lib";
2
- import { generateSlug, isObj, } from "@paroicms/public-anywhere-lib";
3
- import { type } from "arktype";
4
- import mime from "mime";
5
- import { readFile, rm } from "node:fs/promises";
6
- import { basename } from "node:path";
7
- import { createDocumentOnNode, createNodeWithDocument, updateDocument, } from "../admin-backend/document/save-documents.queries.js";
8
- import { saveFieldValues } from "../admin-backend/fields/save-fields.queries.js";
9
- import { addMediaToNode } from "../admin-backend/media/add-media-to-node.js";
10
- import { getTypeNameOf } from "../admin-backend/node/node.queries.js";
11
- import { createNodeWithPart, createPartOnNode } from "../admin-backend/part/part.queries.js";
12
- import { getHandleOfFeaturedImage, getHandleOfField } from "../common/media-handles.helpers.js";
13
- import { createNewRegisteredSite } from "../connector/site-conf/site-conf.js";
14
- import { addRegisteredSite, appConf, platformLogger, registeredSites, removeRegisteredSite, } from "../context.js";
1
+ import { parseLNodeId } from "@paroicms/public-anywhere-lib";
2
+ import { permissionPatGuard } from "../admin-backend/auth/authorization.helper.js";
3
+ import { deleteDocument as deleteDocumentQuery, updateDocument as updateDocumentQuery, } from "../admin-backend/document/save-documents.queries.js";
4
+ import { getSiteFieldValue } from "../admin-backend/fields/load-fields.queries.js";
5
+ import { setLNodeReady } from "../admin-backend/lnode/lnode.queries.js";
6
+ import { getTypeNameOf, setNodePublishDate } from "../admin-backend/node/node.queries.js";
7
+ import { appConf } from "../context.js";
15
8
  import { siteReadyGuard } from "../graphql/graphql.types.js";
16
- import { hashPassword } from "../helpers/passwordEncrypt-helper.js";
17
- import { getActiveSiteContext, getSiteContext, unloadSiteContext, } from "../site-context/site-context.js";
9
+ import { getSiteContext } from "../site-context/site-context.js";
18
10
  import { migrateSiteSchemas } from "../site-schema-migration/site-schema-migration.js";
11
+ import { getFullDocumentProgrammaticApi } from "./get-document-api.js";
12
+ import { setMediaProgrammaticApi } from "./media-api.js";
13
+ import { searchDocumentsProgrammaticApi } from "./search-documents-api.js";
19
14
  import { createBlankSiteFromExisting } from "./single-site-generator.js";
15
+ import { createAccountProgrammaticApi, updateSiteFieldsProgrammaticApi, } from "./site-content-api.js";
16
+ import { buildClusterNodeInfo } from "./site-info-api.js";
17
+ import { registerNewSite, removeSite } from "./site-lifecycle-api.js";
18
+ import { createDocumentProgrammaticApi, createDocumentTranslationProgrammaticApi, createPartProgrammaticApi, createPartTranslationProgrammaticApi, updateFieldsProgrammaticApi, } from "./write-document-api.js";
20
19
  export function createRunningServerConnector() {
21
20
  return {
22
21
  getSitePackConf: (packName) => {
@@ -31,335 +30,168 @@ export function createRunningServerConnector() {
31
30
  trusted: pack.trusted !== false,
32
31
  };
33
32
  },
34
- loadSiteSchemaAndIds: async (fqdn) => {
35
- const siteContext = await getSiteContext(fqdn);
36
- siteReadyGuard(siteContext);
37
- const { siteSchema, homeRoutingCluster } = siteContext;
38
- return { siteSchema, homeRoutingCluster };
39
- },
40
- createAccount,
41
- updateSiteFields,
42
- updateNodeContent,
43
- addMultipleDocumentContents,
44
- addMultiplePartContents,
45
33
  registerNewSite,
46
- removeSite,
47
34
  migrateSiteSchemas,
48
35
  createBlankSiteFromExisting,
49
36
  };
50
37
  }
51
- async function createAccount(fqdn, account, options) {
52
- const siteContext = await getSiteContext(fqdn);
53
- siteReadyGuard(siteContext);
54
- const siteNodeId = siteContext.homeRoutingCluster.siteNodeId;
55
- const siteType = siteContext.siteSchema.nodeTypes._site;
56
- const { kind, email, name } = account;
57
- const [inserted] = await siteContext
58
- .cn("PaAccount")
59
- .insert({
60
- email,
61
- name,
62
- passwordHash: kind === "local" ? await hashPassword(account.password) : undefined,
63
- })
64
- .returning("id");
65
- const insertedId = String(type({ id: "number", "+": "reject" }).assert(inserted).id);
66
- if (account.roles.length > 0) {
67
- await siteContext
68
- .cn("PaAccountRole")
69
- .insert(account.roles.map((role) => ({ accountId: insertedId, role })));
70
- }
71
- if (options?.asContactEmail) {
72
- await saveFieldValues(siteContext, {
73
- typeName: siteType.typeName,
74
- nodeId: siteNodeId,
75
- values: {
76
- contactEmail: email,
77
- },
78
- force: true,
79
- });
80
- }
81
- return insertedId;
82
- }
83
- async function updateSiteFields(fqdn, fields) {
84
- const siteContext = await getSiteContext(fqdn);
85
- siteReadyGuard(siteContext);
86
- const siteNodeId = siteContext.homeRoutingCluster.siteNodeId;
87
- const siteType = siteContext.siteSchema.nodeTypes._site;
88
- const { multilingualFieldValues, fieldMedias } = createFieldValuesToAdd(fields, siteType.fields);
89
- for (const [language, values] of Object.entries(multilingualFieldValues)) {
90
- await saveFieldValues(siteContext, {
91
- typeName: siteType.typeName,
92
- nodeId: siteNodeId,
93
- language,
94
- values,
95
- force: true,
96
- });
97
- }
98
- for (const fieldMedia of fieldMedias) {
99
- await addFieldMedia(siteContext, fieldMedia, siteNodeId, siteType);
100
- }
101
- }
102
- async function updateNodeContent(fqdn, options) {
103
- const { nodeId, content } = options;
104
- const siteContext = await getSiteContext(fqdn);
105
- siteReadyGuard(siteContext);
106
- const typeName = await getTypeNameOf(siteContext, nodeId);
107
- const nodeType = getDocumentTypeByName(siteContext.siteSchema, typeName);
108
- const { multilingualFieldValues, fieldMedias } = createFieldValuesToAdd(content.fields, nodeType.fields ?? []);
109
- if (nodeType.kind !== content.kind) {
110
- throw new Error(`Node "${nodeId}" is of type "${nodeType.kind}", but got "${content.kind}"`);
111
- }
112
- if (content.kind === "document" && content.title) {
113
- for (const [language, title] of Object.entries(content.title)) {
114
- const slug = generateSlug(title);
115
- await updateDocument(siteContext, { nodeId, language }, { title, slug });
116
- }
117
- }
118
- for (const [language, values] of Object.entries(multilingualFieldValues)) {
119
- await saveFieldValues(siteContext, {
120
- typeName,
121
- nodeId,
122
- language,
123
- values,
124
- });
125
- }
126
- if (content.kind === "document" && content.featuredImage && nodeType.withFeaturedImage) {
127
- await addMediaFile(siteContext, {
128
- nodeId,
129
- nodeType,
130
- handle: getHandleOfFeaturedImage(nodeId),
131
- path: content.featuredImage.file,
132
- });
133
- }
134
- for (const fieldMedia of fieldMedias) {
135
- await addFieldMedia(siteContext, fieldMedia, nodeId, nodeType);
136
- }
137
- }
138
- async function addMultipleDocumentContents(fqdn, options) {
139
- const { parentNodeId, contents } = options;
140
- const siteContext = await getSiteContext(fqdn);
141
- siteReadyGuard(siteContext);
142
- const parentType = getNodeTypeByName(siteContext.siteSchema, await getTypeNameOf(siteContext, parentNodeId));
143
- if (parentType.kind !== "document") {
144
- throw new Error(`Cannot add documents as children of "${parentType.typeName}"`);
145
- }
146
- const insertedIds = [];
147
- for (const content of contents) {
148
- const typeName = content.typeName;
149
- if (!parentType.regularChildren?.includes(typeName)) {
150
- throw new Error(`Type "${typeName}" is not a regular child of "${parentType.typeName}"`);
151
- }
152
- const childType = getRegularDocumentTypeByName(siteContext.siteSchema, typeName);
153
- const { multilingualFieldValues, fieldMedias } = createFieldValuesToAdd(content.fields, childType.fields ?? []);
154
- let nodeId;
155
- for (const [language, values] of Object.entries(multilingualFieldValues)) {
156
- const title = content.title?.[language];
157
- const slug = title ? generateSlug(title) : undefined;
158
- if (nodeId === undefined) {
159
- const created = await createNodeWithDocument(siteContext, {
160
- parentId: {
161
- nodeId: parentNodeId,
162
- language,
163
- },
164
- values: { typeName, title, slug },
165
- forceReady: true,
166
- });
167
- nodeId = created.nodeId;
38
+ export function createRunningSiteConnector(input) {
39
+ const { fqdn } = input;
40
+ return {
41
+ loadSiteSchemaAndIds: async () => {
42
+ const siteContext = await getSiteContext(fqdn);
43
+ siteReadyGuard(siteContext);
44
+ if (input.authMethod === "pat") {
45
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
46
+ }
47
+ const { siteSchema, homeRoutingCluster } = siteContext;
48
+ return { siteSchema, homeRoutingCluster };
49
+ },
50
+ getSiteInfo: async () => {
51
+ const siteContext = await getSiteContext(fqdn);
52
+ siteReadyGuard(siteContext);
53
+ if (input.authMethod === "pat") {
54
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
168
55
  }
169
- else {
170
- await createDocumentOnNode(siteContext, {
56
+ const { siteSchema, homeRoutingCluster, siteNodeId } = siteContext;
57
+ const title = {};
58
+ for (const language of siteSchema.languages) {
59
+ const titleValue = await getSiteFieldValue(siteContext, {
60
+ fieldName: "title",
171
61
  language,
172
- nodeId,
173
- values: { title, slug },
174
- forceReady: true,
62
+ publishedOnly: false,
175
63
  });
64
+ title[language] = typeof titleValue === "string" ? titleValue : undefined;
176
65
  }
177
- await saveFieldValues(siteContext, { typeName, nodeId, language, values });
178
- insertedIds.push({ nodeId, language });
179
- }
180
- if (nodeId !== undefined) {
181
- if (content.featuredImage && childType.withFeaturedImage) {
182
- await addMediaFile(siteContext, {
183
- nodeId,
184
- nodeType: childType,
185
- handle: getHandleOfFeaturedImage(nodeId),
186
- path: content.featuredImage.file,
187
- });
66
+ const mainCluster = await buildClusterNodeInfo(siteContext, homeRoutingCluster);
67
+ return { siteNodeId, title, siteSchema, mainCluster };
68
+ },
69
+ createAccount: async (account, options) => {
70
+ const siteContext = await getSiteContext(fqdn);
71
+ siteReadyGuard(siteContext);
72
+ if (input.authMethod === "pat") {
73
+ await permissionPatGuard(siteContext, input.pat, "site.manageUsers");
188
74
  }
189
- for (const fieldMedia of fieldMedias) {
190
- await addFieldMedia(siteContext, fieldMedia, nodeId, childType);
75
+ return await createAccountProgrammaticApi(siteContext, account, options);
76
+ },
77
+ updateSiteFields: async (language, values) => {
78
+ const siteContext = await getSiteContext(fqdn);
79
+ siteReadyGuard(siteContext);
80
+ if (input.authMethod === "pat") {
81
+ await permissionPatGuard(siteContext, input.pat, "site.editProperties");
191
82
  }
192
- }
193
- }
194
- return insertedIds;
195
- }
196
- async function addMultiplePartContents(fqdn, options) {
197
- const { parentNodeId, contents } = options;
198
- const siteContext = await getSiteContext(fqdn);
199
- siteReadyGuard(siteContext);
200
- const parentType = getNodeTypeByName(siteContext.siteSchema, await getTypeNameOf(siteContext, parentNodeId));
201
- if (parentType.kind !== "document" && parentType.kind !== "part") {
202
- throw new Error(`Cannot add parts as children of "${parentType.typeName}"`);
203
- }
204
- const insertedIds = [];
205
- for (const content of contents) {
206
- const typeName = content.typeName;
207
- const listType = parentType.kind === "document"
208
- ? parentType.lists?.find((l) => l.parts.includes(typeName))
209
- : parentType.kind === "part"
210
- ? parentType.list
211
- : undefined;
212
- if (!listType || !listType.parts.includes(typeName)) {
213
- throw new Error(`Type "${typeName}" is not a part of "${parentType.typeName}"`);
214
- }
215
- const nodeType = getNodeTypeByName(siteContext.siteSchema, typeName);
216
- const { multilingualFieldValues, fieldMedias } = createFieldValuesToAdd(content.fields, nodeType.fields ?? []);
217
- let nodeId;
218
- for (const [language, values] of Object.entries(multilingualFieldValues)) {
219
- if (nodeId === undefined) {
220
- const created = await createNodeWithPart(siteContext, {
221
- parentLNodeId: {
222
- nodeId: parentNodeId,
223
- language,
224
- },
225
- listName: listType.listName,
226
- typeName,
227
- });
228
- nodeId = created.nodeId;
83
+ await updateSiteFieldsProgrammaticApi(siteContext, language, values);
84
+ },
85
+ removeSite: async () => {
86
+ const siteContext = await getSiteContext(fqdn);
87
+ siteReadyGuard(siteContext);
88
+ if (input.authMethod === "pat") {
89
+ await permissionPatGuard(siteContext, input.pat, "site.administer");
229
90
  }
230
- else {
231
- await createPartOnNode(siteContext, { language, nodeId });
91
+ return await removeSite(siteContext);
92
+ },
93
+ searchDocuments: async (searchInput) => {
94
+ const siteContext = await getSiteContext(fqdn);
95
+ siteReadyGuard(siteContext);
96
+ if (input.authMethod === "pat") {
97
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
232
98
  }
233
- await saveFieldValues(siteContext, { typeName, nodeId, language, values });
234
- insertedIds.push({ nodeId, language });
235
- }
236
- if (nodeId !== undefined) {
237
- for (const fieldMedia of fieldMedias) {
238
- await addFieldMedia(siteContext, fieldMedia, nodeId, nodeType);
99
+ return await searchDocumentsProgrammaticApi(siteContext, searchInput);
100
+ },
101
+ deleteDocument: async (documentId) => {
102
+ const siteContext = await getSiteContext(fqdn);
103
+ siteReadyGuard(siteContext);
104
+ if (input.authMethod === "pat") {
105
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
239
106
  }
240
- }
241
- }
242
- return insertedIds;
243
- }
244
- async function addFieldMedia(siteContext, fieldMedia, nodeId, nodeType) {
245
- const { fieldType, language, files } = fieldMedia;
246
- const handle = getHandleOfField(siteContext, {
247
- fieldType,
248
- nodeId,
249
- language,
250
- });
251
- for (const path of files) {
252
- await addMediaFile(siteContext, { nodeId, nodeType, path, handle });
253
- }
254
- }
255
- async function addMediaFile(siteContext, options) {
256
- const { nodeId, nodeType, path, handle } = options;
257
- const filename = basename(path);
258
- const binaryFile = await readFile(path);
259
- const mediaType = mime.getType(path);
260
- if (!mediaType) {
261
- throw new Error(`Cannot determine media type of "${path}"`);
262
- }
263
- await addMediaToNode(siteContext, {
264
- binaryFile,
265
- originalName: filename,
266
- weightB: binaryFile.byteLength,
267
- mediaType,
268
- }, {
269
- nodeId,
270
- nodeType,
271
- handle,
272
- });
273
- }
274
- function createFieldValuesToAdd(fields, fieldTypes) {
275
- const multilingualFieldValues = {};
276
- const medias = [];
277
- for (const fieldType of fieldTypes) {
278
- const content = fields[fieldType.name];
279
- if (!content)
280
- continue;
281
- const { dataType, localized, value } = content;
282
- if (dataType !== fieldType.dataType) {
283
- throw new Error(`Field "${fieldType.name}" has a data type of "${fieldType.dataType}" but got "${dataType}"`);
284
- }
285
- if (localized !== fieldType.localized) {
286
- throw new Error(`Field "${fieldType.name}" should be ${fieldType.localized ? "localized" : "not localized"}"`);
287
- }
288
- if (dataType === "media") {
289
- if (!value)
290
- continue;
291
- if (localized) {
292
- for (const [language, v] of Object.entries(value)) {
293
- if (!v)
294
- continue;
295
- medias.push({ fieldType, files: [v.file], language });
296
- }
107
+ await deleteDocumentQuery(siteContext, parseLNodeId(documentId));
108
+ },
109
+ publishDocument: async (documentId, publishDateStr) => {
110
+ const siteContext = await getSiteContext(fqdn);
111
+ siteReadyGuard(siteContext);
112
+ if (input.authMethod === "pat") {
113
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
297
114
  }
298
- else {
299
- medias.push({ fieldType, files: [value.file] });
115
+ const parsedId = parseLNodeId(documentId);
116
+ const publishDate = publishDateStr ? new Date(publishDateStr) : new Date();
117
+ await setNodePublishDate(siteContext, { nodeId: parsedId.nodeId, publishDate });
118
+ await setLNodeReady(siteContext, { lNodeId: parsedId, ready: true });
119
+ },
120
+ unpublishDocument: async (documentId) => {
121
+ const siteContext = await getSiteContext(fqdn);
122
+ siteReadyGuard(siteContext);
123
+ if (input.authMethod === "pat") {
124
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
300
125
  }
301
- }
302
- else if (dataType === "gallery") {
303
- if (!value)
304
- continue;
305
- if (localized) {
306
- for (const [language, v] of Object.entries(value)) {
307
- if (!v)
308
- continue;
309
- medias.push({ fieldType, files: v.files, language });
310
- }
126
+ await setLNodeReady(siteContext, { lNodeId: parseLNodeId(documentId), ready: false });
127
+ },
128
+ getDocument: async (documentId) => {
129
+ const siteContext = await getSiteContext(fqdn);
130
+ siteReadyGuard(siteContext);
131
+ if (input.authMethod === "pat") {
132
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
311
133
  }
312
- else {
313
- medias.push({ fieldType, files: value.files });
134
+ return await getFullDocumentProgrammaticApi(siteContext, parseLNodeId(documentId));
135
+ },
136
+ updateDocument: async (documentId, values) => {
137
+ const siteContext = await getSiteContext(fqdn);
138
+ siteReadyGuard(siteContext);
139
+ if (input.authMethod === "pat") {
140
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
314
141
  }
315
- }
316
- else if (localized) {
317
- for (const [language, v] of Object.entries(value)) {
318
- multilingualFieldValues[language] ??= {};
319
- multilingualFieldValues[language][fieldType.name] = v;
142
+ await updateDocumentQuery(siteContext, parseLNodeId(documentId), values);
143
+ },
144
+ updateFields: async (lNodeId, values) => {
145
+ const siteContext = await getSiteContext(fqdn);
146
+ siteReadyGuard(siteContext);
147
+ const parsedId = parseLNodeId(lNodeId);
148
+ if (input.authMethod === "pat") {
149
+ const typeName = await getTypeNameOf(siteContext, parsedId.nodeId);
150
+ const permission = typeName === "_site" ? "site.editProperties" : "document.edit";
151
+ await permissionPatGuard(siteContext, input.pat, permission);
320
152
  }
321
- }
322
- else {
323
- multilingualFieldValues["."] ??= {};
324
- multilingualFieldValues["."][fieldType.name] = value;
325
- }
326
- }
327
- return { multilingualFieldValues, fieldMedias: medias };
328
- }
329
- async function registerNewSite(options) {
330
- if (appConf.kind !== "multisite") {
331
- throw new Error("registerNewSite is only available in multisite mode");
332
- }
333
- const newRegSite = await createNewRegisteredSite(options, appConf);
334
- addRegisteredSite(newRegSite);
335
- return newRegSite;
336
- }
337
- async function removeSite(fqdn) {
338
- if (appConf.kind !== "multisite") {
339
- throw new Error("removeSite is only available in multisite mode");
340
- }
341
- const regSite = registeredSites.get(fqdn);
342
- if (!regSite)
343
- throw new Error(`unknown site "${fqdn}"`);
344
- removeRegisteredSite(fqdn);
345
- const siteContext = getActiveSiteContext(fqdn, { returnsUndef: true });
346
- if (siteContext) {
347
- await unloadSiteContext(siteContext);
348
- }
349
- const directories = Array.from(new Set([regSite.dataDir, regSite.cacheDir, regSite.backupDir, regSite.siteDir])).sort();
350
- platformLogger.info(`Remove site "${fqdn}": ${directories.join(", ")}`);
351
- for (const dir of directories) {
352
- await rmDirRecursive(dir);
353
- }
354
- }
355
- async function rmDirRecursive(dir) {
356
- try {
357
- await rm(dir, { recursive: true, force: true });
358
- }
359
- catch (error) {
360
- if (!isObj(error) || (error.code !== "ENOENT" && error.code !== "ENOTDIR")) {
361
- throw error;
362
- }
363
- }
153
+ await updateFieldsProgrammaticApi(siteContext, parsedId, values);
154
+ },
155
+ createDocument: async (createInput) => {
156
+ const siteContext = await getSiteContext(fqdn);
157
+ siteReadyGuard(siteContext);
158
+ if (input.authMethod === "pat") {
159
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
160
+ }
161
+ return await createDocumentProgrammaticApi(siteContext, createInput);
162
+ },
163
+ createDocumentTranslation: async (createInput) => {
164
+ const siteContext = await getSiteContext(fqdn);
165
+ siteReadyGuard(siteContext);
166
+ if (input.authMethod === "pat") {
167
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
168
+ }
169
+ return await createDocumentTranslationProgrammaticApi(siteContext, createInput);
170
+ },
171
+ createPart: async (createInput) => {
172
+ const siteContext = await getSiteContext(fqdn);
173
+ siteReadyGuard(siteContext);
174
+ if (input.authMethod === "pat") {
175
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
176
+ }
177
+ return await createPartProgrammaticApi(siteContext, createInput);
178
+ },
179
+ createPartTranslation: async (createInput) => {
180
+ const siteContext = await getSiteContext(fqdn);
181
+ siteReadyGuard(siteContext);
182
+ if (input.authMethod === "pat") {
183
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
184
+ }
185
+ return await createPartTranslationProgrammaticApi(siteContext, createInput);
186
+ },
187
+ setMedia: async (mediaInput) => {
188
+ const siteContext = await getSiteContext(fqdn);
189
+ siteReadyGuard(siteContext);
190
+ if (input.authMethod === "pat") {
191
+ await permissionPatGuard(siteContext, input.pat, "document.edit");
192
+ }
193
+ return await setMediaProgrammaticApi(siteContext, mediaInput);
194
+ },
195
+ };
364
196
  }
365
197
  //# sourceMappingURL=running-server-connector.js.map