structured-fw 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/Config.ts +47 -0
  2. package/LICENSE +21 -0
  3. package/README.md +332 -0
  4. package/app/Types.ts +1 -0
  5. package/app/models/README.md +9 -0
  6. package/app/routes/README.md +19 -0
  7. package/app/views/README.md +1 -0
  8. package/app/views/layout.html +1 -0
  9. package/bin/structured +114 -0
  10. package/build/Config.d.ts +2 -0
  11. package/build/Config.js +31 -0
  12. package/build/app/Types.d.ts +1 -0
  13. package/build/app/Types.js +1 -0
  14. package/build/app/models/Users.d.ts +0 -0
  15. package/build/app/models/Users.js +1 -0
  16. package/build/app/routes/Auth.d.ts +0 -0
  17. package/build/app/routes/Auth.js +1 -0
  18. package/build/app/routes/Test.d.ts +2 -0
  19. package/build/app/routes/Test.js +101 -0
  20. package/build/app/routes/Todo.d.ts +0 -0
  21. package/build/app/routes/Todo.js +1 -0
  22. package/build/app/routes/Upload.d.ts +0 -0
  23. package/build/app/routes/Upload.js +1 -0
  24. package/build/app/routes/Validation.d.ts +2 -0
  25. package/build/app/routes/Validation.js +34 -0
  26. package/build/app/views/components/ClientImport/ClientImport.client.d.ts +2 -0
  27. package/build/app/views/components/ClientImport/ClientImport.client.js +4 -0
  28. package/build/app/views/components/ClientImport/Export.d.ts +1 -0
  29. package/build/app/views/components/ClientImport/Export.js +1 -0
  30. package/build/app/views/components/Conditionals/Conditionals.client.d.ts +2 -0
  31. package/build/app/views/components/Conditionals/Conditionals.client.js +43 -0
  32. package/build/app/views/components/FormTest/FormTestNested/FormTestNested.d.ts +8 -0
  33. package/build/app/views/components/FormTest/FormTestNested/FormTestNested.js +7 -0
  34. package/build/app/views/components/ModelsTest/ModelsTest.client.d.ts +2 -0
  35. package/build/app/views/components/ModelsTest/ModelsTest.client.js +5 -0
  36. package/build/app/views/components/MultipartForm/MultipartForm.client.d.ts +0 -0
  37. package/build/app/views/components/MultipartForm/MultipartForm.client.js +1 -0
  38. package/build/app/views/components/PassObject/PassObject.d.ts +10 -0
  39. package/build/app/views/components/PassObject/PassObject.js +10 -0
  40. package/build/app/views/components/PassObject/ReceiveObj/ReceiveObj.d.ts +6 -0
  41. package/build/app/views/components/PassObject/ReceiveObj/ReceiveObj.js +6 -0
  42. package/build/app/views/components/RedrawAbort/RedrawAbort.client.d.ts +2 -0
  43. package/build/app/views/components/RedrawAbort/RedrawAbort.client.js +6 -0
  44. package/build/app/views/components/RedrawAbort/RedrawAbort.d.ts +8 -0
  45. package/build/app/views/components/RedrawAbort/RedrawAbort.js +8 -0
  46. package/build/app/views/components/ServerSideContext/ServerSideContext.d.ts +7 -0
  47. package/build/app/views/components/ServerSideContext/ServerSideContext.js +10 -0
  48. package/build/assets/ts/Export.d.ts +1 -0
  49. package/build/assets/ts/Export.js +1 -0
  50. package/build/index.d.ts +1 -0
  51. package/build/index.js +3 -0
  52. package/build/system/Helpers.d.ts +3 -0
  53. package/build/system/Helpers.js +72 -0
  54. package/build/system/Symbols.d.ts +3 -0
  55. package/build/system/Symbols.js +3 -0
  56. package/build/system/Types.d.ts +171 -0
  57. package/build/system/Types.js +1 -0
  58. package/build/system/Util.d.ts +20 -0
  59. package/build/system/Util.js +336 -0
  60. package/build/system/client/App.d.ts +7 -0
  61. package/build/system/client/App.js +8 -0
  62. package/build/system/client/Client.d.ts +6 -0
  63. package/build/system/client/Client.js +9 -0
  64. package/build/system/client/ClientComponent.d.ts +68 -0
  65. package/build/system/client/ClientComponent.js +734 -0
  66. package/build/system/client/DataStore.d.ts +22 -0
  67. package/build/system/client/DataStore.js +64 -0
  68. package/build/system/client/DataStoreView.d.ts +19 -0
  69. package/build/system/client/DataStoreView.js +56 -0
  70. package/build/system/client/EventEmitter.d.ts +7 -0
  71. package/build/system/client/EventEmitter.js +31 -0
  72. package/build/system/client/Net.d.ts +13 -0
  73. package/build/system/client/Net.js +39 -0
  74. package/build/system/client/NetRequest.d.ts +13 -0
  75. package/build/system/client/NetRequest.js +45 -0
  76. package/build/system/server/Application.d.ts +31 -0
  77. package/build/system/server/Application.js +171 -0
  78. package/build/system/server/Component.d.ts +27 -0
  79. package/build/system/server/Component.js +249 -0
  80. package/build/system/server/Components.d.ts +12 -0
  81. package/build/system/server/Components.js +77 -0
  82. package/build/system/server/Cookies.d.ts +6 -0
  83. package/build/system/server/Cookies.js +19 -0
  84. package/build/system/server/Document.d.ts +24 -0
  85. package/build/system/server/Document.js +107 -0
  86. package/build/system/server/DocumentHead.d.ts +32 -0
  87. package/build/system/server/DocumentHead.js +118 -0
  88. package/build/system/server/FormValidation.d.ts +16 -0
  89. package/build/system/server/FormValidation.js +197 -0
  90. package/build/system/server/Handlebars.d.ts +11 -0
  91. package/build/system/server/Handlebars.js +34 -0
  92. package/build/system/server/Request.d.ts +21 -0
  93. package/build/system/server/Request.js +356 -0
  94. package/build/system/server/Session.d.ts +23 -0
  95. package/build/system/server/Session.js +114 -0
  96. package/build/system/server/dom/DOMFragment.d.ts +4 -0
  97. package/build/system/server/dom/DOMFragment.js +6 -0
  98. package/build/system/server/dom/DOMNode.d.ts +31 -0
  99. package/build/system/server/dom/DOMNode.js +110 -0
  100. package/build/system/server/dom/HTMLParser.d.ts +21 -0
  101. package/build/system/server/dom/HTMLParser.js +204 -0
  102. package/index.ts +4 -0
  103. package/package.json +31 -0
  104. package/system/Helpers.ts +97 -0
  105. package/system/Symbols.ts +6 -0
  106. package/system/Types.ts +234 -0
  107. package/system/Util.ts +488 -0
  108. package/system/client/App.ts +11 -0
  109. package/system/client/Client.ts +9 -0
  110. package/system/client/ClientComponent.ts +1117 -0
  111. package/system/client/DataStore.ts +101 -0
  112. package/system/client/DataStoreView.ts +82 -0
  113. package/system/client/EventEmitter.ts +38 -0
  114. package/system/client/Net.ts +58 -0
  115. package/system/client/NetRequest.ts +64 -0
  116. package/system/server/Application.ts +230 -0
  117. package/system/server/Component.ts +404 -0
  118. package/system/server/Components.ts +111 -0
  119. package/system/server/Cookies.ts +29 -0
  120. package/system/server/Document.ts +163 -0
  121. package/system/server/DocumentHead.ts +150 -0
  122. package/system/server/FormValidation.ts +231 -0
  123. package/system/server/Handlebars.ts +51 -0
  124. package/system/server/Request.ts +497 -0
  125. package/system/server/Session.ts +151 -0
  126. package/system/server/dom/DOMFragment.ts +7 -0
  127. package/system/server/dom/DOMNode.ts +140 -0
  128. package/system/server/dom/HTMLParser.ts +238 -0
  129. package/tsconfig.json +35 -0
