@akc42/app-utils 5.0.10 → 5.0.11

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
@@ -94,9 +94,9 @@ The response is aysnchronousally returned as an object. Errors are throw using
94
94
  If for any reason you want more info about the keyPress, access
95
95
  `this.keys.lastPressed`, and it will return the complete binding object
96
96
 
97
- ## calcTextColour
97
+ ## utilities
98
98
 
99
- This is a utility function to determine the correct foreground colour (black or white) to use with a background colour
99
+ **calcTextColour** is a utility function to determine the correct foreground colour (black or white) to use with a background colour
100
100
  passed as the parameter (as a hex strings with an optional proceeding `#` symbol.). The colour is returned as either `#000000` or `#ffffff`
101
101
 
102
102
  ## config and related
@@ -167,6 +167,64 @@ dynamically checks them) are:-
167
167
  **Logger** is like Debug (indeed its a wrapper for it) except it doesn't need short date, or immediate parameters as
168
168
  that is what is assumed.
169
169
 
170
+ It is called with the following parameters in order:-
171
+
172
+ - *logid* The `logid` (the primary key) of the message in the database (only used in the message output if the item was
173
+ a crash).
174
+ - *logtime* This is either a unix timestamp *or* a string with the date and/or time in it. It should be in the same
175
+ format as being formatted (see above).
176
+ - *crash* a 0 or 1 dependant on if this message was a crash or not.
177
+ - *shortdate* a 0 or 1 dependant on if this message has a short date or not,
178
+ - *ipaddress* should be a valid ip address or `null`.
179
+ - *topic*
180
+ - *message* Just a single string
181
+ - *colourspec*
182
+ - *gap* Gap in milliseconds (this routine does the conversion to minutes if a `shortdate`).
183
+
184
+ It returns an Object with 4 properties
185
+
186
+ - *dayoutput* If the first message of the day, text with the date (only) in it, otherwise a zero length string.
187
+ - *message* The complete formatted message
188
+ - *logid* The `logid` the formatter was called with.
189
+ - *ip* The `ipaddress` the formatter was called with.
190
+
191
+ **DebugHelper** is a helper function for *Debug* and performs most of its work. It is called with the same parameters as *Debug* plus an additional one; *writer*. *writer* should be a callback function that can do something with the message and then return the return object that a debug call does. In the use by *Debug* this function is the one writes the data to the database, but other writers can be provided. For instance the *Debug* function in this package uses the writer to send the message from the client to the server, whereas in the server (`@akc42/server-utils`) it is the function that writes the message to the database.
192
+
193
+ *writer* is called with the following parameters (all described above for *debug*, although in this case they *must* be supplied)
194
+
195
+ - *logtime* (unix timestamp)
196
+ - *crash* (0 or 1)
197
+ - *shortdate* (0 or 1)
198
+ - *ipaddress* (or `null`)
199
+ - *topic*
200
+ - *colourspec*
201
+ - *gap*
202
+ - *immediate* (`true` or `false`)
203
+
204
+ **messageFormatter** is the routine that formats the raw message that has been written to the database.
205
+
206
+ It is called with the following parameters in order:-
207
+
208
+ - *logid* The `logid` (the primary key) of the message in the database (only used in the message output if the item was
209
+ a crash).
210
+ - *logtime* This is either a unix timestamp *or* a string with the date and/or time in it. It should be in the same
211
+ format as being formatted (see above).
212
+ - *crash* a 0 or 1 dependant on if this message was a crash or not.
213
+ - *shortdate* a 0 or 1 dependant on if this message has a short date or not,
214
+ - *ipaddress* should be a valid ip address or `null`.
215
+ - *topic*
216
+ - *message* Just a single string
217
+ - *colourspec*
218
+ - *gap* Gap in milliseconds (this routine does the conversion to minutes if a `shortdate`).
219
+
220
+ It returns an Object with 4 properties
221
+
222
+ - *dayoutput* If the first message of the day, text with the date (only) in it, otherwise a zero length string.
223
+ - *message* The complete formatted message
224
+ - *logid* The `logid` the formatter was called with.
225
+ - *ip* The `ipaddress` the formatter was called with.
226
+
227
+
170
228
  ## dom-host
171
229
 
172
230
  The **domHost** function is called with a single parameter (normally `this` inside a custom element)
package/app-keys.js CHANGED
@@ -171,7 +171,7 @@ const SPACE_KEY = /^space(bar)?/;
171
171
 
172
172
  const ESC_KEY = /^escape$/;
173
173
 
