bizlin-chat 0.0.2 → 0.0.4

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 CHANGED
@@ -1,61 +1,40 @@
1
- # bizlin-chat (zchat plugin)
1
+ # Bizlin Chat - WhatsApp Cloud API Team Inbox
2
2
 
3
- This repository provides the bizlin-chat platform a WhatsApp team inbox with backend and frontend, plus a CLI to run the platform.
3
+ Open-source WhatsApp Cloud API Team Inbox with Express.js, Next.js, and TypeScript.
4
4
 
5
- Features
6
- - Backend: Express API, Socket.IO, message persistence (SQLite/Postgres), WhatsApp Cloud API integration, setup endpoints for admin and WhatsApp account.
7
- - Frontend: Next.js app with message list, send text/media/template, setup wizard for initial admin and WhatsApp account.
8
- - CLI: `bizlin-chat` command to run the platform, with background daemon support and log files.
9
- - CI: GitHub Actions workflow for npm publishing with provenance.
10
-
11
- Quick start (local, foreground)
12
-
13
- 1. Install dependencies:
5
+ ## Global Install
14
6
 
15
7
  ```bash
16
- cd backend
17
- npm install
18
- cd ../frontend
19
- npm install
8
+ npm install -g bizlin-chat
20
9
  ```
21
10
 
22
- 2. Run via CLI (foreground):
11
+ ## Usage
23
12
 
24
13
  ```bash
25
- node ./bin/bizlin-chat.js --port 1994 --db sqlite --dbname bizlin_chat
14
+ bizlin-chat start # Start application (ports 4000-4001)
15
+ bizlin-chat stop # Stop application
16
+ bizlin-chat restart # Restart application
17
+ bizlin-chat logs # View logs
18
+
19
+ # Options
20
+ bizlin-chat start --port 5000 # Custom port
21
+ bizlin-chat start --db postgres # Use PostgreSQL
26
22
  ```
27
23
 
28
- This starts the backend on `--port` (default 1994) and the frontend (Next dev) on `port+1`.
29
-
30
- Daemon mode (background)
31
-
32
- - Start background: `bizlin-chat start --port 1994 --db sqlite --dbname bizlin_chat`
33
- - Stop: `bizlin-chat stop`
34
- - Restart: `bizlin-chat restart --port 1994`
35
- - View logs (last ~200 lines): `bizlin-chat logs`
24
+ Access at: http://localhost:4001
36
25
 
37
- Logs are written to `logs/backend.log` and `logs/frontend.log` in the repository root when running in daemon mode.
26
+ ## Environment Setup
38
27
 
39
- Setup wizard
28
+ Create `.env` file (optional):
40
29
 
41
- When you first open the frontend, if no admin exists, the app shows a setup wizard:
42
- - Create admin (username/password)
43
- - Configure WhatsApp Cloud API (phone_id, token, api_version)
44
- - The frontend provides a "Test" button to validate WhatsApp credentials before saving.
45
-
46
- Database
47
-
48
- - Default: SQLite file `data/<dbname>.sqlite` (default dbname `bizlin_chat`).
49
- - To use Postgres: `--db postgres --dbname my_db` and ensure `DATABASE_URL` is set or the default postgres URL is reachable.
30
+ ```env
31
+ PORT=4000
32
+ DB_CLIENT=sqlite
33
+ WHATSAPP_PHONE_NUMBER_ID=your_phone_id
34
+ WHATSAPP_ACCESS_TOKEN=your_access_token
35
+ WHATSAPP_VERIFY_TOKEN=your_verify_token
36
+ ```
50
37
 
51
- API endpoints
52
- - `GET /api/setup/status` — check if admin exists
53
- - `POST /api/setup/create-admin` — create admin
54
- - `POST /api/setup/test-whatsapp` — test WhatsApp credentials
55
- - `POST /api/setup/whatsapp` — save WhatsApp account
56
- - `GET /api/messages`, `POST /api/messages` — messages
57
- - `POST /api/send`, `POST /api/sendMedia`, `POST /api/sendTemplate` — send via WhatsApp (uses saved account)
38
+ ## License
58
39
 
59
- Notes
60
- - Credentials are stored in the database; passwords are hashed.
61
- - The CLI writes PID to `.bizlin-chat.pid` for background control.
40
+ MIT
@@ -1,21 +1,51 @@
1
1
  {
2
- "name": "backend",
2
+ "name": "@bizlin/backend",
3
3
  "version": "0.1.0",
4
- "private": true,
5
- "main": "src/index.js",
4
+ "private": false,
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "description": "WhatsApp Team Inbox Backend API",
8
+ "keywords": ["whatsapp", "api", "express", "typescript"],
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/yourusername/zchat.git",
12
+ "directory": "backend"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src",
17
+ "tsconfig.json"
18
+ ],
6
19
  "scripts": {
7
- "start": "node src/index.js",
8
- "dev": "nodemon src/index.js"
20
+ "build": "tsc",
21
+ "start": "node dist/index.js",
22
+ "dev": "ts-node --transpile-only src/index.ts",
23
+ "dev:watch": "nodemon --exec ts-node --transpile-only src/index.ts"
9
24
  },
10
25
  "dependencies": {
26
+ "express": "4.18.2",
11
27
  "axios": "1.5.0",
28
+ "bcryptjs": "2.4.3",
12
29
  "cors": "2.8.5",
13
- "express": "4.18.2",
14
- "socket.io": "4.7.2",
15
- "uuid": "9.0.0",
30
+ "form-data": "^4.0.5",
31
+ "multer": "^2.1.1",
16
32
  "pg": "8.11.0",
33
+ "socket.io": "4.7.2",
17
34
  "sqlite3": "5.1.6",
18
- "bcryptjs": "2.4.3"
35
+ "uuid": "9.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.1.3",
39
+ "ts-node": "^10.9.1",
40
+ "nodemon": "^3.0.1",
41
+ "@types/express": "^4.17.17",
42
+ "@types/node": "^20.3.1",
43
+ "@types/bcryptjs": "^2.4.2",
44
+ "@types/multer": "^2.1.0",
45
+ "@types/uuid": "^9.0.2",
46
+ "@types/pg": "^8.10.9"
47
+ },
48
+ "engines": {
49
+ "node": ">=14"
19
50
  }
20
-
21
51
  }
