structured-fw 0.8.41 → 0.8.43

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 (90) hide show
  1. package/README.md +92 -10
  2. package/package.json +10 -3
  3. package/app/models/README.md +0 -9
  4. package/app/routes/README.md +0 -19
  5. package/app/views/README.md +0 -1
  6. package/app/views/layout.html +0 -1
  7. package/build/Config.d.ts +0 -2
  8. package/build/Config.js +0 -30
  9. package/build/app/Types.d.ts +0 -5
  10. package/build/app/Types.js +0 -1
  11. package/build/app/global.d.ts +0 -3
  12. package/build/app/global.js +0 -1
  13. package/build/app/models/Users.d.ts +0 -0
  14. package/build/app/models/Users.js +0 -1
  15. package/build/app/routes/Auth.d.ts +0 -0
  16. package/build/app/routes/Auth.js +0 -1
  17. package/build/app/routes/Test.d.ts +0 -2
  18. package/build/app/routes/Test.js +0 -101
  19. package/build/app/routes/Todo.d.ts +0 -0
  20. package/build/app/routes/Todo.js +0 -1
  21. package/build/app/routes/Upload.d.ts +0 -0
  22. package/build/app/routes/Upload.js +0 -1
  23. package/build/app/routes/Validation.d.ts +0 -2
  24. package/build/app/routes/Validation.js +0 -34
  25. package/build/app/routess/Auth.d.ts +0 -0
  26. package/build/app/routess/Auth.js +0 -1
  27. package/build/app/routess/Test.d.ts +0 -2
  28. package/build/app/routess/Test.js +0 -101
  29. package/build/app/routess/Todo.d.ts +0 -0
  30. package/build/app/routess/Todo.js +0 -1
  31. package/build/app/routess/Upload.d.ts +0 -0
  32. package/build/app/routess/Upload.js +0 -1
  33. package/build/app/routess/Validation.d.ts +0 -2
  34. package/build/app/routess/Validation.js +0 -34
  35. package/build/app/views/components/ClientImport/ClientImport.client.d.ts +0 -2
  36. package/build/app/views/components/ClientImport/ClientImport.client.js +0 -4
  37. package/build/app/views/components/ClientImport/Export.d.ts +0 -1
  38. package/build/app/views/components/ClientImport/Export.js +0 -1
  39. package/build/app/views/components/Conditionals/Conditionals.client.d.ts +0 -2
  40. package/build/app/views/components/Conditionals/Conditionals.client.js +0 -43
  41. package/build/app/views/components/FormTest/FormTestNested/FormTestNested.d.ts +0 -8
  42. package/build/app/views/components/FormTest/FormTestNested/FormTestNested.js +0 -7
  43. package/build/app/views/components/ModelsTest/ModelsTest.client.d.ts +0 -2
  44. package/build/app/views/components/ModelsTest/ModelsTest.client.js +0 -5
  45. package/build/app/views/components/MultipartForm/MultipartForm.client.d.ts +0 -0
  46. package/build/app/views/components/MultipartForm/MultipartForm.client.js +0 -1
  47. package/build/app/views/components/PassObject/PassObject.d.ts +0 -10
  48. package/build/app/views/components/PassObject/PassObject.js +0 -10
  49. package/build/app/views/components/PassObject/ReceiveObj/ReceiveObj.d.ts +0 -6
  50. package/build/app/views/components/PassObject/ReceiveObj/ReceiveObj.js +0 -6
  51. package/build/app/views/components/RedrawAbort/RedrawAbort.client.d.ts +0 -2
  52. package/build/app/views/components/RedrawAbort/RedrawAbort.client.js +0 -6
  53. package/build/app/views/components/RedrawAbort/RedrawAbort.d.ts +0 -8
  54. package/build/app/views/components/RedrawAbort/RedrawAbort.js +0 -8
  55. package/build/app/views/components/ServerSideContext/ServerSideContext.d.ts +0 -7
  56. package/build/app/views/components/ServerSideContext/ServerSideContext.js +0 -10
  57. package/build/assets/ts/Export.d.ts +0 -1
  58. package/build/assets/ts/Export.js +0 -1
  59. package/build/index.d.ts +0 -1
  60. package/build/index.js +0 -8
  61. package/build/tsconfig.tsbuildinfo +0 -1
  62. package/jsr.json +0 -35
  63. package/system/EventEmitter.ts +0 -38
  64. package/system/Helpers.ts +0 -97
  65. package/system/Symbols.ts +0 -6
  66. package/system/Types.ts +0 -232
  67. package/system/Util.ts +0 -488
  68. package/system/bin/structured.ts +0 -115
  69. package/system/client/App.ts +0 -11
  70. package/system/client/Client.ts +0 -9
  71. package/system/client/ClientComponent.ts +0 -1107
  72. package/system/client/DataStore.ts +0 -101
  73. package/system/client/DataStoreView.ts +0 -82
  74. package/system/client/Net.ts +0 -58
  75. package/system/client/NetRequest.ts +0 -64
  76. package/system/global.d.ts +0 -12
  77. package/system/server/Application.ts +0 -239
  78. package/system/server/Component.ts +0 -409
  79. package/system/server/Components.ts +0 -114
  80. package/system/server/Cookies.ts +0 -29
  81. package/system/server/Document.ts +0 -163
  82. package/system/server/DocumentHead.ts +0 -150
  83. package/system/server/FormValidation.ts +0 -231
  84. package/system/server/Handlebars.ts +0 -51
  85. package/system/server/Request.ts +0 -502
  86. package/system/server/Session.ts +0 -151
  87. package/system/server/dom/DOMFragment.ts +0 -7
  88. package/system/server/dom/DOMNode.ts +0 -140
  89. package/system/server/dom/HTMLParser.ts +0 -238
  90. package/tsconfig.json +0 -31