174
- class AppKeys {
174
+ export class AppKeys {
175
175
  constructor(target, keys, stop) {
176
176
  this.stop = stop; //marker to say stop propagation;
177
177
  if (!(target instanceof HTMLElement)) throw new Error('AppKeys required an HTML Element as target');
@@ -291,4 +291,4 @@ class AppKeys {
291
291
  }
292
292
  }
293
293
  }
294
- export default AppKeys;
294
+
package/app-utils.js CHANGED
@@ -1,37 +1,22 @@
1
1
  import {api, ApiError} from './api.js';
2
- import AppKeys from './app-keys.js';
3
- import calcTextColor from './colour.js';
2
+ import {AppKeys} from './app-keys.js';
3
+ import {calcTextColor, capitalise} from './utils.js';
4
4
  import config, {setConfig, reReadConfig}from './config.js'
5
- import csv from './csv.js';
5
+ import {csv} from './csv.js';
6
6
  import {Debug,Logger} from './debug.js';
7
- import domHost from './dom-host.js';
7
+ import {domHost} from './dom-host.js';
8
8
  import { connectUrl, disconnectUrl} from './location.js';
9
9
  import getMasterTabPromise from './master-tab-promise.js';
10
10
  import {partMap} from './partMap.js';
11
- import pdf from './pdf.js';
12
- import Route from './route.js';
13
- import submit from './submit-function.js';
11
+ import {pdf} from './pdf.js';
12
+ import {Route} from './route.js';
13
+ import {submit} from './submit-function.js';
14
14
  import {switchPath, generateUri, navigate} from './switch-path.js';
15
15
  import { minToTime,timeToMin,strToUrlDate,urlDateToStr } from './date-utils.js';
16
+ import { DebugHelper, messageFormatter, COLOURS } from './debug-utils.js';
16
17
 
17
- function capitalise(name) {
18
- if (name.length > 0 ) {
19
- let words = name.split(' ');
20
- for(let i = 0; i < words.length; i++) {
21
- if (i > 0 && ( words[i].toLowerCase() === 'de' || words[i].toLowerCase() === 'la')) {
22
- words[i] = words[i].toLowerCase();
23
- } else if (words[i].length > 2 && words[i].toUpperCase().substring(0,2) === `O'` ) {
24
- const newword = capitalise(words[i].substring(2))
25
- words[i] = words[i].substring(0,2).toUpperCase() + newword;
26
- } else {
27
- words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1).toLowerCase();
28
- }
29
- }
30
- return words.join(' ');
31
- }
32
- return '';
33
- };
34
18
 
