0z2i6v3u5t 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/devcontainer.json +4 -0
- package/.devcontainer/setup.sh +11 -0
- package/.dockerignore +2 -0
- package/.github/CONTRIBUTING.md +52 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +59 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +43 -0
- package/.github/dependabot.yml +17 -0
- package/.github/workflows/codeql.yml +76 -0
- package/.github/workflows/publish_docs.yml +25 -0
- package/.github/workflows/test.yml +78 -0
- package/.nvmrc +1 -0
- package/.prettierignore +1 -0
- package/.prettierrc +1 -0
- package/.vscode/launch.json +42 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/Dockerfile +17 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/SECURITY.md +5 -0
- package/__tests__/actions/cacheTest.ts +58 -0
- package/__tests__/actions/randomNumber.ts +26 -0
- package/__tests__/actions/recursiveAction.ts +16 -0
- package/__tests__/actions/sleepTest.ts +24 -0
- package/__tests__/actions/status.ts +17 -0
- package/__tests__/actions/swagger.ts +76 -0
- package/__tests__/actions/validationTest.ts +63 -0
- package/__tests__/cli/cli.ts +126 -0
- package/__tests__/core/api.ts +632 -0
- package/__tests__/core/cache.ts +400 -0
- package/__tests__/core/chatRoom.ts +589 -0
- package/__tests__/core/cli.ts +349 -0
- package/__tests__/core/cluster.ts +132 -0
- package/__tests__/core/config.ts +78 -0
- package/__tests__/core/errors.ts +112 -0
- package/__tests__/core/log.ts +23 -0
- package/__tests__/core/middleware.ts +427 -0
- package/__tests__/core/plugins/partialPlugin.ts +94 -0
- package/__tests__/core/plugins/withPlugin.ts +88 -0
- package/__tests__/core/plugins/withoutPlugin.ts +81 -0
- package/__tests__/core/process.ts +42 -0
- package/__tests__/core/specHelper.ts +330 -0
- package/__tests__/core/staticFile/compression.ts +99 -0
- package/__tests__/core/staticFile/staticFile.ts +180 -0
- package/__tests__/core/tasks/customQueueFunction.ts +67 -0
- package/__tests__/core/tasks/fullWorkerFlow.ts +199 -0
- package/__tests__/core/tasks/tasks.ts +605 -0
- package/__tests__/integration/browser.ts +133 -0
- package/__tests__/integration/ioredis-mock.ts +194 -0
- package/__tests__/integration/sendBuffer.ts +97 -0
- package/__tests__/integration/sendFile.ts +24 -0
- package/__tests__/integration/sharedFingerprint.ts +82 -0
- package/__tests__/integration/taskFlow.ts +110 -0
- package/__tests__/jest.ts +5 -0
- package/__tests__/modules/action.ts +103 -0
- package/__tests__/modules/config.ts +19 -0
- package/__tests__/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +24 -0
- package/__tests__/servers/web/allowedRequestHosts.ts +88 -0
- package/__tests__/servers/web/enableMultiples.ts +83 -0
- package/__tests__/servers/web/fileUpload.ts +79 -0
- package/__tests__/servers/web/jsonp.ts +57 -0
- package/__tests__/servers/web/nonMultiples.ts +83 -0
- package/__tests__/servers/web/rawBody.ts +208 -0
- package/__tests__/servers/web/returnErrorCodes.ts +55 -0
- package/__tests__/servers/web/routes/deepRoutes.ts +96 -0
- package/__tests__/servers/web/routes/routes.ts +579 -0
- package/__tests__/servers/web/routes/veryDeepRoutes.ts +92 -0
- package/__tests__/servers/web/web.ts +1031 -0
- package/__tests__/servers/websocket.ts +795 -0
- package/__tests__/tasks/runAction.ts +37 -0
- package/__tests__/template.ts.example +20 -0
- package/__tests__/testCliCommands/hello.ts +44 -0
- package/__tests__/testPlugin/public/plugin.html +1 -0
- package/__tests__/testPlugin/src/actions/pluginAction.ts +14 -0
- package/__tests__/testPlugin/src/bin/hello.ts +22 -0
- package/__tests__/testPlugin/src/initializers/pluginInitializer.ts +17 -0
- package/__tests__/testPlugin/src/tasks/pluginTask.ts +15 -0
- package/__tests__/testPlugin/tsconfig.json +10 -0
- package/__tests__/utils/utils.ts +492 -0
- package/app.json +23 -0
- package/bin/deploy-docs +39 -0
- package/client/ActionheroWebsocketClient.js +277 -0
- package/docker-compose.yml +73 -0
- package/package.json +24 -0
- package/public/chat.html +194 -0
- package/public/css/cosmo.css +12 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +115 -0
- package/public/javascript/.gitkeep +0 -0
- package/public/linkedSession.html +80 -0
- package/public/logo/actionhero-small.png +0 -0
- package/public/logo/actionhero.png +0 -0
- package/public/pixel.gif +0 -0
- package/public/simple.html +2 -0
- package/public/swagger.html +32 -0
- package/public/websocketLoadTest.html +322 -0
- package/src/actions/cacheTest.ts +58 -0
- package/src/actions/createChatRoom.ts +20 -0
- package/src/actions/randomNumber.ts +17 -0
- package/src/actions/recursiveAction.ts +13 -0
- package/src/actions/sendFile.ts +12 -0
- package/src/actions/sleepTest.ts +40 -0
- package/src/actions/status.ts +73 -0
- package/src/actions/swagger.ts +155 -0
- package/src/actions/validationTest.ts +36 -0
- package/src/bin/actionhero.ts +225 -0
- package/src/bin/methods/actions/list.ts +30 -0
- package/src/bin/methods/console.ts +26 -0
- package/src/bin/methods/generate/action.ts +58 -0
- package/src/bin/methods/generate/cli.ts +51 -0
- package/src/bin/methods/generate/initializer.ts +54 -0
- package/src/bin/methods/generate/plugin.ts +57 -0
- package/src/bin/methods/generate/server.ts +38 -0
- package/src/bin/methods/generate/task.ts +68 -0
- package/src/bin/methods/generate.ts +176 -0
- package/src/bin/methods/task/enqueue.ts +35 -0
- package/src/classes/action.ts +98 -0
- package/src/classes/actionProcessor.ts +463 -0
- package/src/classes/api.ts +51 -0
- package/src/classes/cli.ts +67 -0
- package/src/classes/config.ts +15 -0
- package/src/classes/connection.ts +321 -0
- package/src/classes/exceptionReporter.ts +9 -0
- package/src/classes/initializer.ts +59 -0
- package/src/classes/initializers.ts +5 -0
- package/src/classes/input.ts +9 -0
- package/src/classes/inputs.ts +34 -0
- package/src/classes/process/actionheroVersion.ts +15 -0
- package/src/classes/process/env.ts +16 -0
- package/src/classes/process/id.ts +34 -0
- package/src/classes/process/pid.ts +32 -0
- package/src/classes/process/projectRoot.ts +16 -0
- package/src/classes/process/typescript.ts +47 -0
- package/src/classes/process.ts +479 -0
- package/src/classes/server.ts +251 -0
- package/src/classes/task.ts +87 -0
- package/src/config/api.ts +107 -0
- package/src/config/errors.ts +162 -0
- package/src/config/logger.ts +113 -0
- package/src/config/plugins.ts +37 -0
- package/src/config/redis.ts +78 -0
- package/src/config/routes.ts +44 -0
- package/src/config/tasks.ts +84 -0
- package/src/config/web.ts +136 -0
- package/src/config/websocket.ts +62 -0
- package/src/index.ts +46 -0
- package/src/initializers/actions.ts +125 -0
- package/src/initializers/chatRoom.ts +214 -0
- package/src/initializers/connections.ts +124 -0
- package/src/initializers/exceptions.ts +155 -0
- package/src/initializers/params.ts +52 -0
- package/src/initializers/redis.ts +191 -0
- package/src/initializers/resque.ts +248 -0
- package/src/initializers/routes.ts +229 -0
- package/src/initializers/servers.ts +134 -0
- package/src/initializers/specHelper.ts +195 -0
- package/src/initializers/staticFile.ts +253 -0
- package/src/initializers/tasks.ts +188 -0
- package/src/modules/action.ts +89 -0
- package/src/modules/cache.ts +326 -0
- package/src/modules/chatRoom.ts +321 -0
- package/src/modules/config.ts +246 -0
- package/src/modules/log.ts +62 -0
- package/src/modules/redis.ts +93 -0
- package/src/modules/route.ts +59 -0
- package/src/modules/specHelper.ts +182 -0
- package/src/modules/task.ts +527 -0
- package/src/modules/utils/argv.ts +3 -0
- package/src/modules/utils/arrayStartingMatch.ts +21 -0
- package/src/modules/utils/arrayUnique.ts +15 -0
- package/src/modules/utils/collapseObjectToArray.ts +33 -0
- package/src/modules/utils/deepCopy.ts +3 -0
- package/src/modules/utils/ensureNoTsHeaderOrSpecFiles.ts +19 -0
- package/src/modules/utils/eventLoopDelay.ts +34 -0
- package/src/modules/utils/fileUtils.ts +119 -0
- package/src/modules/utils/filterObjectForLogging.ts +51 -0
- package/src/modules/utils/filterResponseForLogging.ts +53 -0
- package/src/modules/utils/getExternalIPAddress.ts +17 -0
- package/src/modules/utils/hashMerge.ts +63 -0
- package/src/modules/utils/isPlainObject.ts +45 -0
- package/src/modules/utils/isRunning.ts +7 -0
- package/src/modules/utils/parseCookies.ts +20 -0
- package/src/modules/utils/parseHeadersForClientAddress.ts +53 -0
- package/src/modules/utils/parseIPv6URI.ts +24 -0
- package/src/modules/utils/replaceDistWithSrc.ts +9 -0
- package/src/modules/utils/safeGlob.ts +6 -0
- package/src/modules/utils/sleep.ts +8 -0
- package/src/modules/utils/sortGlobalMiddleware.ts +17 -0
- package/src/modules/utils/sourceRelativeLinkPath.ts +29 -0
- package/src/modules/utils.ts +66 -0
- package/src/server.ts +20 -0
- package/src/servers/web.ts +894 -0
- package/src/servers/websocket.ts +304 -0
- package/src/tasks/runAction.ts +29 -0
- package/tea.yaml +9 -0
- package/templates/README.md.template +17 -0
- package/templates/action.ts.template +15 -0
- package/templates/boot.js.template +9 -0
- package/templates/cli.ts.template +15 -0
- package/templates/gitignore.template +23 -0
- package/templates/initializer.ts.template +17 -0
- package/templates/package-plugin.json.template +12 -0
- package/templates/package.json.template +45 -0
- package/templates/projectMap.txt +39 -0
- package/templates/projectServer.ts.template +20 -0
- package/templates/server.ts.template +37 -0
- package/templates/task.ts.template +16 -0
- package/templates/test/action.ts.template +13 -0
- package/templates/test/task.ts.template +20 -0
- package/tsconfig.json +11 -0
package/app.json
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"name": "actionhero.js",
|
3
|
+
"description": "The reusable, scalable, and quick node.js API server for stateless and stateful applications",
|
4
|
+
"repository": "https://github.com/actionhero/actionhero",
|
5
|
+
"logo": "https://raw.githubusercontent.com/actionhero/actionhero/master/public/logo/actionhero.png",
|
6
|
+
"keywords": [
|
7
|
+
"api",
|
8
|
+
"realtime",
|
9
|
+
"socket",
|
10
|
+
"http",
|
11
|
+
"https",
|
12
|
+
"web",
|
13
|
+
"game",
|
14
|
+
"cluster",
|
15
|
+
"soa",
|
16
|
+
"action",
|
17
|
+
"task",
|
18
|
+
"delay",
|
19
|
+
"service",
|
20
|
+
"tcp"
|
21
|
+
],
|
22
|
+
"addons": [{ "plan": "heroku-redis" }]
|
23
|
+
}
|
package/bin/deploy-docs
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -ex
|
4
|
+
|
5
|
+
cd "$(dirname "$0")"
|
6
|
+
cd ..
|
7
|
+
|
8
|
+
## git config
|
9
|
+
GIT_USER_NAME='Github Actions for Actionhero'
|
10
|
+
GIT_USER_EMAIL='admin@actionherojs.com'
|
11
|
+
|
12
|
+
## Configure a new direcotry to hold the site
|
13
|
+
rm -rf gh-pages
|
14
|
+
mkdir gh-pages
|
15
|
+
cd gh-pages
|
16
|
+
git init
|
17
|
+
if git rev-parse --verify origin/gh-pages > /dev/null 2>&1
|
18
|
+
then
|
19
|
+
git checkout gh-pages
|
20
|
+
git rm -rf .
|
21
|
+
else
|
22
|
+
git checkout --orphan gh-pages
|
23
|
+
fi
|
24
|
+
cd ..
|
25
|
+
|
26
|
+
## build master's docs
|
27
|
+
rm -rf docs
|
28
|
+
mkdir docs
|
29
|
+
npm run docs
|
30
|
+
cp -a docs/. gh-pages/
|
31
|
+
touch gh-pages/.nojekyll
|
32
|
+
cp public/favicon.ico gh-pages/favicon.ico
|
33
|
+
echo 'docs.actionherojs.com' >> gh-pages/CNAME
|
34
|
+
|
35
|
+
## make the commmit
|
36
|
+
cd gh-pages
|
37
|
+
git add -A
|
38
|
+
git -c user.name="$GIT_USER_NAME" -c user.email="$GIT_USER_EMAIL" commit --allow-empty -m "deploy static site @ $(date)"
|
39
|
+
|
@@ -0,0 +1,277 @@
|
|
1
|
+
var ActionheroWebsocketClient = function (options, client) {
|
2
|
+
var self = this
|
3
|
+
|
4
|
+
self.callbacks = {}
|
5
|
+
self.id = null
|
6
|
+
self.events = {}
|
7
|
+
self.rooms = []
|
8
|
+
self.state = 'disconnected'
|
9
|
+
|
10
|
+
self.options = self.defaults()
|
11
|
+
for (var i in options) {
|
12
|
+
self.options[i] = options[i]
|
13
|
+
}
|
14
|
+
|
15
|
+
if (client) {
|
16
|
+
self.externalClient = true
|
17
|
+
self.client = client
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
if (typeof Primus === 'undefined') {
|
22
|
+
var util = require('util')
|
23
|
+
var EventEmitter = require('events').EventEmitter
|
24
|
+
util.inherits(ActionheroWebsocketClient, EventEmitter)
|
25
|
+
} else {
|
26
|
+
ActionheroWebsocketClient.prototype = new Primus.EventEmitter()
|
27
|
+
}
|
28
|
+
|
29
|
+
ActionheroWebsocketClient.prototype.defaults = function () {
|
30
|
+
%%DEFAULTS%%
|
31
|
+
}
|
32
|
+
|
33
|
+
// //////////////
|
34
|
+
// CONNECTION //
|
35
|
+
// //////////////
|
36
|
+
|
37
|
+
ActionheroWebsocketClient.prototype.connect = function (callback) {
|
38
|
+
var self = this
|
39
|
+
self.messageId = self.messageId || 0
|
40
|
+
|
41
|
+
if (self.client && self.externalClient !== true) {
|
42
|
+
self.client.end()
|
43
|
+
self.client.removeAllListeners()
|
44
|
+
delete self.client
|
45
|
+
self.client = Primus.connect(self.urlWithSession(), self.options)
|
46
|
+
} else if (self.client && self.externalClient === true) {
|
47
|
+
self.client.end()
|
48
|
+
self.client.open()
|
49
|
+
} else {
|
50
|
+
self.client = Primus.connect(self.urlWithSession(), self.options)
|
51
|
+
}
|
52
|
+
|
53
|
+
self.client.once('open', function () {
|
54
|
+
self.configure(function (details) {
|
55
|
+
self.state = 'connected'
|
56
|
+
self.emit('connected')
|
57
|
+
if (typeof callback === 'function') { callback(null, details) }
|
58
|
+
})
|
59
|
+
})
|
60
|
+
|
61
|
+
self.client.on('error', function (error) {
|
62
|
+
self.emit('error', error)
|
63
|
+
})
|
64
|
+
|
65
|
+
self.client.on('reconnect', function () {
|
66
|
+
self.state = 'connected'
|
67
|
+
self.emit('reconnect')
|
68
|
+
})
|
69
|
+
|
70
|
+
self.client.on('reconnecting', function () {
|
71
|
+
self.emit('reconnecting')
|
72
|
+
self.state = 'reconnecting'
|
73
|
+
self.emit('disconnected')
|
74
|
+
})
|
75
|
+
|
76
|
+
self.client.on('timeout', function () {
|
77
|
+
self.state = 'timeout'
|
78
|
+
self.emit('timeout')
|
79
|
+
})
|
80
|
+
|
81
|
+
self.client.on('close', function () {
|
82
|
+
if (self.state !== 'disconnected') {
|
83
|
+
self.state = 'disconnected'
|
84
|
+
self.emit('disconnected')
|
85
|
+
}
|
86
|
+
})
|
87
|
+
|
88
|
+
self.client.on('end', function () {
|
89
|
+
if (self.state !== 'disconnected') {
|
90
|
+
self.state = 'disconnected'
|
91
|
+
self.emit('disconnected')
|
92
|
+
}
|
93
|
+
})
|
94
|
+
|
95
|
+
self.client.on('data', function (data) {
|
96
|
+
self.handleMessage(data)
|
97
|
+
})
|
98
|
+
}
|
99
|
+
|
100
|
+
ActionheroWebsocketClient.prototype.urlWithSession = function () {
|
101
|
+
var self = this
|
102
|
+
var url = self.options.url
|
103
|
+
if (self.options.cookieKey && self.options.cookieKey.length > 0) {
|
104
|
+
var cookieValue = self.getCookie(self.options.cookieKey)
|
105
|
+
if (cookieValue && cookieValue.length > 0 ) { url += '?' + self.options.cookieKey + '=' + cookieValue }
|
106
|
+
}
|
107
|
+
|
108
|
+
return url
|
109
|
+
}
|
110
|
+
|
111
|
+
ActionheroWebsocketClient.prototype.getCookie = function (name) {
|
112
|
+
if (typeof document === 'undefined' || !document.cookie) { return }
|
113
|
+
var match = document.cookie.match(new RegExp(name + '=([^;]+)'))
|
114
|
+
if (match) return match[1]
|
115
|
+
}
|
116
|
+
|
117
|
+
ActionheroWebsocketClient.prototype.configure = function (callback) {
|
118
|
+
var self = this
|
119
|
+
|
120
|
+
self.rooms.forEach(function (room) {
|
121
|
+
self.send({event: 'roomAdd', room: room})
|
122
|
+
})
|
123
|
+
|
124
|
+
self.detailsView(function (details) {
|
125
|
+
self.id = details.data.id
|
126
|
+
self.fingerprint = details.data.fingerprint
|
127
|
+
self.rooms = details.data.rooms
|
128
|
+
return callback(details)
|
129
|
+
})
|
130
|
+
}
|
131
|
+
|
132
|
+
// /////////////
|
133
|
+
// MESSAGING //
|
134
|
+
// /////////////
|
135
|
+
|
136
|
+
ActionheroWebsocketClient.prototype.send = function (args, callback) {
|
137
|
+
// primus will buffer messages when not connected
|
138
|
+
var self = this
|
139
|
+
self.messageId++
|
140
|
+
args.messageId = args.params
|
141
|
+
? (args.params.messageId || args.messageId || self.messageId )
|
142
|
+
: ( args.messageId || self.messageId )
|
143
|
+
if (typeof callback === 'function') { self.callbacks[args.messageId] = callback }
|
144
|
+
self.client.write(args)
|
145
|
+
}
|
146
|
+
|
147
|
+
ActionheroWebsocketClient.prototype.handleMessage = function (message) {
|
148
|
+
var self = this
|
149
|
+
self.emit('message', message)
|
150
|
+
var messageId = message.messageId
|
151
|
+
|
152
|
+
if (message.context === 'response') {
|
153
|
+
if (typeof self.callbacks[messageId] === 'function') {
|
154
|
+
self.callbacks[messageId](message)
|
155
|
+
}
|
156
|
+
delete self.callbacks[messageId]
|
157
|
+
} else if (message.context === 'user') {
|
158
|
+
self.emit('say', message)
|
159
|
+
} else if (message.context === 'alert') {
|
160
|
+
self.emit('alert', message)
|
161
|
+
} else if (message.welcome && message.context === 'api') {
|
162
|
+
self.welcomeMessage = message.welcome
|
163
|
+
self.emit('welcome', message)
|
164
|
+
} else if (message.context === 'api') {
|
165
|
+
self.emit('api', message)
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
// ///////////
|
170
|
+
// ACTIONS //
|
171
|
+
// ///////////
|
172
|
+
|
173
|
+
ActionheroWebsocketClient.prototype.action = function (action, params, callback) {
|
174
|
+
if (!callback && typeof params === 'function') {
|
175
|
+
callback = params
|
176
|
+
params = null
|
177
|
+
}
|
178
|
+
if (!params) { params = {} }
|
179
|
+
params.action = action
|
180
|
+
|
181
|
+
if (this.state !== 'connected') {
|
182
|
+
this.actionWeb(params, callback)
|
183
|
+
} else {
|
184
|
+
this.actionWebSocket(params, callback)
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
ActionheroWebsocketClient.prototype.actionWeb = function (params, callback) {
|
189
|
+
var xmlhttp = new XMLHttpRequest()
|
190
|
+
xmlhttp.onreadystatechange = function () {
|
191
|
+
var response
|
192
|
+
if (xmlhttp.readyState === 4) {
|
193
|
+
if (xmlhttp.status === 200) {
|
194
|
+
response = JSON.parse(xmlhttp.responseText)
|
195
|
+
} else {
|
196
|
+
try {
|
197
|
+
response = JSON.parse(xmlhttp.responseText)
|
198
|
+
} catch (e) {
|
199
|
+
response = { error: {statusText: xmlhttp.statusText, responseText: xmlhttp.responseText} }
|
200
|
+
}
|
201
|
+
}
|
202
|
+
callback(response)
|
203
|
+
}
|
204
|
+
}
|
205
|
+
|
206
|
+
var method = (params.httpMethod || 'POST').toUpperCase()
|
207
|
+
var url = this.options.url + this.options.apiPath + '?action=' + params.action
|
208
|
+
|
209
|
+
if (method === 'GET') {
|
210
|
+
for (var param in params) {
|
211
|
+
if (~['action', 'httpMethod'].indexOf(param)) continue
|
212
|
+
url += '&' + param + '=' + params[param]
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
xmlhttp.open(method, url, true)
|
217
|
+
xmlhttp.setRequestHeader('Content-Type', 'application/json')
|
218
|
+
xmlhttp.send(JSON.stringify(params))
|
219
|
+
}
|
220
|
+
|
221
|
+
ActionheroWebsocketClient.prototype.actionWebSocket = function (params, callback) {
|
222
|
+
this.send({event: 'action', params: params}, callback)
|
223
|
+
}
|
224
|
+
|
225
|
+
// ////////////
|
226
|
+
// COMMANDS //
|
227
|
+
// ////////////
|
228
|
+
|
229
|
+
ActionheroWebsocketClient.prototype.say = function (room, message, callback) {
|
230
|
+
this.send({event: 'say', room: room, message: message}, callback)
|
231
|
+
}
|
232
|
+
|
233
|
+
ActionheroWebsocketClient.prototype.file = function (file, callback) {
|
234
|
+
this.send({event: 'file', file: file}, callback)
|
235
|
+
}
|
236
|
+
|
237
|
+
ActionheroWebsocketClient.prototype.detailsView = function (callback) {
|
238
|
+
this.send({event: 'detailsView'}, callback)
|
239
|
+
}
|
240
|
+
|
241
|
+
ActionheroWebsocketClient.prototype.roomView = function (room, callback) {
|
242
|
+
this.send({event: 'roomView', room: room}, callback)
|
243
|
+
}
|
244
|
+
|
245
|
+
ActionheroWebsocketClient.prototype.roomAdd = function (room, callback) {
|
246
|
+
var self = this
|
247
|
+
self.send({event: 'roomAdd', room: room}, function (data) {
|
248
|
+
self.configure(function () {
|
249
|
+
if (typeof callback === 'function') { callback(data) }
|
250
|
+
})
|
251
|
+
})
|
252
|
+
}
|
253
|
+
|
254
|
+
ActionheroWebsocketClient.prototype.roomLeave = function (room, callback) {
|
255
|
+
var self = this
|
256
|
+
var index = self.rooms.indexOf(room)
|
257
|
+
if (index > -1) { self.rooms.splice(index, 1) }
|
258
|
+
this.send({event: 'roomLeave', room: room}, function (data) {
|
259
|
+
self.configure(function () {
|
260
|
+
if (typeof callback === 'function') { callback(data) }
|
261
|
+
})
|
262
|
+
})
|
263
|
+
}
|
264
|
+
|
265
|
+
ActionheroWebsocketClient.prototype.documentation = function (callback) {
|
266
|
+
this.send({event: 'documentation'}, callback)
|
267
|
+
}
|
268
|
+
|
269
|
+
ActionheroWebsocketClient.prototype.disconnect = function () {
|
270
|
+
this.state = 'disconnected'
|
271
|
+
this.client.end()
|
272
|
+
this.emit('disconnected')
|
273
|
+
}
|
274
|
+
|
275
|
+
// depreciated lowercase name
|
276
|
+
var ActionheroWebsocketClient = ActionheroWebsocketClient;
|
277
|
+
ActionheroWebsocketClient;
|
@@ -0,0 +1,73 @@
|
|
1
|
+
version: "3.1"
|
2
|
+
services:
|
3
|
+
redis:
|
4
|
+
image: redis
|
5
|
+
networks:
|
6
|
+
- actionhero_backend
|
7
|
+
|
8
|
+
actionhero:
|
9
|
+
image: actionhero/actionhero
|
10
|
+
environment:
|
11
|
+
REDIS_HOST: redis
|
12
|
+
ports:
|
13
|
+
- 8080
|
14
|
+
environment:
|
15
|
+
SERVICE_PORTS: 8080
|
16
|
+
REDIS_HOST: redis
|
17
|
+
depends_on:
|
18
|
+
- redis
|
19
|
+
deploy:
|
20
|
+
mode: replicated
|
21
|
+
replicas: 3
|
22
|
+
networks:
|
23
|
+
- actionhero_frontend
|
24
|
+
- actionhero_backend
|
25
|
+
|
26
|
+
# OR, Build it locally:
|
27
|
+
#
|
28
|
+
# actionhero:
|
29
|
+
# build: ./
|
30
|
+
# image: actionhero
|
31
|
+
# ports:
|
32
|
+
# - 8080
|
33
|
+
# environment:
|
34
|
+
# SERVICE_PORTS: 8080
|
35
|
+
# REDIS_HOST: redis
|
36
|
+
# REDIS_PORT: 6379
|
37
|
+
# REDIS_DB: 0
|
38
|
+
# depends_on:
|
39
|
+
# - redis
|
40
|
+
# deploy:
|
41
|
+
# mode: replicated
|
42
|
+
# replicas: 3
|
43
|
+
# networks:
|
44
|
+
# - actionhero_frontend
|
45
|
+
# - actionhero_backend
|
46
|
+
|
47
|
+
proxy:
|
48
|
+
image: dockercloud/haproxy
|
49
|
+
depends_on:
|
50
|
+
- actionhero
|
51
|
+
environment:
|
52
|
+
- BALANCE=leastconn
|
53
|
+
volumes:
|
54
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
55
|
+
ports:
|
56
|
+
- 80:80
|
57
|
+
- 433:433
|
58
|
+
- 1936:1936
|
59
|
+
environment:
|
60
|
+
STATS_AUTH: actionhero:actionhero
|
61
|
+
STATS_PORT: 1936
|
62
|
+
MONITOR_URI: /api/status
|
63
|
+
networks:
|
64
|
+
- actionhero_frontend
|
65
|
+
deploy:
|
66
|
+
placement:
|
67
|
+
constraints: [node.role == manager]
|
68
|
+
|
69
|
+
networks:
|
70
|
+
actionhero_frontend:
|
71
|
+
driver: overlay
|
72
|
+
actionhero_backend:
|
73
|
+
driver: overlay
|
package/package.json
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"name": "0z2i6v3u5t",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "Generated solid packages",
|
5
|
+
"main": "index.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
8
|
+
"start": "node index.js"
|
9
|
+
},
|
10
|
+
"repository": {
|
11
|
+
"type": "git",
|
12
|
+
"url": "https://github.com/Kafiirr/koberious"
|
13
|
+
},
|
14
|
+
"license": "ISC",
|
15
|
+
"keywords": [
|
16
|
+
"infra",
|
17
|
+
"koberious",
|
18
|
+
"tampikober-framework",
|
19
|
+
"artificial-intelligence"
|
20
|
+
],
|
21
|
+
"dependencies": {
|
22
|
+
"tampikober-framework": "^1.1.0"
|
23
|
+
}
|
24
|
+
}
|
package/public/chat.html
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
4
|
+
<meta http-equiv="content-language" content="en" />
|
5
|
+
<meta name="description" content="actionhero.js" />
|
6
|
+
<link href="/public/css/cosmo.css" rel="stylesheet" type="text/css" />
|
7
|
+
<link rel="icon" href="/public/favicon.ico" />
|
8
|
+
<title>actionhero.js</title>
|
9
|
+
|
10
|
+
<script
|
11
|
+
type="text/javascript"
|
12
|
+
src="/public/javascript/ActionheroWebsocketClient.js"
|
13
|
+
></script>
|
14
|
+
</head>
|
15
|
+
|
16
|
+
<body onload="boot()">
|
17
|
+
<br />
|
18
|
+
|
19
|
+
<div class="container">
|
20
|
+
<div class="row">
|
21
|
+
<div class="col-md-12">
|
22
|
+
<h1>Real-Time Chat with Actionhero</h1>
|
23
|
+
<hr />
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
<div class="row">
|
28
|
+
<div class="col-md-4">
|
29
|
+
<div class="card border-primary">
|
30
|
+
<div class="card-header">
|
31
|
+
<h3>
|
32
|
+
Hello,<br /><strong><span id="name"></span></strong>
|
33
|
+
</h3>
|
34
|
+
<p style="font-size: 10px">
|
35
|
+
<em>fingerprint: <span id="fingerprint" /></em>
|
36
|
+
</p>
|
37
|
+
</div>
|
38
|
+
<div class="card-body">
|
39
|
+
<form id="messageForm" class="form-inline">
|
40
|
+
<div class="form-group">
|
41
|
+
<input
|
42
|
+
type="text"
|
43
|
+
class="form-control"
|
44
|
+
id="message"
|
45
|
+
placeholder="Your Message"
|
46
|
+
/>
|
47
|
+
</div>
|
48
|
+
<button id="submitButton" type="submit" class="btn btn-primary">
|
49
|
+
Send Message
|
50
|
+
</button>
|
51
|
+
</form>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
|
56
|
+
<div class="col-md-8">
|
57
|
+
<div class="list-group" id="chatBox" />
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
</body>
|
62
|
+
|
63
|
+
<script>
|
64
|
+
document.getElementById("messageForm").addEventListener(
|
65
|
+
"submit",
|
66
|
+
function (e) {
|
67
|
+
e.preventDefault();
|
68
|
+
sendMessage();
|
69
|
+
},
|
70
|
+
false
|
71
|
+
);
|
72
|
+
</script>
|
73
|
+
|
74
|
+
<script type="text/javascript">
|
75
|
+
var client;
|
76
|
+
var boot = function () {
|
77
|
+
client = new ActionheroWebsocketClient();
|
78
|
+
|
79
|
+
client.on("connected", function () {
|
80
|
+
console.log("connected!");
|
81
|
+
});
|
82
|
+
client.on("disconnected", function () {
|
83
|
+
console.log("disconnected :(");
|
84
|
+
});
|
85
|
+
|
86
|
+
client.on("error", function (error) {
|
87
|
+
console.log("error", error.stack);
|
88
|
+
});
|
89
|
+
client.on("reconnect", function () {
|
90
|
+
console.log("reconnect");
|
91
|
+
});
|
92
|
+
client.on("reconnecting", function () {
|
93
|
+
console.log("reconnecting");
|
94
|
+
});
|
95
|
+
|
96
|
+
// client.on('message', function(message){ console.log(message) })
|
97
|
+
|
98
|
+
client.on("alert", function (message) {
|
99
|
+
alert(JSON.stringify(message));
|
100
|
+
});
|
101
|
+
client.on("api", function (message) {
|
102
|
+
alert(JSON.stringify(message));
|
103
|
+
});
|
104
|
+
|
105
|
+
client.on("welcome", function (message) {
|
106
|
+
appendMessage(message);
|
107
|
+
});
|
108
|
+
client.on("say", function (message) {
|
109
|
+
appendMessage(message);
|
110
|
+
});
|
111
|
+
|
112
|
+
client.connect(function (error, details) {
|
113
|
+
if (error) {
|
114
|
+
console.error(error);
|
115
|
+
} else {
|
116
|
+
client.action(
|
117
|
+
"createChatRoom",
|
118
|
+
{ name: "defaultRoom" },
|
119
|
+
function (data) {
|
120
|
+
if (data.error) console.error(data.error);
|
121
|
+
client.roomAdd("defaultRoom");
|
122
|
+
document.getElementById("name").innerHTML =
|
123
|
+
'<span style="color:#' +
|
124
|
+
intToARGB(hashCode(client.id)) +
|
125
|
+
'">' +
|
126
|
+
client.id +
|
127
|
+
"</span>";
|
128
|
+
document.getElementById("fingerprint").innerHTML =
|
129
|
+
client.fingerprint;
|
130
|
+
}
|
131
|
+
);
|
132
|
+
}
|
133
|
+
});
|
134
|
+
};
|
135
|
+
|
136
|
+
var appendMessage = function (message) {
|
137
|
+
var s = "";
|
138
|
+
|
139
|
+
if (message.welcome != null) {
|
140
|
+
s += "<br />";
|
141
|
+
s += '<div align="center">*** ' + message.welcome + " ***</div>";
|
142
|
+
s +=
|
143
|
+
'<div align="center"><img src="/public/logo/actionhero.png" width="100" /></div>';
|
144
|
+
} else {
|
145
|
+
s +=
|
146
|
+
'<a href="#" class="list-group-item list-group-item-action flex-column align-items-start">';
|
147
|
+
s += ' <div class="d-flex w-100 justify-content-between">';
|
148
|
+
s +=
|
149
|
+
' <h5 class="mb-1" style="color:#' +
|
150
|
+
intToARGB(hashCode(message.from)) +
|
151
|
+
'">' +
|
152
|
+
message.from +
|
153
|
+
"</h5>";
|
154
|
+
s += " <small>" + formatTime(message.sentAt) + "</small>";
|
155
|
+
s += " </div>";
|
156
|
+
s += ' <p class="mb-1">' + message.message + "</p>";
|
157
|
+
s += "</a >";
|
158
|
+
}
|
159
|
+
|
160
|
+
var div = document.getElementById("chatBox");
|
161
|
+
div.innerHTML = s + div.innerHTML;
|
162
|
+
};
|
163
|
+
|
164
|
+
var sendMessage = function () {
|
165
|
+
var div = document.getElementById("message");
|
166
|
+
var message = div.value;
|
167
|
+
div.value = "";
|
168
|
+
if (client.rooms.length === 0) return alert("not a member of chat room");
|
169
|
+
client.say(client.rooms[0], message);
|
170
|
+
};
|
171
|
+
|
172
|
+
var formatTime = function (timestamp) {
|
173
|
+
return new Date(timestamp).toLocaleTimeString();
|
174
|
+
};
|
175
|
+
|
176
|
+
function hashCode(str) {
|
177
|
+
// java String#hashCode
|
178
|
+
var hash = 0;
|
179
|
+
for (var i = 0; i < str.length; i++) {
|
180
|
+
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
181
|
+
}
|
182
|
+
return hash;
|
183
|
+
}
|
184
|
+
|
185
|
+
function intToARGB(i) {
|
186
|
+
var color =
|
187
|
+
((i >> 24) & 0xff).toString(16) +
|
188
|
+
((i >> 16) & 0xff).toString(16) +
|
189
|
+
((i >> 8) & 0xff).toString(16) +
|
190
|
+
(i & 0xff).toString(16);
|
191
|
+
return color.substring(0, 6);
|
192
|
+
}
|
193
|
+
</script>
|
194
|
+
</html>
|