package/README.md CHANGED
@@ -347,13 +347,25 @@ app.request.on('GET', '/home', async (ctx) => {
347
347
  });
348
348
  ```
349
349
 
350
+ > [!TIP]
351
+ > Since version 0.8.4 Document extends EventEmitter, and "componentCreated" event is emitted whenever a component instance is created within the Document.\
352
+ > This makes the following possible:
353
+ > ```
354
+ > app.on('documentCreated', (doc) => {
355
+ > doc.on('componentCreated', (component) => {
356
+ > // do something with the document or the component
357
+ > })
358
+ > })
359
+ > ```
360
+
350
361
  ## Component
351
- A component is comprised of 1-3 files. It always must include one HTML file, while server side and client side files are optional.
362
+ A component is comprised of [1-3 files](#component-parts). It always must include one HTML file, while server side and client side files are optional.
352
363
  * HTML file probably requires no explanation
353
364
  * server side file, code that runs on the server and makes data available to HTML and client side code
354
365
  * client side file, code that runs on the client (in the browser)
355
366
 
356
- You should never need to instantiate a Component on your own. You will always load a Component representing your page into a document (using `Document.loadComponent(componentName: string)`), which will know what to do from there.
367
+ > [!TIP]
368
+ > You should never need to instantiate a Component on your own. You will always load a Component representing your page into a document (using `Document.loadComponent(componentName: string)`), which will know what to do from there.
357
369
 
358
370
  Example component files:
359
371
  - `/app/views/`
@@ -373,6 +385,12 @@ It is recommended, but not necessary, that you contain each component in it's ow
373
385
  - Components HTML file can have a `.hbs` extension (which allows for better Handlebars syntax highlighting)
374
386
  - Components can reside at any depth in the file structure
375
387
 
388
+ ### Component parts
389
+ - [Component HTML](#component-html) (_ComponentName.html_)
390
+ - [Component server-side code](#component-server-side-code) (_ComponentName.ts_)
391
+ - [Component client-side code](#component-client-side-code) (_ComponentName.client.ts_)
392
+
393
+ ### Component HTML
376
394
  Let's create a HelloWorld Component `/app/views/HelloWorld/HelloWorld.html`:\
377
395
  `Hello, World!`
378
396
 
@@ -392,7 +410,12 @@ export default function(app: Application) {
392
410
  You can now run the app and if you open /hello/world in the browser you will see:\
393
411
  `Hello, World!` - which came from your HelloWorld component.
394
412
 
395
- That was the simplest possible example, let's make it more interesting.
413
+ > [!TIP]
414
+ > It is recommended to use .hbs (Handlebars) extension as you will get better syntax highlighting in most IDEs. Other than syntax highlighting there is no difference between using html or hbs extension.
415
+
416
+ That was the simplest possible example, let's make it more interesting by adding some server-side code.
417
+
418
+ ### Component server-side code
396
419
  Create a new file `/app/views/HelloWorld/HelloWorld.ts` (server side component code):
397
420
  ```