35
- export {api,ApiError,AppKeys,calcTextColor,capitalise, config, connectUrl, csv, Debug, disconnectUrl, domHost, generateUri,
36
- getMasterTabPromise, Logger, minToTime, navigate, partMap, pdf, reReadConfig, Route,setConfig, strToUrlDate, submit,
19
+
20
+ export {api,ApiError,AppKeys,calcTextColor,capitalise, COLOURS, config, connectUrl, csv, Debug, DebugHelper, disconnectUrl, domHost, generateUri,
21
+ getMasterTabPromise, Logger, messageFormatter, minToTime, navigate, partMap, pdf, reReadConfig, Route,setConfig, strToUrlDate, submit,
37
22
  switchPath, timeToMin, urlDateToStr };
package/csv.js CHANGED
@@ -22,7 +22,7 @@ import {generateUri} from './switch-path.js';
22
22
  const link = document.createElement('a');
23
23
  link.setAttribute('download', null);
24
24
 
25
- const csv = (url, params) => {
25
+ export const csv = (url, params) => {
26
26
  let href;
27
27
  if (typeof url == 'string') {
28
28
  href = generateUri(`/api/csv/${url}`, params ?? {});
@@ -34,4 +34,3 @@ const csv = (url, params) => {
34
34
  link.click();
35
35
  };
36
36
 
37
- export default csv;
package/debug-utils.js ADDED
@@ -0,0 +1,128 @@
1
+ /**
2
+ @licence
3
+ Copyright (c) 2026 Alan Chandler, all rights reserved
4
+
5
+ This file is part of @akc42/app-utils.
6
+
7
+ @akc42/app-utils is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ @akc42/app-utils is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with @akc42/app-utils. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+ import chalk from "chalk";
21
+
22
+ export const COLOURS = {
23
+ hexmatch: /^#(?:[0-9a-fA-F]{3}){1,2}$/,
24
+ rgbmatch: /^(\d{1,3}), ?(\d{1,3}), ?(\d{1,3})$/,
25
+ COLOURS: {
26
+ app: chalk.rgb(255, 136, 0).bold, //orange,
27
+ db: chalk.greenBright,
28
+ api: chalk.magentaBright,
29
+ client: chalk.redBright,
30
+ log: chalk.hex('#ff651d'),
31
+ mail: chalk.cyanBright,
32
+ //error like have backGround colouring
33
+ auth: chalk.whiteBright.bgBlue,
34
+ error: chalk.whiteBright.bgHex('#ff1165')
35
+ }
36
+ };
37
+ const ipmatch = /^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(\.|$)){4}$/;
38
+ const datematch =/^(\d{4})-([01]\d)-([0-3]\d) ([0-2]\d):([0-5]\d)(:([0-5]\d)(\.(\d{1,3}))?)?$/;
39
+ let lastdate = '';
40
+
41
+ export function messageFormatter(logid,logtime, crash, shortdate, ipaddress, topic, message, colourspec, gap) {
42
+ let matches;
43
+ if (typeof logtime === 'string') {
44
+ matches = logtime.match(datematch);
45
+ } else {
46
+ matches = [logtime];
47
+ }
48
+ const logdate = new Date(matches[0]);
49
+ logdate.setMinutes(logdate.getMinutes() + logdate.getTimezoneOffset());
50
+ const displaydate = `${logdate.getFullYear()}-${(logdate.getMonth() + 1).toString().padStart(2,'0')}-${logdate.getDate().toString().padStart(2,'0')}`;
51
+ const displaytime = `${logdate.getHours().toString().padStart(2,'0')}:${logdate.getMinutes().toString().padStart(2,'0')}:${
52
+ logdate.getSeconds().toString().padStart(2,'0')}.${
53
+ (typeof logtime === 'string')? (matches[9]??'').toString().padStart(3,'0') : logdate.getMilliseconds().toString().padStart(3,'0')}`;
54
+ const d = chalk.blueBright(`${displaydate} ${shortdate === 1? displaytime.slice(0,-7): displaytime}`);
55
+ const ip = ipmatch.test(ipaddress)? chalk.red(` [${ipaddress}]`) : '';
56
+ const t = chalk.greenBright(`(${topic})`);
57
+ let m;
58
+ let l = '';
59
+ if (crash === 1) {
60
+ l = chalk.whiteBright(` ${logid}`)
61
+ m = chalk.white.bgRed(message);
62
+ } else if (colourspec in COLOURS.COLOURS) {
63
+ m = COLOURS.COLOURS[colourspec](message);
64
+ } else if (COLOURS.hexmatch.test(colourspec)) {
65
+ m = chalk.hex(colourspec)(message);
66
+ } else if (COLOURS.rgbmatch.test(colourspec)) {
67
+ const matches = COLOURS.rgbmatch.exec(colourspec);
68
+ m = chalk.rgb(matches[1], matches[2], matches[3])(message);
69
+ } else {
70
+ m = chalk.cyan(message)
71
+ }
72
+ const g = Number.isInteger(gap)?chalk.whiteBright(` gap: ${shortdate? Math.round(gap/60000) + ' mins': gap + 'ms'}`):'';
73
+ let dayoutput = '';
74
+ if (lastdate !== displaydate) {
75
+ dayoutput = `${chalk.whiteBright(displaydate)}:\n`
76
+ lastdate = displaydate;
77
+ }
78
+
79
+ return {
80
+ dayoutput: dayoutput,
81
+ message:`${d}${l}${ip} ${t} ${m}${g}`,
82
+ logid: logid,
83
+ ip: ipaddress
84
+ }
85
+ };
86
+
87
+ export function DebugHelper(topic, colourspec, shortdate, immediate, writer) {
88
+ const t = topic;
89
+ const cs = (colourspec in COLOURS.COLOURS) || COLOURS.hexmatch.test(colourspec) || COLOURS.rgbmatch.test(colourspec) ? colourspec : null;
90
+ const sd = shortdate? 1:0;
91
+ let timestamp = Date.now();
92
+ const i = immediate;
93
+ return function (c, logtime ,ip, ...args) {
94
+ let crash = 1;
95
+ if (c !== 'crash') {
96
+ if (ip !== undefined) {
97
+ if (Array.isArray(ip)) args = ip.concat(args); else args.unshift(ip);
98
+ }
99
+ ip = logtime;
100
+ logtime = c;
101
+ crash = 0;
102
+ }
103
+
104
+ const fromDate = new Date(); //logtime is only possible if later than midnight last night.
105
+ const from = fromDate.setHours(0,0,0,0)
106
+ if (!(Number.isInteger(logtime) && logtime > from)) {
107
+ if (ip !== undefined) {
108
+ if (Array.isArray(ip)) args = ip.concat(args); else args.unshift(ip);
109
+ }
110
+ ip = logtime;
111
+ logtime = Date.now();
112
+ }
113
+ if (!ipmatch.test(ip)) {
114
+ if (ip !== undefined){
115
+ if (Array.isArray(ip)) args = ip.concat(args); else args.unshift(ip);
116
+ }
117
+ ip = null
118
+ }
119
+ const now = Date.now();
120
+ const gap = now - timestamp;
121
+ timestamp = now;
122
+ const message = args.reduce((cum, arg) => {
123
+ if (arg === undefined) return cum;
124
+ return `${cum} ${arg}`.trim();
125
+ },'');
126
+ return writer(logtime, crash, sd, ip, t, message, cs, gap,i)
127
+ }
128
+ };
package/debug.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  @licence
3
- Copyright (c) 2021 Alan Chandler, all rights reserved
3
+ Copyright (c) 2026 Alan Chandler, all rights reserved
4
4
 
5
5
  This file is part of @akc42/app-utils.
6
6
 
@@ -50,7 +50,7 @@
50
50
  It doesn't need short date, or immediate parameters as thats whats assumed
51
51
 
52
52
  */
53
- import {DebugHelper, messageFormatter} from '@akc42/server-utils';
53
+ import {DebugHelper, messageFormatter} from './debug-utils.js';
54
54
 
55
55
  export function Logger(topic, colourspec) {
56
56
  const debug = Debug(topic, colourspec, 1,1);
package/dom-host.js CHANGED
@@ -20,12 +20,11 @@
20
20
 
21
21
 
22
22
 
23
- function domHost(self) {
23
+ export function domHost(self) {
24
24
  let parent = self.parentNode;
25
25
  while (parent && parent.nodeType !== 11) {
26
26
  parent = parent.parentNode; //work up the hierarchy
27
27
  }
28
28
 
29
29
  return parent ? parent.host : self;
30
- }
31
- export default domHost;
30
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akc42/app-utils",
3
- "version": "5.0.10",
3
+ "version": "5.0.11",
4
4
  "description": "General Utilities for SPAs",
5
5
  "mains": "app-utils.js",
6
6
  "scripts": {
@@ -20,7 +20,6 @@
20
20
  },
21
21
  "homepage": "https://github.com/akc42/app-utils#readme",
22
22
  "dependencies": {
23
- "@akc42/server-utils": "^4.0.2",
24
23
  "lit": "^3.3.1"
25
24
  }
26
25
  }
package/pdf.js CHANGED
@@ -18,6 +18,6 @@
18
18
  along with @akc42/app-utils. If not, see <http://www.gnu.org/licenses/>.
19
19
  */
20
20
  import {api} from './api.js';
21
- export default (url,params) => {
21
+ export function pdf (url,params) {
22
22
  api(`pdf/${url}`,params,true);
23
23
  }
package/route.js CHANGED
@@ -18,7 +18,7 @@
18
18
  along with Distributed Router. If not, see <http://www.gnu.org/licenses/>.
19
19
  */
20
20
 
21
- export default class Route {
21
+ export class Route {
22
22
  constructor(match = '', ifmatched = '') {
23
23
  //set default values
24
24
  this.preroute = {active: false, segment: 0, path: '', params: {}, query: {}};
@@ -64,7 +64,7 @@ function checkLevel(target, params) {
64
64
  return Array.prototype.filter.call(target.children, n => n.nodeType === Node.ELEMENT_NODE).reduce((acc, node) => checkNode(node, params) && acc, true);
65
65
  }
66
66
 
67
- export default function submit(e) {
67
+ export function submit(e) {
68
68
  let target;
69
69
  if (e.currentTarget) {
70
70
  e.stopPropagation();
@@ -23,12 +23,29 @@
23
23
  proceeded by #
24
24
  */
25
25
 
26
- function calcTextColor(backgroundColor) {
26
+ export function calcTextColor(backgroundColor) {
27
27
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(backgroundColor);
28
28
  if (result) {
29
29
  const luminance = (0.2126 * parseInt(result[1], 16) + 0.7152 * parseInt(result[2], 16) + 0.0722 * parseInt(result[3], 16));
30
30
  return (luminance < 140) ? "#ffffff" : "#000000";
31
31
  }
32
32
  return "#000000"
33
- }
34
- export default calcTextColor;
33
+ };
34
+
35
+ export function capitalise(name) {
36
+ if (name.length > 0 ) {
37
+ let words = name.split(' ');
38
+ for(let i = 0; i < words.length; i++) {
39
+ if (i > 0 && ( words[i].toLowerCase() === 'de' || words[i].toLowerCase() === 'la')) {
40
+ words[i] = words[i].toLowerCase();
41
+ } else if (words[i].length > 2 && words[i].toUpperCase().substring(0,2) === `O'` ) {
42
+ const newword = capitalise(words[i].substring(2))
43
+ words[i] = words[i].substring(0,2).toUpperCase() + newword;
44
+ } else {
45
+ words[i] = words[i].charAt(0).toUpperCase() + words[i].substring(1).toLowerCase();
46
+ }
47
+ }
48
+ return words.join(' ');
49
+ }
50
+ return '';
51
+ };