@things-factory/integration-base 8.0.0-alpha.8 → 8.0.0-beta.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.
Files changed (65) hide show
  1. package/dist-server/controllers/scenario-controller.d.ts +2 -0
  2. package/dist-server/controllers/scenario-controller.js +16 -19
  3. package/dist-server/controllers/scenario-controller.js.map +1 -1
  4. package/dist-server/engine/connection-manager.js.map +1 -1
  5. package/dist-server/engine/connector/headless-connector.d.ts +23 -0
  6. package/dist-server/engine/connector/headless-connector.js +283 -0
  7. package/dist-server/engine/connector/headless-connector.js.map +1 -0
  8. package/dist-server/engine/connector/http-connector.js +1 -1
  9. package/dist-server/engine/connector/http-connector.js.map +1 -1
  10. package/dist-server/engine/connector/index.d.ts +1 -0
  11. package/dist-server/engine/connector/index.js +1 -0
  12. package/dist-server/engine/connector/index.js.map +1 -1
  13. package/dist-server/engine/connector/operato-connector.js +3 -4
  14. package/dist-server/engine/connector/operato-connector.js.map +1 -1
  15. package/dist-server/engine/index.d.ts +1 -0
  16. package/dist-server/engine/index.js +1 -0
  17. package/dist-server/engine/index.js.map +1 -1
  18. package/dist-server/engine/resource-pool/headless-pool.d.ts +1 -0
  19. package/dist-server/engine/resource-pool/headless-pool.js +121 -0
  20. package/dist-server/engine/resource-pool/headless-pool.js.map +1 -0
  21. package/dist-server/engine/resource-pool/index.d.ts +1 -0
  22. package/dist-server/engine/resource-pool/index.js +5 -0
  23. package/dist-server/engine/resource-pool/index.js.map +1 -0
  24. package/dist-server/engine/task/headless-post.js +19 -33
  25. package/dist-server/engine/task/headless-post.js.map +1 -1
  26. package/dist-server/engine/task/headless-scrap.js +20 -13
  27. package/dist-server/engine/task/headless-scrap.js.map +1 -1
  28. package/dist-server/engine/task/utils/headless-pool-for-scenario.js +1 -1
  29. package/dist-server/engine/task/utils/headless-pool-for-scenario.js.map +1 -1
  30. package/dist-server/service/payload-log/payload-log.js +7 -4
  31. package/dist-server/service/payload-log/payload-log.js.map +1 -1
  32. package/dist-server/service/scenario/scenario-query.d.ts +2 -1
  33. package/dist-server/service/scenario/scenario-query.js +10 -0
  34. package/dist-server/service/scenario/scenario-query.js.map +1 -1
  35. package/dist-server/service/scenario/scenario-type.d.ts +3 -3
  36. package/dist-server/service/scenario/scenario-type.js +7 -7
  37. package/dist-server/service/scenario/scenario-type.js.map +1 -1
  38. package/dist-server/service/scenario/scenario.d.ts +3 -1
  39. package/dist-server/service/scenario/scenario.js +9 -0
  40. package/dist-server/service/scenario/scenario.js.map +1 -1
  41. package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
  42. package/dist-server/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +12 -11
  44. package/server/controllers/scenario-controller.ts +27 -36
  45. package/server/engine/connection-manager.ts +1 -1
  46. package/server/engine/connector/headless-connector.ts +341 -0
  47. package/server/engine/connector/http-connector.ts +1 -1
  48. package/server/engine/connector/index.ts +1 -0
  49. package/server/engine/connector/operato-connector.ts +4 -7
  50. package/server/engine/index.ts +1 -0
  51. package/server/engine/resource-pool/headless-pool.ts +136 -0
  52. package/server/engine/resource-pool/index.ts +1 -0
  53. package/server/engine/task/headless-post.ts +21 -40
  54. package/server/engine/task/headless-scrap.ts +21 -18
  55. package/server/engine/task/utils/headless-pool-for-scenario.ts +1 -1
  56. package/server/service/payload-log/payload-log.ts +8 -4
  57. package/server/service/scenario/scenario-query.ts +6 -1
  58. package/server/service/scenario/scenario-type.ts +5 -5
  59. package/server/service/scenario/scenario.ts +15 -19
  60. package/server/service/scenario-instance/scenario-instance-type.ts +1 -1
  61. package/translations/en.json +12 -5
  62. package/translations/ja.json +12 -5
  63. package/translations/ko.json +12 -5
  64. package/translations/ms.json +12 -5
  65. package/translations/zh.json +12 -5
@@ -147,7 +147,7 @@ class OperatoConnector {
147
147
  }