398
421
  import { ComponentScaffold } from 'system/Types.js';
@@ -426,7 +449,15 @@ Your lucky number is [a number from 0-100]
426
449
  This demonstrates the use of a *server side component code* to make data available to HTML.
427
450
  We just generated a random number, but the data could be anything and will more often come from a database, session, or be provided by the parent component.
428
451
 
452
+ > [!IMPORTANT]
453
+ > Server side `getData` will receive the following arguments:
454
+ > - `data: LooseObject` any data passed in (either by attributes, ClientComponent.add or ClientComponent.redraw)
455
+ > - `ctx: RequestContext` - current `RequestContext`, you will often use this to access for example ctx.data (`RequestContextData`) or ctx.sessionId to interact with session
456
+ > - `app: Application` - your Application instance. You can use it to, for example, access the session in combination with ctx.sessionId
457
+
429
458
  Let's make it even more interesting by adding some client side code to it.
459
+
460
+ ### Component client-side code
430
461
  Create `/app/views/HelloWorld/HelloWorld.client.ts`:
431
462
  ```
432
463
  import { InitializerFunction } from 'system/Types.js';
@@ -509,12 +540,6 @@ What about client side? **By default, data returned by server side code is not a
509
540
  > [!NOTE]
510
541
  > Whenever a component with server-side code is rendered, `getData` is automatically called and anything it returns is available in HTML. You can export all returned data to client-side code by setting `exportData = true` or you can export some of the fields by setting `exportFields = ["field1", "field2", ...]` as a direct property of the class. To access the exported data from client-side use `ClientComponent`.`getData(key: string)` which will be `this.getData(key:string)` within client side code.
511
542
 
512
- > [!IMPORTANT]
513
- > Server side `getData` will receive the following arguments:
514
- > - `data: LooseObject` any data passed in (either by attributes, ClientComponent.add or ClientComponent.redraw)
515
- > - `ctx: RequestContext` - current `RequestContext`, you will often use this to access for example ctx.data (`RequestContextData`) or ctx.sessionId to interact with session
516
- > - `app: Application` - your Application instance. You can use it to, for example, access the session in combination with ctx.sessionId
517
-
518
543
  Let's create a client side code for `AnotherComponent` and export the `betterNumber` to it, create `/app/views/AnotherComponent/AnotherComponent.client.ts`:
519
544
  ```
520
545
  import { InitializerFunction } from 'system/Types.js';
@@ -611,13 +636,67 @@ Methods:
611
636
  - `query(componentName: string, recursive: boolean = true): Array<ClientComponent>` - return all components with given name found within this component, if `recursive = false`, only direct children are considered
612
637
  - `ref<T>(refName: string): T` - get a HTMLElement or ClientComponent that has attribute `ref="[refName]"`
613
638
  - `arrayRef<T>(refName: string): Array<T>` - get an array of HTMLElement or ClientComponent that have attribute `array:ref="[refName]"`