@@ -21,13 +21,14 @@ function start(name, cmd, args, env) {
21
21
 
22
22
  function parseArgs() {
23
23
  const args = process.argv.slice(2)
24
- const out = { port: 1994, db: 'sqlite' }
24
+ const out = { port: 1994, db: 'sqlite', extra: [] }
25
25
  for (let i = 0; i < args.length; i++) {
26
26
  const a = args[i]
27
27
  if (a === '--port' && args[i+1]) { out.port = parseInt(args[i+1], 10); i++ }
28
28
  else if (a === '--db' && args[i+1]) { out.db = args[i+1]; i++ }
29
29
  else if (a === '--dbname' && args[i+1]) { out.dbname = args[i+1]; i++ }
30
30
  else if (a === '--help' || a === '-h') { out.action = 'help' }
31
+ else if (['start','stop','restart','run','logs','help'].includes(a)) { out.action = a }
31
32
  else out.extra.push(a)
32
33
  }
33
34
  return out
@@ -1,16 +1,61 @@
1
1
  {
2
- "name": "frontend",
2
+ "name": "@bizlin/frontend",
3
3
  "version": "0.1.0",
4
- "private": true,
4
+ "private": false,
5
+ "description": "WhatsApp Team Inbox Frontend Application",
6
+ "keywords": [
7
+ "whatsapp",
8
+ "next.js",
9
+ "react",
10
+ "typescript"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/yourusername/zchat.git",
15
+ "directory": "frontend"
16
+ },
17
+ "files": [
18
+ ".next",
19
+ "public",
20
+ "app",
21
+ "components",
22
+ "context",
23
+ "hooks",
24
+ "lib",
25
+ "styles",
26
+ "pages",
27
+ "package.json",
28
+ "next.config.js",
29
+ "tsconfig.json",
30
+ "tailwind.config.js",
31
+ "postcss.config.js"
32
+ ],
5
33
  "scripts": {
6
34
  "dev": "next dev",
7
35
  "build": "next build",
8
- "start": "next start -p 3000"
36
+ "start": "next start -p 3000",
37
+ "lint": "next lint"
9
38
  },
10
39
  "dependencies": {
11
40
  "next": "13.4.7",
12
41
  "react": "18.2.0",
13
42
  "react-dom": "18.2.0",
14
- "socket.io-client": "4.7.2"
43
+ "react-icons": "^4.12.0",
44
+ "socket.io-client": "4.7.2",
45
+ "axios": "1.5.0",
46
+ "utf-8-validate": "^6.0.0",
47
+ "bufferutil": "^4.0.8"
48
+ },
49
+ "devDependencies": {
50
+ "typescript": "^5.1.3",
51
+ "@types/react": "^18.2.12",
52
+ "@types/react-dom": "^18.2.5",
53
+ "@types/node": "^20.3.1",
54
+ "autoprefixer": "^10.4.0",
55
+ "postcss": "^8.4.0",
56
+ "tailwindcss": "^3.4.8"
57
+ },
58
+ "engines": {
59
+ "node": ">=14"
15
60
  }
16
61
  }
@@ -0,0 +1 @@
1
+ {"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/next/dist/styled-jsx/types/css.d.ts","./node_modules/@types/react/global.d.ts","./node_modules/csstype/index.d.ts","./node_modules/@types/prop-types/index.d.ts","./node_modules/@types/react/index.d.ts","./node_modules/next/dist/styled-jsx/types/index.d.ts","./node_modules/next/dist/styled-jsx/types/macro.d.ts","./node_modules/next/dist/styled-jsx/types/style.d.ts","./node_modules/next/dist/styled-jsx/types/global.d.ts","./node_modules/next/dist/shared/lib/amp.d.ts","./node_modules/next/amp.d.ts","./node_modules/@types/node/compatibility/disposable.d.ts","./node_modules/@types/node/compatibility/indexable.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/compatibility/index.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/file.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/filereader.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/next/dist/server/get-page-files.d.ts","./node_modules/@types/react/canary.d.ts","./node_modules/@types/react/experimental.d.ts","./node_modules/@types/react-dom/index.d.ts","./node_modules/@types/react-dom/canary.d.ts","./node_modules/@types/react-dom/experimental.d.ts","./node_modules/next/dist/compiled/webpack/webpack.d.ts","./node_modules/next/dist/server/config.d.ts","./node_modules/next/dist/lib/load-custom-routes.d.ts","./node_modules/next/dist/shared/lib/image-config.d.ts","./node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","./node_modules/next/dist/server/body-streams.d.ts","./node_modules/next/dist/server/future/route-kind.d.ts","./node_modules/next/dist/server/future/route-definitions/route-definition.d.ts","./node_modules/next/dist/server/future/route-matches/route-match.d.ts","./node_modules/next/dist/client/components/app-router-headers.d.ts","./node_modules/next/dist/server/request-meta.d.ts","./node_modules/next/dist/server/config-shared.d.ts","./node_modules/next/dist/server/base-http/index.d.ts","./node_modules/next/dist/server/api-utils/index.d.ts","./node_modules/next/dist/server/node-environment.d.ts","./node_modules/next/dist/server/require-hook.d.ts","./node_modules/next/dist/server/node-polyfill-fetch.d.ts","./node_modules/next/dist/server/node-polyfill-form.d.ts","./node_modules/next/dist/server/node-polyfill-web-streams.d.ts","./node_modules/next/dist/server/node-polyfill-crypto.d.ts","./node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","./node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","./node_modules/next/dist/server/future/route-matchers/route-matcher.d.ts","./node_modules/next/dist/server/future/route-matcher-providers/route-matcher-provider.d.ts","./node_modules/next/dist/server/future/helpers/i18n-provider.d.ts","./node_modules/next/dist/server/future/route-matcher-managers/route-matcher-manager.d.ts","./node_modules/next/dist/server/router.d.ts","./node_modules/next/dist/build/analysis/get-page-static-info.d.ts","./node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","./node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","./node_modules/next/dist/server/render-result.d.ts","./node_modules/next/dist/server/web/next-url.d.ts","./node_modules/next/dist/compiled/@edge-runtime/cookies/index.d.ts","./node_modules/next/dist/server/web/spec-extension/cookies.d.ts","./node_modules/next/dist/server/web/spec-extension/request.d.ts","./node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","./node_modules/next/dist/server/web/spec-extension/response.d.ts","./node_modules/next/dist/server/web/types.d.ts","./node_modules/next/dist/lib/setup-exception-listeners.d.ts","./node_modules/next/dist/build/index.d.ts","./node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","./node_modules/next/dist/server/send-payload/revalidate-headers.d.ts","./node_modules/next/dist/server/send-payload/index.d.ts","./node_modules/next/dist/server/base-http/node.d.ts","./node_modules/next/dist/server/font-utils.d.ts","./node_modules/next/dist/build/webpack/plugins/flight-manifest-plugin.d.ts","./node_modules/next/dist/server/load-components.d.ts","./node_modules/next/dist/build/webpack/plugins/next-font-manifest-plugin.d.ts","./node_modules/next/dist/server/render.d.ts","./node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","./node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","./node_modules/next/dist/server/response-cache/types.d.ts","./node_modules/next/dist/server/response-cache/index.d.ts","./node_modules/next/dist/server/future/helpers/module-loader/module-loader.d.ts","./node_modules/next/dist/server/future/route-definitions/app-route-route-definition.d.ts","./node_modules/next/dist/build/webpack/plugins/app-build-manifest-plugin.d.ts","./node_modules/next/dist/lib/coalesced-function.d.ts","./node_modules/next/dist/server/lib/incremental-cache/index.d.ts","./node_modules/next/dist/client/components/hooks-server-context.d.ts","./node_modules/next/dist/client/components/static-generation-async-storage.d.ts","./node_modules/next/dist/server/lib/patch-fetch.d.ts","./node_modules/next/dist/build/utils.d.ts","./node_modules/next/dist/server/future/route-modules/route-module.d.ts","./node_modules/next/dist/server/async-storage/async-storage-wrapper.d.ts","./node_modules/next/dist/server/async-storage/static-generation-async-storage-wrapper.d.ts","./node_modules/next/dist/server/web/http.d.ts","./node_modules/next/dist/server/web/spec-extension/adapters/request-cookies.d.ts","./node_modules/next/dist/server/async-storage/draft-mode-provider.d.ts","./node_modules/next/dist/server/web/spec-extension/adapters/headers.d.ts","./node_modules/next/dist/client/components/request-async-storage.d.ts","./node_modules/next/dist/client/components/draft-mode.d.ts","./node_modules/next/dist/client/components/headers.d.ts","./node_modules/next/dist/client/components/static-generation-bailout.d.ts","./node_modules/next/dist/client/components/action-async-storage.d.ts","./node_modules/next/dist/server/future/route-modules/app-route/module.d.ts","./node_modules/next/dist/server/future/route-matches/app-route-route-match.d.ts","./node_modules/next/dist/server/future/route-handler-managers/route-handler-manager.d.ts","./node_modules/next/dist/server/future/normalizers/normalizer.d.ts","./node_modules/next/dist/server/future/normalizers/locale-route-normalizer.d.ts","./node_modules/next/dist/server/base-server.d.ts","./node_modules/next/dist/server/future/route-definitions/locale-route-definition.d.ts","./node_modules/next/dist/server/future/route-definitions/pages-api-route-definition.d.ts","./node_modules/next/dist/server/future/route-matches/pages-api-route-match.d.ts","./node_modules/next/dist/server/lib/cpu-profile.d.ts","./node_modules/next/dist/server/lib/render-server.d.ts","./node_modules/next/dist/server/image-optimizer.d.ts","./node_modules/next/dist/server/next-server.d.ts","./node_modules/next/dist/server/future/route-matcher-managers/default-route-matcher-manager.d.ts","./node_modules/next/dist/server/future/route-matcher-managers/dev-route-matcher-manager.d.ts","./node_modules/next/dist/server/dev/static-paths-worker.d.ts","./node_modules/next/dist/server/dev/next-dev-server.d.ts","./node_modules/next/dist/server/next.d.ts","./node_modules/next/dist/lib/metadata/types/alternative-urls-types.d.ts","./node_modules/next/dist/lib/metadata/types/extra-types.d.ts","./node_modules/next/dist/lib/metadata/types/metadata-types.d.ts","./node_modules/next/dist/lib/metadata/types/manifest-types.d.ts","./node_modules/next/dist/lib/metadata/types/opengraph-types.d.ts","./node_modules/next/dist/lib/metadata/types/twitter-types.d.ts","./node_modules/next/dist/lib/metadata/types/metadata-interface.d.ts","./node_modules/next/types/index.d.ts","./node_modules/next/dist/shared/lib/html-context.d.ts","./node_modules/@next/env/dist/index.d.ts","./node_modules/next/dist/shared/lib/mitt.d.ts","./node_modules/next/dist/client/with-router.d.ts","./node_modules/next/dist/client/router.d.ts","./node_modules/next/dist/client/route-loader.d.ts","./node_modules/next/dist/client/page-loader.d.ts","./node_modules/next/dist/shared/lib/bloom-filter.d.ts","./node_modules/next/dist/shared/lib/router/router.d.ts","./node_modules/next/dist/shared/lib/modern-browserslist-target.d.ts","./node_modules/next/dist/shared/lib/constants.d.ts","./node_modules/next/dist/shared/lib/utils.d.ts","./node_modules/next/dist/pages/_app.d.ts","./node_modules/next/app.d.ts","./node_modules/next/dist/server/web/spec-extension/unstable-cache.d.ts","./node_modules/next/dist/server/web/spec-extension/revalidate-path.d.ts","./node_modules/next/dist/server/web/spec-extension/revalidate-tag.d.ts","./node_modules/next/cache.d.ts","./node_modules/next/dist/shared/lib/runtime-config.d.ts","./node_modules/next/config.d.ts","./node_modules/next/dist/pages/_document.d.ts","./node_modules/next/document.d.ts","./node_modules/next/dist/shared/lib/dynamic.d.ts","./node_modules/next/dynamic.d.ts","./node_modules/next/dist/pages/_error.d.ts","./node_modules/next/error.d.ts","./node_modules/next/dist/shared/lib/head.d.ts","./node_modules/next/head.d.ts","./node_modules/next/dist/client/image.d.ts","./node_modules/next/image.d.ts","./node_modules/next/dist/client/link.d.ts","./node_modules/next/link.d.ts","./node_modules/next/router.d.ts","./node_modules/next/dist/client/script.d.ts","./node_modules/next/script.d.ts","./node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","./node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","./node_modules/next/dist/compiled/@vercel/og/satori/index.d.ts","./node_modules/next/dist/compiled/@vercel/og/emoji/index.d.ts","./node_modules/next/dist/compiled/@vercel/og/types.d.ts","./node_modules/next/dist/compiled/@vercel/og/index.node.d.ts","./node_modules/next/dist/server/web/spec-extension/image-response.d.ts","./node_modules/next/server.d.ts","./node_modules/next/types/global.d.ts","./node_modules/next/index.d.ts","./node_modules/next/image-types/global.d.ts","./node_modules/next/dist/shared/lib/server-inserted-html.d.ts","./node_modules/next/dist/client/components/redirect.d.ts","./node_modules/next/dist/client/components/not-found.d.ts","./node_modules/zod/lib/helpers/typealiases.d.ts","./node_modules/zod/lib/helpers/util.d.ts","./node_modules/zod/lib/zoderror.d.ts","./node_modules/zod/lib/locales/en.d.ts","./node_modules/zod/lib/errors.d.ts","./node_modules/zod/lib/helpers/parseutil.d.ts","./node_modules/zod/lib/helpers/enumutil.d.ts","./node_modules/zod/lib/helpers/errorutil.d.ts","./node_modules/zod/lib/helpers/partialutil.d.ts","./node_modules/zod/lib/types.d.ts","./node_modules/zod/lib/external.d.ts","./node_modules/zod/lib/index.d.ts","./node_modules/zod/index.d.ts","./node_modules/next/dist/server/app-render/types.d.ts","./node_modules/next/dist/client/components/router-reducer/fetch-server-response.d.ts","./node_modules/next/dist/client/components/router-reducer/router-reducer-types.d.ts","./node_modules/next/dist/shared/lib/app-router-context.d.ts","./node_modules/next/dist/client/components/navigation.d.ts","./node_modules/next/navigation.d.ts","./node_modules/next/navigation-types/compat/navigation.d.ts","./next-env.d.ts","./node_modules/@socket.io/component-emitter/lib/cjs/index.d.ts","./node_modules/engine.io-parser/build/esm/commons.d.ts","./node_modules/engine.io-parser/build/esm/encodepacket.d.ts","./node_modules/engine.io-parser/build/esm/decodepacket.d.ts","./node_modules/engine.io-parser/build/esm/index.d.ts","./node_modules/engine.io-client/build/esm/transport.d.ts","./node_modules/engine.io-client/build/esm/socket.d.ts","./node_modules/engine.io-client/build/esm/transports/polling.d.ts","./node_modules/engine.io-client/build/esm/transports/websocket.d.ts","./node_modules/engine.io-client/build/esm/transports/webtransport.d.ts","./node_modules/engine.io-client/build/esm/transports/index.d.ts","./node_modules/engine.io-client/build/esm/util.d.ts","./node_modules/engine.io-client/build/esm/contrib/parseuri.d.ts","./node_modules/engine.io-client/build/esm/transports/websocket-constructor.d.ts","./node_modules/engine.io-client/build/esm/index.d.ts","./node_modules/socket.io-parser/build/esm/index.d.ts","./node_modules/socket.io-client/build/esm/socket.d.ts","./node_modules/socket.io-client/build/esm/manager.d.ts","./node_modules/socket.io-client/build/esm/index.d.ts","./app/chatclient.tsx","./context/authcontext.tsx","./components/header.tsx","./components/sidebar.tsx","./app/layout.tsx","./app/page.tsx","./app/analytics/page.tsx","./node_modules/react-icons/lib/iconsmanifest.d.ts","./node_modules/react-icons/lib/iconbase.d.ts","./node_modules/react-icons/lib/iconcontext.d.ts","./node_modules/react-icons/lib/index.d.ts","./node_modules/react-icons/md/index.d.ts","./components/messagerenderer.tsx","./app/chat/page.tsx","./app/contacts/page.tsx","./app/settings/waba/page.tsx","./app/setup/layout.tsx","./app/setup/page.tsx","./pages/_document.tsx","./.next/types/app/layout.ts","./.next/types/app/page.ts","./.next/types/app/analytics/page.ts","./.next/types/app/chat/page.ts","./.next/types/app/contacts/page.ts","./.next/types/app/settings/waba/page.ts","../node_modules/@types/bcryptjs/index.d.ts","../node_modules/@types/connect/index.d.ts","../node_modules/@types/body-parser/index.d.ts","../node_modules/@types/cookie/index.d.ts","../node_modules/@types/cors/index.d.ts","../node_modules/@types/send/index.d.ts","../node_modules/@types/qs/index.d.ts","../node_modules/@types/range-parser/index.d.ts","../node_modules/@types/express-serve-static-core/index.d.ts","../node_modules/@types/http-errors/index.d.ts","../node_modules/@types/mime/index.d.ts","../node_modules/@types/serve-static/node_modules/@types/send/index.d.ts","../node_modules/@types/serve-static/index.d.ts","../node_modules/@types/express/index.d.ts","../node_modules/pg-types/index.d.ts","../node_modules/pg-protocol/dist/messages.d.ts","../node_modules/pg-protocol/dist/serializer.d.ts","../node_modules/pg-protocol/dist/parser.d.ts","../node_modules/pg-protocol/dist/index.d.ts","../node_modules/@types/pg/lib/type-overrides.d.ts","../node_modules/@types/pg/index.d.ts","../node_modules/@types/uuid/index.d.ts"],"fileIdsList":[[64,110,263,360],[64,110,263,367],[64,110,263,368],[64,110,263,358],[64,110,263,359],[64,110,263,369],[52,64,110,355],[52,64,110,353,355,365,366],[52,64,110,353],[52,64,110,332,333,355,356,357],[52,64,110,296,355],[52,64,110,332,333,355],[52,64,110],[52,64,110,294,365],[52,64,110,296,332,333],[64,110,309,310,333],[64,110],[64,107,110],[64,109,110],[110],[64,110,115,143],[64,110,111,116,121,129,140,151],[64,110,111,112,121,129],[59,60,61,64,110],[64,110,113,152],[64,110,114,115,122,130],[64,110,115,140,148],[64,110,116,118,121,129],[64,109,110,117],[64,110,118,119],[64,110,120,121],[64,109,110,121],[64,110,121,122,123,140,151],[64,110,121,122,123,136,140,143],[64,110,118,121,124,129,140,151],[64,110,121,122,124,125,129,140,148,151],[64,110,124,126,140,148,151],[62,63,64,65,66,67,68,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157],[64,110,121,127],[64,110,128,151,156],[64,110,118,121,129,140],[64,110,130],[64,110,131],[64,109,110,132],[64,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157],[64,110,134],[64,110,135],[64,110,121,136,137],[64,110,136,138,152,154],[64,110,121,140,141,143],[64,110,142,143],[64,110,140,141],[64,110,143],[64,110,144],[64,107,110,140,145],[64,110,121,146,147],[64,110,146,147],[64,110,115,129,140,148],[64,110,149],[64,110,129,150],[64,110,124,135,151],[64,110,115,152],[64,110,140,153],[64,110,128,154],[64,110,155],[64,105,110],[64,105,110,121,123,132,140,143,151,154,156],[64,110,140,157],[52,64,110,162,163,164],[52,64,110,162,163],[52,56,64,110,161,264,304],[52,56,64,110,160,264,304],[49,50,51,64,110],[64,110,340,341,345,346,347,348],[64,110,335,339,340],[64,110,335,339,341],[64,110,342,343,344],[64,110,340],[64,110,339,340],[64,110,336],[64,110,336,337,338],[57,64,110],[64,110,277],[64,110,279,280,281],[64,110,283],[64,110,167,176,193,264],[64,110,178],[64,110,135,158,159,167,176,180,194,220,221,222,225,264],[64,110,165,192],[64,110,165],[64,110,165,192,193],[64,109,110,158],[64,110,232],[64,110,231,233,235],[64,110,311,312,313,330],[64,110,198],[64,109,110,158,198,231,232,233],[64,110,327,329],[64,110,327,328,330],[64,109,110,158,222,223],[52,64,110,168],[52,64,110,151,158],[52,64,110,192,270],[52,64,110,192],[64,110,268,273],[52,64,110,269,276],[52,64,110,140,158,304],[52,56,64,110,124,158,160,161,264,302,303],[64,110,166],[64,110,257,258,259,260,261,262],[64,110,259],[52,64,110,265,276],[52,64,110,276],[64,110,124,158,177,276],[52,64,110,210,211,212,222,264,326],[64,110,124,158,177,178,198,199,231],[64,110,222,224,228],[64,110,124,158,176,178],[64,110,124,140,158,175,177,178,264],[64,110,124,135,151,158,166,167,168,175,176,177,178,186,189,190,191,192,195,204,205,207,209,210,211,212,213,215,217,222,241,243,264],[64,110,124,140,158],[64,110,165,167,168,169,175,276],[64,110,176],[64,110,135,151,158,167,173,175,176,177,186,189,190,191,202,205,208,211,214,222,241,244,251,253,254],[64,110,176,180,222],[64,110,175,176],[64,110,189,242],[64,110,171,172],[64,110,171,245],[64,110,171],[64,110,177,218,239,240],[64,110,171,172,173,187,188,190],[64,110,171,172,173,187,190,252],[64,110,173,188,189],[64,110,187],[64,110,172,173],[64,110,173,219],[64,110,173,246],[64,110,172],[64,110,176,199,204,219,223,224,226,227,229,230,234,236,237,238],[64,110,172,199],[64,110,124,151,158,168,175,176,217],[64,110,204,217,276],[64,110,223,224],[64,110,180],[64,110,159,210,264,276],[64,110,124,135,151,158,167,173,175,177,180,186,191,194,195,202,204,205,207,208,209,213,214,217,222,244,247,249,250,276],[64,110,124,158,175,176,180,251,255],[52,64,110,124,135,158,166,168,175,178,195,209,210,211,212,264],[64,110,124,135,151,158,170,173,174,177],[64,110,216],[64,110,124,158,195],[64,110,135,158,166,167,175,177,186,189,190],[64,110,124,158,195,206],[64,110,124,158,177,207],[64,110,124,158,176,189],[64,110,124,158],[64,110,124,158,177,198],[64,110,197],[64,110,199],[64,110,305],[64,110,176,196,198,202],[64,110,176,196,198],[64,110,124,158,170,176,199,200,201],[52,64,110,327,328,329],[64,110,274],[52,64,110,159,209,212,264,276],[52,64,110,135,151,158,166,267,269,271,272,276],[64,110,177,186,192],[64,110,135,158],[64,110,185],[52,64,110,124,135,158,166,264,265,266,273,275],[48,52,53,54,55,64,110,160,161,264,304],[64,110,285],[64,110,287],[64,110,289],[64,110,291],[64,110,293],[56,58,64,110,264,278,282,284,286,288,290,292,294,296,297,299,307,308],[64,110,295],[64,110,332,333],[64,110,331],[64,110,269],[64,110,298],[64,109,110,199,200,201,202,300,301,304,306],[64,110,158],[52,56,64,110,124,135,158,160,161,162,164,166,178,256,263,276,304],[64,110,361,362,363],[64,110,364],[64,110,350,351,352],[64,110,335,349,350,351],[64,110,335,350,352],[64,110,335],[64,77,81,110,151],[64,77,110,140,151],[64,72,110],[64,74,77,110,148,151],[64,110,129,148],[64,72,110,158],[64,74,77,110,129,151],[64,69,70,73,76,110,121,140,151],[64,77,84,110],[64,69,75,110],[64,77,98,99,110],[64,73,77,110,143,151,158],[64,98,110,158],[64,71,72,110,158],[64,77,110],[64,71,72,73,74,75,76,77,78,79,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,99,100,101,102,103,104,110],[64,77,92,110],[64,77,84,85,110],[64,75,77,85,86,110],[64,76,110],[64,69,72,77,110],[64,77,81,85,86,110],[64,81,110],[64,75,77,80,110,151],[64,69,74,77,84,110],[64,110,140],[64,72,77,98,110,156,158],[64,110,325],[64,110,316,317],[64,110,314,315,316,318,319,323],[64,110,315,316],[64,110,324],[64,110,316],[64,110,314,315,316,319,320,321,322],[64,110,314,315,325],[64,110,286],[64,110,124,158,380],[64,110,121,124,158,384,385,386],[64,110,381,385,387,391],[64,110,121,140,148,158,393,394,397,398,399],[64,110,399],[64,110,122,140,158],[64,110,124,158,388,390],[64,110,122,140,158,389],[64,110,158,394,395,396],[64,110,140,158,394]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"0990a7576222f248f0a3b888adcb7389f957928ce2afb1cd5128169086ff4d29","impliedFormat":1},{"version":"eb5b19b86227ace1d29ea4cf81387279d04bb34051e944bc53df69f58914b788","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"87d9d29dbc745f182683f63187bf3d53fd8673e5fca38ad5eaab69798ed29fbc","impliedFormat":1},{"version":"035312d4945d13efa134ae482f6dc56a1a9346f7ac3be7ccbad5741058ce87f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc69795d9954ee4ad57545b10c7bf1a7260d990231b1685c147ea71a6faa265c","impliedFormat":1},{"version":"8bc6c94ff4f2af1f4023b7bb2379b08d3d7dd80c698c9f0b07431ea16101f05f","impliedFormat":1},{"version":"1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","impliedFormat":1},{"version":"57194e1f007f3f2cbef26fa299d4c6b21f4623a2eddc63dfeef79e38e187a36e","impliedFormat":1},{"version":"0f6666b58e9276ac3a38fdc80993d19208442d6027ab885580d93aec76b4ef00","impliedFormat":1},{"version":"05fd364b8ef02fb1e174fbac8b825bdb1e5a36a016997c8e421f5fab0a6da0a0","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"ba481bca06f37d3f2c137ce343c7d5937029b2468f8e26111f3c9d9963d6568d","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d9ef24f9a22a88e3e9b3b3d8c40ab1ddb0853f1bfbd5c843c37800138437b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2677634fe27e87348825bb041651e22d50a613e2fdf6a4a3ade971d71bac37e","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"8cd19276b6590b3ebbeeb030ac271871b9ed0afc3074ac88a94ed2449174b776","affectsGlobalScope":true,"impliedFormat":1},{"version":"696eb8d28f5949b87d894b26dc97318ef944c794a9a4e4f62360cd1d1958014b","impliedFormat":1},{"version":"3f8fa3061bd7402970b399300880d55257953ee6d3cd408722cb9ac20126460c","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"68bd56c92c2bd7d2339457eb84d63e7de3bd56a69b25f3576e1568d21a162398","affectsGlobalScope":true,"impliedFormat":1},{"version":"3e93b123f7c2944969d291b35fed2af79a6e9e27fdd5faa99748a51c07c02d28","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"87aad3dd9752067dc875cfaa466fc44246451c0c560b820796bdd528e29bef40","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"8db0ae9cb14d9955b14c214f34dae1b9ef2baee2fe4ce794a4cd3ac2531e3255","affectsGlobalScope":true,"impliedFormat":1},{"version":"15fc6f7512c86810273af28f224251a5a879e4261b4d4c7e532abfbfc3983134","impliedFormat":1},{"version":"58adba1a8ab2d10b54dc1dced4e41f4e7c9772cbbac40939c0dc8ce2cdb1d442","impliedFormat":1},{"version":"641942a78f9063caa5d6b777c99304b7d1dc7328076038c6d94d8a0b81fc95c1","impliedFormat":1},{"version":"2de7636e6fbb9e54a61a38bcb7505b94ec5be61197fe9e840cff629ca920c4bc","impliedFormat":1},{"version":"855cd5f7eb396f5f1ab1bc0f8580339bff77b68a770f84c6b254e319bbfd1ac7","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e20d899c28ca26a2a7afc98beaa69e63ff7fba0a8bc47b4e3bf3ede5e09e424","impliedFormat":1},{"version":"2d2fcaab481b31a5882065c7951255703ddbe1c0e507af56ea42d79ac3911201","impliedFormat":1},{"version":"a192fe8ec33f75edbc8d8f3ed79f768dfae11ff5735e7fe52bfa69956e46d78d","impliedFormat":1},{"version":"ca867399f7db82df981d6915bcbb2d81131d7d1ef683bc782b59f71dda59bc85","affectsGlobalScope":true,"impliedFormat":1},{"version":"372413016d17d804e1d139418aca0c68e47a83fb6669490857f4b318de8cccb3","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"6e70e9570e98aae2b825b533aa6292b6abd542e8d9f6e9475e88e1d7ba17c866","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"085f552d005479e2e6a7311cdbbe5d8c55c497b4d19274285df161ee9684cd9c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"007faacc9268357caa21d24169f3f3f2497af3e9241308df2d89f6e6d9bb3f2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"74cf591a0f63db318651e0e04cb55f8791385f86e987a67fd4d2eaab8191f730","impliedFormat":1},{"version":"5eab9b3dc9b34f185417342436ec3f106898da5f4801992d8ff38ab3aff346b5","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"809821b8a065e3234a55b3a9d7846231ed18d66dd749f2494c66288d890daf7f","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"c3b41e74b9a84b88b1dca61ec39eee25c0dbc8e7d519ba11bb070918cfacf656","affectsGlobalScope":true,"impliedFormat":1},{"version":"4737a9dc24d0e68b734e6cfbcea0c15a2cfafeb493485e27905f7856988c6b29","affectsGlobalScope":true,"impliedFormat":1},{"version":"36d8d3e7506b631c9582c251a2c0b8a28855af3f76719b12b534c6edf952748d","impliedFormat":1},{"version":"1ca69210cc42729e7ca97d3a9ad48f2e9cb0042bada4075b588ae5387debd318","impliedFormat":1},{"version":"f5ebe66baaf7c552cfa59d75f2bfba679f329204847db3cec385acda245e574e","impliedFormat":1},{"version":"ed59add13139f84da271cafd32e2171876b0a0af2f798d0c663e8eeb867732cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7c5e2ea4a9749097c347454805e933844ed207b6eefec6b7cfd418b5f5f7b28","impliedFormat":1},{"version":"b1810689b76fd473bd12cc9ee219f8e62f54a7d08019a235d07424afbf074d25","impliedFormat":1},{"version":"8caa5c86be1b793cd5f599e27ecb34252c41e011980f7d61ae4989a149ff6ccc","impliedFormat":1},{"version":"f9fd93190acb1ffe0bc0fb395df979452f8d625071e9ffc8636e4dfb86ab2508","impliedFormat":1},{"version":"5f41fd8732a89e940c58ce22206e3df85745feb8983e2b4c6257fb8cbb118493","impliedFormat":1},{"version":"17ed71200119e86ccef2d96b73b02ce8854b76ad6bd21b5021d4269bec527b5f","impliedFormat":1},{"version":"1cfa8647d7d71cb03847d616bd79320abfc01ddea082a49569fda71ac5ece66b","impliedFormat":1},{"version":"bb7a61dd55dc4b9422d13da3a6bb9cc5e89be888ef23bbcf6558aa9726b89a1c","impliedFormat":1},{"version":"db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","impliedFormat":1},{"version":"4059592a5c2f2d5f75aac6f555702e3e64be45d1f4e54ba2444b92ce5ac84b1f","impliedFormat":1},{"version":"cbea99888785d49bb630dcbb1613c73727f2b5a2cf02e1abcaab7bcf8d6bf3c5","impliedFormat":1},{"version":"a3f1220f5331589384d77ed650001719baac21fcbed91e36b9abc5485b06335a","impliedFormat":1},{"version":"a86f82d646a739041d6702101afa82dcb935c416dd93cbca7fd754fd0282ce1f","impliedFormat":1},{"version":"6ceac05c32f579adbed2f1a9c98cd297de3c00a3caaffc423385d00e82bce4ce","impliedFormat":1},{"version":"fa5bbc7ab4130dd8cdc55ea294ec39f76f2bc507a0f75f4f873e38631a836ca7","impliedFormat":1},{"version":"f7c024ce0f73f3a0e56f35826bed34dd9743ad7daa19068acca653dd7d45f010","impliedFormat":1},{"version":"d10ed89f8eebbf41788ab0a301fe75e3e4bc81133a8acc8fb9f77a800de85308","impliedFormat":1},{"version":"596d057adf5da16026fde7dc76c88c6690ebf16e46c230492a926ea34a88513e","impliedFormat":1},{"version":"5511a5ce5ca0f35a59ec5bbd7fbb7293966177694051a056de7220d4f28be242","impliedFormat":1},{"version":"098c6d4a39f4b57de9b20e611a1ebdc7d86ceaa5a34203b51320469951cf549e","impliedFormat":1},{"version":"653060b69b4c62825fca79d91259a5f42736f56dba428322b36cfae593ee8359","impliedFormat":1},{"version":"d38c7510cee97b30fe3fee6f4729580d29fca94c7115cac0f1197da6af575bfc","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"a9226d6aaddf108b737bc227ba7a5944f787f2c125eb1183047cbe1a04fc4269","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"8a8bf772f83e9546b61720cf3b9add9aa4c2058479ad0d8db0d7c9fd948c4eaf","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"973b59a17aaa817eb205baf6c132b83475a5c0a44e8294a472af7793b1817e89","impliedFormat":1},{"version":"ada39cbb2748ab2873b7835c90c8d4620723aedf323550e8489f08220e477c7f","impliedFormat":1},{"version":"1364f64d2fb03bbb514edc42224abd576c064f89be6a990136774ecdd881a1da","impliedFormat":1},{"version":"741c438ec079a077b08d37d9c0466924b68e98ed47224e83fcb125c5863eb355","impliedFormat":1},{"version":"e8da637cbd6ed1cf6c36e9424f6bcee4515ca2c677534d4006cbd9a05f930f0c","impliedFormat":1},{"version":"fa34a00e044e9a3a6044abdb52d38bc7877ff1d6348aa79be99774e413c2568a","impliedFormat":1},{"version":"424b42ca9bf3d0aa599795b3b7cdebdd40d27c876e77664ec9526f24304b3947","impliedFormat":1},{"version":"97db28013378bc815528290a76a884276aa7a2470728fd212592d1b257d4e4ec","impliedFormat":1},{"version":"a41278669baac3dc42d95e762b810aa9371a613792d330766a7661f03df6fae0","impliedFormat":1},{"version":"4c91cc1ab59b55d880877ccf1999ded0bb2ebc8e3a597c622962d65bf0e76be8","impliedFormat":1},{"version":"5569bf3e094f521e461c0d58981d1381cdb085de1d91b35dcaefc6ed1248fe45","impliedFormat":1},{"version":"ca1b882a105a1972f82cc58e3be491e7d750a1eb074ffd13b198269f57ed9e1b","impliedFormat":1},{"version":"b714a2744382be1f2c8bf6e5376b0e4cc5546c2a0ed7585c8da82a9a3d9675ee","impliedFormat":1},{"version":"3867ca0e9757cc41e04248574f4f07b8f9e3c0c2a796a5eb091c65bfd2fc8bdb","impliedFormat":1},{"version":"fc7214ff37161bf1e89c52b11fc7dddceccab809e36ea0ee26353c7502b0b27b","impliedFormat":1},{"version":"58902668adae2e5eb67efbccb4048afa02308fa684f1a4e4c7d47668ecf58c1b","impliedFormat":1},{"version":"ef2d1bd01d144d426b72db3744e7a6b6bb518a639d5c9c8d86438fb75a3b1934","impliedFormat":1},{"version":"ca3ae117555ae4ddc5d0b38ace215fe645e12cbf36a473290f4804741cff4cdb","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"a38faf2579a5a094409d00e463aa142e8408e065b692742f4305dcda9affc4ec","impliedFormat":1},{"version":"476c48dfa7aef1b279542a1d90018f67912b3c970e147b77c2d8063c40c06b24","impliedFormat":1},{"version":"17937316a2f7f362dd6375251a9ce9e4960cfdc0aa7ba6cbd00656f7ab92334b","impliedFormat":1},{"version":"be2d91ce0cef98ac6a467d0b48813d78ae0a54d5f1a994afb16018a6b45f711d","impliedFormat":1},{"version":"a7a92f071d6891b2fa6542e343bdebc819492e6e14db37563bb71b8bd7e9b83f","impliedFormat":1},{"version":"99ace27cc2c78ef0fe3f92f11164eca7494b9f98a49ee0a19ede0a4c82a6a800","impliedFormat":1},{"version":"7545c9288b771b046c041357be55281f81e916fd978fba8d1ab80f7a19c9872c","impliedFormat":1},{"version":"fafaad58e8fec794bbc0b8471c83a032a6234231e65111d3a123902d085e0929","impliedFormat":1},{"version":"34f13a87ce0b5d9f3177909ea2fefd5f288df9fd1d3b02211d4623a60a4537ec","impliedFormat":1},{"version":"6ef06a3c167e93229e013b3be0eacb869f338262801ff160e840a64504583239","impliedFormat":1},{"version":"6e5f5cee603d67ee1ba6120815497909b73399842254fc1e77a0d5cdc51d8c9c","impliedFormat":1},{"version":"f6404e7837b96da3ea4d38c4f1a3812c96c9dcdf264e93d5bdb199f983a3ef4b","impliedFormat":1},{"version":"53e8716b56477507dcd80b45a516e87e04fddc2815ad1c4a110c577bd6f2a56d","impliedFormat":1},{"version":"3cd0346fc79e262233785d9fe2cbad08fc3fe6339af3419791687152ddfe5596","impliedFormat":1},{"version":"b1645ede06e14485c0cbcae199c5d9075f116fe34d9df7f55609511798e51878","impliedFormat":1},{"version":"2652448ac55a2010a1f71dd141f828b682298d39728f9871e1cdf8696ef443fd","impliedFormat":1},{"version":"361e2b13c6765d7f85bb7600b48fde782b90c7c41105b7dab1f6e7871071ba20","impliedFormat":1},{"version":"6459054aabb306821a043e02b89d54da508e3a6966601a41e71c166e4ea1474f","impliedFormat":1},{"version":"ba7f9c1882b80478c7fe2268f12e06bb02445212ae104c92b03e4f774e605ae5","impliedFormat":1},{"version":"d23518a5f155f1a3e07214baf0295687507122ae2e6e9bd5e772551ebd4b3157","impliedFormat":1},{"version":"a984957da359a346925863242a2e096ce444d7952a6bb683289e1243628bc89d","impliedFormat":1},{"version":"a966ea6e57d54a96fd90453fb40ef482b61cec8e0797e6b3074925226643c7c6","impliedFormat":1},{"version":"700408b4faf9170f6424678e11255fa908467e223e84ed7c10b128243414264b","impliedFormat":1},{"version":"74424c988b16077ad1b318c303b7c1e65ab991cec09710603d39cdd52354bde0","impliedFormat":1},{"version":"88961917ec908f9fde57b86b8038b8b30766ba14cfdcc214c7c5498d7c9f7924","impliedFormat":1},{"version":"369db4c180c005815c807c5a2952d44c38db8572afa1c52565602f44dbdd77b1","impliedFormat":1},{"version":"120599fd965257b1f4d0ff794bc696162832d9d8467224f4665f713a3119078b","impliedFormat":1},{"version":"056903d58aab97535445ec11984be0533769b4a36a422ac6eba01c2e2571dbd7","impliedFormat":1},{"version":"b47bb50ee9d8ac4f69ff2f616b556905e7cb486c554fcc7e04f31c21dfd5e919","impliedFormat":1},{"version":"48e8af7fdb2677a44522fd185d8c87deff4d36ee701ea003c6c780b1407a1397","impliedFormat":1},{"version":"606e6f841ba9667de5d83ca458449f0ed8c511ba635f753eaa731e532dea98c7","impliedFormat":1},{"version":"3026abd48e5e312f2328629ede6e0f770d21c3cd32cee705c450e589d015ee09","impliedFormat":1},{"version":"4a8bae6576783c910147d19ec6bef24fd2a24e83acbbb2043a60eec7134738e6","impliedFormat":1},{"version":"c325e0ae43fb49d82042ad9d8740fb7ae5aa10900697bcc253286bb3b25b5442","impliedFormat":1},{"version":"ad444a874f011d3a797f1a41579dbfcc6b246623f49c20009f60e211dbd5315e","impliedFormat":1},{"version":"368b2100f2635daf950e800f2731b093c5880e276f3773c9b9157ff0aeac0f6e","impliedFormat":1},{"version":"1d07d33162aa6e67fadac57f94278f1993c2cf812235343f0497a052313eddf4","impliedFormat":1},{"version":"d1a8da005ce5b2974b6b4bca95327d6aa230df23a7446e609c7e25ea84d7cf13","impliedFormat":1},{"version":"e927c2c13c4eaf0a7f17e6022eee8519eb29ef42c4c13a31e81a611ab8c95577","impliedFormat":1},{"version":"1822b69406252b606dc1aec3231a7104ac1d456cfa2c0a9041e61061895ae348","impliedFormat":1},{"version":"f7737bc5cdd9e20e64537ace1c892a4868fed47dc87611b8d43f7bd7d4361ccf","impliedFormat":1},{"version":"c1ac179620434b59c1569f2964a5c7354037ac91a212a1fb281673589965c893","impliedFormat":1},{"version":"9f891dc96f3e9343c4e823ba28195fd77e59c84199696a8bdfe7b67925732409","impliedFormat":1},{"version":"27efe8aa87d6699088ba2bb78a2101d51054f6273e0827f24e9caef82647ca5c","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"aa54626cd7dcd44f2cc9fd62c6e7e09aedfcd1372864526f9dd2d5eca16133f6","impliedFormat":1},{"version":"eb9c80fd1c0ea0eff7b0830d8e5eba8af21bb73578aa6c4cb78f7b6e93bc3e28","impliedFormat":1},{"version":"b21962d604522cdec8b13760091c7c83e691062077a5283c5213212bb7ea2db4","impliedFormat":1},{"version":"2c6f043430f24bde409ed1e70d197b3ef70607cd656817bfd6cf02e630bb7a39","impliedFormat":1},{"version":"495a5da35b04cd142d1301921ce8776c3bd8eab85bbf0ea694e631bc5cd35338","impliedFormat":1},{"version":"46ceb528c649c7c2c6d1c46e774c9f049f3e4f15766c5efaf6b510e0b5fd1434","impliedFormat":1},{"version":"9a99ae1436fe41e98bf61280e29e012c3b070d05fba49db37e49a10dffb29715","impliedFormat":1},{"version":"a2251459e8bdd8e9c9883bd9f1b5f18af247fee2b774e0e90d988749ca702c8b","impliedFormat":1},{"version":"55e528b0903b1572cae79a52445d21a66de54001aa4041663b17dcbca78faaa1","impliedFormat":1},{"version":"a805c88b28da817123a9e4c45ceb642ef0154c8ea41ea3dde0e64a70dde7ac5f","impliedFormat":1},{"version":"3182b3720ea5d895d14ecf8c4243c62f91278ea041df16fee6e1e7c820197548","impliedFormat":1},{"version":"32531dfbb0cdc4525296648f53b2b5c39b64282791e2a8c765712e49e6461046","impliedFormat":1},{"version":"3bfd88431ff03e76f98193aff3baea01493c918670dc42e1cedec9ed67cf0141","impliedFormat":1},{"version":"e489985388e2c71d3542612685b4a7db326922b57ac880f299da7026a4e8a117","impliedFormat":1},{"version":"d7f7b8dbdbe51042f63f0d671fc60c22465cb48e18c5dcb4c36baa83d773f5e8","impliedFormat":1},{"version":"19dcdc086f0c02968d5d774a8199dca62e5817797828e8d228658b75dcc1f616","affectsGlobalScope":true,"impliedFormat":1},{"version":"1efc1478edc8047b1cdb25f5138780b117c6502a62aa8b7ee928f269cd2cb1b3","impliedFormat":1},{"version":"991ce7d6e9a68aea60e1f136e9e18bf626857d0b1ad09f070ef2f0666e4f61e5","impliedFormat":1},{"version":"de9d2df7663e64e3a91bf495f315a7577e23ba088f2949d5ce9ec96f44fba37d","impliedFormat":1},{"version":"c7af78a2ea7cb1cd009cfb5bdb48cd0b03dad3b54f6da7aab615c2e9e9d570c5","impliedFormat":1},{"version":"1dc574e42493e8bf9bb37be44d9e38c5bd7bbc04f884e5e58b4d69636cb192b3","impliedFormat":1},{"version":"6bf9cdef836ed04a0b23414d26a134dbee65d8fa50153bbe5bdadc9bd55dd2df","affectsGlobalScope":true,"impliedFormat":1},{"version":"db01d18853469bcb5601b9fc9826931cc84cc1a1944b33cad76fd6f1e3d8c544","affectsGlobalScope":true,"impliedFormat":1},{"version":"6b8e8c0331a0c2e9fb53b8b0d346e44a8db8c788dae727a2c52f4cf3bd857f0d","impliedFormat":1},{"version":"0aa0f0184c0f9635dd1b95c178223aa262bb01ec8ac7b39c911ef2bd32b8f65b","affectsGlobalScope":true,"impliedFormat":1},{"version":"ec29be0737d39268696edcec4f5e97ce26f449fa9b7afc2f0f99a86def34a418","impliedFormat":1},{"version":"d94111e36b98d3cee902610bfcc7f83a473a5790a6ce32975009c7acc127fc4e","impliedFormat":1},{"version":"7ce21be1af9f34e76481d5030aa8b1fa23ff0f10848222fb488668b10dc33052","impliedFormat":1},{"version":"edaa27d57d30467edc63e9da7e7196acd315b02071f2c7ecd8475085a5cab9a2","impliedFormat":1},{"version":"65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","impliedFormat":1},{"version":"ec9fd890d681789cb0aa9efbc50b1e0afe76fbf3c49c3ac50ff80e90e29c6bcb","impliedFormat":1},{"version":"167e0ad8d357a1c1a7d68be49914c7a446560c9c4a35d65c6970635c604e8602","impliedFormat":1},{"version":"9eac5a6beea91cfb119688bf44a5688b129b804ede186e5e2413572a534c21bb","impliedFormat":1},{"version":"6c292de17d4e8763406421cb91f545d1634c81486d8e14fceae65955c119584e","impliedFormat":1},{"version":"b7fff2d004c5879cae335db8f954eb1d61242d9f2d28515e67902032723caeab","impliedFormat":1},{"version":"8303df69e9d100e3df8f2d67ec77348cb6494dc406356fdd9b56e61aa7c3c758","impliedFormat":1},{"version":"3dd1c86894c90acf4f31a9e61de8e7a67158adb8334524930cec92fea73341c1","impliedFormat":1},{"version":"4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","impliedFormat":1},{"version":"15959543f93f27e8e2b1a012fe28e14b682034757e2d7a6c1f02f87107fc731e","impliedFormat":1},{"version":"a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","impliedFormat":1},{"version":"4e828bf688597c32905215785730cbdb603b54e284d472a23fc0195c6d4aeee8","impliedFormat":1},{"version":"a3f41ed1b4f2fc3049394b945a68ae4fdefd49fa1739c32f149d32c0545d67f5","impliedFormat":1},{"version":"4da80db9ed5a1a20fd5bfce863dd178b8928bcaf4a3d75e8657bcae32e572ede","impliedFormat":1},{"version":"47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","impliedFormat":1},{"version":"abe1cd817246c003c25874b191b592aa202b80b763802f1f3cfe1955dff25714","impliedFormat":1},{"version":"42c686ce08bf5576ed178f4a6a62d1b580d941334fb53bdff7054e0980f2dc75","impliedFormat":1},{"version":"7531bb445f08a05e9a83c0a366c67cb5131c9816eb1f00c6362b31792639fc37","impliedFormat":1},{"version":"cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","impliedFormat":1},{"version":"1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","impliedFormat":1},{"version":"e2b097a887dcd8442eaf3668862b6219f078c9c56f1fd0015d8d009bfea57043","impliedFormat":1},{"version":"5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","impliedFormat":1},{"version":"c0eeaaa67c85c3bb6c52b629ebbfd3b2292dc67e8c0ffda2fc6cd2f78dc471e6","impliedFormat":1},{"version":"4b7f74b772140395e7af67c4841be1ab867c11b3b82a51b1aeb692822b76c872","impliedFormat":1},{"version":"cb048c7e28bdc3fc12766cc0203cc1da6c19ecb6d9614c7fc05d9df0908598db","impliedFormat":99},{"version":"c2008605e78208cfa9cd70bd29856b72dda7ad89df5dc895920f8e10bcb9cd0a","impliedFormat":99},{"version":"ec61ebac4d71c4698318673efbb5c481a6c4d374da8d285f6557541a5bd318d0","impliedFormat":99},{"version":"10ec84e648ffc7654868ca02c21a851bc211c8e4d50fd68131c1afa9afd96a33","impliedFormat":99},{"version":"b5934ca186f498c83e9a663d3df019d82290303fd86b1658cf27cf892b50aaf9","impliedFormat":1},{"version":"16fd66ae997b2f01c972531239da90fbf8ab4022bb145b9587ef746f6cecde5a","affectsGlobalScope":true,"impliedFormat":1},{"version":"0bcce57ab91bed60fc66440a053df9254f526ee98a812a35f91604734e21009c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d7a1155bc29ed4f608bad12f17d1eadccfc4a5ca55f0c483255089ab5c30855","impliedFormat":1},{"version":"79d056984a8964d3917c7587067447d7565d9da696fcf6ecaa5e8437a214f04e","impliedFormat":1},{"version":"2e4f37ffe8862b14d8e24ae8763daaa8340c0df0b859d9a9733def0eee7562d9","impliedFormat":1},{"version":"8d8546e8dac9cf56a7853e46d297b560980455f0c99a35c7ac5ebc89e73f649d","impliedFormat":1},{"version":"cd0c5af42811a4a56a0f77856cfa6c170278e9522888db715b11f176df3ff1f2","impliedFormat":1},{"version":"5487b97cfa28b26b4a9ef0770f872bdbebd4c46124858de00f242c3eed7519f4","impliedFormat":1},{"version":"7a01f546ace66019156e4232a1bee2fabc2f8eabeb052473d926ee1693956265","impliedFormat":1},{"version":"fb53b1c6a6c799b7e3cc2de3fb5c9a1c04a1c60d4380a37792d84c5f8b33933b","impliedFormat":1},{"version":"8485b6da53ec35637d072e516631d25dae53984500de70a6989058f24354666f","impliedFormat":1},{"version":"ebe80346928736532e4a822154eb77f57ef3389dbe2b3ba4e571366a15448ef2","impliedFormat":1},{"version":"c2cb3c8ff388781258ea9ddbcd8a947f751bddd6886e1d3b3ea09ddaa895df80","impliedFormat":1},{"version":"f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c","impliedFormat":1},{"version":"98a9cc18f661d28e6bd31c436e1984f3980f35e0f0aa9cf795c54f8ccb667ffe","impliedFormat":1},{"version":"c76b0c5727302341d0bdfa2cc2cee4b19ff185b554edb6e8543f0661d8487116","impliedFormat":1},{"version":"19903057d0249e45c579bef2b771c37609e4853a8b88adbb0b6b63f9e1d1f372","impliedFormat":1},{"version":"f5ef066942e4f0bd98200aa6a6694b831e73200c9b3ade77ad0aa2409e8fe1b1","impliedFormat":1},{"version":"b9e99cd94f4166a245f5158f7286c05406e2a4c694619bceb7a4f3519d1d768e","impliedFormat":1},{"version":"5568d7c32e5cf5f35e092649f4e5e168c3114c800b1d7545b7ae5e0415704802","impliedFormat":1},{"version":"57365ae017e0c541f600938a4deeb228a0e481ade617894dca41437c95dddaa9","impliedFormat":1},{"version":"094220a45928be7bbb5f749fbc5fc9f8183bbd25d0c529dbd09300179d6a39f6","impliedFormat":1},{"version":"20dc11f7647499cd153504af14fd405becdeab2d40dbb40fda66c0f993e0aed9","impliedFormat":1},{"version":"92d4846268140b00e6b116b003bb53112de7914aab0f30e70582cc2cf18e1cb7","impliedFormat":1},{"version":"c52227ccc6a7c340147c3e3e1478af80bfec3210167fd899d6dd08c8f3f24d58","impliedFormat":1},{"version":"1de80059b8078ea5749941c9f863aa970b4735bdbb003be4925c853a8b6b4450","impliedFormat":1},{"version":"ae75542ca40444773c29335014e2114a131b2ccac7bb96fe94fa0f8236cacd1a","impliedFormat":1},"7a1f284364e4e2053860dd4571a8d871b5b4b4b833f49056c7ce83384b5e732d",{"version":"14ecfc29e0c44ad4c5e50f9b597492cd8f45a2a635db8b5fe911a5da83e26cf8","impliedFormat":1},{"version":"569e762cf47aafdad508360a443c6c757e56c61db3b652b65458a7d168d139c4","impliedFormat":99},{"version":"02ed2766d79a00719ac3cc77851d54bd7197c1b12085ea12126bc2a65068223e","impliedFormat":99},{"version":"4b84373e192b7e0f8569b65eb16857098a6ee279b75d49223db2a751fdd7efde","impliedFormat":99},{"version":"5aeea312cd1d3cc5d72fc8a9c964439d771bdf41d9cce46667471b896b997473","impliedFormat":99},{"version":"7c37569e586a3276ae7cbc405c9f1c51efdf3f603cc8b76dd2196d1b01c2f9d0","impliedFormat":99},{"version":"bef359bd6998f4ce186f7450ec3fbd9cf47ee3097d75c26828b6d985c843a48d","impliedFormat":99},{"version":"696a04758e6c58966e18bb99a64292017fac57f0ba5482e1bc0b617be850b12e","impliedFormat":99},{"version":"46fe6faf3d6907bb675b5c37df15b6021b9ca1e4f91b25ccc422630b4c1568e3","impliedFormat":99},{"version":"c45a995ea8fd0d701c3e013dcf7a106809d9b1517c7115ade3f58d4196bd350c","impliedFormat":99},{"version":"0332891c6714ceea22d919677ba76e7875f4be1104dc1c2a19b9359b7a2e08e4","impliedFormat":99},{"version":"38a217719a1e847d3b56f0e513075f07740ea536a838c332d02b2ce4288f23be","impliedFormat":99},{"version":"d51809d133c78da34a13a1b4267e29afb0d979f50acbeb4321e10d74380beeea","impliedFormat":99},{"version":"68745f37d24b1b5800c45d0c5c00abfcbb031f9be0bcecdafd29405667397abe","impliedFormat":99},{"version":"fccc4725f7937821ed7744c796c090963929da13a497a05a58ba478d1c1442ef","impliedFormat":99},{"version":"ba0badf6398010ef0ba77947d4b52078fc84cb4f209f6b70194b3b2cfb1823d8","impliedFormat":99},{"version":"c3e72657ff6de287781e29531f2cceff9d01403f92fbf350dd3aaf3c8e44eced","impliedFormat":99},{"version":"60fbce4fe62a585d67228f8c1e43e7f1e5493519ac7f3d0fb383d95c1f690a1b","impliedFormat":99},{"version":"944248b9c52a2c6dfe7b9a7b0b0c6e42b0bf3469d8dbb05625fd564ee35cb3b0","impliedFormat":99},"42933f697965034ebfbfc920121ec429970bb4a5d68521108ac00153767e5c4b","00068dbbc088601743ab323162720eb0c135be056da394f4a3bcf82b66c5d593","2229b0ab0fc028633876e84ccfc94486413c371c9bda558f7d976c66c3649f02","7100ece4f7e7702f0f27db0d628b55c743ef6c4fd7051064803d7820109339cb","2de88fa8d0c9780a1b6486c3e86f786ce4838d054d21f95630909fcf7a858164","f7d52e8ad99e21071a55228ba506e0d6d52a348cafac27609bc6f4988219ef0c","7e520c3667d81cba10ed744e4ed92409949eb39c3c010a81bcf70638a152f0ff",{"version":"d04f947114fa00a20ee3c3182bb2863c30869df93293cc673f200defadbd69d9","impliedFormat":1},{"version":"c3f3190aa2cdbb8d997ed914f1e7b42848156ba5b47ae570cf7a8753a1811e12","impliedFormat":1},{"version":"785926dee839d0b3f5e479615d5653d77f6a9ef8aa4eea5bbdce2703c860b254","impliedFormat":1},{"version":"66d5c68894bb2975727cd550b53cd6f9d99f7cb77cb0cbecdd4af1c9332b01dd","impliedFormat":1},{"version":"dcd3f12a4f679467c7625ea8ff91c98368e367e922674be3f4a62fef705fe54f","impliedFormat":1},{"version":"212f5fc4d47c00231d36971460a5912f3c802356ef029ecdb178c427916a9a6b","signature":"241ddcd8b5b8196e7fbc5f7046a5f43a32799fc9167cb1a8d8549314a3bca67a"},{"version":"ceaab64372ca1dfa47f1a4b6b951e624b70080befbb28e3e750171033b372667","signature":"52c85d5fc439c63bca3a080904fe064adff41f29318f2332385589f6cb6c69c7"},"fb16d6161557071ae03e8188a6879adf224293b8b96eb45affc464067ec7b228","aaffdbe9d6e43320baec029bf7a236fc15feca90811f20994fe651046b478c2c","10220d5c81afdde6a33b2dae07075363457d46ad68f4ebdea22c4705209ff6a3","d3c48d0bfe53a3409497e2bca4d8197de35f3e88130aae79556f3f834aa0a9f8","35dc94b4942f94b8b09a1788d67612589b606a24b77950f12ae4e8527781627b","bc15ab59c7c9e580236ea31a5263813e61f92e0a7463e1c26effc11981c8ae2b","373e95e60216b7be0d1ad2cb153e46e3df1c31409952ac5992dff05f7251ad83","9dffd08fe87876a0444d3c969598493d87311259028b452149e40468cacf65a6","593c19a95e81604725a80858b7de42b2d5addf352bbc8913f6a02563fd90c7d9","cb974632c06887a38f6b8cbc14dcb724dff88d03cda3806308cadd2f761e3945","3e63babe1884fd22a33ae3372349dd1a50e9eb818c18d6c79d557db4eaf96aca",{"version":"a3d3f704c5339a36da3ca8c62b29072f87e86c783b8452d235992142ec71aa2d","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"117ffeecf6c55e25b6446f449ad079029b5e7317399b0a693858faaaea5ca73e","impliedFormat":1},{"version":"25be1eb939c9c63242c7a45446edb20c40541da967f43f1aa6a00ed53c0552db","impliedFormat":1},{"version":"d34aa8df2d0b18fb56b1d772ff9b3c7aea7256cf0d692f969be6e1d27b74d660","impliedFormat":1},{"version":"93a3b8e57c68e348fc4054b245bd7cf4893225f56c991028844b693c2fa8c03c","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"90407bbaa24977b8a6a90861148ac98d8652afe69992a90d823f29e9807fe2d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"d3f2d715f57df3f04bf7b16dde01dec10366f64fce44503c92b8f78f614c1769","impliedFormat":1},{"version":"cb90077223cc1365fa21ef0911a1f9b8f2f878943523d97350dc557973ca3823","impliedFormat":1},{"version":"18f1541b81b80d806120a3489af683edfb811deb91aeca19735d9bb2613e6311","impliedFormat":1},{"version":"232f118ae64ab84dcd26ddb60eaed5a6e44302d36249abf05e9e3fc2cbb701a2","impliedFormat":1},{"version":"f60e3e3060207ac982da13363181fd7ee4beecc19a7c569f0d6bb034331066c2","impliedFormat":1},{"version":"17230b34bb564a3a2e36f9d3985372ccab4ad1722df2c43f7c5c2b553f68e5db","impliedFormat":1},{"version":"dcb41cc4b671f5f85d3754e68dfde7824686a8adbb4c690cb259c1501cb868e1","impliedFormat":1},{"version":"21ac4cf3f8d8c6e1201cb31f600be708c9a37867fc5c73b7ccf80560fae591c8","impliedFormat":1},{"version":"0dfe35191a04e8f9dc7caeb9f52f2ee07402736563d12cbccd15fb5f31ac877f","impliedFormat":1},{"version":"798367363a3274220cbed839b883fe2f52ba7197b25e8cb2ac59c1e1fd8af6b7","impliedFormat":1},{"version":"2636a309ed87d6876728d9aca846a76b372cf2a21a4fdf9940a82a2dd86687d0","impliedFormat":1},{"version":"7d2b7fe4adb76d8253f20e4dbdce044f1cdfab4902ec33c3604585f553883f7d","impliedFormat":1}],"root":[334,[354,360],[366,378]],"options":{"allowJs":true,"alwaysStrict":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"jsx":1,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":false,"noUnusedParameters":false,"skipLibCheck":true,"sourceMap":true,"strict":true,"strictBindCallApply":true,"strictFunctionTypes":true,"strictNullChecks":true,"strictPropertyInitialization":true,"target":7},"referencedMap":[[375,1],[376,2],[377,3],[373,4],[374,5],[378,6],[360,7],[367,8],[354,9],[368,7],[358,10],[359,11],[369,12],[370,13],[371,12],[356,13],[366,14],[357,15],[355,13],[334,16],[266,17],[335,17],[107,18],[108,18],[109,19],[64,20],[110,21],[111,22],[112,23],[59,17],[62,24],[60,17],[61,17],[113,25],[114,26],[115,27],[116,28],[117,29],[118,30],[119,30],[120,31],[121,32],[122,33],[123,34],[65,17],[63,17],[124,35],[125,36],[126,37],[158,38],[127,39],[128,40],[129,41],[130,42],[131,43],[132,44],[133,45],[134,46],[135,47],[136,48],[137,48],[138,49],[139,17],[140,50],[142,51],[141,52],[143,53],[144,54],[145,55],[146,56],[147,57],[148,58],[149,59],[150,60],[151,61],[152,62],[153,63],[154,64],[155,65],[66,17],[67,17],[68,17],[106,66],[156,67],[157,68],[51,17],[163,69],[164,70],[162,13],[160,71],[161,72],[49,17],[52,73],[50,17],[347,17],[349,74],[341,75],[340,76],[345,77],[342,75],[348,17],[343,78],[344,79],[346,17],[336,17],[338,80],[337,80],[339,81],[58,82],[278,83],[282,84],[284,85],[192,86],[204,87],[226,88],[193,89],[220,17],[210,90],[194,91],[212,90],[205,90],[169,90],[238,92],[174,17],[235,93],[236,94],[223,17],[331,95],[313,17],[312,96],[234,97],[328,98],[329,99],[224,100],[237,17],[293,101],[295,102],[271,103],[270,104],[269,105],[298,13],[268,106],[197,17],[301,17],[303,17],[305,107],[302,13],[304,108],[165,17],[221,17],[167,109],[257,17],[258,17],[260,17],[263,110],[259,17],[261,111],[262,111],[203,17],[277,106],[285,112],[289,113],[178,114],[327,115],[228,92],[232,116],[229,117],[177,118],[208,119],[244,120],[170,121],[176,122],[166,123],[255,124],[254,125],[209,17],[189,126],[218,17],[243,127],[242,17],[219,128],[245,128],[246,129],[172,130],[241,131],[171,17],[252,132],[253,133],[190,134],[188,135],[187,136],[240,137],[247,138],[173,139],[239,140],[227,141],[159,17],[250,142],[248,17],[222,143],[225,144],[249,145],[211,146],[251,147],[256,148],[179,17],[184,17],[181,17],[182,17],[183,17],[195,121],[213,149],[175,150],[180,17],[217,151],[216,152],[191,153],[207,154],[206,155],[230,17],[196,156],[233,157],[231,158],[198,159],[200,160],[306,161],[199,162],[201,163],[280,17],[281,17],[279,17],[300,17],[202,164],[57,17],[330,165],[272,17],[275,166],[287,13],[291,13],[265,167],[168,17],[267,17],[274,17],[273,168],[215,169],[214,170],[186,171],[185,17],[283,17],[311,13],[276,172],[48,17],[56,173],[53,13],[54,17],[55,17],[286,174],[288,175],[290,176],[292,177],[310,178],[294,178],[309,179],[296,180],[333,181],[332,182],[297,183],[299,184],[307,185],[308,186],[264,187],[362,13],[363,13],[361,17],[364,188],[365,189],[353,190],[352,191],[351,192],[350,193],[46,17],[47,17],[8,17],[9,17],[11,17],[10,17],[2,17],[12,17],[13,17],[14,17],[15,17],[16,17],[17,17],[18,17],[19,17],[3,17],[20,17],[21,17],[4,17],[22,17],[26,17],[23,17],[24,17],[25,17],[27,17],[28,17],[29,17],[5,17],[30,17],[31,17],[32,17],[33,17],[6,17],[37,17],[34,17],[35,17],[36,17],[38,17],[7,17],[39,17],[44,17],[45,17],[40,17],[41,17],[42,17],[43,17],[1,17],[84,194],[94,195],[83,194],[104,196],[75,197],[74,198],[103,186],[97,199],[102,200],[77,201],[91,202],[76,203],[100,204],[72,205],[71,186],[101,206],[73,207],[78,208],[79,17],[82,208],[69,17],[105,209],[95,210],[86,211],[87,212],[89,213],[85,214],[88,215],[98,186],[80,216],[81,217],[90,218],[70,219],[93,210],[92,208],[96,17],[99,220],[326,221],[318,222],[324,223],[320,17],[321,17],[319,224],[322,221],[314,17],[315,17],[325,225],[317,226],[323,227],[316,228],[372,229],[379,17],[381,230],[380,157],[382,17],[383,157],[387,231],[392,232],[388,17],[389,17],[399,233],[398,234],[385,17],[386,17],[384,235],[391,236],[390,237],[400,17],[397,238],[394,186],[396,239],[395,186],[393,17]],"affectedFilesPendingEmit":[[375,51],[376,51],[377,51],[373,51],[374,51],[378,51],[360,51],[367,51],[354,51],[368,51],[358,51],[359,51],[369,51],[370,51],[371,51],[356,51],[366,51],[357,51],[355,51],[372,51]],"version":"5.9.3"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "bizlin-chat",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Open-source WhatsApp Cloud API Team Inbox by Bizlin Technologies",
5
- "main": "backend/index.js",
5
+ "main": "backend/src/index.ts",
6
6
  "bin": {
7
7
  "bizlin-chat": "bin/bizlin-chat.js"
8
8
  },
@@ -11,8 +11,18 @@
11
11
  "frontend"
12
12
  ],
13
13
  "scripts": {
14
- "start": "node backend/index.js",
15
- "start:frontend": "node frontend/index.js",
14
+ "dev:backend": "ts-node --transpile-only backend/src/index.ts",
15
+ "dev:frontend": "cd frontend && next dev",
16
+ "dev": "concurrently \"npm:dev:backend\" \"npm:dev:frontend\"",
17
+ "build:backend": "tsc -p backend/tsconfig.json",
18
+ "build:frontend": "cd frontend && next build",
19
+ "build": "npm run build:backend && npm run build:frontend",
20
+ "start:backend": "node backend/dist/index.js",
21
+ "start:frontend": "cd frontend && next start -p 3000",
22
+ "start": "concurrently \"npm:start:backend\" \"npm:start:frontend\"",
23
+ "deploy": "npm run build && npm run deploy:docker",
24
+ "deploy:docker": "docker build -t bizlin-chat:latest . && docker push bizlin-chat:latest",
25
+ "deploy:npm": "npm run build && npm publish",
16
26
  "test": "echo \"No tests specified\" && exit 0"
17
27
  },
18
28
  "keywords": [
@@ -32,5 +42,41 @@
32
42
  "license": "MIT",
33
43
  "engines": {
34
44
  "node": ">=14"
45
+ },
46
+ "dependencies": {
47
+ "axios": "1.5.0",
48
+ "bcryptjs": "2.4.3",
49
+ "bufferutil": "^4.0.8",
50
+ "cors": "2.8.5",
51
+ "express": "4.18.2",
52
+ "form-data": "^4.0.5",
53
+ "multer": "^2.1.1",
54
+ "next": "13.4.7",
55
+ "pg": "8.11.0",
56
+ "react": "18.2.0",
57
+ "react-dom": "18.2.0",
58
+ "react-icons": "^4.12.0",
59
+ "socket.io": "4.7.2",
60
+ "socket.io-client": "4.7.2",
61
+ "sqlite3": "5.1.6",
62
+ "utf-8-validate": "^6.0.0",
63
+ "uuid": "9.0.0"
64
+ },
65
+ "devDependencies": {
66
+ "@types/bcryptjs": "^2.4.2",
67
+ "@types/express": "^4.17.17",
68
+ "@types/multer": "^2.1.0",
69
+ "@types/node": "^20.3.1",
70
+ "@types/pg": "^8.10.9",
71
+ "@types/react": "^18.2.12",
72
+ "@types/react-dom": "^18.2.5",
73
+ "@types/uuid": "^9.0.2",
74
+ "autoprefixer": "^10.4.0",
75
+ "concurrently": "^8.0.1",
76
+ "nodemon": "^3.0.1",
77
+ "postcss": "^8.4.0",
78
+ "tailwindcss": "^3.4.8",
79
+ "ts-node": "^10.9.1",
80
+ "typescript": "^5.1.3"
35
81
  }
36
82
  }
package/backend/README.md DELETED
@@ -1,54 +0,0 @@
1
- # Backend (Node/Express)
2
-
3
- Run locally:
4
-
5
- ```bash
6
- cd backend
7
- npm install
8
- npm start
9
- ```
10
-
11
- API endpoints:
12
-
13
- - `GET /api/messages` — list messages
14
- - `POST /api/messages` — send message, body `{ text, sender? }`
15
-
16
- Realtime: Socket.IO server on the same port (emits `message` events).
17
-
18
- Example: http://localhost:4000/api/hello
19
-
20
- Database (PostgreSQL)
21
-
22
- The backend supports PostgreSQL. By default it connects to the `DATABASE_URL` env var or `postgresql://postgres:postgres@localhost:5432/bizchat`.
23
-
24
- Quick start with Docker Compose:
25
-
26
- ```bash
27
- docker compose up -d
28
- ```
29
-
30
- This starts a Postgres instance on port 5432. Then run the backend as usual and it will auto-create the `messages` table.
31
-
32
- WhatsApp integration
33
-
34
- Set these environment variables for WhatsApp Cloud API integration:
35
-
36
- - `WHATSAPP_PHONE_NUMBER_ID` — your phone number ID from the Meta App Dashboard
37
- - `WHATSAPP_TOKEN` — system user permanent access token (keep secret)
38
- - `WHATSAPP_VERIFY_TOKEN` — a token you set to verify webhook subscription
39
- - `WHATSAPP_API_VERSION` — optional, defaults to `v15.0`
40
-
41
- Endpoints:
42
-
43
- - `GET /webhook` — verification endpoint used when subscribing to webhooks (uses `WHATSAPP_VERIFY_TOKEN`).
44
- - `POST /webhook` — receives webhook events (incoming messages and statuses).
45
- - `POST /api/send` — send a text message via WhatsApp Cloud API. Body: `{ "to": "<whatsapp_number>", "text": "Hello" }`.
46
- - `POST /api/send` — send a text message via WhatsApp Cloud API. Body: `{ "to": "<whatsapp_number>", "text": "Hello" }`.
47
- - `POST /api/sendMedia` — send media by URL. Body: `{ "to": "<whatsapp_number>", "mediaUrl": "https://...", "mediaType": "image|audio|video|document" }`.
48
- - `POST /api/sendTemplate` — send a template message. Body: `{ "to": "<whatsapp_number>", "templateName": "template_name", "language": "en_US", "components": [...] }`.
49
-
50
- The backend persists incoming messages to the `messages` table and emits realtime `message` events via Socket.IO.
51
-
52
- Security
53
- - Webhook requests are verified using `X-Hub-Signature-256` when `WHATSAPP_APP_SECRET` is set.
54
-
package/backend/src/db.js DELETED
@@ -1,185 +0,0 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
-
4
- const DB_CLIENT = (process.env.DB_CLIENT || '').toLowerCase()
5
-
6
- if (DB_CLIENT === 'postgres' || (process.env.DATABASE_URL || '').startsWith('postgres')) {
7
- const { Pool } = require('pg')
8
- const DATABASE_URL = process.env.DATABASE_URL || 'postgresql://postgres:postgres@localhost:5432/bizchat'
9
- const pool = new Pool({ connectionString: DATABASE_URL })
10
-
11
- async function init() {
12
- const sql = `
13
- CREATE TABLE IF NOT EXISTS messages (
14
- id TEXT PRIMARY KEY,
15
- text TEXT NOT NULL,
16
- sender TEXT,
17
- ts BIGINT NOT NULL,
18
- wa_id TEXT,
19
- direction TEXT,
20
- type TEXT,
21
- media_url TEXT,
22
- status TEXT
23
- );
24
- `
25
- await pool.query(sql)
26
- // accounts table
27
- await pool.query(`
28
- CREATE TABLE IF NOT EXISTS accounts (
29
- id SERIAL PRIMARY KEY,
30
- username TEXT UNIQUE NOT NULL,
31
- password_hash TEXT NOT NULL,
32
- name TEXT,
33
- email TEXT,
34
- role TEXT DEFAULT 'admin'
35
- );
36
- `)
37
- // whatsapp accounts
38
- await pool.query(`
39
- CREATE TABLE IF NOT EXISTS whatsapp_accounts (
40
- id SERIAL PRIMARY KEY,
41
- phone_id TEXT,
42
- token TEXT,
43
- api_version TEXT
44
- );
45
- `)
46
- }
47
-
48
- async function getMessages() {
49
- const res = await pool.query('SELECT id, text, sender, ts, wa_id, direction, type, media_url FROM messages ORDER BY ts ASC')
50
- return res.rows
51
- }
52
-
53
- async function addMessage(message) {
54
- const { id, text, sender, ts, wa_id, direction, type, media_url, status } = message
55
- const sql = 'INSERT INTO messages(id, text, sender, ts, wa_id, direction, type, media_url, status) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9)'
56
- await pool.query(sql, [id, text, sender, ts, wa_id || null, direction || null, type || null, media_url || null, status || null])
57
- return message
58
- }
59
-
60
- async function updateMessageStatus(id, status) {
61
- const sql = 'UPDATE messages SET status = $1 WHERE id = $2'
62
- await pool.query(sql, [status, id])
63
- }
64
-
65
- async function getAdminCount() {
66
- const res = await pool.query('SELECT COUNT(*)::int AS cnt FROM accounts')
67
- return res.rows[0] && res.rows[0].cnt
68
- }
69
-
70
- async function createAdmin({ username, password_hash, name, email }) {
71
- const sql = 'INSERT INTO accounts(username, password_hash, name, email, role) VALUES($1,$2,$3,$4,$5)'
72
- await pool.query(sql, [username, password_hash, name || null, email || null, 'admin'])
73
- }
74
-
75
- async function saveWhatsAppAccount({ phone_id, token, api_version }) {
76
- await pool.query('DELETE FROM whatsapp_accounts')
77
- const sql = 'INSERT INTO whatsapp_accounts(phone_id, token, api_version) VALUES($1,$2,$3)'
78
- await pool.query(sql, [phone_id || null, token || null, api_version || null])
79
- }
80
-
81
- async function getWhatsAppAccount() {
82
- const res = await pool.query('SELECT phone_id, token, api_version FROM whatsapp_accounts LIMIT 1')
83
- return res.rows[0]
84
- }
85
-
86
- module.exports = { init, getMessages, addMessage, updateMessageStatus, getAdminCount, createAdmin, saveWhatsAppAccount, getWhatsAppAccount, pool }
87
-
88
- } else {
89
- // Default to sqlite
90
- const sqlite3 = require('sqlite3')
91
- const dbPath = (process.env.DATABASE_URL && process.env.DATABASE_URL.startsWith('sqlite:'))
92
- ? process.env.DATABASE_URL.replace(/^sqlite:/, '')
93
- : path.join(process.cwd(), 'data', 'bizchat.sqlite')
94
-
95
- const dir = path.dirname(dbPath)
96
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
97
-
98
- const db = new sqlite3.Database(dbPath)
99
-
100
- function run(sql, params=[]) {
101
- return new Promise((resolve, reject) => db.run(sql, params, function(err) {
102
- if (err) reject(err); else resolve(this)
103
- }))
104
- }
105
-
106
- function all(sql, params=[]) {
107
- return new Promise((resolve, reject) => db.all(sql, params, (err, rows) => err ? reject(err) : resolve(rows)))
108
- }
109
-
110
- async function init() {
111
- const sql = `
112
- CREATE TABLE IF NOT EXISTS messages (
113
- id TEXT PRIMARY KEY,
114
- text TEXT NOT NULL,
115
- sender TEXT,
116
- ts BIGINT NOT NULL,
117
- wa_id TEXT,
118
- direction TEXT,
119
- type TEXT,
120
- media_url TEXT,
121
- status TEXT
122
- );
123
- `
124
- await run(sql)
125
- // accounts table
126
- await run(`
127
- CREATE TABLE IF NOT EXISTS accounts (
128
- id INTEGER PRIMARY KEY AUTOINCREMENT,
129
- username TEXT UNIQUE NOT NULL,
130
- password_hash TEXT NOT NULL,
131
- name TEXT,
132
- email TEXT,
133
- role TEXT DEFAULT 'admin'
134
- );
135
- `)
136
- await run(`
137
- CREATE TABLE IF NOT EXISTS whatsapp_accounts (
138
- id INTEGER PRIMARY KEY AUTOINCREMENT,
139
- phone_id TEXT,
140
- token TEXT,
141
- api_version TEXT
142
- );
143
- `)
144
- }
145
-
146
- async function getMessages() {
147
- const rows = await all('SELECT id, text, sender, ts, wa_id, direction, type, media_url FROM messages ORDER BY ts ASC')
148
- return rows
149
- }
150
-
151
- async function addMessage(message) {
152
- const { id, text, sender, ts, wa_id, direction, type, media_url, status } = message
153
- const sql = 'INSERT OR REPLACE INTO messages(id, text, sender, ts, wa_id, direction, type, media_url, status) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)'
154
- await run(sql, [id, text, sender, ts, wa_id || null, direction || null, type || null, media_url || null, status || null])
155
- return message
156
- }
157
-
158
- async function updateMessageStatus(id, status) {
159
- const sql = 'UPDATE messages SET status = ? WHERE id = ?'
160
- await run(sql, [status, id])
161
- }
162
-
163
- async function getAdminCount() {
164
- const rows = await all('SELECT COUNT(*) as cnt FROM accounts')
165
- return rows && rows[0] && rows[0].cnt
166
- }
167
-
168
- async function createAdmin({ username, password_hash, name, email }) {
169
- const sql = 'INSERT INTO accounts(username, password_hash, name, email, role) VALUES(?, ?, ?, ?, ?)'
170
- await run(sql, [username, password_hash, name || null, email || null, 'admin'])
171
- }
172
-
173
- async function saveWhatsAppAccount({ phone_id, token, api_version }) {
174
- await run('DELETE FROM whatsapp_accounts')
175
- const sql = 'INSERT INTO whatsapp_accounts(phone_id, token, api_version) VALUES(?, ?, ?)'
176
- await run(sql, [phone_id || null, token || null, api_version || null])
177
- }
178
-
179
- async function getWhatsAppAccount() {
180
- const rows = await all('SELECT phone_id, token, api_version FROM whatsapp_accounts LIMIT 1')
181
- return rows && rows[0]
182
- }
183
-
184
- module.exports = { init, getMessages, addMessage, updateMessageStatus, getAdminCount, createAdmin, saveWhatsAppAccount, getWhatsAppAccount, db }
185
- }
@@ -1,262 +0,0 @@
1
- const express = require('express')
2
- const cors = require('cors')
3
- const http = require('http')
4
- const { Server } = require('socket.io')
5
- const { v4: uuidv4 } = require('uuid')
6
- const db = require('./db')
7
- const whatsapp = require('./whatsapp')
8
- const crypto = require('crypto')
9
-
10
- const app = express()
11
- app.use(cors())
12
- app.use(express.json())
13
- const bcrypt = require('bcryptjs')
14
-
15
- app.get('/api/hello', (req, res) => {
16
- res.json({ message: 'Hello from backend' })
17
- })
18
-
19
- app.get('/api/messages', async (req, res) => {
20
- try {
21
- const rows = await db.getMessages()
22
- res.json(rows)
23
- } catch (err) {
24
- console.error(err)
25
- res.status(500).json({ error: 'failed to load messages' })
26
- }
27
- })
28
-
29
- // Setup endpoints
30
- app.get('/api/setup/status', async (req, res) => {
31
- try {
32
- const cnt = await db.getAdminCount()
33
- res.json({ setup: !!cnt })
34
- } catch (err) {
35
- console.error('setup status error', err)
36
- res.status(500).json({ error: 'failed to check setup status' })
37
- }
38
- })
39
-
40
- app.post('/api/setup/create-admin', async (req, res) => {
41
- try {
42
- const { username, password, name, email } = req.body
43
- if (!username || !password) return res.status(400).json({ error: 'username and password required' })
44
- const hash = bcrypt.hashSync(password, 10)
45
- await db.createAdmin({ username, password_hash: hash, name, email })
46
- res.status(201).json({ ok: true })
47
- } catch (err) {
48
- console.error('create admin error', err)
49
- res.status(500).json({ error: 'failed to create admin' })
50
- }
51
- })
52
-
53
- app.post('/api/setup/whatsapp', async (req, res) => {
54
- try {
55
- const { phone_id, token, api_version } = req.body
56
- if (!phone_id || !token) return res.status(400).json({ error: 'phone_id and token required' })
57
- await db.saveWhatsAppAccount({ phone_id, token, api_version })
58
- res.status(201).json({ ok: true })
59
- } catch (err) {
60
- console.error('save whatsapp account error', err)
61
- res.status(500).json({ error: 'failed to save whatsapp account' })
62
- }
63
- })
64
-
65
- app.post('/api/setup/test-whatsapp', async (req, res) => {
66
- try {
67
- const { phone_id, token, api_version } = req.body
68
- if (!phone_id || !token) return res.status(400).json({ error: 'phone_id and token required' })
69
- const result = await whatsapp.testAccount({ phone_id, token, api_version })
70
- if (result.ok) return res.json({ ok: true, info: result.body })
71
- return res.status(400).json({ ok: false, error: result.error })
72
- } catch (err) {
73
- console.error('test whatsapp error', err)
74
- res.status(500).json({ error: 'failed to test whatsapp account' })
75
- }
76
- })
77
-
78
- app.post('/api/messages', async (req, res) => {
79
- try {
80
- const { text, sender } = req.body
81
- if (!text) return res.status(400).json({ error: 'text is required' })
82
- const message = { id: uuidv4(), text, sender: sender || 'agent', ts: Date.now() }
83
- await db.addMessage(message)
84
- io.emit('message', message)
85
- res.status(201).json(message)
86
- } catch (err) {
87
- console.error(err)
88
- res.status(500).json({ error: 'failed to save message' })
89
- }
90
- })
91
-
92
- // Send outbound message via WhatsApp Cloud API
93
- app.post('/api/send', async (req, res) => {
94
- const { to, text } = req.body
95
- if (!to || !text) return res.status(400).json({ error: 'to and text are required' })
96
- try {
97
- const account = await db.getWhatsAppAccount()
98
- const resp = await whatsapp.sendText(account, to, text)
99
- const waMessageId = resp && resp.messages && resp.messages[0] && resp.messages[0].id
100
- const message = { id: waMessageId || uuidv4(), text, sender: 'us', ts: Date.now(), wa_id: to, direction: 'outbound', type: 'text' }
101
- await db.addMessage(message)
102
- io.emit('message', message)
103
- res.status(200).json(message)
104
- } catch (err) {
105
- console.error('send failed', err?.response?.data || err.message || err)
106
- res.status(500).json({ error: 'failed to send message' })
107
- }
108
- })
109
-
110
- app.post('/api/sendMedia', async (req, res) => {
111
- const { to, mediaUrl, mediaType } = req.body
112
- if (!to || !mediaUrl) return res.status(400).json({ error: 'to and mediaUrl are required' })
113
- try {
114
- const account = await db.getWhatsAppAccount()
115
- const resp = await whatsapp.sendMedia(account, to, mediaUrl, mediaType || 'image')
116
- const waMessageId = resp && resp.messages && resp.messages[0] && resp.messages[0].id
117
- const message = { id: waMessageId || uuidv4(), text: mediaUrl, sender: 'us', ts: Date.now(), wa_id: to, direction: 'outbound', type: mediaType || 'image', media_url: mediaUrl }
118
- await db.addMessage(message)
119
- io.emit('message', message)
120
- res.status(200).json(message)
121
- } catch (err) {
122
- console.error('sendMedia failed', err?.response?.data || err.message || err)
123
- res.status(500).json({ error: 'failed to send media' })
124
- }
125
- })
126
-
127
- app.post('/api/sendTemplate', async (req, res) => {
128
- const { to, templateName, language, components } = req.body
129
- if (!to || !templateName) return res.status(400).json({ error: 'to and templateName are required' })
130
- try {
131
- const account = await db.getWhatsAppAccount()
132
- const resp = await whatsapp.sendTemplate(account, to, templateName, language || 'en_US', components || [])
133
- const waMessageId = resp && resp.messages && resp.messages[0] && resp.messages[0].id
134
- const message = { id: waMessageId || uuidv4(), text: `[template:${templateName}]`, sender: 'us', ts: Date.now(), wa_id: to, direction: 'outbound', type: 'template' }
135
- await db.addMessage(message)
136
- io.emit('message', message)
137
- res.status(200).json(message)
138
- } catch (err) {
139
- console.error('sendTemplate failed', err?.response?.data || err.message || err)
140
- res.status(500).json({ error: 'failed to send template' })
141
- }
142
- })
143
-
144
- // Webhook verification endpoint (GET)
145
- app.get('/webhook', (req, res) => {
146
- const mode = req.query['hub.mode']
147
- const token = req.query['hub.verify_token']
148
- const challenge = req.query['hub.challenge']
149
- if (mode && token) {
150
- if (mode === 'subscribe' && token === process.env.WHATSAPP_VERIFY_TOKEN) {
151
- console.log('WEBHOOK_VERIFIED')
152
- res.status(200).send(challenge)
153
- } else {
154
- res.sendStatus(403)
155
- }
156
- } else {
157
- res.sendStatus(400)
158
- }
159
- })
160
-
161
- // Webhook receiver (POST)
162
- // Use raw body parsing for webhook to allow signature verification
163
- app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
164
- const raw = req.body
165
- const sig = req.headers['x-hub-signature-256']
166
- const appSecret = process.env.WHATSAPP_APP_SECRET
167
- if (appSecret && sig) {
168
- const hmac = crypto.createHmac('sha256', appSecret).update(raw).digest('hex')
169
- const expected = `sha256=${hmac}`
170
- if (sig !== expected) {
171
- console.warn('Invalid webhook signature')
172
- return res.sendStatus(403)
173
- }
174
- }
175
- let body
176
- try {
177
- body = JSON.parse(raw.toString())
178
- } catch (err) {
179
- console.error('invalid json', err)
180
- return res.sendStatus(400)
181
- }
182
-
183
- if (body.object === 'whatsapp_business_account') {
184
- const account = await db.getWhatsAppAccount()
185
- try {
186
- for (const entry of body.entry || []) {
187
- for (const change of entry.changes || []) {
188
- const value = change.value || {}
189
- // Incoming messages
190
- if (value.messages) {
191
- for (const msg of value.messages) {
192
- const wa_id = msg.from || (value.contacts && value.contacts[0] && value.contacts[0].wa_id)
193
- const senderName = (value.contacts && value.contacts[0] && value.contacts[0].profile && value.contacts[0].profile.name) || wa_id
194
- let text = ''
195
- let media_url = null
196
- if (msg.type === 'text') text = msg.text && msg.text.body
197
- else if (['image', 'audio', 'video', 'document'].includes(msg.type)) {
198
- const media = msg[msg.type]
199
- // media.id is present — get downloadable url
200
- if (media && media.id) {
201
- try {
202
- const url = await whatsapp.getMediaUrl(account, media.id)
203
- media_url = url
204
- } catch (e) {
205
- console.warn('failed to fetch media url', e?.message || e)
206
- }
207
- }
208
- } else if (msg.type === 'interactive') {
209
- // buttons or list replies
210
- if (msg.interactive && msg.interactive.type === 'button_reply') {
211
- text = msg.interactive.button_reply && msg.interactive.button_reply.title
212
- } else if (msg.interactive && msg.interactive.type === 'list_reply') {
213
- text = msg.interactive.list_reply && msg.interactive.list_reply.title
214
- }
215
- } else if (msg.type === 'contacts') {
216
- text = JSON.stringify(msg.contacts)
217
- } else if (msg.type === 'location') {
218
- text = JSON.stringify(msg.location)
219
- }
220
- const message = { id: msg.id || uuidv4(), text, sender: senderName, ts: Date.now(), wa_id, direction: 'inbound', type: msg.type, media_url }
221
- await db.addMessage(message)
222
- io.emit('message', message)
223
- }
224
- }
225
- // Status updates
226
- if (value.statuses) {
227
- for (const st of value.statuses) {
228
- const msgId = st.id
229
- const status = st.status
230
- if (msgId) await db.updateMessageStatus(msgId, status)
231
- }
232
- }
233
- }
234
- }
235
- res.sendStatus(200)
236
- } catch (err) {
237
- console.error('webhook processing error', err)
238
- res.sendStatus(500)
239
- }
240
- } else {
241
- res.sendStatus(404)
242
- }
243
- })
244
-
245
- const port = process.env.PORT || 4000
246
- const server = http.createServer(app)
247
- const io = new Server(server, { cors: { origin: '*' } })
248
-
249
- io.on('connection', (socket) => {
250
- console.log('socket connected', socket.id)
251
- socket.on('disconnect', () => console.log('socket disconnected', socket.id))
252
- })
253
-
254
- ;(async () => {
255
- try {
256
- await db.init()
257
- server.listen(port, () => console.log(`Backend listening on ${port}`))
258
- } catch (err) {
259
- console.error('Failed to initialize database', err)
260
- process.exit(1)
261
- }
262
- })()
@@ -1,65 +0,0 @@
1
- const axios = require('axios')
2
-
3
- const API_DEFAULT = 'v15.0'
4
-
5
- function makeUrl(apiVersion, phoneId) {
6
- return `https://graph.facebook.com/${apiVersion || API_DEFAULT}/${phoneId}/messages`
7
- }
8
-
9
- async function sendText(account, to, text) {
10
- const phoneId = account && account.phone_id
11
- const token = account && account.token
12
- const apiVersion = (account && account.api_version) || API_DEFAULT
13
- if (!phoneId || !token) throw new Error('WhatsApp account not configured')
14
- const url = makeUrl(apiVersion, phoneId)
15
- const body = { messaging_product: 'whatsapp', to, type: 'text', text: { body: text } }
16
- const res = await axios.post(url, body, { headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } })
17
- return res.data
18
- }
19
-
20
- async function sendMedia(account, to, mediaUrl, mediaType = 'image') {
21
- const phoneId = account && account.phone_id
22
- const token = account && account.token
23
- const apiVersion = (account && account.api_version) || API_DEFAULT
24
- if (!phoneId || !token) throw new Error('WhatsApp account not configured')
25
- const url = makeUrl(apiVersion, phoneId)
26
- const body = { messaging_product: 'whatsapp', to, type: mediaType, [mediaType]: { link: mediaUrl } }
27
- const res = await axios.post(url, body, { headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } })
28
- return res.data
29
- }
30
-
31
- async function sendTemplate(account, to, templateName, language = 'en_US', components = []) {
32
- const phoneId = account && account.phone_id
33
- const token = account && account.token
34
- const apiVersion = (account && account.api_version) || API_DEFAULT
35
- if (!phoneId || !token) throw new Error('WhatsApp account not configured')
36
- const url = makeUrl(apiVersion, phoneId)
37
- const body = { messaging_product: 'whatsapp', to, type: 'template', template: { name: templateName, language: { code: language }, components } }
38
- const res = await axios.post(url, body, { headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } })
39
- return res.data
40
- }
41
-
42
- async function getMediaUrl(account, mediaId) {
43
- const token = account && account.token
44
- const apiVersion = (account && account.api_version) || API_DEFAULT
45
- if (!token) throw new Error('WhatsApp token not configured')
46
- const url = `https://graph.facebook.com/${apiVersion}/${mediaId}`
47
- const res = await axios.get(url, { headers: { Authorization: `Bearer ${token}` } })
48
- return res.data && res.data.url
49
- }
50
-
51
- module.exports = { sendText, sendMedia, sendTemplate, getMediaUrl }
52
-
53
- async function testAccount({ phone_id, token, api_version }) {
54
- const apiVersion = api_version || API_DEFAULT
55
- if (!phone_id || !token) throw new Error('phone_id and token required')
56
- const url = `https://graph.facebook.com/${apiVersion}/${phone_id}`
57
- try {
58
- const res = await axios.get(url, { params: { access_token: token } })
59
- return { ok: true, body: res.data }
60
- } catch (err) {
61
- return { ok: false, error: err?.response?.data || err.message }
62
- }
63
- }
64
-
65
- module.exports = { sendText, sendMedia, sendTemplate, getMediaUrl, testAccount }
@@ -1,11 +0,0 @@
1
- # Frontend (Next.js)
2
-
3
- Run locally:
4
-
5
- ```bash
6
- cd frontend
7
- npm install
8
- npm run dev
9
- ```
10
-
11
- Open http://localhost:3000. The frontend connects to the backend at `http://localhost:4000` and listens for realtime `message` events from Socket.IO.
@@ -1,172 +0,0 @@
1
- import { useEffect, useState, useRef } from 'react'
2
- import { io } from 'socket.io-client'
3
-
4
- export default function Home() {
5
- const [messages, setMessages] = useState([])
6
- const [text, setText] = useState('')
7
- const [to, setTo] = useState('')
8
- const [mediaUrl, setMediaUrl] = useState('')
9
- const [templateName, setTemplateName] = useState('')
10
- const [templateLang, setTemplateLang] = useState('en_US')
11
- const socketRef = useRef(null)
12
- const [setupNeeded, setSetupNeeded] = useState(false)
13
- const [adminForm, setAdminForm] = useState({ username: '', password: '', name: '', email: '' })
14
- const [waForm, setWaForm] = useState({ phone_id: '', token: '', api_version: 'v15.0' })
15
- const [setupStep, setSetupStep] = useState(0)
16
-
17
- const BACKEND = (process.env.NEXT_PUBLIC_BACKEND_URL) || 'http://localhost:4000'
18
-
19
- useEffect(() => {
20
- // check setup status first
21
- fetch(BACKEND + '/api/setup/status')
22
- .then((r) => r.json())
23
- .then((d) => {
24
- if (d && d.setup) {
25
- setSetupNeeded(false)
26
- // load messages and connect socket
27
- fetch(BACKEND + '/api/messages')
28
- .then((r) => r.json())
29
- .then((msgs) => setMessages(msgs)).catch(() => setMessages([]))
30
- socketRef.current = io(BACKEND)
31
- socketRef.current.on('message', (msg) => setMessages((m) => [...m, msg]))
32
- } else {
33
- setSetupNeeded(true)
34
- setSetupStep(0)
35
- }
36
- })
37
-
38
- return () => {
39
- if (socketRef.current) socketRef.current.disconnect()
40
- }
41
- }, [])
42
-
43
- const send = async () => {
44
- if (!text) return
45
- // If `to` is provided, send via WhatsApp Cloud API through backend
46
- if (to) {
47
- await fetch('http://localhost:4000/api/send', {
48
- method: 'POST',
49
- headers: { 'Content-Type': 'application/json' },
50
- body: JSON.stringify({ to, text })
51
- })
52
- } else {
53
- await fetch('http://localhost:4000/api/messages', {
54
- method: 'POST',
55
- headers: { 'Content-Type': 'application/json' },
56
- body: JSON.stringify({ text, sender: 'web' })
57
- })
58
- }
59
- setText('')
60
- }
61
-
62
- const createAdmin = async () => {
63
- const resp = await fetch('/api/setup/create-admin', {
64
- method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(adminForm)
65
- })
66
- if (resp.ok) {
67
- setSetupStep(1)
68
- } else {
69
- alert('Failed to create admin')
70
- }
71
- }
72
-
73
- const saveWa = async () => {
74
- const resp = await fetch('/api/setup/whatsapp', {
75
- method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(waForm)
76
- })
77
- if (resp.ok) {
78
- // reload page to initialize socket/messages
79
- window.location.reload()
80
- } else {
81
- alert('Failed to save WhatsApp account')
82
- }
83
- }
84
-
85
- const sendMedia = async () => {
86
- if (!to || !mediaUrl) return
87
- await fetch('http://localhost:4000/api/sendMedia', {
88
- method: 'POST',
89
- headers: { 'Content-Type': 'application/json' },
90
- body: JSON.stringify({ to, mediaUrl, mediaType: 'image' })
91
- })
92
- setMediaUrl('')
93
- }
94
-
95
- const sendTemplate = async () => {
96
- if (!to || !templateName) return
97
- await fetch('http://localhost:4000/api/sendTemplate', {
98
- method: 'POST',
99
- headers: { 'Content-Type': 'application/json' },
100
- body: JSON.stringify({ to, templateName, language: templateLang, components: [] })
101
- })
102
- setTemplateName('')
103
- }
104
-
105
- return (
106
- <main style={{ fontFamily: 'system-ui, sans-serif', padding: 24 }}>
107
- <h1>WhatsApp Team Inbox (Frontend)</h1>
108
- <div style={{ maxWidth: 720 }}>
109
- {setupNeeded ? (
110
- <div>
111
- {setupStep === 0 ? (
112
- <div>
113
- <h2>Initial setup — create admin</h2>
114
- <input placeholder="username" value={adminForm.username} onChange={(e)=>setAdminForm({...adminForm, username: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
115
- <input placeholder="password" type="password" value={adminForm.password} onChange={(e)=>setAdminForm({...adminForm, password: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
116
- <input placeholder="name" value={adminForm.name} onChange={(e)=>setAdminForm({...adminForm, name: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
117
- <input placeholder="email" value={adminForm.email} onChange={(e)=>setAdminForm({...adminForm, email: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
118
- <button onClick={createAdmin} style={{padding:'8px 12px'}}>Create Admin</button>
119
- </div>
120
- ) : (
121
- <div>
122
- <h2>Configure WhatsApp Cloud API</h2>
123
- <input placeholder="phone_id" value={waForm.phone_id} onChange={(e)=>setWaForm({...waForm, phone_id: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
124
- <input placeholder="token" value={waForm.token} onChange={(e)=>setWaForm({...waForm, token: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
125
- <input placeholder="api_version" value={waForm.api_version} onChange={(e)=>setWaForm({...waForm, api_version: e.target.value})} style={{padding:8, display:'block', marginBottom:8}} />
126
- <div style={{display:'flex', gap:8}}>
127
- <button onClick={async()=>{
128
- // test credentials
129
- try {
130
- const r = await fetch(BACKEND + '/api/setup/test-whatsapp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(waForm) })
131
- const j = await r.json()
132
- if (r.ok) alert('Credentials valid')
133
- else alert('Invalid credentials: ' + (j.error?.message || JSON.stringify(j.error)))
134
- } catch (e) { alert('Test failed: '+e.message) }
135
- }} style={{padding:'8px 12px'}}>Test</button>
136
- <button onClick={saveWa} style={{padding:'8px 12px'}}>Save WhatsApp Account</button>
137
- </div>
138
- </div>
139
- )}
140
- </div>
141
- ) : (
142
-
143
- <div>
144
- <div style={{ border: '1px solid #ddd', padding: 12, minHeight: 200 }}>
145
- {messages.map((m) => (
146
- <div key={m.id} style={{ padding: 8, borderBottom: '1px solid #eee' }}>
147
- <div style={{ fontSize: 12, color: '#666' }}>{m.sender} • {new Date(m.ts).toLocaleTimeString()}</div>
148
- <div>{m.text}</div>
149
- </div>
150
- ))}
151
- </div>
152
-
153
- <div style={{ display: 'flex', marginTop: 12, gap: 8 }}>
154
- <input placeholder="To (WhatsApp number, optional)" value={to} onChange={(e) => setTo(e.target.value)} style={{ width: 220, padding: 8 }} />
155
- <input value={text} onChange={(e) => setText(e.target.value)} style={{ flex: 1, padding: 8 }} />
156
- <button onClick={send} style={{ padding: '8px 12px' }}>Send</button>
157
- </div>
158
- <div style={{ display: 'flex', marginTop: 8, gap: 8 }}>
159
- <input placeholder="Media URL (optional)" value={mediaUrl} onChange={(e) => setMediaUrl(e.target.value)} style={{ flex: 1, padding: 8 }} />
160
- <button onClick={sendMedia} style={{ padding: '8px 12px' }}>Send Media</button>
161
- </div>
162
- <div style={{ display: 'flex', marginTop: 8, gap: 8 }}>
163
- <input placeholder="Template name" value={templateName} onChange={(e) => setTemplateName(e.target.value)} style={{ width: 240, padding: 8 }} />
164
- <input placeholder="lang" value={templateLang} onChange={(e) => setTemplateLang(e.target.value)} style={{ width: 100, padding: 8 }} />
165
- <button onClick={sendTemplate} style={{ padding: '8px 12px' }}>Send Template</button>
166
- </div>
167
- </div>
168
- )}
169
- </div>
170
- </main>
171
- )
172
- }