@memberjunction/core-actions 6.2.0-edge.0 → 6.2.0-edge.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.
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -4
- package/dist/config.js.map +1 -1
- package/dist/custom/ai/base-find-actions.action.js +6 -6
- package/dist/custom/ai/base-find-agents.action.js +6 -6
- package/dist/custom/ai/find-candidate-agents.action.js +2 -2
- package/dist/custom/ai/semantic-entity-search.helper.d.ts +6 -0
- package/dist/custom/ai/semantic-entity-search.helper.d.ts.map +1 -1
- package/dist/custom/ai/semantic-entity-search.helper.js +16 -4
- package/dist/custom/ai/semantic-entity-search.helper.js.map +1 -1
- package/dist/custom/data/search-query-catalog.action.js +2 -2
- package/dist/custom/integration/api-rate-limiter.action.d.ts +4 -0
- package/dist/custom/integration/api-rate-limiter.action.d.ts.map +1 -1
- package/dist/custom/integration/api-rate-limiter.action.js +10 -2
- package/dist/custom/integration/api-rate-limiter.action.js.map +1 -1
- package/dist/custom/integration/gamma-generate-presentation.action.js +2 -2
- package/dist/custom/integration/integration-action-executor.d.ts +22 -22
- package/dist/custom/integration/integration-action-executor.js +83 -83
- package/dist/custom/interactive-forms/_shared.d.ts +69 -0
- package/dist/custom/interactive-forms/_shared.d.ts.map +1 -1
- package/dist/custom/interactive-forms/_shared.js +118 -38
- package/dist/custom/interactive-forms/_shared.js.map +1 -1
- package/dist/custom/interactive-forms/activate-interactive-form-version.action.js +25 -25
- package/dist/custom/interactive-forms/create-interactive-form.action.js +22 -22
- package/dist/custom/interactive-forms/modify-interactive-form.action.js +35 -35
- package/dist/custom/interactive-forms/revert-interactive-form.action.js +32 -32
- package/dist/custom/lists/_action-helpers.d.ts +10 -0
- package/dist/custom/lists/_action-helpers.d.ts.map +1 -1
- package/dist/custom/lists/_action-helpers.js +26 -6
- package/dist/custom/lists/_action-helpers.js.map +1 -1
- package/dist/custom/lists/add-view-results-to-list.action.js +8 -8
- package/dist/custom/lists/bulk-update-list-item-status.action.js +8 -8
- package/dist/custom/lists/compose-lists.action.js +14 -14
- package/dist/custom/lists/invite-to-list.action.js +10 -10
- package/dist/custom/lists/materialize-list-from-view.action.js +13 -13
- package/dist/custom/lists/move-list-members.action.js +12 -12
- package/dist/custom/lists/refresh-list-from-source.action.js +8 -8
- package/dist/custom/lists/resolve-audience.action.js +7 -7
- package/dist/custom/lists/revoke-list-invitation.action.js +3 -3
- package/dist/custom/lists/share-list.action.js +8 -8
- package/dist/custom/lists/unshare-list.action.js +3 -3
- package/dist/custom/utilities/address-services.action.js +2 -2
- package/dist/custom/utilities/artifact-builder-service.d.ts +16 -16
- package/dist/custom/utilities/artifact-builder-service.js +39 -39
- package/dist/custom/utilities/artifact-builder-service.js.map +1 -1
- package/dist/custom/utilities/docx-renderer.d.ts +17 -11
- package/dist/custom/utilities/docx-renderer.d.ts.map +1 -1
- package/dist/custom/utilities/docx-renderer.js +60 -48
- package/dist/custom/utilities/docx-renderer.js.map +1 -1
- package/dist/custom/utilities/json-param-helper.d.ts +6 -0
- package/dist/custom/utilities/json-param-helper.d.ts.map +1 -1
- package/dist/custom/utilities/json-param-helper.js +16 -4
- package/dist/custom/utilities/json-param-helper.js.map +1 -1
- package/dist/custom/utilities/pdf-renderer.d.ts +13 -7
- package/dist/custom/utilities/pdf-renderer.d.ts.map +1 -1
- package/dist/custom/utilities/pdf-renderer.js +27 -15
- package/dist/custom/utilities/pdf-renderer.js.map +1 -1
- package/dist/custom/utilities/xlsx-renderer.d.ts +19 -11
- package/dist/custom/utilities/xlsx-renderer.d.ts.map +1 -1
- package/dist/custom/utilities/xlsx-renderer.js +55 -39
- package/dist/custom/utilities/xlsx-renderer.js.map +1 -1
- package/dist/custom/visualization/create-svg-chart.action.js +23 -23
- package/dist/custom/visualization/create-svg-diagram.action.js +10 -10
- package/dist/custom/visualization/create-svg-infographic.action.js +4 -4
- package/dist/custom/visualization/create-svg-network.action.js +12 -12
- package/dist/custom/visualization/create-svg-sketch-diagram.action.js +10 -10
- package/dist/custom/visualization/create-svg-word-cloud.action.js +11 -11
- package/dist/custom/visualization/shared/svg-theming.d.ts +17 -0
- package/dist/custom/visualization/shared/svg-theming.d.ts.map +1 -1
- package/dist/custom/visualization/shared/svg-theming.js +34 -10
- package/dist/custom/visualization/shared/svg-theming.js.map +1 -1
- package/dist/custom/visualization/shared/svg-utils.d.ts +39 -0
- package/dist/custom/visualization/shared/svg-utils.d.ts.map +1 -1
- package/dist/custom/visualization/shared/svg-utils.js +81 -17
- package/dist/custom/visualization/shared/svg-utils.js.map +1 -1
- package/dist/custom/web/duckduckgo-rate-limiter.d.ts +17 -1
- package/dist/custom/web/duckduckgo-rate-limiter.d.ts.map +1 -1
- package/dist/custom/web/duckduckgo-rate-limiter.js +26 -6
- package/dist/custom/web/duckduckgo-rate-limiter.js.map +1 -1
- package/dist/custom/web/google-custom-search.action.js +2 -2
- package/dist/custom/web/rss-feed-parsing.d.ts +19 -0
- package/dist/custom/web/rss-feed-parsing.d.ts.map +1 -1
- package/dist/custom/web/rss-feed-parsing.js +45 -13
- package/dist/custom/web/rss-feed-parsing.js.map +1 -1
- package/dist/custom/web/rss-feed-read.action.js +5 -5
- package/dist/custom/web/tavily-search.action.js +2 -2
- package/package.json +40 -40
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { ListOperations } from '@memberjunction/lists';
|
|
10
|
-
import {
|
|
10
|
+
import { AddOutputParam, GetBooleanParam, GetStringParam, MissingParam, } from './_action-helpers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Materialize a new MJ List from a User View. Thin wrapper around
|
|
13
13
|
* `ListOperations.MaterializeFromView` — every drop-guard, permission, and
|
|
@@ -30,13 +30,13 @@ import { addOutputParam, getBooleanParam, getStringParam, missingParam, } from '
|
|
|
30
30
|
*/
|
|
31
31
|
let MaterializeListFromViewAction = class MaterializeListFromViewAction extends BaseAction {
|
|
32
32
|
async InternalRunAction(params) {
|
|
33
|
-
const viewId =
|
|
34
|
-
const listName =
|
|
33
|
+
const viewId = GetStringParam(params, 'ViewID');
|
|
34
|
+
const listName = GetStringParam(params, 'ListName');
|
|
35
35
|
if (!viewId)
|
|
36
|
-
return
|
|
36
|
+
return MissingParam('ViewID');
|
|
37
37
|
if (!listName)
|
|
38
|
-
return
|
|
39
|
-
const refreshMode = (
|
|
38
|
+
return MissingParam('ListName');
|
|
39
|
+
const refreshMode = (GetStringParam(params, 'RefreshMode') ?? 'Additive');
|
|
40
40
|
if (refreshMode !== 'Additive' && refreshMode !== 'Sync') {
|
|
41
41
|
return {
|
|
42
42
|
Success: false,
|
|
@@ -46,17 +46,17 @@ let MaterializeListFromViewAction = class MaterializeListFromViewAction extends
|
|
|
46
46
|
}
|
|
47
47
|
const opts = {
|
|
48
48
|
ListName: listName,
|
|
49
|
-
CategoryId:
|
|
50
|
-
Description:
|
|
51
|
-
RememberLineage:
|
|
52
|
-
UseSnapshot:
|
|
49
|
+
CategoryId: GetStringParam(params, 'CategoryID'),
|
|
50
|
+
Description: GetStringParam(params, 'Description'),
|
|
51
|
+
RememberLineage: GetBooleanParam(params, 'RememberLineage', true),
|
|
52
|
+
UseSnapshot: GetBooleanParam(params, 'UseSnapshot', false),
|
|
53
53
|
RefreshMode: refreshMode,
|
|
54
54
|
};
|
|
55
55
|
const ops = new ListOperations(params.ContextUser, params.Provider);
|
|
56
56
|
const result = await ops.MaterializeFromView(viewId, opts);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
AddOutputParam(params, 'CreatedListID', result.CreatedListId);
|
|
58
|
+
AddOutputParam(params, 'Added', result.Counts?.Added);
|
|
59
|
+
AddOutputParam(params, 'Failed', result.Counts?.Failed);
|
|
60
60
|
return {
|
|
61
61
|
Success: result.Success,
|
|
62
62
|
ResultCode: result.ResultCode,
|
|
@@ -8,7 +8,7 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
8
8
|
import { Metadata, RunView } from '@memberjunction/core';
|
|
9
9
|
import { RegisterClass } from '@memberjunction/global';
|
|
10
10
|
import { ListOperations } from '@memberjunction/lists';
|
|
11
|
-
import {
|
|
11
|
+
import { AddOutputParam, GetBooleanParam, GetJsonParam, GetStringParam, MissingParam, } from './_action-helpers.js';
|
|
12
12
|
/**
|
|
13
13
|
* Move a set of records from one list to another. Implemented as a
|
|
14
14
|
* thin wrapper over `ListOperations` semantics:
|
|
@@ -25,13 +25,13 @@ import { addOutputParam, getBooleanParam, getJsonParam, getStringParam, missingP
|
|
|
25
25
|
*/
|
|
26
26
|
let MoveListMembersAction = class MoveListMembersAction extends BaseAction {
|
|
27
27
|
async InternalRunAction(params) {
|
|
28
|
-
const sourceListId =
|
|
29
|
-
const targetListId =
|
|
30
|
-
const recordIds =
|
|
28
|
+
const sourceListId = GetStringParam(params, 'SourceListID');
|
|
29
|
+
const targetListId = GetStringParam(params, 'TargetListID');
|
|
30
|
+
const recordIds = GetJsonParam(params, 'RecordIDs');
|
|
31
31
|
if (!sourceListId)
|
|
32
|
-
return
|
|
32
|
+
return MissingParam('SourceListID');
|
|
33
33
|
if (!targetListId)
|
|
34
|
-
return
|
|
34
|
+
return MissingParam('TargetListID');
|
|
35
35
|
if (!recordIds || !Array.isArray(recordIds) || recordIds.length === 0) {
|
|
36
36
|
return {
|
|
37
37
|
Success: false,
|
|
@@ -39,7 +39,7 @@ let MoveListMembersAction = class MoveListMembersAction extends BaseAction {
|
|
|
39
39
|
Message: "'RecordIDs' must be a JSON-stringified non-empty string array",
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
const mode = (
|
|
42
|
+
const mode = (GetStringParam(params, 'Mode') ?? 'move').toLowerCase();
|
|
43
43
|
if (mode !== 'move' && mode !== 'copy') {
|
|
44
44
|
return {
|
|
45
45
|
Success: false,
|
|
@@ -47,7 +47,7 @@ let MoveListMembersAction = class MoveListMembersAction extends BaseAction {
|
|
|
47
47
|
Message: `Mode must be 'move' or 'copy' (got '${mode}')`,
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
const confirmDrops =
|
|
50
|
+
const confirmDrops = GetBooleanParam(params, 'ConfirmDrops', false);
|
|
51
51
|
if (mode === 'move' && !confirmDrops) {
|
|
52
52
|
return {
|
|
53
53
|
Success: false,
|
|
@@ -129,10 +129,10 @@ let MoveListMembersAction = class MoveListMembersAction extends BaseAction {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
AddOutputParam(params, 'Added', added);
|
|
133
|
+
AddOutputParam(params, 'Removed', removed);
|
|
134
|
+
AddOutputParam(params, 'Failed', failedAdds);
|
|
135
|
+
AddOutputParam(params, 'Errors', errors);
|
|
136
136
|
const success = failedAdds === 0 && errors.length === failedAdds;
|
|
137
137
|
return {
|
|
138
138
|
Success: success,
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { ListOperations } from '@memberjunction/lists';
|
|
10
|
-
import {
|
|
10
|
+
import { AddOutputParam, GetBooleanParam, GetStringParam, MissingParam, } from './_action-helpers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Refresh an existing List against its captured source view.
|
|
13
13
|
*
|
|
@@ -19,10 +19,10 @@ import { addOutputParam, getBooleanParam, getStringParam, missingParam, } from '
|
|
|
19
19
|
*/
|
|
20
20
|
let RefreshListFromSourceAction = class RefreshListFromSourceAction extends BaseAction {
|
|
21
21
|
async InternalRunAction(params) {
|
|
22
|
-
const listId =
|
|
22
|
+
const listId = GetStringParam(params, 'ListID');
|
|
23
23
|
if (!listId)
|
|
24
|
-
return
|
|
25
|
-
const mode = (
|
|
24
|
+
return MissingParam('ListID');
|
|
25
|
+
const mode = (GetStringParam(params, 'Mode') ?? 'Additive');
|
|
26
26
|
if (mode !== 'Additive' && mode !== 'Sync') {
|
|
27
27
|
return {
|
|
28
28
|
Success: false,
|
|
@@ -30,12 +30,12 @@ let RefreshListFromSourceAction = class RefreshListFromSourceAction extends Base
|
|
|
30
30
|
Message: `Mode must be 'Additive' or 'Sync', got '${mode}'`,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
const confirmDrops =
|
|
33
|
+
const confirmDrops = GetBooleanParam(params, 'ConfirmDrops', false);
|
|
34
34
|
const ops = new ListOperations(params.ContextUser, params.Provider);
|
|
35
35
|
const result = await ops.RefreshFromSource(listId, mode, { ConfirmDrops: confirmDrops });
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
AddOutputParam(params, 'Added', result.Counts?.Added);
|
|
37
|
+
AddOutputParam(params, 'Removed', result.Counts?.Removed);
|
|
38
|
+
AddOutputParam(params, 'Failed', result.Counts?.Failed);
|
|
39
39
|
return {
|
|
40
40
|
Success: result.Success,
|
|
41
41
|
ResultCode: result.ResultCode,
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { AudienceResolver } from '@memberjunction/lists';
|
|
10
|
-
import {
|
|
10
|
+
import { AddOutputParam, GetJsonParam, GetStringParam, MissingParam, } from './_action-helpers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Resolve an `AudienceSource` to its current record IDs.
|
|
13
13
|
*
|
|
@@ -20,14 +20,14 @@ import { addOutputParam, getJsonParam, getStringParam, missingParam, } from './_
|
|
|
20
20
|
*/
|
|
21
21
|
let ResolveAudienceAction = class ResolveAudienceAction extends BaseAction {
|
|
22
22
|
async InternalRunAction(params) {
|
|
23
|
-
const source =
|
|
23
|
+
const source = GetJsonParam(params, 'Source');
|
|
24
24
|
if (!source) {
|
|
25
25
|
// Surface a clear contract hint — `getJsonParam` swallows parse
|
|
26
26
|
// errors, so the caller might be supplying a non-JSON string by
|
|
27
27
|
// mistake. Distinguish missing vs unparseable for grep-ability.
|
|
28
|
-
const raw =
|
|
28
|
+
const raw = GetStringParam(params, 'Source');
|
|
29
29
|
if (raw == null || raw.length === 0)
|
|
30
|
-
return
|
|
30
|
+
return MissingParam('Source');
|
|
31
31
|
return {
|
|
32
32
|
Success: false,
|
|
33
33
|
ResultCode: 'INVALID_PARAMETER',
|
|
@@ -37,9 +37,9 @@ let ResolveAudienceAction = class ResolveAudienceAction extends BaseAction {
|
|
|
37
37
|
const resolver = new AudienceResolver(params.ContextUser, params.Provider);
|
|
38
38
|
try {
|
|
39
39
|
const resolved = await resolver.Resolve(source);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
AddOutputParam(params, 'EntityName', resolved.EntityName);
|
|
41
|
+
AddOutputParam(params, 'RecordCount', resolved.RecordIds.length);
|
|
42
|
+
AddOutputParam(params, 'RecordIDs', resolved.RecordIds);
|
|
43
43
|
return {
|
|
44
44
|
Success: true,
|
|
45
45
|
ResultCode: 'SUCCESS',
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { ListSharing } from '@memberjunction/lists';
|
|
10
|
-
import {
|
|
10
|
+
import { GetStringParam, MissingParam } from './_action-helpers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Revoke a pending List invitation before acceptance. Once an invitation
|
|
13
13
|
* has been accepted, callers should `Unshare List` the resulting
|
|
@@ -16,9 +16,9 @@ import { getStringParam, missingParam } from './_action-helpers.js';
|
|
|
16
16
|
*/
|
|
17
17
|
let RevokeListInvitationAction = class RevokeListInvitationAction extends BaseAction {
|
|
18
18
|
async InternalRunAction(params) {
|
|
19
|
-
const invitationId =
|
|
19
|
+
const invitationId = GetStringParam(params, 'InvitationID');
|
|
20
20
|
if (!invitationId)
|
|
21
|
-
return
|
|
21
|
+
return MissingParam('InvitationID');
|
|
22
22
|
const sharing = new ListSharing(params.ContextUser, params.Provider);
|
|
23
23
|
const result = await sharing.RevokeInvitation(invitationId);
|
|
24
24
|
return { Success: result.Success, ResultCode: result.ResultCode, Message: result.Message };
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { ListSharing } from '@memberjunction/lists';
|
|
10
|
-
import {
|
|
10
|
+
import { AddOutputParam, GetStringParam, MissingParam } from './_action-helpers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Grant a direct share on a List to a user or role. Mirrors
|
|
13
13
|
* `ListSharing.Share` — idempotent at the (list, target) pair.
|
|
@@ -20,11 +20,11 @@ import { addOutputParam, getStringParam, missingParam } from './_action-helpers.
|
|
|
20
20
|
*/
|
|
21
21
|
let ShareListAction = class ShareListAction extends BaseAction {
|
|
22
22
|
async InternalRunAction(params) {
|
|
23
|
-
const listId =
|
|
24
|
-
const targetKind =
|
|
25
|
-
const targetId =
|
|
23
|
+
const listId = GetStringParam(params, 'ListID');
|
|
24
|
+
const targetKind = GetStringParam(params, 'TargetKind');
|
|
25
|
+
const targetId = GetStringParam(params, 'TargetID');
|
|
26
26
|
if (!listId)
|
|
27
|
-
return
|
|
27
|
+
return MissingParam('ListID');
|
|
28
28
|
if (targetKind !== 'user' && targetKind !== 'role') {
|
|
29
29
|
return {
|
|
30
30
|
Success: false,
|
|
@@ -33,8 +33,8 @@ let ShareListAction = class ShareListAction extends BaseAction {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
if (!targetId)
|
|
36
|
-
return
|
|
37
|
-
const level = (
|
|
36
|
+
return MissingParam('TargetID');
|
|
37
|
+
const level = (GetStringParam(params, 'PermissionLevel') ?? 'View');
|
|
38
38
|
if (level !== 'View' && level !== 'Edit' && level !== 'Owner') {
|
|
39
39
|
return {
|
|
40
40
|
Success: false,
|
|
@@ -45,7 +45,7 @@ let ShareListAction = class ShareListAction extends BaseAction {
|
|
|
45
45
|
const target = targetKind === 'user' ? { kind: 'user', userId: targetId } : { kind: 'role', roleId: targetId };
|
|
46
46
|
const sharing = new ListSharing(params.ContextUser, params.Provider);
|
|
47
47
|
const result = await sharing.Share({ ListID: listId, Target: target, PermissionLevel: level });
|
|
48
|
-
|
|
48
|
+
AddOutputParam(params, 'PermissionID', result.PermissionID);
|
|
49
49
|
return { Success: result.Success, ResultCode: result.ResultCode, Message: result.Message };
|
|
50
50
|
}
|
|
51
51
|
};
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { BaseAction } from '@memberjunction/actions';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { ListSharing } from '@memberjunction/lists';
|
|
10
|
-
import {
|
|
10
|
+
import { GetStringParam, MissingParam } from './_action-helpers.js';
|
|
11
11
|
/**
|
|
12
12
|
* Revoke a previously-granted permission row. Soft-revokes (sets
|
|
13
13
|
* `Status='Revoked'` on `MJResourcePermission`) so the audit trail
|
|
@@ -15,9 +15,9 @@ import { getStringParam, missingParam } from './_action-helpers.js';
|
|
|
15
15
|
*/
|
|
16
16
|
let UnshareListAction = class UnshareListAction extends BaseAction {
|
|
17
17
|
async InternalRunAction(params) {
|
|
18
|
-
const permissionId =
|
|
18
|
+
const permissionId = GetStringParam(params, 'PermissionID');
|
|
19
19
|
if (!permissionId)
|
|
20
|
-
return
|
|
20
|
+
return MissingParam('PermissionID');
|
|
21
21
|
const sharing = new ListSharing(params.ContextUser, params.Provider);
|
|
22
22
|
const result = await sharing.Unshare(permissionId);
|
|
23
23
|
return { Success: result.Success, ResultCode: result.ResultCode, Message: result.Message };
|
|
@@ -8,13 +8,13 @@ import { BaseAction } from "@memberjunction/actions";
|
|
|
8
8
|
import { RegisterClass } from "@memberjunction/global";
|
|
9
9
|
import { HttpPost, IsHttpError } from "@memberjunction/network-utils";
|
|
10
10
|
import { GeocodingProviderRegistry } from "@memberjunction/geo-core";
|
|
11
|
-
import {
|
|
11
|
+
import { GetApiIntegrationsConfig } from "../../config.js";
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
// Helper: get Google API key from config (used by ValidateAddressAction only;
|
|
14
14
|
// the geocoding actions below now resolve their provider via the registry)
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
function getGoogleApiKey() {
|
|
17
|
-
const config =
|
|
17
|
+
const config = GetApiIntegrationsConfig();
|
|
18
18
|
return config.google?.geocoding?.apiKey
|
|
19
19
|
|| process.env.GOOGLE_GEOCODING_API_KEY
|
|
20
20
|
|| process.env.GOOGLE_MAPS_API_KEY;
|
|
@@ -3,9 +3,9 @@ import { WordOptions } from './docx-renderer.js';
|
|
|
3
3
|
import { ExcelOptions } from './xlsx-renderer.js';
|
|
4
4
|
export type DocumentType = 'pdf' | 'docx' | 'xlsx';
|
|
5
5
|
export interface DocumentOptions {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Pdf?: Partial<PDFOptions>;
|
|
7
|
+
Word?: Partial<WordOptions>;
|
|
8
|
+
Excel?: Partial<ExcelOptions>;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* A single content operation that can be added to a document.
|
|
@@ -13,13 +13,13 @@ export interface DocumentOptions {
|
|
|
13
13
|
*/
|
|
14
14
|
export type DocumentOperation = {
|
|
15
15
|
type: 'heading';
|
|
16
|
-
|
|
16
|
+
Level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
17
17
|
text: string;
|
|
18
18
|
} | {
|
|
19
19
|
type: 'paragraph';
|
|
20
20
|
text: string;
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
Bold?: boolean;
|
|
22
|
+
Italic?: boolean;
|
|
23
23
|
align?: string;
|
|
24
24
|
} | {
|
|
25
25
|
type: 'table';
|
|
@@ -27,14 +27,14 @@ export type DocumentOperation = {
|
|
|
27
27
|
rows: string[][];
|
|
28
28
|
} | {
|
|
29
29
|
type: 'list';
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
Items: string[];
|
|
31
|
+
Ordered?: boolean;
|
|
32
32
|
} | {
|
|
33
33
|
type: 'image';
|
|
34
34
|
src: string;
|
|
35
35
|
width?: number;
|
|
36
36
|
height?: number;
|
|
37
|
-
|
|
37
|
+
Caption?: string;
|
|
38
38
|
} | {
|
|
39
39
|
type: 'pageBreak';
|
|
40
40
|
} | {
|
|
@@ -44,16 +44,16 @@ export type DocumentOperation = {
|
|
|
44
44
|
name: string;
|
|
45
45
|
data: Record<string, unknown>[];
|
|
46
46
|
headers?: string[];
|
|
47
|
-
|
|
47
|
+
ColumnWidths?: number[];
|
|
48
48
|
} | {
|
|
49
49
|
type: 'formula';
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
Sheet: string;
|
|
51
|
+
Cell: string;
|
|
52
|
+
Formula: string;
|
|
53
53
|
};
|
|
54
54
|
export interface DocumentSectionInfo {
|
|
55
55
|
id: string;
|
|
56
|
-
|
|
56
|
+
Operations: DocumentOperation[];
|
|
57
57
|
}
|
|
58
58
|
export interface InProgressDocument {
|
|
59
59
|
handle: string;
|
|
@@ -61,8 +61,8 @@ export interface InProgressDocument {
|
|
|
61
61
|
fileName: string;
|
|
62
62
|
options: DocumentOptions;
|
|
63
63
|
sections: DocumentSectionInfo[];
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
CreatedAt: Date;
|
|
65
|
+
LastModifiedAt: Date;
|
|
66
66
|
}
|
|
67
67
|
export interface DocumentPreview {
|
|
68
68
|
handle: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DEFAULT_PDF_OPTIONS,
|
|
2
|
-
import { DEFAULT_WORD_OPTIONS,
|
|
3
|
-
import {
|
|
1
|
+
import { DEFAULT_PDF_OPTIONS, RenderPDFFromNodes } from './pdf-renderer.js';
|
|
2
|
+
import { DEFAULT_WORD_OPTIONS, RenderDocxFromSections } from './docx-renderer.js';
|
|
3
|
+
import { RenderExcelFromSheets } from './xlsx-renderer.js';
|
|
4
4
|
// ── TTL ───────────────────────────────────────────────────────────────────────
|
|
5
5
|
const TTL_MS = 30 * 60 * 1000; // 30 minutes
|
|
6
6
|
const CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // Check every 5 minutes
|
|
@@ -36,8 +36,8 @@ export class ArtifactBuilderService {
|
|
|
36
36
|
fileName: fileName || defaultFileName,
|
|
37
37
|
options: options || {},
|
|
38
38
|
sections: [],
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
CreatedAt: new Date(),
|
|
40
|
+
LastModifiedAt: new Date(),
|
|
41
41
|
};
|
|
42
42
|
this.documents.set(handle, doc);
|
|
43
43
|
return handle;
|
|
@@ -49,8 +49,8 @@ export class ArtifactBuilderService {
|
|
|
49
49
|
AddContent(handle, operations) {
|
|
50
50
|
const doc = this.getDocument(handle);
|
|
51
51
|
const sectionId = crypto.randomUUID();
|
|
52
|
-
doc.sections.push({ id: sectionId, operations });
|
|
53
|
-
doc.
|
|
52
|
+
doc.sections.push({ id: sectionId, Operations: operations });
|
|
53
|
+
doc.LastModifiedAt = new Date();
|
|
54
54
|
return [sectionId];
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
@@ -65,10 +65,10 @@ export class ArtifactBuilderService {
|
|
|
65
65
|
sectionCount: doc.sections.length,
|
|
66
66
|
sections: doc.sections.map(s => ({
|
|
67
67
|
id: s.id,
|
|
68
|
-
operationCount: s.
|
|
68
|
+
operationCount: s.Operations.length,
|
|
69
69
|
summary: this.summarizeSection(s),
|
|
70
70
|
})),
|
|
71
|
-
totalOperations: doc.sections.reduce((sum, s) => sum + s.
|
|
71
|
+
totalOperations: doc.sections.reduce((sum, s) => sum + s.Operations.length, 0),
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
@@ -80,8 +80,8 @@ export class ArtifactBuilderService {
|
|
|
80
80
|
if (!section) {
|
|
81
81
|
throw new Error(`Section "${sectionId}" not found in document "${handle}"`);
|
|
82
82
|
}
|
|
83
|
-
section.
|
|
84
|
-
doc.
|
|
83
|
+
section.Operations = operations;
|
|
84
|
+
doc.LastModifiedAt = new Date();
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
87
|
* Remove a section by ID.
|
|
@@ -93,7 +93,7 @@ export class ArtifactBuilderService {
|
|
|
93
93
|
throw new Error(`Section "${sectionId}" not found in document "${handle}"`);
|
|
94
94
|
}
|
|
95
95
|
doc.sections.splice(index, 1);
|
|
96
|
-
doc.
|
|
96
|
+
doc.LastModifiedAt = new Date();
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
99
|
* Render the accumulated document to a binary buffer.
|
|
@@ -104,20 +104,20 @@ export class ArtifactBuilderService {
|
|
|
104
104
|
if (doc.sections.length === 0) {
|
|
105
105
|
throw new Error(`Cannot finalize an empty document (handle: "${handle}")`);
|
|
106
106
|
}
|
|
107
|
-
const allOperations = doc.sections.flatMap(s => s.
|
|
107
|
+
const allOperations = doc.sections.flatMap(s => s.Operations);
|
|
108
108
|
let buffer;
|
|
109
109
|
let mimeType;
|
|
110
110
|
switch (doc.documentType) {
|
|
111
111
|
case 'pdf':
|
|
112
|
-
buffer = await this.finalizePDF(allOperations, doc.options.
|
|
112
|
+
buffer = await this.finalizePDF(allOperations, doc.options.Pdf);
|
|
113
113
|
mimeType = 'application/pdf';
|
|
114
114
|
break;
|
|
115
115
|
case 'docx':
|
|
116
|
-
buffer = await this.finalizeDocx(allOperations, doc.options.
|
|
116
|
+
buffer = await this.finalizeDocx(allOperations, doc.options.Word);
|
|
117
117
|
mimeType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
|
|
118
118
|
break;
|
|
119
119
|
case 'xlsx':
|
|
120
|
-
buffer = await this.finalizeXlsx(allOperations, doc.options.
|
|
120
|
+
buffer = await this.finalizeXlsx(allOperations, doc.options.Excel);
|
|
121
121
|
mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|
122
122
|
break;
|
|
123
123
|
default:
|
|
@@ -143,19 +143,19 @@ export class ArtifactBuilderService {
|
|
|
143
143
|
async finalizePDF(operations, pdfOpts) {
|
|
144
144
|
const options = { ...DEFAULT_PDF_OPTIONS, ...pdfOpts };
|
|
145
145
|
const nodes = this.operationsToPDFNodes(operations);
|
|
146
|
-
return
|
|
146
|
+
return RenderPDFFromNodes(nodes, options);
|
|
147
147
|
}
|
|
148
148
|
async finalizeDocx(operations, wordOpts) {
|
|
149
149
|
const options = { ...DEFAULT_WORD_OPTIONS, ...wordOpts };
|
|
150
150
|
const sections = this.operationsToDocxSections(operations);
|
|
151
|
-
return
|
|
151
|
+
return RenderDocxFromSections(sections, options);
|
|
152
152
|
}
|
|
153
153
|
async finalizeXlsx(operations, excelOpts) {
|
|
154
154
|
const sheets = this.operationsToSheets(operations);
|
|
155
155
|
if (sheets.length === 0) {
|
|
156
156
|
throw new Error('No sheet operations found. Excel documents require at least one "sheet" operation.');
|
|
157
157
|
}
|
|
158
|
-
const result = await
|
|
158
|
+
const result = await RenderExcelFromSheets(sheets, excelOpts || {});
|
|
159
159
|
return result.buffer;
|
|
160
160
|
}
|
|
161
161
|
// ── Operation → renderer format converters ────────────────────────────────
|
|
@@ -164,19 +164,19 @@ export class ArtifactBuilderService {
|
|
|
164
164
|
for (const op of operations) {
|
|
165
165
|
switch (op.type) {
|
|
166
166
|
case 'heading':
|
|
167
|
-
nodes.push({ type: 'heading',
|
|
167
|
+
nodes.push({ type: 'heading', Level: op.Level, text: op.text });
|
|
168
168
|
break;
|
|
169
169
|
case 'paragraph':
|
|
170
|
-
nodes.push({ type: 'paragraph', text: op.text,
|
|
170
|
+
nodes.push({ type: 'paragraph', text: op.text, Bold: op.Bold, Italic: op.Italic });
|
|
171
171
|
break;
|
|
172
172
|
case 'table':
|
|
173
173
|
nodes.push({ type: 'table', headers: op.headers, rows: op.rows });
|
|
174
174
|
break;
|
|
175
175
|
case 'list':
|
|
176
|
-
nodes.push({ type: 'list',
|
|
176
|
+
nodes.push({ type: 'list', Items: op.Items, Ordered: op.Ordered ?? false });
|
|
177
177
|
break;
|
|
178
178
|
case 'image':
|
|
179
|
-
nodes.push({ type: 'image', src: op.src, alt: op.
|
|
179
|
+
nodes.push({ type: 'image', src: op.src, alt: op.Caption });
|
|
180
180
|
break;
|
|
181
181
|
case 'hr':
|
|
182
182
|
nodes.push({ type: 'hr' });
|
|
@@ -200,12 +200,12 @@ export class ArtifactBuilderService {
|
|
|
200
200
|
switch (op.type) {
|
|
201
201
|
case 'heading':
|
|
202
202
|
// Headings start new sections
|
|
203
|
-
if (currentSection.
|
|
203
|
+
if (currentSection.Heading || (currentSection.content?.length ?? 0) > 0) {
|
|
204
204
|
sections.push(currentSection);
|
|
205
205
|
}
|
|
206
206
|
currentSection = {
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
Heading: op.text,
|
|
208
|
+
Level: op.Level,
|
|
209
209
|
content: [],
|
|
210
210
|
};
|
|
211
211
|
break;
|
|
@@ -214,8 +214,8 @@ export class ArtifactBuilderService {
|
|
|
214
214
|
currentSection.content.push({
|
|
215
215
|
type: 'paragraph',
|
|
216
216
|
text: op.text,
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
Bold: op.Bold,
|
|
218
|
+
Italic: op.Italic,
|
|
219
219
|
align: op.align,
|
|
220
220
|
});
|
|
221
221
|
break;
|
|
@@ -231,8 +231,8 @@ export class ArtifactBuilderService {
|
|
|
231
231
|
currentSection.content = currentSection.content ?? [];
|
|
232
232
|
currentSection.content.push({
|
|
233
233
|
type: 'list',
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
Items: op.Items,
|
|
235
|
+
Ordered: op.Ordered ?? false,
|
|
236
236
|
});
|
|
237
237
|
break;
|
|
238
238
|
case 'image':
|
|
@@ -242,7 +242,7 @@ export class ArtifactBuilderService {
|
|
|
242
242
|
url: op.src,
|
|
243
243
|
width: op.width,
|
|
244
244
|
height: op.height,
|
|
245
|
-
|
|
245
|
+
Caption: op.Caption,
|
|
246
246
|
});
|
|
247
247
|
break;
|
|
248
248
|
// Skip page breaks, hr, and Excel-specific ops for DOCX
|
|
@@ -254,7 +254,7 @@ export class ArtifactBuilderService {
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
// Push remaining section
|
|
257
|
-
if (currentSection.
|
|
257
|
+
if (currentSection.Heading || (currentSection.content?.length ?? 0) > 0) {
|
|
258
258
|
sections.push(currentSection);
|
|
259
259
|
}
|
|
260
260
|
return sections;
|
|
@@ -265,9 +265,9 @@ export class ArtifactBuilderService {
|
|
|
265
265
|
// Collect formulas first
|
|
266
266
|
for (const op of operations) {
|
|
267
267
|
if (op.type === 'formula') {
|
|
268
|
-
const existing = formulasBySheet.get(op.
|
|
269
|
-
existing.push({ cell: op.
|
|
270
|
-
formulasBySheet.set(op.
|
|
268
|
+
const existing = formulasBySheet.get(op.Sheet) || [];
|
|
269
|
+
existing.push({ cell: op.Cell, formula: op.Formula });
|
|
270
|
+
formulasBySheet.set(op.Sheet, existing);
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
// Build sheets
|
|
@@ -277,11 +277,11 @@ export class ArtifactBuilderService {
|
|
|
277
277
|
name: op.name,
|
|
278
278
|
data: op.data,
|
|
279
279
|
headers: op.headers,
|
|
280
|
-
|
|
280
|
+
ColumnWidths: op.ColumnWidths,
|
|
281
281
|
};
|
|
282
282
|
const formulas = formulasBySheet.get(op.name);
|
|
283
283
|
if (formulas) {
|
|
284
|
-
sheet.
|
|
284
|
+
sheet.Formulas = formulas;
|
|
285
285
|
}
|
|
286
286
|
sheets.push(sheet);
|
|
287
287
|
}
|
|
@@ -304,7 +304,7 @@ export class ArtifactBuilderService {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
summarizeSection(section) {
|
|
307
|
-
const ops = section.
|
|
307
|
+
const ops = section.Operations;
|
|
308
308
|
if (ops.length === 0)
|
|
309
309
|
return '(empty)';
|
|
310
310
|
const typeCounts = {};
|
|
@@ -324,7 +324,7 @@ export class ArtifactBuilderService {
|
|
|
324
324
|
this.cleanupTimer = setInterval(() => {
|
|
325
325
|
const now = Date.now();
|
|
326
326
|
for (const [handle, doc] of this.documents) {
|
|
327
|
-
if (now - doc.
|
|
327
|
+
if (now - doc.LastModifiedAt.getTime() > TTL_MS) {
|
|
328
328
|
this.documents.delete(handle);
|
|
329
329
|
}
|
|
330
330
|
}
|