614
- - `add(appendTo: HTMLElement, componentName: string, data?: LooseObject)` - add `componentName` component to `appendTo` element, optionally passing `data` to the component when it's being rendered
639
+ - `add(appendTo: HTMLElement, componentName: string, data?: LooseObject): Promise<ClientComponent | null>` - add `componentName` component to `appendTo` element, optionally passing `data` to the component when it's being rendered. Returns a promise that resolves with added ClientComponent or null if something went wrong
640
+ - `redraw(data?: LooseObject): Promise<void>` - redraw the component, optionally provide data which will be available server side
641
+
642
+ ### Conditionals
643
+ You can make any DOM node within your components conditionally shown/hidden using `data-if` attribute.\
644
+ For example:
645
+ ```
646
+ <div data-if="showDiv"></div>
647
+ ```
648
+ Above div will only be shown if store.showDiv = true
649
+
650
+ You can also use `!` to invert the value, `!showDiv` in which case div would be shown if showDiv is false.
651
+
652
+ You can also use comparison:
653
+ ```
654
+ <div data-if="val === 1"></div>
655
+ <div data-if="val == 1"></div>
656
+ <div data-if="val !== 1"></div>
657
+ <div data-if="val != 1"></div>
658
+ <div data-if="val > 1"></div>
659
+ <div data-if="val < 1"></div>
660
+ <div data-if="val <= 1"></div>
661
+ <div data-if="val >= 1"></div>
662
+ ```
663
+
664
+ The right hand side of the comparison does not have to be boolean or number. It can be a string or any primitive value, but the numeric comparisons don't make sense in such case.
665
+
666
+ You can also define callbacks and use them as the condition, in you ComponentName.client.ts:
667
+ ```
668
+ import { InitializerFunction } from 'structured-fw/Types';
669
+ export const init: InitializerFunction = async function() {
670
+ this.conditionalCallback('showDiv', () => {
671
+ // return a boolean here
672
+ });
673
+ }
674
+ ```
675
+
676
+ then in ComponentName.html:
677
+ ```
678
+ <div data-if="showDiv()"></div>
679
+ ```
680
+
681
+ **Basic animation/transitions**\
682
+ If you use conditionals on any DOM node, you may also enable basic animations/transitions using following attributes:
683
+ - Enable transition:
684
+ - `data-transition-show-slide="durationMilliseconds"` - when DOM node is shown, slide it in
685
+ - `data-transition-hide-slide="durationMilliseconds"` - when DOM node is hidden, slide it out
686
+ - `data-transition-show-fade="durationMilliseconds"` - fade DOM node in
687
+ - `data-transition-hide-fade="durationMilliseconds"` - fade DOM node out
688
+ - Modify transition (slide only)
689
+ - `data-transform-origin-show="CSS transform origin"` - from where does the component slide in for example `0% 50%` to slide it in from mid-left
690
+ - `data-transform-origin-hide="CSS transform origin"` - where does the component slide out to for example `100% 100%` to slide it out to bottom-right
691
+ - `data-transition-axis-show="X | Y"` - slide animation axis
692
+ - `data-transition-axis-hide="X | Y"` - slide animation axis
615
693
 
616
694
  ## Good to know
