@scout9/app 1.0.0-alpha.0.1.9 → 1.0.0-alpha.0.1.90
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/README.md +32 -0
- package/dist/{index-92deaa5f.cjs → exports-e7d51b70.cjs} +46618 -4591
- package/dist/index.cjs +58 -15
- package/dist/{multipart-parser-090f08a9.cjs → multipart-parser-e09a67c9.cjs} +13 -7
- package/dist/spirits-3b603262.cjs +1218 -0
- package/dist/spirits.cjs +9 -0
- package/dist/testing-tools.cjs +48 -0
- package/package.json +30 -8
- package/src/cli.js +162 -69
- package/src/core/config/agents.js +300 -7
- package/src/core/config/entities.js +58 -28
- package/src/core/config/index.js +37 -15
- package/src/core/config/project.js +160 -6
- package/src/core/config/workflow.js +13 -12
- package/src/core/data.js +27 -0
- package/src/core/index.js +386 -137
- package/src/core/sync.js +71 -0
- package/src/core/templates/Dockerfile +22 -0
- package/src/core/templates/app.js +453 -0
- package/src/core/templates/project-files.js +36 -0
- package/src/core/templates/template-package.json +13 -0
- package/src/exports.js +21 -17
- package/src/platform.js +189 -33
- package/src/public.d.ts.text +330 -0
- package/src/report.js +117 -0
- package/src/runtime/client/api.js +56 -159
- package/src/runtime/client/config.js +60 -11
- package/src/runtime/client/entity.js +19 -6
- package/src/runtime/client/index.js +5 -3
- package/src/runtime/client/message.js +13 -3
- package/src/runtime/client/platform.js +86 -0
- package/src/runtime/client/{agent.js → users.js} +35 -3
- package/src/runtime/client/utils.js +10 -9
- package/src/runtime/client/workflow.js +131 -9
- package/src/runtime/entry.js +2 -2
- package/src/testing-tools/dev.js +373 -0
- package/src/testing-tools/index.js +1 -0
- package/src/testing-tools/mocks.js +37 -5
- package/src/testing-tools/spirits.js +530 -0
- package/src/utils/audio-buffer.js +16 -0
- package/src/utils/audio-type.js +27 -0
- package/src/utils/configs/agents.js +68 -0
- package/src/utils/configs/entities.js +145 -0
- package/src/utils/configs/project.js +23 -0
- package/src/utils/configs/workflow.js +47 -0
- package/src/utils/file-type.js +569 -0
- package/src/utils/file.js +158 -0
- package/src/utils/glob.js +30 -0
- package/src/utils/image-buffer.js +23 -0
- package/src/utils/image-type.js +39 -0
- package/src/utils/index.js +1 -0
- package/src/utils/is-svg.js +37 -0
- package/src/utils/logger.js +111 -0
- package/src/utils/module.js +14 -25
- package/src/utils/project-templates.js +191 -0
- package/src/utils/project.js +387 -0
- package/src/utils/video-type.js +29 -0
- package/types/index.d.ts +7588 -206
- package/types/index.d.ts.map +97 -22
- package/dist/index-1b8d7dd2.cjs +0 -49555
- package/dist/index-2ccb115e.cjs +0 -49514
- package/dist/index-66b06a30.cjs +0 -49549
- package/dist/index-bc029a1d.cjs +0 -49528
- package/dist/index-d9a93523.cjs +0 -49527
- package/dist/multipart-parser-1508046a.cjs +0 -413
- package/dist/multipart-parser-7007403a.cjs +0 -413
- package/dist/multipart-parser-70c32c1d.cjs +0 -413
- package/dist/multipart-parser-71dec101.cjs +0 -413
- package/dist/multipart-parser-f15bf2e0.cjs +0 -414
- package/src/public.d.ts +0 -209
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function normalizeGlobPattern(pattern) {
|
|
2
|
+
let normalizedPattern = pattern;
|
|
3
|
+
let matchFound = /\{([^,]+),?.*?\}/.test(normalizedPattern);
|
|
4
|
+
let iterations = 0; // Safeguard against potential infinite loops
|
|
5
|
+
const maxIterations = 100; // Set a reasonable limit based on expected complexity
|
|
6
|
+
|
|
7
|
+
while (matchFound && iterations < maxIterations) {
|
|
8
|
+
normalizedPattern = normalizedPattern.replace(/\{([^,]+),?.*?\}/, '$1');
|
|
9
|
+
matchFound = /\{([^,]+),?.*?\}/.test(normalizedPattern);
|
|
10
|
+
iterations++;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (iterations >= maxIterations) {
|
|
14
|
+
console.warn('Reached max iterations - pattern may be too complex or improperly formatted');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return normalizedPattern;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function escapeSquareBrackets(pattern) {
|
|
21
|
+
// Escaping both opening and closing square brackets
|
|
22
|
+
return pattern.replace(/\[/g, '\\[').replace(/\]/g, '\\]');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function formatGlobPattern(pattern) {
|
|
26
|
+
return escapeSquareBrackets(pattern);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { toBuffer } from './file.js';
|
|
2
|
+
import { imageExtensions } from './image-type.js';
|
|
3
|
+
import { isSvg } from './is-svg.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {string | Buffer} img
|
|
8
|
+
* @param [allowSvg=false]
|
|
9
|
+
* @param [source='']
|
|
10
|
+
* @returns {Promise<{buffer: Buffer, ext: string, mime: string, isAudio: boolean, isVideo: boolean, isImage: boolean}>}
|
|
11
|
+
*/
|
|
12
|
+
export default async function imageBuffer(img, allowSvg = false, source = '') {
|
|
13
|
+
const imageResult = await toBuffer(img, source);
|
|
14
|
+
if (!imageResult) {
|
|
15
|
+
throw new Error(`Invalid image type: ${typeof img}`);
|
|
16
|
+
}
|
|
17
|
+
if (!imageExtensions.has(imageResult.ext)) {
|
|
18
|
+
if (!(allowSvg && isSvg(img.toString('utf-8')))) {
|
|
19
|
+
throw new Error(`Invalid image type: ${imageResult.ext}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return imageResult;
|
|
23
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { fileTypeFromBuffer } from './file-type.js';
|
|
2
|
+
|
|
3
|
+
export const imageExtensions = new Set([
|
|
4
|
+
'jpg',
|
|
5
|
+
'png',
|
|
6
|
+
'gif',
|
|
7
|
+
'webp',
|
|
8
|
+
'flif',
|
|
9
|
+
'cr2',
|
|
10
|
+
'tif',
|
|
11
|
+
'bmp',
|
|
12
|
+
'jxr',
|
|
13
|
+
'psd',
|
|
14
|
+
'ico',
|
|
15
|
+
'bpg',
|
|
16
|
+
'jp2',
|
|
17
|
+
'jpm',
|
|
18
|
+
'jpx',
|
|
19
|
+
'heic',
|
|
20
|
+
'cur',
|
|
21
|
+
'dcm',
|
|
22
|
+
'avif'
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {Object} ImageTypeResult
|
|
27
|
+
* @property {string} ext - One of the supported [file types](https://github.com/sindresorhus/image-type#supported-file-types).
|
|
28
|
+
* @property {string} mime - The detected [MIME type](https://en.wikipedia.org/wiki/Internet_media_type).
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {Buffer | Uint8Array} input
|
|
34
|
+
* @returns {Promise<ImageTypeResult | undefined>}
|
|
35
|
+
*/
|
|
36
|
+
export default async function imageType(input) {
|
|
37
|
+
const result = await fileTypeFromBuffer(input);
|
|
38
|
+
return imageExtensions.has(result?.ext) && result;
|
|
39
|
+
}
|
package/src/utils/index.js
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { XMLParser, XMLValidator } from 'fast-xml-parser';
|
|
2
|
+
|
|
3
|
+
export function isSvg(str) {
|
|
4
|
+
if (typeof str !== 'string') {
|
|
5
|
+
throw new TypeError(`Expected a \`string\`, got \`${typeof str}\``);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
str = str.trim();
|
|
9
|
+
|
|
10
|
+
if (str.length === 0) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Has to be `!==` as it can also return an object with error info.
|
|
15
|
+
if (XMLValidator.validate(str) !== true) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let jsonObject;
|
|
20
|
+
const parser = new XMLParser();
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
jsonObject = parser.parse(str);
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!jsonObject) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!('svg' in jsonObject)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import readline from 'node:readline';
|
|
2
|
+
import logUpdate from 'log-update';
|
|
3
|
+
import colors from 'kleur';
|
|
4
|
+
|
|
5
|
+
export class ProgressLogger {
|
|
6
|
+
constructor(initialMessage = null) {
|
|
7
|
+
this.lines = [];
|
|
8
|
+
this._indents = 0;
|
|
9
|
+
this._interval = -1;
|
|
10
|
+
this._frames = [
|
|
11
|
+
"010010",
|
|
12
|
+
"001100",
|
|
13
|
+
"100101",
|
|
14
|
+
"111010",
|
|
15
|
+
"111101",
|
|
16
|
+
"010111",
|
|
17
|
+
"101011",
|
|
18
|
+
"111000",
|
|
19
|
+
"110011",
|
|
20
|
+
"110101"
|
|
21
|
+
]
|
|
22
|
+
this._framesSpeed = 80;
|
|
23
|
+
if (initialMessage) {
|
|
24
|
+
this.log(initialMessage);
|
|
25
|
+
this.write(initialMessage)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set indents(value) {
|
|
30
|
+
this._indents = value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
log(message, ...args) {
|
|
34
|
+
const formatted = this._format(message);
|
|
35
|
+
|
|
36
|
+
// const frames = ['-', '\\', '|', '/'];
|
|
37
|
+
let index = 0;
|
|
38
|
+
|
|
39
|
+
logUpdate.clear();
|
|
40
|
+
clearInterval(this._interval);
|
|
41
|
+
this._interval = setInterval(() => {
|
|
42
|
+
const frame = this._frames[index = ++index % this._frames.length];
|
|
43
|
+
logUpdate(`${colors.bold(colors.green(frame))}: ${colors.white(formatted)}`);
|
|
44
|
+
}, this._framesSpeed);
|
|
45
|
+
|
|
46
|
+
this.lines.push({message: formatted, type: 'log'});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
info(message, ...args) {
|
|
50
|
+
return this.write('\t - ' + colors.italic(colors.gray(message)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
primary(message, ...args) {
|
|
54
|
+
return this.write(`${colors.cyan(message)}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
success(message, ...args) {
|
|
58
|
+
return this.write(`✅ ${colors.green(message)}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
error(message, ...args) {
|
|
62
|
+
return this.write(`❌ ${colors.red(message)}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
warn(message, ...args) {
|
|
66
|
+
return this.write(`⚠️ ${colors.yellow(message)}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
write(newMessage) {
|
|
70
|
+
if (this.lines.length === 0) {
|
|
71
|
+
throw new Error("No lines to update");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
logUpdate.clear();
|
|
75
|
+
clearInterval(this._interval);
|
|
76
|
+
logUpdate.done();
|
|
77
|
+
|
|
78
|
+
// Update the last line in the array
|
|
79
|
+
const lastLine = this.lines[this.lines.length - 1];
|
|
80
|
+
if (lastLine.type === 'log') {
|
|
81
|
+
// Replace the last log line
|
|
82
|
+
this.lines[this.lines.length - 1] = {message: this._format(newMessage), type: 'written'};
|
|
83
|
+
} else {
|
|
84
|
+
// Append the new line
|
|
85
|
+
this.lines.push({message: this._format(newMessage), type: 'written'});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Clear all the logged lines and reprint them
|
|
89
|
+
readline.moveCursor(process.stdout, 0, -this.lines.length);
|
|
90
|
+
readline.clearScreenDown(process.stdout);
|
|
91
|
+
this.lines.forEach(line => console.log(line.message));
|
|
92
|
+
|
|
93
|
+
// // Move up to the last line
|
|
94
|
+
// readline.moveCursor(process.stdout, 0, -1);
|
|
95
|
+
// readline.clearLine(process.stdout, 0);
|
|
96
|
+
// readline.cursorTo(process.stdout, 0);
|
|
97
|
+
|
|
98
|
+
// Log the updated line
|
|
99
|
+
// console.log(newMessage);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
done() {
|
|
103
|
+
logUpdate.clear();
|
|
104
|
+
logUpdate.done();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
_format(message) {
|
|
108
|
+
const indentText = '\t'.repeat(this._indents);
|
|
109
|
+
return `${indentText}${message}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
package/src/utils/module.js
CHANGED
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// // allowConfigurationWithComments: false,
|
|
7
|
-
// useCache: false
|
|
8
|
-
// })
|
|
9
|
-
// .then((res) => {
|
|
10
|
-
// console.log('tsImport.load', res);
|
|
11
|
-
// return res;
|
|
12
|
-
// })
|
|
13
|
-
// .catch((err) => {
|
|
14
|
-
// console.log('tsImport.load fail', err);
|
|
15
|
-
// throw err;
|
|
16
|
-
// });
|
|
17
|
-
// } else {
|
|
18
|
-
// return import(filePath);
|
|
19
|
-
// }
|
|
20
|
-
//
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
|
|
3
|
+
export async function importFile(filePath) {
|
|
4
|
+
const fileUrl = pathToFileURL(filePath);
|
|
5
|
+
return import(fileUrl.href);
|
|
21
6
|
}
|
|
22
7
|
|
|
23
8
|
export async function requireProjectFile(filePath) {
|
|
@@ -29,11 +14,15 @@ export async function requireProjectFile(filePath) {
|
|
|
29
14
|
}
|
|
30
15
|
|
|
31
16
|
export async function requireOptionalProjectFile(filePath) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
return importFile(filePath).catch((e) => {
|
|
18
|
+
switch (e.code) {
|
|
19
|
+
case 'ERR_MODULE_NOT_FOUND':
|
|
20
|
+
case 'MODULE_NOT_FOUND':
|
|
21
|
+
return null;
|
|
22
|
+
default:
|
|
23
|
+
throw e;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
37
26
|
}
|
|
38
27
|
|
|
39
28
|
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Scout9ProjectBuildConfig['agents']} agents
|
|
3
|
+
* @param {string} exe - file extension
|
|
4
|
+
* @returns {string}
|
|
5
|
+
*/
|
|
6
|
+
function agentsTemplate(agents, exe = 'js') {
|
|
7
|
+
return `
|
|
8
|
+
/**
|
|
9
|
+
* Required core entity type: Agents represents you and your team
|
|
10
|
+
* @returns {Array<import('@scout9/app').IAgent>}
|
|
11
|
+
*/
|
|
12
|
+
export default function Agents() {
|
|
13
|
+
return ${JSON.stringify(agents, null, 2)};
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {Scout9ProjectBuildConfig} config
|
|
20
|
+
* @param {string} exe - file extension
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
function rootTemplate(config, exe = 'js') {
|
|
25
|
+
return `
|
|
26
|
+
/**
|
|
27
|
+
* Configuration for the Scout9 project.
|
|
28
|
+
* @type {import('@scout9/app').IScout9ProjectConfig}
|
|
29
|
+
*/
|
|
30
|
+
export default {
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Configure large language model (LLM) settings to generate auto replies
|
|
34
|
+
*/
|
|
35
|
+
llm: {
|
|
36
|
+
engine: ${config?.llm?.engine ? `'${config.llm.engine}'` : `'openai'`},
|
|
37
|
+
model: ${config?.llm?.model ? `'${config.llm.model}'` : `'gpt-3.5-turbo'`},
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* Configure personal model transformer (PMT) settings to align auto replies the agent's tone
|
|
41
|
+
*/
|
|
42
|
+
pmt: {
|
|
43
|
+
engine: ${config?.pmt?.engine ? `'${config.pmt.engine}'` : `'scout9'`},
|
|
44
|
+
model: ${config?.pmt?.model ? `'${config.pmt.model}'` : `'orin-2.2'`},
|
|
45
|
+
},
|
|
46
|
+
organization: ${config?.organization ? JSON.stringify(config.organization, null, 2) : `{name: "Organization Name", description: "Organization description."}`},
|
|
47
|
+
initialContext: ${config?.initialContext ? JSON.stringify(config.initialContext, null, 2) : `[]`}
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function appTemplate() {
|
|
53
|
+
return `
|
|
54
|
+
/**
|
|
55
|
+
* @param {import('@scout9/app').IWorkflowEvent} event - every workflow receives an event object
|
|
56
|
+
* @returns {Promise<import('@scout9/app').IWorkflowResponse>} - every workflow must return a WorkflowResponse
|
|
57
|
+
*/
|
|
58
|
+
export default async function Scout9App(event) {
|
|
59
|
+
return {
|
|
60
|
+
forward: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {ExportedEntityBuildConfig} entity
|
|
68
|
+
* @param {string} exe - file extension
|
|
69
|
+
*/
|
|
70
|
+
function entityTemplate(entity, exe = 'js') {
|
|
71
|
+
let {entity: _entity, entities, api, id, ...rest} = entity;
|
|
72
|
+
if (!_entity.endsWith('Entity')) {
|
|
73
|
+
_entity = `${_entity}Entity`;
|
|
74
|
+
}
|
|
75
|
+
return `
|
|
76
|
+
/**
|
|
77
|
+
* ${rest.description || 'Example entity to help us differentiate if a user wants a delivery or pickup order'}
|
|
78
|
+
* @returns {IEntityBuildConfig}
|
|
79
|
+
*/
|
|
80
|
+
export default async function ${_entity}() {
|
|
81
|
+
return ${JSON.stringify(rest, null, 2)};
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function customersTemplate() {
|
|
87
|
+
return `
|
|
88
|
+
import Scout9CRM from '@scout9/crm';
|
|
89
|
+
import { EventResponse } from '@scout9/app';
|
|
90
|
+
|
|
91
|
+
const crm = new Scout9CRM({apiKey: process.env.SCOUT9_API_KEY});
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Required entity - use this to sync with your CRM
|
|
96
|
+
*
|
|
97
|
+
* Query customer info from your CRM
|
|
98
|
+
* @returns {Promise<import('@scout9/app').EventResponse<Array<import('@scout9/app').Customer>>>}
|
|
99
|
+
*/
|
|
100
|
+
export const QUERY = async ({searchParams}) => {
|
|
101
|
+
const {page, q, orderBy, endAt, startAt, limit} = searchParams;
|
|
102
|
+
const customers = await crm.query(
|
|
103
|
+
q,
|
|
104
|
+
page ? parseInt(page) : undefined,
|
|
105
|
+
limit ? parseInt(limit) : undefined,
|
|
106
|
+
orderBy ? parseInt(orderBy) : undefined,
|
|
107
|
+
endAt ? parseInt(endAt) : undefined,
|
|
108
|
+
startAt ? parseInt(startAt) : undefined,
|
|
109
|
+
);
|
|
110
|
+
return EventResponse.json(customers, {status: 200});
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function customerTemplate() {
|
|
116
|
+
return `
|
|
117
|
+
import Scout9CRM from '@scout9/crm';
|
|
118
|
+
import { json } from '@scout9/app';
|
|
119
|
+
|
|
120
|
+
const crm = new Scout9CRM({apiKey: process.env.SCOUT9_API_KEY});
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get customer info from your CRM
|
|
124
|
+
* @returns {Promise<import('@scout9/app').EventResponse<import('@scout9/app').Customer>>}
|
|
125
|
+
*/
|
|
126
|
+
export const GET = async ({params}) => {
|
|
127
|
+
return json(await crm.get(params.customer));
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* When a customer is created on scout9's side
|
|
132
|
+
*
|
|
133
|
+
* Example:
|
|
134
|
+
* A new or unrecognized customer has contacted an agent. Scout9 has captured some preliminary information
|
|
135
|
+
* about them and sent this POST request. Take the information to either add a new customer record to your CRM
|
|
136
|
+
* or return an existing customer id to map the correct customer document.
|
|
137
|
+
*
|
|
138
|
+
* @returns {Promise<import('@scout9/app').EventResponse>}
|
|
139
|
+
*/
|
|
140
|
+
export const POST = async ({params, body: newCustomer}) => {
|
|
141
|
+
// Scout9 will generate random id for new customers, but whatever id you return back will be used for the new customer
|
|
142
|
+
const {id: crmId} = await crm.add({$id: params.customer, newCustomer});
|
|
143
|
+
return json({success: true, id: crmId}, {status: 200});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* New customer info revealed, use this to save the customer info to your CRM
|
|
148
|
+
*
|
|
149
|
+
* Example:
|
|
150
|
+
* In a conversation, if any new data is found, Scout9 will send a PUT or PATCH request to allow for you to update
|
|
151
|
+
* your CRM accordingly.
|
|
152
|
+
*
|
|
153
|
+
* @returns {Promise<import('@scout9/app').EventResponse>}
|
|
154
|
+
*/
|
|
155
|
+
export const PUT = async ({params, body: updatedCustomer}) => {
|
|
156
|
+
// const id = params.customer;
|
|
157
|
+
|
|
158
|
+
console.log('updatedCustomer', updatedCustomer);
|
|
159
|
+
// @TODO REST call to api to save customer info
|
|
160
|
+
|
|
161
|
+
// @TODO REST call to api to save customer info
|
|
162
|
+
return json({success: true}, {status: 200});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Customer request to be removed from platform, use this to remove/update the customer info from your CRM
|
|
168
|
+
*
|
|
169
|
+
* Example:
|
|
170
|
+
* A customer has opt-out of text messaging, Scout9 will send a DELETE message for you to remove any data, returning
|
|
171
|
+
* back success: true will then have Scout9 delete any data on their end as well.
|
|
172
|
+
*
|
|
173
|
+
* @returns {Promise<import('@scout9/app').EventResponse>}
|
|
174
|
+
*/
|
|
175
|
+
export const DELETE = async ({params, request}) => {
|
|
176
|
+
await crm.remove(params.customer);
|
|
177
|
+
return json({success: true}, {status: 200});
|
|
178
|
+
};
|
|
179
|
+
`
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const projectTemplates = {
|
|
183
|
+
entities: {
|
|
184
|
+
agents: agentsTemplate,
|
|
185
|
+
entity: entityTemplate,
|
|
186
|
+
customers: customersTemplate,
|
|
187
|
+
customer: customerTemplate,
|
|
188
|
+
},
|
|
189
|
+
root: rootTemplate,
|
|
190
|
+
app: appTemplate
|
|
191
|
+
}
|