@@ -0,0 +1,101 @@
1
+ import { Document } from '../../system/server/Document.js';
2
+ import { Request } from '../../system/server/Request.js';
3
+ export default function (app) {
4
+ app.request.on('GET', '/test/form', async (ctx) => {
5
+ const doc = new Document(app, 'Form test', ctx);
6
+ await doc.loadComponent('FormTestNested', { test: 3 });
7
+ ctx.respondWith(doc);
8
+ });
9
+ app.request.on('POST', '/test/form', async (ctx) => {
10
+ console.log(JSON.stringify(ctx.body, undefined, 4));
11
+ const userImage = ctx.files.user.image[0];
12
+ ctx.response.setHeader('Content-Type', userImage.type);
13
+ ctx.respondWith(userImage.data);
14
+ });
15
+ app.request.on('GET', '/test/client_import', async (ctx) => {
16
+ const doc = new Document(app, 'Test', ctx);
17
+ await doc.loadComponent('ClientImport', { xyz: 10, asd: 12 });
18
+ ctx.respondWith(doc);
19
+ });
20
+ app.request.on('GET', '/test/redraw', async (ctx) => {
21
+ const doc = new Document(app, 'Test', ctx);
22
+ await doc.loadComponent('RedrawAbort');
23
+ ctx.respondWith(doc);
24
+ });
25
+ app.request.on('GET', '/test/models', async (ctx) => {
26
+ const doc = new Document(app, 'Test', ctx);
27
+ await doc.loadComponent('ModelsTest');
28
+ ctx.respondWith(doc);
29
+ });
30
+ app.request.on('GET', '/getargs', async (ctx) => {
31
+ ctx.respondWith(ctx.getArgs);
32
+ });
33
+ app.request.on('GET', '/form/multipart', async (ctx) => {
34
+ const doc = new Document(app, 'Test multipart form', ctx);
35
+ await doc.loadComponent('MultipartForm');
36
+ ctx.respondWith(doc);
37
+ });
38
+ app.request.on('POST', '/form/multipart', async (ctx) => {
39
+ console.log(ctx.files);
40
+ ctx.respondWith(ctx.body);
41
+ });
42
+ app.request.on('GET', '/conditional', async (ctx) => {
43
+ const doc = new Document(app, 'Test multipart form', ctx);
44
+ await doc.loadComponent('Conditionals');
45
+ ctx.respondWith(doc);
46
+ });
47
+ app.request.on('GET', '/urldecode', async (ctx) => {
48
+ const noVal = 'noVal';
49
+ const noValNested = 'filters[beds][min]';
50
+ const simple = 'simple=2';
51
+ const simpleObj = 'person[name]=fname&person[last_name]=lname';
52
+ const simpleArray = 'colors[]=red&colors[]=blue';
53
+ const orderedArray = 'colorsOrdered[1]=red&colorsOrdered[0]=blue';
54
+ const indexedArray = 'months[0]=Jan&months[1]=Feb&months[2]=Mar';
55
+ const arrayOfObjects = 'users[0][name]=John&users[0][email]=johndoe@gmail.com&users[1][name]=Tim&users[1][email]=tim@gmail.com';
56
+ const objectWithArrayValues = 'user[name]=John&user[last_name]=Doe&user[sports][]=table tennis&user[sports][]=football';
57
+ const objectWithObjectValues = 'data[paper][props][size]=10x13&data[paper][props][type]=matte';
58
+ const nestedArraySimple = 'colorStack[0][]=red&colorStack[0][]=blue&colorStack[1][]=green';
59
+ const arrayOfObjectsWithArrayValues = 'usersArr[0][name]=John&usersArr[0][email]=johndoe@gmail.com&usersArr[0][sports][]=football&usersArr[0][sports][]=basketball&usersArr[1][name]=Too&usersArr[1][email]=tootoo@gmail.com&usersArr[1][sports][]=bocce&usersArr[1][sports][]=cricket&usersArr[1][sports][]=dancing';
60
+ const missingValue = 'missing=';
61
+ const missingArrayValue = 'missingArr[]=';
62
+ const objBlankValue = `objBlank[0][email]=`;
63
+ const spaces = `spaces=value%20with%20spaces`;
64
+ const special = `garbage=` + encodeURIComponent('value!@#&$%^*()');
65
+ const nonLatin = `key3=` + encodeURIComponent('привет');
66
+ const t = new Date().getTime();
67
+ const test = Request.queryStringDecode([noVal, noValNested, simple, simpleObj, simpleArray, orderedArray, indexedArray, arrayOfObjects, objectWithArrayValues, objectWithObjectValues, nestedArraySimple, arrayOfObjectsWithArrayValues, missingValue, nonLatin, spaces, special, objBlankValue, missingArrayValue, simple].join('&'));
68
+ const dur = new Date().getTime() - t;
69
+ console.log(dur);
70
+ ctx.respondWith(test);
71
+ });
72
+ app.request.on('GET', '/client_import', async (ctx) => {
73
+ const doc = new Document(app, 'Test multipart form', ctx);
74
+ await doc.loadComponent('ClientImport');
75
+ doc.head.add(`
76
+ <script type="importmap">
77
+ {
78
+ imports: {
79
+ 'components/*' : '/build/app/views/components/*'
80
+ }
81
+ }
82
+ </script>
83
+ `);
84
+ ctx.respondWith(doc);
85
+ });
86
+ app.request.on('GET', '/serverclass', async (ctx) => {
87
+ const doc = new Document(app, 'Test multipart form', ctx);
88
+ await doc.loadComponent('ServerSideContext');
89
+ ctx.respondWith(doc);
90
+ });
91
+ app.request.on('GET', '/routes/new', async (ctx) => {
92
+ const doc = new Document(app, 'Test multipart form', ctx);
93
+ await doc.loadComponent('Conditionals');
94
+ return doc;
95
+ });
96
+ app.request.on('GET', '/passObj', async (ctx) => {
97
+ const doc = new Document(app, 'Test pass obj', ctx);
98
+ await doc.loadComponent('PassObject');
99
+ ctx.respondWith(doc);
100
+ });
101
+ }
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,2 @@
1
+ import { Application } from "../../system/server/Application.js";
2
+ export default function (app: Application): void;
@@ -0,0 +1,34 @@
1
+ import { FormValidation } from '../../system/server/FormValidation.js';
2
+ import { Document } from "../../system/server/Document.js";
3
+ export default function (app) {
4
+ let validator = new FormValidation();
5
+ validator.singleError = true;
6
+ validator.addRule('name', 'Name', ['required', ['minLength', 3]]);
7
+ validator.addRule('email', 'Email', ['validEmail']);
8
+ validator.addRule('number', 'Number', ['number', 'required']);
9
+ validator.addRule('numeric', 'Numeric', ['numeric', 'required']);
10
+ validator.addRule('float', 'Float', ['float', 'required']);
11
+ app.request.on('POST', '/validation', async (ctx) => {
12
+ if (ctx.body) {
13
+ let validationResult = await validator.validate(ctx.body);
14
+ if (validationResult.valid) {
15
+ ctx.response.write('Valid');
16
+ }
17
+ else {
18
+ app.session.setValue(ctx.sessionId, 'validationErrors', validationResult.errors);
19
+ app.session.setValue(ctx.sessionId, 'formValues', ctx.body);
20
+ app.request.redirect(ctx.response, '/validation');
21
+ }
22
+ }
23
+ });
24
+ app.request.on('GET', '/validation', async (ctx) => {
25
+ let doc = new Document(app, 'Form validation');
26
+ await doc.loadView('pages/validation', app.session.extract(ctx.sessionId, [
27
+ { validationErrors: 'errors' },
28
+ { formValues: 'values' }
29
+ ]));
30
+ ctx.response.write(doc.toString());
31
+ app.session.removeValue(ctx.sessionId, 'validationErrors');
32
+ app.session.removeValue(ctx.sessionId, 'formValues');
33
+ });
34
+ }
@@ -0,0 +1,2 @@
1
+ import { InitializerFunction } from '../../../../system/Types.js';
2
+ export declare const init: InitializerFunction;
@@ -0,0 +1,4 @@
1
+ export const init = async function () {
2
+ const test = await import('/assets/ts/Export.js');
3
+ console.log(test);
4
+ };
@@ -0,0 +1 @@
1
+ export declare const test = 1;
@@ -0,0 +1 @@
1
+ export const test = 1;
@@ -0,0 +1,2 @@
1
+ import { InitializerFunction } from '../../../../system/Types.js';
2
+ export declare const init: InitializerFunction;
@@ -0,0 +1,43 @@
1
+ export const init = async function () {
2
+ const style = document.createElement('style');
3
+ style.type = 'text/css';
4
+ style.textContent = `
5
+ .active {
6
+ font-weight: 800;
7
+ }
8
+ `;
9
+ document.head.appendChild(style);
10
+ this.store.set('showMessage', false);
11
+ this.bind(this.ref('setShowMessage'), 'click', () => {
12
+ this.store.set('showMessage', true);
13
+ });
14
+ this.bind(this.ref('unsetShowMessage'), 'click', () => {
15
+ this.store.set('showMessage', false);
16
+ });
17
+ let num = 0;
18
+ const increaseNum = () => {
19
+ num++;
20
+ setNum();
21
+ };
22
+ const decreaseNum = () => {
23
+ num--;
24
+ setNum();
25
+ };
26
+ const setNum = () => {
27
+ this.store.set('number', num);
28
+ this.ref('num').textContent = num.toString();
29
+ };
30
+ this.bind(this.ref('numIncrease'), 'click', () => {
31
+ increaseNum();
32
+ });
33
+ this.bind(this.ref('numDecrease'), 'click', () => {
34
+ decreaseNum();
35
+ });
36
+ setNum();
37
+ this.conditionalCallback('method1', () => {
38
+ return this.store.get('showMessage') === true && num > 3;
39
+ });
40
+ this.conditionalCallback('method2', (number) => {
41
+ return number === num;
42
+ });
43
+ };
@@ -0,0 +1,8 @@
1
+ import { ComponentScaffold, RequestContext } from '../../../../../system/Types.js';
2
+ type ComponentData = {
3
+ test: number;
4
+ };
5
+ export default class FormTestNested implements ComponentScaffold {
6
+ getData(data: ComponentData, ctx: RequestContext): Promise<ComponentData>;
7
+ }
8
+ export {};
@@ -0,0 +1,7 @@
1
+ export default class FormTestNested {
2
+ async getData(data, ctx) {
3
+ return {
4
+ test: 123
5
+ };
6
+ }
7
+ }
@@ -0,0 +1,2 @@
1
+ import { InitializerFunction } from '../../../../system/Types.js';
2
+ export declare const init: InitializerFunction;
@@ -0,0 +1,5 @@
1
+ export const init = async function () {
2
+ this.store.onChange('test', (key, val) => {
3
+ this.find('ModelTestNested')?.redraw(this.getData());
4
+ });
5
+ };
@@ -0,0 +1,10 @@
1
+ import { ComponentScaffold, RequestContext } from '../../../../system/Types.js';
2
+ type ComponentData = {};
3
+ export default class PassObj implements ComponentScaffold {
4
+ getData(data: ComponentData, ctx: RequestContext): Promise<{
5
+ obj: {
6
+ uuid: string;
7
+ };
8
+ }>;
9
+ }
10
+ export {};
@@ -0,0 +1,10 @@
1
+ import { randomString } from '../../../../system/Util.js';
2
+ export default class PassObj {
3
+ async getData(data, ctx) {
4
+ return {
5
+ obj: {
6
+ uuid: randomString(12)
7
+ }
8
+ };
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ import { ComponentScaffold, RequestContext } from '../../../../../system/Types.js';
2
+ type ComponentData = {};
3
+ export default class ReceiveObj implements ComponentScaffold {
4
+ getData(data: ComponentData, ctx: RequestContext): Promise<ComponentData>;
5
+ }
6
+ export {};
@@ -0,0 +1,6 @@
1
+ export default class ReceiveObj {
2
+ async getData(data, ctx) {
3
+ console.log('a', data);
4
+ return data;
5
+ }
6
+ }
@@ -0,0 +1,2 @@
1
+ import { InitializerFunction } from '../../../../system/Types.js';
2
+ export declare const init: InitializerFunction;
@@ -0,0 +1,6 @@
1
+ export const init = async function () {
2
+ setTimeout(() => {
3
+ this.redraw();
4
+ this.redraw();
5
+ }, 1000);
6
+ };
@@ -0,0 +1,8 @@
1
+ import { ComponentScaffold, RequestContext } from '../../../../system/Types.js';
2
+ type ComponentData = {};
3
+ export default class RedrawAbort implements ComponentScaffold {
4
+ getData(data: ComponentData, ctx: RequestContext): Promise<{
5
+ key: string;
6
+ }>;
7
+ }
8
+ export {};
@@ -0,0 +1,8 @@
1
+ import { randomString } from '../../../../system/Util.js';
2
+ export default class RedrawAbort {
3
+ async getData(data, ctx) {
4
+ return {
5
+ key: randomString(5)
6
+ };
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ import { ComponentScaffold } from '../../../../system/Types.js';
2
+ export default class ServerSideContext implements ComponentScaffold {
3
+ getData(): Promise<{
4
+ number: number;
5
+ }>;
6
+ num(): number;
7
+ }
@@ -0,0 +1,10 @@
1
+ export default class ServerSideContext {
2
+ async getData() {
3
+ return {
4
+ number: this.num()
5
+ };
6
+ }
7
+ num() {
8
+ return Math.floor(Math.random() * 100);
9
+ }
10
+ }
@@ -0,0 +1 @@
1
+ export declare const test: number;
@@ -0,0 +1 @@
1
+ export const test = 123;
@@ -0,0 +1 @@
1
+ export {};
package/build/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { Application } from "@structured/Application.js";
2
+ import { config } from './Config.js';
3
+ new Application(config);
@@ -0,0 +1,3 @@
1
+ import { HelperDelegate } from "handlebars";
2
+ declare const helpers: Record<string, HelperDelegate>;
3
+ export default helpers;
@@ -0,0 +1,72 @@
1
+ import { attributeValueToString, objectEach } from "./Util.js";
2
+ const helpers = {
3
+ htmlTag: function (...args) {
4
+ return `<${args[0]}></${args[0]}>`;
5
+ },
6
+ layoutComponent: function (...args) {
7
+ if (args.length < 2 || args.length > 4) {
8
+ console.warn('layoutComponent expects 1 - 3 arguments (componentName, data?, attributes?) got ' + (args.length - 1));
9
+ }
10
+ const argsUsed = args.slice(0, args.length - 1);
11
+ const componentName = argsUsed[0];
12
+ const data = argsUsed[1];
13
+ const attributes = argsUsed[2];
14
+ const dataAttributes = [];
15
+ let attributesString = '';
16
+ if (attributes) {
17
+ if (attributes) {
18
+ const attrNames = Object.keys(attributes);
19
+ attributesString = attrNames.map((attrName) => {
20
+ const val = attributes[attrName];
21
+ if (typeof val === 'string' || typeof val === 'number') {
22
+ return `${attrName}="${val}"`;
23
+ }
24
+ if (val === true) {
25
+ return attrName;
26
+ }
27
+ return null;
28
+ }).filter((val) => val !== null).join(' ');
29
+ }
30
+ }
31
+ if (data) {
32
+ objectEach(data, (key, val) => {
33
+ dataAttributes.push(`data-${key}="${attributeValueToString(key, val)}"`);
34
+ });
35
+ }
36
+ return `<${componentName} ${dataAttributes.length > 0 ? dataAttributes.join(' ') : ''} ${attributesString}></${componentName}>`;
37
+ },
38
+ json: function (...args) {
39
+ if (args.length > 1) {
40
+ if (typeof args[0] === 'object' && args[0] !== null) {
41
+ return JSON.stringify(args[0]);
42
+ }
43
+ return '';
44
+ }
45
+ return '';
46
+ },
47
+ attr: function (key, val) {
48
+ return `data-${key}="${attributeValueToString(key, val)}"`;
49
+ },
50
+ nl2br: function (...args) {
51
+ if (args.length === 1 && 'fn' in args[0]) {
52
+ return (args[0].fn(this) || '').replaceAll('\n', '<br>');
53
+ }
54
+ if (args.length === 2) {
55
+ if (typeof args[0] !== 'string') {
56
+ return '';
57
+ }
58
+ return args[0].replaceAll('\n', '<br>');
59
+ }
60
+ return '';
61
+ },
62
+ indent: function (...args) {
63
+ if (args.length === 1 && 'fn' in args[0]) {
64
+ return args[0].fn(this).replaceAll(' ', '&nbsp;').replaceAll('\t', '&nbsp;'.repeat(4));
65
+ }
66
+ if (args.length === 2) {
67
+ return args[0].replaceAll(' ', '&nbsp;').replaceAll('\t', '&nbsp;'.repeat(4));
68
+ }
69
+ return '';
70
+ }
71
+ };
72
+ export default helpers;
@@ -0,0 +1,3 @@
1
+ export declare const symbolSession: unique symbol;
2
+ export declare const symbolAny: unique symbol;
3
+ export declare const symbolArrays: unique symbol;
@@ -0,0 +1,3 @@
1
+ export const symbolSession = Symbol('session');
2
+ export const symbolAny = Symbol('*');
3
+ export const symbolArrays = Symbol.for('arrays');
@@ -0,0 +1,171 @@
1
+ import { IncomingMessage, ServerResponse } from "node:http";
2
+ import { Application } from "./server/Application.js";
3
+ import { symbolArrays } from "./Symbols.js";
4
+ import { RequestContextData } from "../app/Types.js";
5
+ import { Net } from './client/Net.js';
6
+ import { ClientComponent } from './client/ClientComponent.js';
7
+ import { Component } from "./server/Component.js";
8
+ export type StructuredConfig = {
9
+ readonly envPrefix?: string;
10
+ readonly autoInit: boolean;
11
+ url: {
12
+ removeTrailingSlash: boolean;
13
+ componentRender: false | string;
14
+ isAsset: (url: string) => boolean;
15
+ };
16
+ routes: {
17
+ readonly path: string;
18
+ };
19
+ components: {
20
+ readonly path: string;
21
+ readonly componentNameAttribute: string;
22
+ };
23
+ session: {
24
+ readonly cookieName: string;
25
+ readonly keyLength: number;
26
+ readonly durationSeconds: number;
27
+ readonly garbageCollectIntervalSeconds: number;
28
+ readonly garbageCollectAfterSeconds: number;
29
+ };
30
+ http: {
31
+ host?: string;
32
+ port: number;
33
+ linkHeaderRel: 'preload' | 'preconnect';
34
+ };
35
+ readonly runtime: 'Node.js' | 'Deno';
36
+ };
37
+ export type StructuredClientConfig = {
38
+ componentRender: StructuredConfig['url']['componentRender'];
39
+ componentNameAttribute: string;
40
+ };
41
+ export type RequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
42
+ export type RequestCallback = (ctx: RequestContext) => Promise<any>;
43
+ export type RequestHandler = {
44
+ match: Array<URISegmentPattern> | RegExp;
45
+ methods: Array<RequestMethod>;
46
+ callback: RequestCallback;
47
+ scope: any;
48
+ staticAsset: boolean;
49
+ };
50
+ export type RequestContext = {
51
+ request: IncomingMessage;
52
+ response: ServerResponse;
53
+ args: URIArguments;
54
+ handler: null | RequestHandler;
55
+ cookies: Record<string, string>;
56
+ body?: PostedDataDecoded;
57
+ bodyRaw?: Buffer;
58
+ files?: Record<string, RequestBodyRecordValue>;
59
+ data: RequestContextData;
60
+ sessionId?: string;
61
+ isAjax: boolean;
62
+ getArgs: PostedDataDecoded;
63
+ respondWith: (data: any) => void;
64
+ redirect: (to: string, statusCode?: number) => void;
65
+ show404: () => Promise<void>;
66
+ };
67
+ export type PostedDataDecoded = Record<string, string | boolean | Array<string | boolean | PostedDataDecoded> | Record<string, string | boolean | Array<string | boolean | PostedDataDecoded>> | Record<string, string | boolean | Array<string | boolean>>>;
68
+ export type RequestBodyRecordValue = string | Array<RequestBodyRecordValue> | {
69
+ [key: string]: RequestBodyRecordValue;
70
+ } | {
71
+ [key: string]: RequestBodyFile;
72
+ } | Array<RequestBodyFile> | RequestBodyFile;
73
+ export interface RequestBodyArguments {
74
+ [key: string]: RequestBodyRecordValue;
75
+ [symbolArrays]?: {
76
+ [key: string]: Array<string>;
77
+ };
78
+ }
79
+ export type RequestBodyFiles = {
80
+ [key: string]: RequestBodyFile;
81
+ };
82
+ export type RequestBodyFile = {
83
+ fileName: string;
84
+ data: Buffer;
85
+ type: string;
86
+ };
87
+ export type URISegmentPattern = {
88
+ pattern: string | RegExp;
89
+ name?: string;
90
+ type?: 'string' | 'number';
91
+ };
92
+ export type URIArguments = {
93
+ [key: string]: string | number | RegExpExecArray;
94
+ };
95
+ export type DocumentResource = {
96
+ path: string;
97
+ attributes: Record<string, string | null>;
98
+ priority: number;
99
+ };
100
+ export type ComponentEntry = {
101
+ name: string;
102
+ path: {
103
+ absolute: string;
104
+ relative: string;
105
+ relativeToViews: string;
106
+ build: string;
107
+ html: string;
108
+ jsServer?: string;
109
+ jsClient?: string;
110
+ };
111
+ hasJS: boolean;
112
+ html: string;
113
+ static: boolean;
114
+ module?: ComponentScaffold;
115
+ renderTagName?: string;
116
+ exportData: boolean;
117
+ exportFields?: Array<string>;
118
+ attributes?: Record<string, string>;
119
+ initializer?: InitializerFunction;
120
+ };
121
+ export interface ComponentScaffold {
122
+ tagName?: string;
123
+ exportData?: boolean;
124
+ exportFields?: Array<string>;
125
+ static?: boolean;
126
+ deferred?: (data: Record<string, any>, ctx: RequestContext | undefined, app: Application) => boolean;
127
+ attributes?: Record<string, string>;
128
+ getData: (this: ComponentScaffold, data: RequestBodyArguments | LooseObject, ctx: undefined | RequestContext, app: Application, component: Component) => Promise<LooseObject | null>;
129
+ [key: string]: any;
130
+ }
131
+ export type LooseObject = Record<string, any>;
132
+ export type ApplicationEvents = 'serverStarted' | 'beforeRequestHandler' | 'afterRequestHandler' | 'beforeRoutes' | 'afterRoutes' | 'beforeComponentLoad' | 'afterComponentLoad' | 'documentCreated' | 'beforeAssetAccess' | 'afterAssetAccess' | 'pageNotFound';
133
+ export type SessionEntry = {
134
+ sessionId: string;
135
+ lastRequest: number;
136
+ data: LooseObject;
137
+ };
138
+ export type ValidationRuleWithArguments = [string, any];
139
+ export type FormValidationEntry = {
140
+ field: [string, string];
141
+ rules: Array<string | ValidationRuleWithArguments | ValidatorFunction>;
142
+ };
143
+ export type ValidatorFunction = (data: PostedDataDecoded, field: string, arg: number, rules: Array<string | ValidationRuleWithArguments | ValidatorFunction>) => Promise<boolean>;
144
+ export type ValidatorErrorDecorator = (fieldHumanReadable: string, data: PostedDataDecoded, field: string, arg: any) => string | Promise<string>;
145
+ export type ValidationErrors = {
146
+ [field: string]: Array<string>;
147
+ };
148
+ export type ValidationErrorsSingle = {
149
+ [field: string]: string;
150
+ };
151
+ export type ValidationResult = {
152
+ valid: boolean;
153
+ errors: ValidationErrors | ValidationErrorsSingle;
154
+ };
155
+ export type InitializerFunction = (this: ClientComponent, ctx: InitializerFunctionContext) => Promise<void>;
156
+ export type Initializers = {
157
+ [key: string]: InitializerFunction;
158
+ };
159
+ export type InitializerFunctionContext = {
160
+ net: Net;
161
+ isRedraw: boolean;
162
+ };
163
+ export type StoreChangeCallback = (key: string, value: any, oldValue: any, componentId: string) => void;
164
+ export type AsteriskAny = '*';
165
+ export type ClientComponentTransition = {
166
+ fade: false | number;
167
+ slide: false | number;
168
+ };
169
+ export type ClientComponentTransitionEvent = 'show' | 'hide';
170
+ export type ClientComponentTransitions = Record<ClientComponentTransitionEvent, ClientComponentTransition>;
171
+ export type EventEmitterCallback = (payload: any) => void;
@@ -0,0 +1 @@
1
+ import { symbolArrays } from "./Symbols.js";
@@ -0,0 +1,20 @@
1
+ import { LooseObject, PostedDataDecoded } from "./Types.js";
2
+ export declare function queryStringDecode(queryString: string, initialValue?: PostedDataDecoded, trimValues?: boolean): PostedDataDecoded;
3
+ export declare function queryStringDecodedSetValue(obj: PostedDataDecoded | string, value: any): LooseObject;
4
+ export declare function objectEach<T>(obj: T, callbackEach: (key: keyof T, value: T[keyof T]) => void): void;
5
+ export declare function toCamelCase(dataKey: string, separator?: string): string;
6
+ export declare function toSnakeCase(str: string, joinWith?: string): string;
7
+ export declare function capitalize(str: string): string;
8
+ export declare function isAsync(fn: Function): boolean;
9
+ export declare function randomString(len: number): string;
10
+ export declare function unique<T>(arr: Array<T>): Array<T>;
11
+ export declare function stripTags(contentWithHTML: string, keepTags?: Array<string>): string;
12
+ export declare function attributeValueToString(key: string, value: any): string;
13
+ export declare function attributeValueFromString(attributeValue: string): string | {
14
+ key: string;
15
+ value: any;
16
+ };
17
+ export declare function attributeValueEscape(str: string): string;
18
+ export declare function isObject(item: any): boolean;
19
+ export declare function equalDeep(a: LooseObject, b: LooseObject): boolean;
20
+ export declare function mergeDeep(target: any, ...sources: Array<any>): LooseObject;