617
695
  - [Using CSS frameworks](#css-frameworks)
618
696
  - [Using JS runtimes other than Node.js](#runtimes)
619
697
  - [Why not JSR](#jsr)
620
698
  - [Best practices](#best-practices)
699
+ - [Having an issue?](#issues-and-feedback)
621
700
 
622
701
  ### CSS frameworks
623
702
  We rarely write all CSS from scratch, usually we use a CSS framework to speed us up. Structured allows you to work with any CSS frameworks such as Tailwind, PostCSS or Bootstrap.
@@ -762,6 +841,9 @@ If you ran `npx structured init`, it has created /app/models for you. Structured
762
841
 
763
842
  You can create additional code separation, for example, it would make sense to have /app/lib for code that interfaces an API, or have /app/Util.ts where you export utility functions. Structured boilerplate does not include these as not all applications will need them.
764
843
 
844
+ ### Issues and feedback
845
+ If you have any issues with the framework or the npm package, please don't hesitate to open an issue on [github](https://github.com/julijan/structured). Feedback is also welcome!
846
+
765
847
  ## Why Structured
766
848
  Framework was developed by someone who has been a web developer for almost 20 years (me), and did not like the path web development has taken.
767
849
  \
package/package.json CHANGED
@@ -14,13 +14,12 @@
14
14
  "license": "MIT",
15
15
  "type": "module",
16
16
  "main": "build/index",
17
- "version": "0.8.41",
17
+ "version": "0.8.43",
18
18
  "scripts": {
19
19
  "develop": "tsc --watch",
20
20
  "startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,css index.js",
21
21
  "start": "cd build && node index.js",
22
- "prepublish": "tsc",
23
- "postinstall": "rm tsconfig.json"
22
+ "prepublish": "tsc"
24
23
  },
25
24
  "bin": {
26
25
  "structured": "./build/system/bin/structured.js"
@@ -35,6 +34,14 @@
35
34
  "mime-types": "^3.0.0",
36
35
  "ts-md5": "^1.3.1"
37
36
  },
37
+ "files": [
38
+ "build/system/*",
39
+ "app/Types.ts",
40
+ "index.ts",
41
+ "Config.ts",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
38
45
  "exports" : {
39
46
  "./Types": "./build/system/Types.js",
40
47
  "./Symbols": "./build/system/Symbols.js",
@@ -1,9 +0,0 @@
1
- You don't have to use this directory, but if you are keen on MVC concept, this would be the place for your models.
2
-
3
- There are not specific rules for these files. They are never loaded automaticallt by the framework, instead you should
4
- load them where you want to use them.
5
-
6
- Usually a model will export a class or a class instance, but it could be a function, set of functions, or anything really.
7
-
8
- Models are meant to abstract the logic and data layer for a specific entity of your app. For example a web shop would likely
9
- have a model Product.ts which exports a class with methods such as create(productData: ProductData) to create a new product and delete(productId: number) to delete an existing product.
@@ -1,19 +0,0 @@
1
- Routes:
2
-
3
- You can add routes directly in index.ts using app.request.on
4
- but in order to avoid clutter and keep the code structured, you should add the routes here (/app/routes)
5
-
6
- All files in this directory will be loaded once the server is started,
7
- so feel free to separate your routes in as many files as you feel makes sense, eg. it would make sense
8
- to have Auth.ts that would add routes for everything auth related, such as /login, /register, etc...
9
-
10
- Example:
11
-
12
- export default async function(app: Application) {
13
-
14
- app.request.on('GET', '/login', async (ctx) => {
15
- // ctx is a RequestContext
16
- ctx.response.write('Login page');
17
- });
18
-
19
- }
@@ -1 +0,0 @@
1
- Place for pages and components
@@ -1 +0,0 @@
1
- {{{layoutComponent component data attributes}}}
package/build/Config.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { StructuredConfig } from 'structured-fw/Types';
2
- export declare const config: StructuredConfig;
package/build/Config.js DELETED
@@ -1,30 +0,0 @@
1
- export const config = {
2
- envPrefix: 'STRUCTURED',
3
- autoInit: true,
4
- url: {
5
- removeTrailingSlash: true,
6
- componentRender: '/componentRender',
7
- isAsset: function (uri) {
8
- return uri.indexOf('/assets/') === 0;
9
- }
10
- },
11
- routes: {
12
- path: '/app/routes'
13
- },
14
- components: {
15
- path: '/app/views',
16
- componentNameAttribute: 'structured-component'
17
- },
18
- session: {
19
- cookieName: 'session',
20
- keyLength: 24,
21
- durationSeconds: 60 * 60,
22
- garbageCollectIntervalSeconds: 60
23
- },
24
- http: {
25
- port: 9191,
26
- host: '0.0.0.0',
27
- linkHeaderRel: 'preload'
28
- },
29
- runtime: 'Node.js'
30
- };
@@ -1,5 +0,0 @@
1
- export {};
2
- declare global {
3
- interface RequestContextData {
4
- }
5
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,3 +0,0 @@
1
- export interface RequestContextData {
2
- user: string;
3
- }
@@ -1 +0,0 @@
1
- export {};
File without changes
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,2 +0,0 @@
1
- import { Application } from '../../system/server/Application.js';
2
- export default function (app: Application): void;
@@ -1,101 +0,0 @@
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
- return 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
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,2 +0,0 @@
1
- import { Application } from "../../system/server/Application.js";
2
- export default function (app: Application): void;
@@ -1,34 +0,0 @@
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
- }
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,2 +0,0 @@
1
- import { Application } from '../../system/server/Application.js';
2
- export default function (app: Application): void;
@@ -1,101 +0,0 @@
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
@@ -1 +0,0 @@
1
- "use strict";
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,2 +0,0 @@
1
- import { Application } from "../../system/server/Application.js";
2
- export default function (app: Application): void;
@@ -1,34 +0,0 @@
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
- }
@@ -1,2 +0,0 @@
1
- import { InitializerFunction } from '../../../../system/Types.js';
2
- export declare const init: InitializerFunction;
@@ -1,4 +0,0 @@
1
- export const init = async function () {
2
- const test = await import('/assets/ts/Export.js');
3
- console.log(test);
4
- };
@@ -1 +0,0 @@
1
- export declare const test = 1;
@@ -1 +0,0 @@
1
- export const test = 1;
@@ -1,2 +0,0 @@
1
- import { InitializerFunction } from '../../../../system/Types.js';
2
- export declare const init: InitializerFunction;