structured-fw 0.8.1 → 0.8.21
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 +117 -1
- package/build/system/client/ClientComponent.d.ts +1 -7
- package/jsr.json +35 -0
- package/package.json +1 -1
- package/system/client/ClientComponent.ts +1 -11
- package/system/global.d.ts +12 -0
package/README.md
CHANGED
|
@@ -8,15 +8,20 @@ It works with Node.js and Deno runtimes. Other runtimes are not tested.
|
|
|
8
8
|
- [Why Structured](#why-structured)
|
|
9
9
|
- [Audience](#audience)
|
|
10
10
|
- [Getting started](#getting-started)
|
|
11
|
+
- [Key concepts](#key-concepts)
|
|
12
|
+
- [Good to know](#good-to-know)
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
### Key concepts:
|
|
13
16
|
* [Application](#application)
|
|
14
17
|
* [Route](#route)
|
|
15
18
|
* [Document](#document)
|
|
16
|
-
* [
|
|
19
|
+
* [Component](#component)
|
|
17
20
|
|
|
18
21
|
## Getting started
|
|
19
22
|
|
|
23
|
+
_Following getting started instructions are relevant for Node.js runtime, if you are using Deno skip to [runtimes](#runtimes) section._
|
|
24
|
+
|
|
20
25
|
### Initialize a Node.js project
|
|
21
26
|
```
|
|
22
27
|
cd /path/to/project
|
|
@@ -605,6 +610,117 @@ Methods:
|
|
|
605
610
|
- `arrayRef<T>(refName: string): Array<T>` - get an array of HTMLElement or ClientComponent that have attribute `array:ref="[refName]"`
|
|
606
611
|
- `add(appendTo: HTMLElement, componentName: string, data?: LooseObject)` - add `componentName` component to `appendTo` element, optionally passing `data` to the component when it's being rendered
|
|
607
612
|
|
|
613
|
+
## Good to know
|
|
614
|
+
- [Uing CSS frameworks](#css-frameworks)
|
|
615
|
+
- [Using JS runtimes other than Node.js](#runtimes)
|
|
616
|
+
- [Why not JSR](#jsr)
|
|
617
|
+
|
|
618
|
+
### CSS frameworks
|
|
619
|
+
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.
|
|
620
|
+
|
|
621
|
+
Your Tailwind configuration may look something like:
|
|
622
|
+
```
|
|
623
|
+
/** @type {import('tailwindcss').Config} */
|
|
624
|
+
module.exports = {
|
|
625
|
+
content: ["./app/views/**/*.html", "./app/views/**/*.hbs"],
|
|
626
|
+
...
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
Above we just defined where all our HTML resides, which is within /app/views. That is all there is to it. From there, you can generate the CSS, for example:\
|
|
631
|
+
`npx tailwindcss -i ./assets/css/src/style.css -o ./assets/css/dist.css`
|
|
632
|
+
|
|
633
|
+
**Including the output CSS**\
|
|
634
|
+
To include the output CSS in all pages, you can add the following to `index.ts`:
|
|
635
|
+
```
|
|
636
|
+
const app = new Application(config);
|
|
637
|
+
|
|
638
|
+
app.on('documentCreated', (doc) => {
|
|
639
|
+
doc.head.addCSS('/assets/css/dist.css');
|
|
640
|
+
});
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Runtimes
|
|
644
|
+
Structured is tested with Node.js and Deno. Other runtimes would likely work as well.
|
|
645
|
+
|
|
646
|
+
To use Structured with Deno, you can:
|
|
647
|
+
```
|
|
648
|
+
cd /path/to/project
|
|
649
|
+
deno init
|
|
650
|
+
deno add npm:structured-fw
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
With Deno, we can't use the cli to create the boilerplate, so you will need to create it yourself.
|
|
654
|
+
```
|
|
655
|
+
mkdir app
|
|
656
|
+
mkdir app/views
|
|
657
|
+
mkdir app/routes
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
Create `Config.ts`:
|
|
661
|
+
```
|
|
662
|
+
import { StructuredConfig } from "structured-fw/Types";
|
|
663
|
+
|
|
664
|
+
export const config: StructuredConfig = {
|
|
665
|
+
// Application.importEnv will load all env variables starting with [envPrefix]_
|
|
666
|
+
envPrefix: 'STRUCTURED',
|
|
667
|
+
|
|
668
|
+
// whether to call Application.init when an instance of Application is created
|
|
669
|
+
autoInit: true,
|
|
670
|
+
|
|
671
|
+
url: {
|
|
672
|
+
removeTrailingSlash: true,
|
|
673
|
+
|
|
674
|
+
// if you want to enable individual component rendering set this to URI (string)
|
|
675
|
+
// to disable component rendering set it to false
|
|
676
|
+
// setting this to false disallows the use of ClientComponent.redraw and ClientComponent.add
|
|
677
|
+
componentRender: '/componentRender',
|
|
678
|
+
|
|
679
|
+
// function that receives the requested URL and returns boolean, if true, treat as static asset
|
|
680
|
+
// if there is a registered request handler that matches this same URL, it takes precedence over this
|
|
681
|
+
isAsset: function(uri: string) {
|
|
682
|
+
return uri.indexOf('/assets/') === 0;
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
routes: {
|
|
686
|
+
path: '/app/routes'
|
|
687
|
+
},
|
|
688
|
+
components : {
|
|
689
|
+
// relative to index.ts
|
|
690
|
+
path: '/app/views',
|
|
691
|
+
|
|
692
|
+
componentNameAttribute: 'structured-component'
|
|
693
|
+
},
|
|
694
|
+
session: {
|
|
695
|
+
cookieName: 'session',
|
|
696
|
+
keyLength: 24,
|
|
697
|
+
durationSeconds: 60 * 60,
|
|
698
|
+
garbageCollectIntervalSeconds: 60
|
|
699
|
+
},
|
|
700
|
+
http: {
|
|
701
|
+
port: 9191,
|
|
702
|
+
host: '0.0.0.0',
|
|
703
|
+
// used by Document.push, can be preload or preconnect
|
|
704
|
+
linkHeaderRel : 'preload'
|
|
705
|
+
},
|
|
706
|
+
runtime: 'Deno'
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
Import `Config.ts` in `main.ts` and create the Application instance:
|
|
711
|
+
```
|
|
712
|
+
import { Application } from 'structured-fw/Application';
|
|
713
|
+
import { config } from './Config.ts';
|
|
714
|
+
|
|
715
|
+
new Application(config);
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
Run application using `deno main.ts`
|
|
719
|
+
|
|
720
|
+
### JSR
|
|
721
|
+
It would make a lot of sense to have Structured hosted on JSR (JavaScript Registry) given Structured is a TypeScript framework, and JSR is a TypeScript-first registry, however, the issue is that Deno imposes [limitations with dynamic imports](https://docs.deno.com/deploy/api/dynamic-import/) with JSR-imported dependencies, which are required for the framework (to dynamically import your routes and components).\
|
|
722
|
+
This does not stop the framework from working with Deno, but for the time being, we have to stick with good old npm.
|
|
723
|
+
|
|
608
724
|
## Why Structured
|
|
609
725
|
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.
|
|
610
726
|
\
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LooseObject } from '../Types.js';
|
|
2
2
|
import { DataStoreView } from './DataStoreView.js';
|
|
3
3
|
import { DataStore } from './DataStore.js';
|
|
4
4
|
import { Net } from './Net.js';
|
|
5
5
|
import { EventEmitter } from './EventEmitter.js';
|
|
6
|
-
declare global {
|
|
7
|
-
interface Window {
|
|
8
|
-
initializers: Record<string, InitializerFunction | string>;
|
|
9
|
-
structuredClientConfig: StructuredClientConfig;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
6
|
export declare class ClientComponent extends EventEmitter {
|
|
13
7
|
readonly name: string;
|
|
14
8
|
children: Array<ClientComponent>;
|
package/jsr.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@structured/structured-fw",
|
|
3
|
+
"version": "0.8.21",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"exports" : {
|
|
6
|
+
"./Types": "./system/Types.ts",
|
|
7
|
+
"./Symbols": "./system/Symbols.ts",
|
|
8
|
+
"./Util": "./system/Util.ts",
|
|
9
|
+
"./Application": "./system/server/Application.ts",
|
|
10
|
+
"./Document": "./system/server/Document.ts",
|
|
11
|
+
"./FormValidation": "./system/server/FormValidation.ts",
|
|
12
|
+
"./ClientComponent": "./system/client/ClientComponent.ts"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"handlebars": "^4.7.8",
|
|
16
|
+
"mime-types": "^3.0.0",
|
|
17
|
+
"ts-md5": "^1.3.1",
|
|
18
|
+
"@types/node": "^22.9.3",
|
|
19
|
+
"@types/mime-types": "^2.1.4"
|
|
20
|
+
},
|
|
21
|
+
"exclude": [
|
|
22
|
+
"build",
|
|
23
|
+
"assets",
|
|
24
|
+
"node_modules",
|
|
25
|
+
"tsconfig.json",
|
|
26
|
+
"package.json",
|
|
27
|
+
"package.lock.json",
|
|
28
|
+
"tailwind.config.cjs",
|
|
29
|
+
".vscode",
|
|
30
|
+
"app/Types.ts",
|
|
31
|
+
"app/views/*",
|
|
32
|
+
"app/routes/*",
|
|
33
|
+
"app/models/*"
|
|
34
|
+
]
|
|
35
|
+
}
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"main": "build/index",
|
|
17
|
-
"version": "0.8.
|
|
17
|
+
"version": "0.8.21",
|
|
18
18
|
"scripts": {
|
|
19
19
|
"develop": "tsc --watch",
|
|
20
20
|
"startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,css index.js",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientComponentTransition, ClientComponentTransitions, InitializerFunction, LooseObject, StoreChangeCallback
|
|
1
|
+
import { ClientComponentTransition, ClientComponentTransitions, InitializerFunction, LooseObject, StoreChangeCallback } from '../Types.js';
|
|
2
2
|
import { attributeValueFromString, attributeValueToString, mergeDeep, objectEach, queryStringDecodedSetValue, toCamelCase } from '../Util.js';
|
|
3
3
|
import { DataStoreView } from './DataStoreView.js';
|
|
4
4
|
import { DataStore } from './DataStore.js';
|
|
@@ -6,16 +6,6 @@ import { Net } from './Net.js';
|
|
|
6
6
|
import { NetRequest } from './NetRequest.js';
|
|
7
7
|
import { EventEmitter } from './EventEmitter.js';
|
|
8
8
|
|
|
9
|
-
// window.initializers will always be present
|
|
10
|
-
// each Document has a list of initializers used in components within it
|
|
11
|
-
// and they will be output as initializers = { componentName : initializer }
|
|
12
|
-
declare global {
|
|
13
|
-
interface Window {
|
|
14
|
-
initializers: Record<string, InitializerFunction | string>;
|
|
15
|
-
structuredClientConfig: StructuredClientConfig;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
9
|
export class ClientComponent extends EventEmitter {
|
|
20
10
|
readonly name: string;
|
|
21
11
|
children: Array<ClientComponent> = [];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InitializerFunction, StructuredClientConfig } from "./Types.js";
|
|
2
|
+
|
|
3
|
+
export {}
|
|
4
|
+
// window.initializers will always be present
|
|
5
|
+
// each Document has a list of initializers used in components within it
|
|
6
|
+
// and they will be output as initializers = { componentName : initializer }
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
initializers: Record<string, InitializerFunction | string>;
|
|
10
|
+
structuredClientConfig: StructuredClientConfig;
|
|
11
|
+
}
|
|
12
|
+
}
|