148
148
  async runScenario(subscriptions, variables) {
149
149
  var _a;
150
- const { domain, user, unsafeIP, prohibitedPrivileges } = this.context;
150
+ const { domain, user } = this.context;
151
151
  const { tag } = variables;
152
152
  if (!tag) {
153
153
  throw new Error(`tag is invalid - ${tag}`);
@@ -156,9 +156,8 @@ class OperatoConnector {
156
156
  if (!scenario) {
157
157
  throw new Error(`scenario is not found - ${tag}`);
158
158
  }
159
- if (!(await (0, auth_base_1.checkPermission)(scenario.privilege, user, domain, unsafeIP, prohibitedPrivileges))) {
160
- const { category, privilege } = scenario.privilege || {};
161
- throw new Error(`Unauthorized! ${category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'} required`);
159
+ if (!(await (0, auth_base_1.checkUserHasRole)(scenario.roleId, domain, user))) {
160
+ throw new Error(`Unauthorized! ${scenario.name} doesn't have required role.`);
162
161
  }
163
162
  /* create a scenario instance */
164
163
  const instanceName = scenario.name + '-' + String(Date.now());
@@ -1 +1 @@
1
- {"version":3,"file":"operato-connector.js","sourceRoot":"","sources":["../../../server/engine/connector/operato-connector.ts"],"names":[],"mappings":"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","sourcesContent":["import 'cross-fetch/polyfill'\n\nimport { ApolloClient, InMemoryCache, createHttpLink, split } from '@apollo/client/core'\nimport { setContext } from '@apollo/client/link/context'\n\nimport WebSocket from 'ws'\nimport { createClient } from 'graphql-ws'\nimport { GraphQLWsLink } from '@apollo/client/link/subscriptions'\nimport { getMainDefinition } from '@apollo/client/utilities'\nimport gql from 'graphql-tag'\n\nimport { ConnectionManager } from '../connection-manager'\nimport { Connector } from '../types'\nimport { InputConnection } from '../../service/connection/connection-type'\n\nimport { Scenario } from '../../service/scenario/scenario'\nimport { ScenarioInstance } from '../../service/scenario-instance/scenario-instance-type'\n\nimport { getRepository, GraphqlLocalClient, Domain } from '@things-factory/shell'\nimport { User, checkPermission } from '@things-factory/auth-base'\n\nconst debug = require('debug')('things-factory:integration-base:operato-connector')\n\nconst defaultOptions: any = {\n watchQuery: {\n fetchPolicy: 'no-cache',\n errorPolicy: 'ignore'\n },\n query: {\n fetchPolicy: 'no-cache', //'network-only'\n errorPolicy: 'all'\n },\n mutate: {\n errorPolicy: 'all'\n }\n}\n\nexport const GRAPHQL_URI = '/graphql'\nexport const SUBSCRIPTION_URI = GRAPHQL_URI\n\ninterface SubscriberData {\n tag: string\n scenario: any\n subscriptionObserver: any\n}\n\nexport class OperatoConnector implements Connector {\n private context: any\n\n async ready(connectionConfigs: InputConnection[]) {\n await Promise.all(connectionConfigs.map(this.connect.bind(this)))\n\n ConnectionManager.logger.info('operato-connector connections are ready')\n }\n\n async connect(connection: InputConnection) {\n const {\n endpoint: uri,\n params: { authKey, domain, subscriptionHandlers = {} }\n } = connection\n\n if (!authKey || !domain) {\n throw new Error('some connection paramter missing.')\n }\n\n const domainOwner = await getRepository(User).findOne({\n where: {\n id: connection.domain.owner\n }\n })\n\n this.context = {\n domain: connection.domain,\n user: domainOwner\n /* TODO: domainOwner 대신 특정 유저를 지정할 수 있도록 개선해야함. 모든 커넥션에 유저를 지정하는 기능으로 일반화할 필요가 있는 지 고민해야함 */\n }\n\n const httpLink = createHttpLink({\n uri: uri\n })\n\n /* \n CHECKPOINT: \n 1. GraphqQLWsLink를 사용하면 setContext를 통한 추가 헤더 설정이 무시됩니다.\n 따라서, GraphQLWsLink를 사용하려면, connectionParams를 통해 헤더를 설정해야 합니다.\n \n 2. 서버에서 실행시, webSocketImpl을 명시적으로 지정해야 합니다.\n */\n const wsLink = new GraphQLWsLink(\n createClient({\n url: uri.replace(/^http/, 'ws'),\n keepAlive: 10_000,\n retryAttempts: 1_000_000,\n shouldRetry: e => true,\n webSocketImpl: WebSocket,\n connectionParams: {\n headers: {\n 'x-things-factory-domain': domain,\n authorization: authKey ? `Bearer ${authKey}` : ''\n }\n }\n })\n )\n\n const splitLink = split(\n ({ query }) => {\n const def = getMainDefinition(query)\n return def.kind === 'OperationDefinition' && def.operation === 'subscription'\n },\n wsLink,\n setContext((_, { headers }) => {\n return {\n headers: {\n ...headers,\n 'x-things-factory-domain': domain,\n authorization: authKey ? `Bearer ${authKey}` : ''\n }\n }\n }).concat(httpLink)\n )\n\n const cache = new InMemoryCache({\n addTypename: false\n })\n\n const client = new ApolloClient({\n defaultOptions,\n cache,\n link: splitLink\n })\n\n const subscriptions: SubscriberData[] = []\n Object.keys(subscriptionHandlers).forEach(async tag => {\n if (!tag || !subscriptionHandlers[tag]) return\n\n const scenarioName = subscriptionHandlers[tag]\n\n // fetch a scenario\n const selectedScenario = await getRepository(Scenario).findOne({\n where: {\n name: scenarioName\n },\n relations: ['steps', 'domain']\n })\n\n const subscription = client.subscribe({\n query: gql`\n subscription {\n data(tag: \"${tag}\") {\n tag\n data\n }\n }\n `\n })\n\n const subscriptionObserver = subscription.subscribe({\n next: async data => {\n debug('received pubsub msg.:', data?.data)\n await this.runScenario(subscriptions, data?.data?.data)\n },\n error: error => {\n ConnectionManager.logger.error(`(${connection.name}:${connection.endpoint}) subscription error`, error)\n },\n complete: () => {\n ConnectionManager.logger.info(`(${connection.name}:${connection.endpoint}) subscription complete`)\n }\n })\n\n ConnectionManager.logger.info(\n `(${connection.name}:${connection.endpoint}) subscription closed flag: ${subscriptionObserver.closed}`\n )\n\n subscriptions.push({\n tag,\n scenario: selectedScenario,\n subscriptionObserver\n })\n ConnectionManager.logger.info(`(${tag}:${scenarioName}) subscription closed flag: ${subscriptionObserver.closed}`)\n })\n\n client['subscriptions'] = subscriptions\n ConnectionManager.addConnectionInstance(connection, client)\n\n ConnectionManager.logger.info(\n `operato-connector connection(${connection.name}:${connection.endpoint}) is connected`\n )\n }\n\n async disconnect(connection: InputConnection) {\n const client = ConnectionManager.getConnectionInstance(connection)\n const subscriptions: SubscriberData[] = client['subscriptions']\n subscriptions.forEach(subscription => subscription.subscriptionObserver.unsubscribe())\n client.stop()\n ConnectionManager.removeConnectionInstance(connection)\n\n ConnectionManager.logger.info(`operato-connector connection(${connection.name}) is disconnected`)\n }\n\n async runScenario(subscriptions: SubscriberData[], variables: any): Promise<ScenarioInstance> {\n const { domain, user, unsafeIP, prohibitedPrivileges } = this.context\n const { tag } = variables\n\n if (!tag) {\n throw new Error(`tag is invalid - ${tag}`)\n }\n\n const scenario = subscriptions.find(subscription => subscription.tag === tag)?.scenario\n if (!scenario) {\n throw new Error(`scenario is not found - ${tag}`)\n }\n\n if (!(await checkPermission(scenario.privilege, user, domain, unsafeIP, prohibitedPrivileges))) {\n const { category, privilege } = scenario.privilege || {}\n throw new Error(\n `Unauthorized! ${category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'} required`\n )\n }\n\n /* create a scenario instance */\n const instanceName = scenario.name + '-' + String(Date.now())\n const instance = new ScenarioInstance(instanceName, scenario, {\n user,\n domain,\n variables,\n client: GraphqlLocalClient.client\n })\n\n // run scenario\n await instance.run()\n return instance\n }\n\n get parameterSpec() {\n return [\n {\n type: 'string',\n name: 'authKey',\n label: 'auth-key'\n },\n {\n type: 'string',\n name: 'domain',\n label: 'domain'\n },\n {\n type: 'tag-scenarios',\n name: 'subscriptionHandlers',\n label: 'subscription-handlers'\n }\n ]\n }\n\n get taskPrefixes() {\n return ['graphql']\n }\n\n get help() {\n return 'integration/connector/operato-connector'\n }\n\n get description() {\n return 'Operato Graphql Connector'\n }\n}\n\nConnectionManager.registerConnector('operato-connector', new OperatoConnector())\n"]}
1
+ {"version":3,"file":"operato-connector.js","sourceRoot":"","sources":["../../../server/engine/connector/operato-connector.ts"],"names":[],"mappings":"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","sourcesContent":["import 'cross-fetch/polyfill'\n\nimport { ApolloClient, InMemoryCache, createHttpLink, split } from '@apollo/client/core'\nimport { setContext } from '@apollo/client/link/context'\n\nimport WebSocket from 'ws'\nimport { createClient } from 'graphql-ws'\nimport { GraphQLWsLink } from '@apollo/client/link/subscriptions'\nimport { getMainDefinition } from '@apollo/client/utilities'\nimport gql from 'graphql-tag'\n\nimport { ConnectionManager } from '../connection-manager'\nimport { Connector } from '../types'\nimport { InputConnection } from '../../service/connection/connection-type'\n\nimport { Scenario } from '../../service/scenario/scenario'\nimport { ScenarioInstance } from '../../service/scenario-instance/scenario-instance-type'\n\nimport { getRepository, GraphqlLocalClient, Domain } from '@things-factory/shell'\nimport { User, checkUserHasRole } from '@things-factory/auth-base'\n\nconst debug = require('debug')('things-factory:integration-base:operato-connector')\n\nconst defaultOptions: any = {\n watchQuery: {\n fetchPolicy: 'no-cache',\n errorPolicy: 'ignore'\n },\n query: {\n fetchPolicy: 'no-cache', //'network-only'\n errorPolicy: 'all'\n },\n mutate: {\n errorPolicy: 'all'\n }\n}\n\nexport const GRAPHQL_URI = '/graphql'\nexport const SUBSCRIPTION_URI = GRAPHQL_URI\n\ninterface SubscriberData {\n tag: string\n scenario: any\n subscriptionObserver: any\n}\n\nexport class OperatoConnector implements Connector {\n private context: any\n\n async ready(connectionConfigs: InputConnection[]) {\n await Promise.all(connectionConfigs.map(this.connect.bind(this)))\n\n ConnectionManager.logger.info('operato-connector connections are ready')\n }\n\n async connect(connection: InputConnection) {\n const {\n endpoint: uri,\n params: { authKey, domain, subscriptionHandlers = {} }\n } = connection\n\n if (!authKey || !domain) {\n throw new Error('some connection paramter missing.')\n }\n\n const domainOwner = await getRepository(User).findOne({\n where: {\n id: connection.domain.owner\n }\n })\n\n this.context = {\n domain: connection.domain,\n user: domainOwner\n /* TODO: domainOwner 대신 특정 유저를 지정할 수 있도록 개선해야함. 모든 커넥션에 유저를 지정하는 기능으로 일반화할 필요가 있는 지 고민해야함 */\n }\n\n const httpLink = createHttpLink({\n uri: uri\n })\n\n /* \n CHECKPOINT: \n 1. GraphqQLWsLink를 사용하면 setContext를 통한 추가 헤더 설정이 무시됩니다.\n 따라서, GraphQLWsLink를 사용하려면, connectionParams를 통해 헤더를 설정해야 합니다.\n \n 2. 서버에서 실행시, webSocketImpl을 명시적으로 지정해야 합니다.\n */\n const wsLink = new GraphQLWsLink(\n createClient({\n url: uri.replace(/^http/, 'ws'),\n keepAlive: 10_000,\n retryAttempts: 1_000_000,\n shouldRetry: e => true,\n webSocketImpl: WebSocket,\n connectionParams: {\n headers: {\n 'x-things-factory-domain': domain,\n authorization: authKey ? `Bearer ${authKey}` : ''\n }\n }\n })\n )\n\n const splitLink = split(\n ({ query }) => {\n const def = getMainDefinition(query)\n return def.kind === 'OperationDefinition' && def.operation === 'subscription'\n },\n wsLink,\n setContext((_, { headers }) => {\n return {\n headers: {\n ...headers,\n 'x-things-factory-domain': domain,\n authorization: authKey ? `Bearer ${authKey}` : ''\n }\n }\n }).concat(httpLink)\n )\n\n const cache = new InMemoryCache({\n addTypename: false\n })\n\n const client = new ApolloClient({\n defaultOptions,\n cache,\n link: splitLink\n })\n\n const subscriptions: SubscriberData[] = []\n Object.keys(subscriptionHandlers).forEach(async tag => {\n if (!tag || !subscriptionHandlers[tag]) return\n\n const scenarioName = subscriptionHandlers[tag]\n\n // fetch a scenario\n const selectedScenario = await getRepository(Scenario).findOne({\n where: {\n name: scenarioName\n },\n relations: ['steps', 'domain']\n })\n\n const subscription = client.subscribe({\n query: gql`\n subscription {\n data(tag: \"${tag}\") {\n tag\n data\n }\n }\n `\n })\n\n const subscriptionObserver = subscription.subscribe({\n next: async data => {\n debug('received pubsub msg.:', data?.data)\n await this.runScenario(subscriptions, data?.data?.data)\n },\n error: error => {\n ConnectionManager.logger.error(`(${connection.name}:${connection.endpoint}) subscription error`, error)\n },\n complete: () => {\n ConnectionManager.logger.info(`(${connection.name}:${connection.endpoint}) subscription complete`)\n }\n })\n\n ConnectionManager.logger.info(\n `(${connection.name}:${connection.endpoint}) subscription closed flag: ${subscriptionObserver.closed}`\n )\n\n subscriptions.push({\n tag,\n scenario: selectedScenario,\n subscriptionObserver\n })\n ConnectionManager.logger.info(`(${tag}:${scenarioName}) subscription closed flag: ${subscriptionObserver.closed}`)\n })\n\n client['subscriptions'] = subscriptions\n ConnectionManager.addConnectionInstance(connection, client)\n\n ConnectionManager.logger.info(\n `operato-connector connection(${connection.name}:${connection.endpoint}) is connected`\n )\n }\n\n async disconnect(connection: InputConnection) {\n const client = ConnectionManager.getConnectionInstance(connection)\n const subscriptions: SubscriberData[] = client['subscriptions']\n subscriptions.forEach(subscription => subscription.subscriptionObserver.unsubscribe())\n client.stop()\n ConnectionManager.removeConnectionInstance(connection)\n\n ConnectionManager.logger.info(`operato-connector connection(${connection.name}) is disconnected`)\n }\n\n async runScenario(subscriptions: SubscriberData[], variables: any): Promise<ScenarioInstance> {\n const { domain, user } = this.context\n const { tag } = variables\n\n if (!tag) {\n throw new Error(`tag is invalid - ${tag}`)\n }\n\n const scenario = subscriptions.find(subscription => subscription.tag === tag)?.scenario\n if (!scenario) {\n throw new Error(`scenario is not found - ${tag}`)\n }\n\n if (!(await checkUserHasRole(scenario.roleId, domain, user))) {\n throw new Error(`Unauthorized! ${scenario.name} doesn't have required role.`)\n }\n\n /* create a scenario instance */\n const instanceName = scenario.name + '-' + String(Date.now())\n const instance = new ScenarioInstance(instanceName, scenario, {\n user,\n domain,\n variables,\n client: GraphqlLocalClient.client\n })\n\n // run scenario\n await instance.run()\n return instance\n }\n\n get parameterSpec() {\n return [\n {\n type: 'string',\n name: 'authKey',\n label: 'auth-key'\n },\n {\n type: 'string',\n name: 'domain',\n label: 'domain'\n },\n {\n type: 'tag-scenarios',\n name: 'subscriptionHandlers',\n label: 'subscription-handlers'\n }\n ]\n }\n\n get taskPrefixes() {\n return ['graphql']\n }\n\n get help() {\n return 'integration/connector/operato-connector'\n }\n\n get description() {\n return 'Operato Graphql Connector'\n }\n}\n\nConnectionManager.registerConnector('operato-connector', new OperatoConnector())\n"]}
@@ -5,4 +5,5 @@ export * from './scenario-engine';
5
5
  export * from './task-registry';
6
6
  export * from './analyzer/analyze-integration';
7
7
  export * from './edge-client';
8
+ export * from './resource-pool';
8
9
  export { Connector, Context, TaskHandler } from './types';
@@ -8,4 +8,5 @@ tslib_1.__exportStar(require("./scenario-engine"), exports);
8
8
  tslib_1.__exportStar(require("./task-registry"), exports);
9
9
  tslib_1.__exportStar(require("./analyzer/analyze-integration"), exports);
10
10
  tslib_1.__exportStar(require("./edge-client"), exports);
11
+ tslib_1.__exportStar(require("./resource-pool"), exports);
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;;AAAA,uBAAoB;AACpB,kBAAe;AAEf,+DAAoC;AACpC,4DAAiC;AACjC,0DAA+B;AAC/B,yEAA8C;AAC9C,wDAA6B","sourcesContent":["import './connector'\nimport './task'\n\nexport * from './connection-manager'\nexport * from './scenario-engine'\nexport * from './task-registry'\nexport * from './analyzer/analyze-integration'\nexport * from './edge-client'\n\nexport { Connector, Context, TaskHandler } from './types'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;;AAAA,uBAAoB;AACpB,kBAAe;AAEf,+DAAoC;AACpC,4DAAiC;AACjC,0DAA+B;AAC/B,yEAA8C;AAC9C,wDAA6B;AAC7B,0DAA+B","sourcesContent":["import './connector'\nimport './task'\n\nexport * from './connection-manager'\nexport * from './scenario-engine'\nexport * from './task-registry'\nexport * from './analyzer/analyze-integration'\nexport * from './edge-client'\nexport * from './resource-pool'\n\nexport { Connector, Context, TaskHandler } from './types'\n"]}
@@ -0,0 +1 @@
1
+ export declare function getHeadlessPool(): any;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getHeadlessPool = getHeadlessPool;
4
+ const tslib_1 = require("tslib");
5
+ const genericPool = tslib_1.__importStar(require("generic-pool"));
6
+ const env_1 = require("@things-factory/env");
7
+ try {
8
+ var puppeteer = require('puppeteer');
9
+ }
10
+ catch (err) {
11
+ env_1.logger.error(err);
12
+ }
13
+ let headlessPool;
14
+ function getHeadlessPool() {
15
+ if (!headlessPool) {
16
+ headlessPool = createHeadlessPool({ min: 2, max: 20, acquireTimeoutMillis: 15000, testOnBorrow: true });
17
+ }
18
+ return headlessPool;
19
+ }
20
+ function createHeadlessPool(options) {
21
+ return genericPool.createPool({
22
+ create() {
23
+ console.log('headless instance in headless-pool-integration about to create');
24
+ return initializeChromium();
25
+ },
26
+ validate(browser) {
27
+ return Promise.race([
28
+ new Promise(res => setTimeout(() => res(false), 1500)),
29
+ browser
30
+ //@ts-ignore
31
+ .version()
32
+ .then(() => true)
33
+ .catch(() => false)
34
+ ]);
35
+ },
36
+ destroy(browser) {
37
+ //@ts-ignore
38
+ return browser.close();
39
+ }
40
+ }, options);
41
+ }
42
+ async function destroyHeadlessPool() {
43
+ if (headlessPool) {
44
+ console.log('headless-pool-integration about to destroy');
45
+ try {
46
+ await Promise.race([
47
+ headlessPool.drain().then(() => headlessPool.clear()), // 정리 작업
48
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Destroy timeout')), 5000) // 5초 타임아웃 설정
49
+ )
50
+ ]);
51
+ console.log('Headless pool destroyed');
52
+ }
53
+ catch (err) {
54
+ env_1.logger.error('Failed to destroy headless pool:', err);
55
+ }
56
+ }
57
+ }
58
+ const CHROMIUM_PATH = env_1.config.get('CHROMIUM_PATH');
59
+ async function initializeChromium() {
60
+ try {
61
+ if (!puppeteer) {
62
+ return;
63
+ }
64
+ const launchSetting = {
65
+ args: ['--hide-scrollbars', '--mute-audio', '--no-sandbox', '--use-gl=egl'],
66
+ headless: 'shell'
67
+ };
68
+ if (CHROMIUM_PATH) {
69
+ launchSetting['executablePath'] = CHROMIUM_PATH;
70
+ }
71
+ const browser = await puppeteer.launch(launchSetting);
72
+ return browser;
73
+ }
74
+ catch (err) {
75
+ env_1.logger.error(err);
76
+ }
77
+ }
78
+ // Graceful shutdown logic
79
+ function setupProcessExitHandlers() {
80
+ let isCleaningUp = false; // 중복 정리를 방지
81
+ const cleanup = async () => {
82
+ if (isCleaningUp)
83
+ return; // 이미 정리 중이면 무시
84
+ isCleaningUp = true;
85
+ console.log('Application is shutting down. Cleaning up resources...');
86
+ try {
87
+ // Pool 정리 작업 실행
88
+ await destroyHeadlessPool();
89
+ }
90
+ catch (err) {
91
+ env_1.logger.error('Error during cleanup:', err);
92
+ }
93
+ finally {
94
+ console.log('Cleanup completed.');
95
+ }
96
+ };
97
+ const onExit = async (signal) => {
98
+ console.log(`Received signal: ${signal || 'unknown'}`);
99
+ await cleanup();
100
+ // 다른 핸들러가 실행될 수 있도록 exit 호출을 지연
101
+ process.nextTick(() => process.exit(0)); // Tick 뒤에 종료
102
+ };
103
+ // Handle termination signals
104
+ process.once('SIGINT', () => onExit('SIGINT')); // Ctrl+C
105
+ process.once('SIGTERM', () => onExit('SIGTERM')); // Termination signal
106
+ // Handle uncaught exceptions
107
+ process.once('uncaughtException', async (err) => {
108
+ env_1.logger.error('Uncaught Exception:', err);
109
+ await cleanup();
110
+ process.nextTick(() => process.exit(1)); // Tick 뒤에 종료
111
+ });
112
+ // Handle unhandled promise rejections
113
+ process.once('unhandledRejection', async (reason) => {
114
+ env_1.logger.error('Unhandled Rejection:', reason);
115
+ await cleanup();
116
+ process.nextTick(() => process.exit(1)); // Tick 뒤에 종료
117
+ });
118
+ }
119
+ // Initialize process exit handlers
120
+ setupProcessExitHandlers();
121
+ //# sourceMappingURL=headless-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headless-pool.js","sourceRoot":"","sources":["../../../server/engine/resource-pool/headless-pool.ts"],"names":[],"mappings":"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","sourcesContent":["import * as genericPool from 'generic-pool'\nimport { config, logger } from '@things-factory/env'\n\ntry {\n var puppeteer = require('puppeteer')\n} catch (err) {\n logger.error(err)\n}\n\nlet headlessPool\n\nexport function getHeadlessPool() {\n if (!headlessPool) {\n headlessPool = createHeadlessPool({ min: 2, max: 20, acquireTimeoutMillis: 15000, testOnBorrow: true })\n }\n\n return headlessPool\n}\n\nfunction createHeadlessPool(options: genericPool.Options) {\n return genericPool.createPool(\n {\n create() {\n console.log('headless instance in headless-pool-integration about to create')\n return initializeChromium()\n },\n validate(browser) {\n return Promise.race([\n new Promise(res => setTimeout(() => res(false), 1500)),\n browser\n //@ts-ignore\n .version()\n .then(() => true)\n .catch(() => false)\n ])\n },\n destroy(browser) {\n //@ts-ignore\n return browser.close()\n }\n } as genericPool.Factory<any>,\n options\n )\n}\n\nasync function destroyHeadlessPool() {\n if (headlessPool) {\n console.log('headless-pool-integration about to destroy')\n\n try {\n await Promise.race([\n headlessPool.drain().then(() => headlessPool.clear()), // 정리 작업\n new Promise(\n (_, reject) => setTimeout(() => reject(new Error('Destroy timeout')), 5000) // 5초 타임아웃 설정\n )\n ])\n console.log('Headless pool destroyed')\n } catch (err) {\n logger.error('Failed to destroy headless pool:', err)\n }\n }\n}\n\nconst CHROMIUM_PATH = config.get('CHROMIUM_PATH')\n\nasync function initializeChromium() {\n try {\n if (!puppeteer) {\n return\n }\n\n const launchSetting = {\n args: ['--hide-scrollbars', '--mute-audio', '--no-sandbox', '--use-gl=egl'],\n headless: 'shell'\n }\n\n if (CHROMIUM_PATH) {\n launchSetting['executablePath'] = CHROMIUM_PATH\n }\n\n const browser = await puppeteer.launch(launchSetting)\n\n return browser\n } catch (err) {\n logger.error(err)\n }\n}\n\n// Graceful shutdown logic\nfunction setupProcessExitHandlers() {\n let isCleaningUp = false // 중복 정리를 방지\n\n const cleanup = async () => {\n if (isCleaningUp) return // 이미 정리 중이면 무시\n isCleaningUp = true\n\n console.log('Application is shutting down. Cleaning up resources...')\n try {\n // Pool 정리 작업 실행\n await destroyHeadlessPool()\n } catch (err) {\n logger.error('Error during cleanup:', err)\n } finally {\n console.log('Cleanup completed.')\n }\n }\n\n const onExit = async (signal?: string) => {\n console.log(`Received signal: ${signal || 'unknown'}`)\n await cleanup()\n\n // 다른 핸들러가 실행될 수 있도록 exit 호출을 지연\n process.nextTick(() => process.exit(0)) // Tick 뒤에 종료\n }\n\n // Handle termination signals\n process.once('SIGINT', () => onExit('SIGINT')) // Ctrl+C\n process.once('SIGTERM', () => onExit('SIGTERM')) // Termination signal\n\n // Handle uncaught exceptions\n process.once('uncaughtException', async err => {\n logger.error('Uncaught Exception:', err)\n await cleanup()\n process.nextTick(() => process.exit(1)) // Tick 뒤에 종료\n })\n\n // Handle unhandled promise rejections\n process.once('unhandledRejection', async reason => {\n logger.error('Unhandled Rejection:', reason)\n await cleanup()\n process.nextTick(() => process.exit(1)) // Tick 뒤에 종료\n })\n}\n\n// Initialize process exit handlers\nsetupProcessExitHandlers()\n"]}
@@ -0,0 +1 @@
1
+ export * from './headless-pool';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./headless-pool"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/resource-pool/index.ts"],"names":[],"mappings":";;;AAAA,0DAA+B","sourcesContent":["export * from './headless-pool'\n"]}
@@ -6,17 +6,16 @@ const url_1 = require("url");
6
6
  const utils_1 = require("@things-factory/utils");
7
7
  const task_registry_1 = require("../task-registry");
8
8
  const connection_manager_1 = require("../connection-manager");
9
- const headless_pool_for_scenario_1 = require("./utils/headless-pool-for-scenario");
10
9
  async function HeadlessPost(step, { logger, data, domain }) {
11
- var { connection: connectionName, params: stepOptions } = step;
12
- var { headers: requestHeaders, contentType, path, accessor } = stepOptions || {};
13
- var connection = connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
10
+ const { connection: connectionName, params: stepOptions } = step;
11
+ const { headers: requestHeaders, contentType, path, accessor } = stepOptions || {};
12
+ const connection = connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
14
13
  if (!connection) {
15
- throw new Error(`connection '${connectionName}' is not established.`);
14
+ throw new Error(`Connection '${connectionName}' is not established.`);
16
15
  }
17
- var { endpoint, params: connectionParams, authHeaders = {} } = connection;
18
- var headers = Object.assign(Object.assign({}, authHeaders), requestHeaders);
19
- var body = (0, utils_1.access)(accessor, data);
16
+ const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection;
17
+ const headers = Object.assign({}, requestHeaders);
18
+ let body = (0, utils_1.access)(accessor, data);
20
19
  if (contentType && body) {
21
20
  headers['content-type'] = contentType;
22
21
  switch (contentType) {
@@ -31,24 +30,23 @@ async function HeadlessPost(step, { logger, data, domain }) {
31
30
  for (const prop in body) {
32
31
  searchParams.set(prop, body[prop]);
33
32
  }
34
- body = searchParams;
33
+ body = searchParams.toString();
35
34
  break;
36
35
  }
37
36
  }
38
- var options = {
37
+ const options = {
39
38
  method: 'POST',
40
39
  headers,
41
40
  body
42
41
  };
43
- var { rejectUnauthorized } = connectionParams;
42
+ const { rejectUnauthorized } = connectionParams;
44
43
  if (!rejectUnauthorized) {
45
44
  const httpsAgent = new https_1.default.Agent({
46
45
  rejectUnauthorized
47
46
  });
48
47
  options.agent = httpsAgent;
49
48
  }
50
- const browser = (await (0, headless_pool_for_scenario_1.getHeadlessPool)().acquire());
51
- const page = await browser.newPage();
49
+ const page = await acquireSessionPage();
52
50
  try {
53
51
  page.on('console', async (msg) => {
54
52
  console.log(`[browser ${msg.type()}] ${msg.text()}`);
@@ -70,12 +68,12 @@ async function HeadlessPost(step, { logger, data, domain }) {
70
68
  data: response
71
69
  };
72
70
  }
73
- catch (e) {
74
- console.error(e);
71
+ catch (error) {
72
+ logger.error('Error in HeadlessPost:', error);
73
+ throw error;
75
74
  }
76
75
  finally {
77
- page.close();
78
- (0, headless_pool_for_scenario_1.getHeadlessPool)().release(browser);
76
+ await releasePage(page);
79
77
  }
80
78
  }
81
79
  HeadlessPost.parameterSpec = [
@@ -95,22 +93,10 @@ HeadlessPost.parameterSpec = [
95
93
  label: 'content-type',
96
94
  property: {
97
95
  options: [
98
- {
99
- display: '',
100
- value: ''
101
- },
102
- {
103
- display: 'application/json',
104
- value: 'application/json'
105
- },
106
- {
107
- display: 'text/plain',
108
- value: 'text/plain'
109
- },
110
- {
111
- display: 'application/x-www-form-urlencoded',
112
- value: 'application/x-www-form-urlencoded'
113
- }
96
+ { display: '', value: '' },
97
+ { display: 'application/json', value: 'application/json' },
98
+ { display: 'text/plain', value: 'text/plain' },
99
+ { display: 'application/x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' }
114
100
  ]
115
101
  }
116
102
  },
@@ -1 +1 @@
1
- {"version":3,"file":"headless-post.js","sourceRoot":"","sources":["../../../server/engine/task/headless-post.ts"],"names":[],"mappings":"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","sourcesContent":["import https from 'https'\nimport { URL } from 'url'\n\nimport { access } from '@things-factory/utils'\nimport { TaskRegistry } from '../task-registry'\nimport { ConnectionManager } from '../connection-manager'\n\nimport { getHeadlessPool } from './utils/headless-pool-for-scenario'\n\nimport { InputStep } from '../../service/step/step-type'\nimport { Context } from '../types'\n\nasync function HeadlessPost(step: InputStep, { logger, data, domain }: Context) {\n var { connection: connectionName, params: stepOptions } = step\n var { headers: requestHeaders, contentType, path, accessor } = stepOptions || {}\n\n var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n\n if (!connection) {\n throw new Error(`connection '${connectionName}' is not established.`)\n }\n\n var { endpoint, params: connectionParams, authHeaders = {} } = connection\n\n var headers = {\n ...authHeaders,\n ...requestHeaders\n }\n\n var body = access(accessor, data)\n if (contentType && body) {\n headers['content-type'] = contentType\n switch (contentType) {\n case 'text/plain':\n body = JSON.stringify(body)\n break\n case 'application/json':\n body = JSON.stringify(body)\n break\n case 'application/x-www-form-urlencoded':\n const searchParams = new URLSearchParams()\n for (const prop in body) {\n searchParams.set(prop, body[prop])\n }\n body = searchParams\n break\n }\n }\n\n var options: any = {\n method: 'POST',\n headers,\n body\n }\n\n var { rejectUnauthorized } = connectionParams\n\n if (!rejectUnauthorized) {\n const httpsAgent = new https.Agent({\n rejectUnauthorized\n })\n options.agent = httpsAgent\n }\n\n const browser = (await getHeadlessPool().acquire()) as any\n const page = await browser.newPage()\n\n try {\n page.on('console', async msg => {\n console.log(`[browser ${msg.type()}] ${msg.text()}`)\n })\n\n page.on('requestfailed', request => {\n console.log('Request failed:', request.url())\n })\n\n await page.goto(endpoint, { waitUntil: 'networkidle2' })\n\n const response = await page.evaluate(\n async (urlString, options) => {\n const response = await fetch(urlString, options)\n\n if (response.ok && response.headers.get('content-type').includes('application/json')) {\n return await response.json()\n } else {\n return await response.text()\n }\n },\n new URL(path, endpoint),\n options\n )\n\n return {\n data: response\n }\n } catch (e) {\n console.error(e)\n } finally {\n page.close()\n getHeadlessPool().release(browser)\n }\n}\n\nHeadlessPost.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'select',\n name: 'contentType',\n label: 'content-type',\n property: {\n options: [\n {\n display: '',\n value: ''\n },\n {\n display: 'application/json',\n value: 'application/json'\n },\n {\n display: 'text/plain',\n value: 'text/plain'\n },\n {\n display: 'application/x-www-form-urlencoded',\n value: 'application/x-www-form-urlencoded'\n }\n ]\n }\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-post', HeadlessPost)\n"]}
1
+ {"version":3,"file":"headless-post.js","sourceRoot":"","sources":["../../../server/engine/task/headless-post.ts"],"names":[],"mappings":"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","sourcesContent":["import https from 'https'\nimport { URL } from 'url'\n\nimport { access } from '@things-factory/utils'\nimport { TaskRegistry } from '../task-registry'\nimport { ConnectionManager } from '../connection-manager'\n\nasync function HeadlessPost(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, contentType, path, accessor } = stepOptions || {}\n\n const connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n\n if (!connection) {\n throw new Error(`Connection '${connectionName}' is not established.`)\n }\n\n const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection\n\n const headers = {\n ...requestHeaders\n }\n\n let body = access(accessor, data)\n if (contentType && body) {\n headers['content-type'] = contentType\n switch (contentType) {\n case 'text/plain':\n body = JSON.stringify(body)\n break\n case 'application/json':\n body = JSON.stringify(body)\n break\n case 'application/x-www-form-urlencoded':\n const searchParams = new URLSearchParams()\n for (const prop in body) {\n searchParams.set(prop, body[prop])\n }\n body = searchParams.toString()\n break\n }\n }\n\n const options = {\n method: 'POST',\n headers,\n body\n } as any\n\n const { rejectUnauthorized } = connectionParams\n\n if (!rejectUnauthorized) {\n const httpsAgent = new https.Agent({\n rejectUnauthorized\n })\n options.agent = httpsAgent\n }\n\n const page = await acquireSessionPage()\n\n try {\n page.on('console', async msg => {\n console.log(`[browser ${msg.type()}] ${msg.text()}`)\n })\n\n page.on('requestfailed', request => {\n console.log('Request failed:', request.url())\n })\n\n await page.goto(endpoint, { waitUntil: 'networkidle2' })\n\n const response = await page.evaluate(\n async (urlString, options) => {\n const response = await fetch(urlString, options)\n\n if (response.ok && response.headers.get('content-type').includes('application/json')) {\n return await response.json()\n } else {\n return await response.text()\n }\n },\n new URL(path, endpoint),\n options\n )\n\n return {\n data: response\n }\n } catch (error) {\n logger.error('Error in HeadlessPost:', error)\n throw error\n } finally {\n await releasePage(page)\n }\n}\n\nHeadlessPost.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'select',\n name: 'contentType',\n label: 'content-type',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'application/json', value: 'application/json' },\n { display: 'text/plain', value: 'text/plain' },\n { display: 'application/x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' }\n ]\n }\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-post', HeadlessPost)\n"]}
@@ -3,24 +3,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const url_1 = require("url");
4
4
  const task_registry_1 = require("../task-registry");
5
5
  const connection_manager_1 = require("../connection-manager");
6
- const headless_pool_for_scenario_1 = require("./utils/headless-pool-for-scenario");
7
6
  async function HeadlessScrap(step, { logger, data, domain }) {
8
- var { connection: connectionName, params: stepOptions } = step;
9
- var { headers: requestHeaders, path, selectors = [] } = stepOptions || {};
10
- var connection = connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
7
+ const { connection: connectionName, params: stepOptions } = step;
8
+ const { headers: requestHeaders, path, selectors = [] } = stepOptions || {};
9
+ const connection = connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
11
10
  if (!connection) {
12
- throw new Error(`connection '${connectionName}' is not established.`);
11
+ throw new Error(`Connection '${connectionName}' is not established.`);
13
12
  }
14
- var { endpoint, params: connectionParams, authHeaders = {} } = connection;
15
- var headers = Object.assign(Object.assign({}, authHeaders), requestHeaders);
16
- const browser = (await (0, headless_pool_for_scenario_1.getHeadlessPool)().acquire());
17
- const page = await browser.newPage();
13
+ const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection;
14
+ const headers = Object.assign({}, requestHeaders);
15
+ const page = await acquireSessionPage();
18
16
  try {
19
17
  page.on('console', async (msg) => {
20
18
  console.log(`[browser ${msg.type()}] ${msg.text()}`);
21
19
  });
22
20
  page.on('requestfailed', request => {
23
- console.log('Request failed:', request.url());
21
+ var _a;
22
+ console.log('Request failed:');
23
+ console.log(`- URL: ${request.url()}`);
24
+ console.log(`- Method: ${request.method()}`);
25
+ console.log(`- Failure Text: ${(_a = request.failure()) === null || _a === void 0 ? void 0 : _a.errorText}`);
26
+ console.log(`- Headers:`, request.headers());
27
+ // POST 데이터 (필요한 경우)
28
+ if (request.postData()) {
29
+ console.log(`- Post Data: ${request.postData()}`);
30
+ }
24
31
  });
25
32
  await page.setExtraHTTPHeaders(headers);
26
33
  await page.goto(new url_1.URL(path, endpoint), { waitUntil: 'networkidle2' });
@@ -36,11 +43,11 @@ async function HeadlessScrap(step, { logger, data, domain }) {
36
43
  };
37
44
  }
38
45
  catch (e) {
39
- console.error(e);
46
+ logger.error('Error in HeadlessScrap:', e);
47
+ throw e;
40
48
  }
41
49
  finally {
42
- page.close();
43
- (0, headless_pool_for_scenario_1.getHeadlessPool)().release(browser);
50
+ await releasePage(page);
44
51
  }
45
52
  }
46
53
  HeadlessScrap.parameterSpec = [
@@ -1 +1 @@
1
- {"version":3,"file":"headless-scrap.js","sourceRoot":"","sources":["../../../server/engine/task/headless-scrap.ts"],"names":[],"mappings":"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","sourcesContent":["import { URL } from 'url'\n\nimport { TaskRegistry } from '../task-registry'\nimport { ConnectionManager } from '../connection-manager'\n\nimport { getHeadlessPool } from './utils/headless-pool-for-scenario'\nimport { InputStep } from '../../service/step/step-type'\nimport { Context } from '../types'\n\nasync function HeadlessScrap(step: InputStep, { logger, data, domain }: Context) {\n var { connection: connectionName, params: stepOptions } = step\n var { headers: requestHeaders, path, selectors = [] } = stepOptions || {}\n\n var connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n\n if (!connection) {\n throw new Error(`connection '${connectionName}' is not established.`)\n }\n\n var { endpoint, params: connectionParams, authHeaders = {} } = connection\n\n var headers = {\n ...authHeaders,\n ...requestHeaders\n }\n\n const browser = (await getHeadlessPool().acquire()) as any\n const page = await browser.newPage()\n\n try {\n page.on('console', async msg => {\n console.log(`[browser ${msg.type()}] ${msg.text()}`)\n })\n\n page.on('requestfailed', request => {\n console.log('Request failed:', request.url())\n })\n\n await page.setExtraHTTPHeaders(headers)\n await page.goto(new URL(path, endpoint), { waitUntil: 'networkidle2' })\n\n const result = {}\n\n for (const selector of selectors) {\n const { text, value } = selector\n result[text] = await page.$$eval(value, elements => {\n return elements.map(element => element.textContent.trim())\n })\n }\n\n return {\n data: result\n }\n } catch (e) {\n console.error(e)\n } finally {\n page.close()\n getHeadlessPool().release(browser)\n }\n}\n\nHeadlessScrap.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'selectors',\n label: 'selectors'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-scrap', HeadlessScrap)\n"]}
1
+ {"version":3,"file":"headless-scrap.js","sourceRoot":"","sources":["../../../server/engine/task/headless-scrap.ts"],"names":[],"mappings":"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","sourcesContent":["import { URL } from 'url'\n\nimport { TaskRegistry } from '../task-registry'\nimport { ConnectionManager } from '../connection-manager'\n\nasync function HeadlessScrap(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, path, selectors = [] } = stepOptions || {}\n\n const connection = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n\n if (!connection) {\n throw new Error(`Connection '${connectionName}' is not established.`)\n }\n\n const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection\n\n const headers = {\n ...requestHeaders\n }\n\n const page = await acquireSessionPage()\n\n try {\n page.on('console', async msg => {\n console.log(`[browser ${msg.type()}] ${msg.text()}`)\n })\n\n page.on('requestfailed', request => {\n console.log('Request failed:')\n console.log(`- URL: ${request.url()}`)\n console.log(`- Method: ${request.method()}`)\n console.log(`- Failure Text: ${request.failure()?.errorText}`)\n console.log(`- Headers:`, request.headers())\n\n // POST 데이터 (필요한 경우)\n if (request.postData()) {\n console.log(`- Post Data: ${request.postData()}`)\n }\n })\n\n await page.setExtraHTTPHeaders(headers)\n await page.goto(new URL(path, endpoint), { waitUntil: 'networkidle2' })\n\n const result = {}\n\n for (const selector of selectors) {\n const { text, value } = selector\n result[text] = await page.$$eval(value, elements => {\n return elements.map(element => element.textContent.trim())\n })\n }\n\n return {\n data: result\n }\n } catch (e) {\n logger.error('Error in HeadlessScrap:', e)\n throw e\n } finally {\n await releasePage(page)\n }\n}\n\nHeadlessScrap.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'selectors',\n label: 'selectors'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-scrap', HeadlessScrap)\n"]}
@@ -15,7 +15,7 @@ function getHeadlessPool() {
15
15
  if (!headlessPool) {
16
16
  headlessPool = genericPool.createPool({
17
17
  create() {
18
- console.log('headless-pool-for-scensrio about to create');
18
+ console.log('headless instance in headless-pool-for-scensrio about to create');
19
19
  return initializeChromium();
20
20
  },
21
21
  validate(browser) {
@@ -1 +1 @@
1
- {"version":3,"file":"headless-pool-for-scenario.js","sourceRoot":"","sources":["../../../../server/engine/task/utils/headless-pool-for-scenario.ts"],"names":[],"mappings":";;AAYA,0CAiCC;;AA7CD,kEAA2C;AAE3C,6CAAoD;AAEpD,IAAI,CAAC;IACH,IAAI,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AACtC,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,YAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AACnB,CAAC;AAED,IAAI,YAAY,CAAA;AAEhB,SAAgB,eAAe;IAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,WAAW,CAAC,UAAU,CACnC;YACE,MAAM;gBACJ,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAA;gBACzD,OAAO,kBAAkB,EAAE,CAAA;YAC7B,CAAC;YACD,QAAQ,CAAC,OAAO;gBACd,OAAO,OAAO,CAAC,IAAI,CAAC;oBAClB,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;oBACtD,OAAO;wBACL,YAAY;yBACX,OAAO,EAAE;yBACT,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC;yBACf,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;iBACrB,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,CAAC,OAAO;gBACb,YAAY;gBACZ,OAAO,OAAO,CAAC,KAAK,EAAE,CAAA;YACxB,CAAC;SACF,EACD;YACE,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,EAAE;YACP,YAAY,EAAE,IAAI;YAClB,oBAAoB,EAAE,KAAK;SAC5B,CACF,CAAA;IACH,CAAC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,aAAa,GAAG,YAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;AAEjD,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAM;QACR,CAAC;QAED,IAAI,aAAa,GAAG;YAClB,IAAI,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;YACtC,QAAQ,EAAE,OAAO;SAClB,CAAA;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,CAAC,gBAAgB,CAAC,GAAG,aAAa,CAAA;QACjD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QAErD,OAAO,OAAO,CAAA;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,YAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC;AACH,CAAC","sourcesContent":["import * as genericPool from 'generic-pool'\n\nimport { config, logger } from '@things-factory/env'\n\ntry {\n var puppeteer = require('puppeteer')\n} catch (err) {\n logger.error(err)\n}\n\nvar headlessPool\n\nexport function getHeadlessPool() {\n if (!headlessPool) {\n headlessPool = genericPool.createPool(\n {\n create() {\n console.log('headless-pool-for-scensrio about to create')\n return initializeChromium()\n },\n validate(browser) {\n return Promise.race([\n new Promise(res => setTimeout(() => res(false), 1500)),\n browser\n //@ts-ignore\n .version()\n .then(_ => true)\n .catch(_ => false)\n ])\n },\n destroy(browser) {\n //@ts-ignore\n return browser.close()\n }\n },\n {\n min: 2,\n max: 10,\n testOnBorrow: true,\n acquireTimeoutMillis: 15000\n }\n )\n }\n\n return headlessPool\n}\n\nconst CHROMIUM_PATH = config.get('CHROMIUM_PATH')\n\nasync function initializeChromium() {\n try {\n if (!puppeteer) {\n return\n }\n\n var launchSetting = {\n args: ['--mute-audio', '--no-sandbox'],\n headless: 'shell'\n }\n\n if (CHROMIUM_PATH) {\n launchSetting['executablePath'] = CHROMIUM_PATH\n }\n\n const browser = await puppeteer.launch(launchSetting)\n\n return browser\n } catch (err) {\n logger.error(err)\n }\n}\n"]}
1
+ {"version":3,"file":"headless-pool-for-scenario.js","sourceRoot":"","sources":["../../../../server/engine/task/utils/headless-pool-for-scenario.ts"],"names":[],"mappings":";;AAYA,0CAiCC;;AA7CD,kEAA2C;AAE3C,6CAAoD;AAEpD,IAAI,CAAC;IACH,IAAI,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AACtC,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,YAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AACnB,CAAC;AAED,IAAI,YAAY,CAAA;AAEhB,SAAgB,eAAe;IAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,WAAW,CAAC,UAAU,CACnC;YACE,MAAM;gBACJ,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAA;gBAC9E,OAAO,kBAAkB,EAAE,CAAA;YAC7B,CAAC;YACD,QAAQ,CAAC,OAAO;gBACd,OAAO,OAAO,CAAC,IAAI,CAAC;oBAClB,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;oBACtD,OAAO;wBACL,YAAY;yBACX,OAAO,EAAE;yBACT,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC;yBACf,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;iBACrB,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,CAAC,OAAO;gBACb,YAAY;gBACZ,OAAO,OAAO,CAAC,KAAK,EAAE,CAAA;YACxB,CAAC;SACF,EACD;YACE,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,EAAE;YACP,YAAY,EAAE,IAAI;YAClB,oBAAoB,EAAE,KAAK;SAC5B,CACF,CAAA;IACH,CAAC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,aAAa,GAAG,YAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;AAEjD,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAM;QACR,CAAC;QAED,IAAI,aAAa,GAAG;YAClB,IAAI,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;YACtC,QAAQ,EAAE,OAAO;SAClB,CAAA;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,CAAC,gBAAgB,CAAC,GAAG,aAAa,CAAA;QACjD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QAErD,OAAO,OAAO,CAAA;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,YAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnB,CAAC;AACH,CAAC","sourcesContent":["import * as genericPool from 'generic-pool'\n\nimport { config, logger } from '@things-factory/env'\n\ntry {\n var puppeteer = require('puppeteer')\n} catch (err) {\n logger.error(err)\n}\n\nvar headlessPool\n\nexport function getHeadlessPool() {\n if (!headlessPool) {\n headlessPool = genericPool.createPool(\n {\n create() {\n console.log('headless instance in headless-pool-for-scensrio about to create')\n return initializeChromium()\n },\n validate(browser) {\n return Promise.race([\n new Promise(res => setTimeout(() => res(false), 1500)),\n browser\n //@ts-ignore\n .version()\n .then(_ => true)\n .catch(_ => false)\n ])\n },\n destroy(browser) {\n //@ts-ignore\n return browser.close()\n }\n },\n {\n min: 2,\n max: 10,\n testOnBorrow: true,\n acquireTimeoutMillis: 15000\n }\n )\n }\n\n return headlessPool\n}\n\nconst CHROMIUM_PATH = config.get('CHROMIUM_PATH')\n\nasync function initializeChromium() {\n try {\n if (!puppeteer) {\n return\n }\n\n var launchSetting = {\n args: ['--mute-audio', '--no-sandbox'],\n headless: 'shell'\n }\n\n if (CHROMIUM_PATH) {\n launchSetting['executablePath'] = CHROMIUM_PATH\n }\n\n const browser = await puppeteer.launch(launchSetting)\n\n return browser\n } catch (err) {\n logger.error(err)\n }\n}\n"]}
@@ -38,14 +38,17 @@ tslib_1.__decorate([
38
38
  ], PayloadLog.prototype, "name", void 0);
39
39
  tslib_1.__decorate([
40
40
  (0, typeorm_1.Column)({
41
+ nullable: true,
41
42
  type: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
42
43
  ? 'enum'
43
44
  : DATABASE_TYPE == 'oracle'
44
45
  ? 'varchar2'
45
- : 'smallint',
46
- enum: PayloadType,
47
- default: PayloadType.EGESTION,
48
- nullable: true
46
+ : DATABASE_TYPE == 'mssql'
47
+ ? 'nvarchar'
48
+ : 'varchar',
49
+ enum: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? PayloadType : undefined,
50
+ length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32,
51
+ default: PayloadType.EGESTION
49
52
  }),
50
53
  (0, type_graphql_1.Field)(type => String),
51
54
  tslib_1.__metadata("design:type", String)
@@ -1 +1 @@
1
- {"version":3,"file":"payload-log.js","sourceRoot":"","sources":["../../../server/service/payload-log/payload-log.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'\n\nimport { config } from '@things-factory/env'\nimport { Bizplace } from '@things-factory/biz-base'\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum PayloadType {\n INGESTION = 'ingestion',\n EGESTION = 'egestion'\n}\n@Entity()\n@Index('ix_payload_log_0', (payloadLog: PayloadLog) => [payloadLog.domain])\n@Index('ix_payload_log_1', (payloadLog: PayloadLog) => [payloadLog.domain, payloadLog.endpoint])\n@ObjectType({ description: 'Entity for PayloadLog' })\nexport class PayloadLog {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain)\n domain?: Domain\n\n @RelationId((payloadLog: PayloadLog) => payloadLog.domain)\n domainId?: string\n\n @Column()\n @Field()\n name: string\n\n @Column({\n type:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'enum'\n : DATABASE_TYPE == 'oracle'\n ? 'varchar2'\n : 'smallint',\n enum: PayloadType,\n default: PayloadType.EGESTION,\n nullable: true\n })\n @Field(type => String)\n type: PayloadType\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n src: string\n\n @Column()\n @Field()\n endpoint: string\n\n @Column()\n @Field()\n request: string\n\n @Column()\n @Field()\n response: string\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((payloadLog: PayloadLog) => payloadLog.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((payloadLog: PayloadLog) => payloadLog.updater)\n updaterId?: string\n}\n"]}
1
+ {"version":3,"file":"payload-log.js","sourceRoot":"","sources":["../../../server/service/payload-log/payload-log.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CreateDateColumn,\n UpdateDateColumn,\n Entity,\n Index,\n Column,\n RelationId,\n ManyToOne,\n PrimaryGeneratedColumn\n} from 'typeorm'\nimport { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'\n\nimport { config } from '@things-factory/env'\nimport { Bizplace } from '@things-factory/biz-base'\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nexport enum PayloadType {\n INGESTION = 'ingestion',\n EGESTION = 'egestion'\n}\n@Entity()\n@Index('ix_payload_log_0', (payloadLog: PayloadLog) => [payloadLog.domain])\n@Index('ix_payload_log_1', (payloadLog: PayloadLog) => [payloadLog.domain, payloadLog.endpoint])\n@ObjectType({ description: 'Entity for PayloadLog' })\nexport class PayloadLog {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain)\n domain?: Domain\n\n @RelationId((payloadLog: PayloadLog) => payloadLog.domain)\n domainId?: string\n\n @Column()\n @Field()\n name: string\n\n @Column({\n nullable: true,\n type:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'enum'\n : DATABASE_TYPE == 'oracle'\n ? 'varchar2'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'varchar',\n enum:\n DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? PayloadType : undefined,\n length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 32,\n default: PayloadType.EGESTION\n })\n @Field(type => String)\n type: PayloadType\n\n @Column({ nullable: true })\n @Field({ nullable: true })\n src: string\n\n @Column()\n @Field()\n endpoint: string\n\n @Column()\n @Field()\n request: string\n\n @Column()\n @Field()\n response: string\n\n @CreateDateColumn()\n @Field({ nullable: true })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((payloadLog: PayloadLog) => payloadLog.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((payloadLog: PayloadLog) => payloadLog.updater)\n updaterId?: string\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { User } from '@things-factory/auth-base';
1
+ import { User, Role } from '@things-factory/auth-base';
2
2
  import { Domain, ListParam } from '@things-factory/shell';
3
3
  import { ScenarioInstance } from '../scenario-instance/scenario-instance-type';
4
4
  import { Step } from '../step/step-type';
@@ -15,4 +15,5 @@ export declare class ScenarioQuery {
15
15
  publishTags(scenario: Scenario, context: ResolverContext): Promise<any[]>;
16
16
  state(scenario: Scenario, context: ResolverContext): Promise<string>;
17
17
  instances(scenario: Scenario, context: ResolverContext): Promise<ScenarioInstance[]>;
18
+ role(scenario: Scenario): Promise<Role>;
18
19
  }
@@ -70,6 +70,9 @@ let ScenarioQuery = class ScenarioQuery {
70
70
  const { domain } = context.state;
71
71
  return engine_1.ScenarioEngine.getScenarioInstances(domain, scenario.name);
72
72
  }
73
+ async role(scenario) {
74
+ return scenario.roleId && (await (0, shell_1.getRepository)(auth_base_1.Role).findOneBy({ id: scenario.roleId }));
75
+ }
73
76
  };
74
77
  exports.ScenarioQuery = ScenarioQuery;
75
78
  tslib_1.__decorate([
@@ -151,6 +154,13 @@ tslib_1.__decorate([
151
154
  tslib_1.__metadata("design:paramtypes", [scenario_1.Scenario, Object]),
152
155
  tslib_1.__metadata("design:returntype", Promise)
153
156
  ], ScenarioQuery.prototype, "instances", null);
157
+ tslib_1.__decorate([
158
+ (0, type_graphql_1.FieldResolver)(type => auth_base_1.Role),
159
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
160
+ tslib_1.__metadata("design:type", Function),
161
+ tslib_1.__metadata("design:paramtypes", [scenario_1.Scenario]),
162
+ tslib_1.__metadata("design:returntype", Promise)
163
+ ], ScenarioQuery.prototype, "role", null);
154
164
  exports.ScenarioQuery = ScenarioQuery = tslib_1.__decorate([
155
165
  (0, type_graphql_1.Resolver)(scenario_1.Scenario)
156
166
  ], ScenarioQuery);