structured-fw 0.7.6 → 0.7.8

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
@@ -7,32 +7,274 @@ It works with Node.js and Deno runtimes. Other runtimes are not tested.
7
7
 
8
8
  - [Why Structured](#why-structured)
9
9
  - [Audience](#audience)
10
-
10
+ - [Getting started](#getting-started)
11
11
 
12
12
  ### Key concepts:
13
+ * [Application](#application)
13
14
  * [Route](#route)
14
15
  * [Document](#document)
15
16
  * [ClientComponent](#component) (component)
16
17
 
18
+ ## Getting started
19
+
20
+ ### Initialize a Node.js project
21
+ ```
22
+ cd /path/to/project
23
+ npm init -y
24
+ npm install @types/node
25
+ ```
26
+
27
+ *If you have TypeScript installed globally then you can skip the following*\
28
+ `npm install --save-dev typescript`
29
+
30
+ ### Install Structured
31
+ `npm install structured-fw`
32
+
33
+ ### Create boilerplate
34
+ `npx structured init`
35
+
36
+ ### Compile
37
+ `tsc`\
38
+ This will create a directory `build` (or whatever you have in tsconfig.json as compilerOptions.outputDir)
39
+
40
+ ### Run
41
+ ```
42
+ cd build
43
+ node index.js
44
+ ```
45
+
46
+ Of course, you can use pm2 or other process managers to run it, with pm2:
47
+ ```
48
+ cd build
49
+ pm2 start index.js --name="[appName]"
50
+ ```
51
+
52
+ # Key concepts
53
+
54
+ ## Application
55
+ Application instance is the base of any Structured application. You will usually create an instance of Application in index.ts (or whatever you decide to be the entry point file name). Application starts a http server, creates instances of all classes that are required for the functioning of your application and allows handling of various events that will occur when your app is running.\
56
+ Application constructor requires one argument of type `StructuredConfig`:
57
+ ```
58
+ type StructuredConfig = {
59
+ readonly envPrefix?: string,
60
+ readonly autoInit: boolean,
61
+ url: {
62
+ removeTrailingSlash: boolean,
63
+ componentRender: false | string,
64
+ isAsset: (url: string) => boolean
65
+ },
66
+ routes: {
67
+ readonly path: string
68
+ },
69
+ components: {
70
+ readonly path: string,
71
+ readonly componentNameAttribute: string
72
+ },
73
+ session: {
74
+ readonly cookieName: string,
75
+ readonly keyLength: number,
76
+ readonly durationSeconds: number,
77
+ readonly garbageCollectIntervalSeconds: number,
78
+ readonly garbageCollectAfterSeconds: number
79
+ },
80
+ http: {
81
+ host?: string,
82
+ port: number,
83
+ linkHeaderRel: 'preload' | 'preconnect'
84
+ },
85
+ readonly runtime: 'Node.js' | 'Deno'
86
+ }
87
+ ```
88
+
89
+ If you created the boilerplate using `npx structured init` then a sample `Config.ts` has been created in the project root. You can read the comments there if you need clarification on what each config option affects.
90
+
91
+ The most basic entry point may look something like this:
92
+ ```
93
+ import { Application } from "structured-fw/Application";
94
+ import { config } from "./Config.js";
95
+
96
+ new Application(config);
97
+ ```
98
+
99
+ ### Properties
100
+ - `cookies` - Instance of Cookies, allows you to set a cookie
101
+ - `session` - Instance of Session, utilities to manage sessions and data
102
+ - `request` - Instance of Request, you will use this to add routes, but usually not directly by accessing Application.request, more on that in [routes](#route) section
103
+ - `handlebars` - Instance of Handlebars (wrapper around Handlebars templating engine)
104
+ - `components` - Instance of Components, this is the components registry, you should never need to use this directly
105
+
106
+ ### Methods
107
+ - `init(): Promise<void>` - initializes application, you only need to run this if you set `autoInit = false` in config, otherwise this will be ran when you create the Application instance
108
+ - `on(evt: ApplicationEvents, callback: RequestCallback|((payload?: any) => void))` - allows you to add event listeners for specific `ApplicationEvenets`:
109
+ - `serverStarted` - executed once the built-in http server is started and running. Callback receives no arguments
110
+ - `beforeRequestHandler` - runs before any request handler (route) is executed. Callback receives `RequestContext` as the first argument. Useful for example to set `RequestContext.data: RequestContextData` (user defined data, to make it available to routes and components)
111
+ - `afterRequestHandler` - runs after any request handler (route) is executed. Callback receives `RequestContext` as the first argument
112
+ - `afterRoutes` - runs after all routes are loaded from `StructuredConfig.routes.path`. Callback receives no arguments
113
+ - `beforeComponentLoad` - runs before components are loaded from `StructuredConfig.components.path`. Callback receives no arguments
114
+ - `afterComponentLoad` - runs after all components are loaded from `StructuredConfig.components.path`. Callback receives no arguments
115
+ - `documentCreated` - runs whenever an instance of a [Document](#document) is created. Callback receives the Document instance as the first argument. You will often use this, for example if you want to include a CSS file to all pages `Document.head.addCSS(...)`
116
+ - `beforeAssetAccess` - runs when assets are being accessed, before response is sent. Callback receives `RequestContext` as the first argument
117
+ - `afterAssetAccess` - runs when assets are being accessed, after response is sent. Callback receives `RequestContext` as the first argument
118
+ - `pageNotFound` - runs when a request is received for which there is no registered request handler (route), and the requested URL is not an asset. Callback receives `RequestContext` as the first argument
119
+ - **Callback to any of the `ApplicationEvents` is expected to be an async function**
120
+ - `importEnv<T extends LooseObject>(smartPrimitives: boolean = true): T` - import ENV variables that start with `StructuredConfig.envPrefix`_ (if envPrefix is omitted from config, all ENV variables are returned). It is a generic method so that you can specify the expected return type. If `smartPrimitives = true` importEnv will convert the ENV values to type it feels is appropriate:
121
+ - numeric values -> `number`
122
+ - "true"|"false" -> `boolean`
123
+ - "null" -> `null`
124
+ - "undefined" -> `undefined`
125
+ - `exportContextFields(...fields: Array<keyof RequestContextData>): void` - allows you to export any fields from `RequestContextData` to all components (even if they don't have server side code)
126
+
127
+ What your entry point may look like in a real-world application:
128
+ ```
129
+ import { Application } from "structured-fw/Application";
130
+ import { config } from './Config.js';
131
+ import { userModel } from './app/models/User.js';
132
+
133
+ const app = new Application(config);
134
+
135
+ const env = app.importEnv<{ COOKIE_AUTOLOGIN: string }>();
136
+
137
+ app.on('documentCreated', (doc: Document) => {
138
+ doc.head.setFavicon({
139
+ image: '/assets/img/favicon.png',
140
+ type: 'image/png'
141
+ });
142
+ doc.head.addCSS('/assets/css/dist.css', 0);
143
+ });
144
+
145
+ app.on('beforeRequestHandler', async (ctx: RequestContext) => {
146
+
147
+ // set ctx.data.user from session
148
+ ctx.data.user = app.session.getValue<User>(ctx.sessionId, 'user');
149
+
150
+ if (! ctx.data.user) {
151
+ // check if user has an autologinKey cookie set
152
+ const autologinCookie = ctx.cookies[env.COOKIE_AUTOLOGIN];
153
+ if (autologinCookie) {
154
+ const user = await userModel.getByAutologinKey(autologinCookie);
155
+ if (user) {
156
+ ctx.data.user = user;
157
+ }
158
+ }
159
+ }
160
+ });
161
+
162
+ // load handlebars helpers (which will become available in all components)
163
+ app.handlebars.loadHelpers(path.resolve('./app/Helpers.js'));
164
+
165
+ // make user available to all components
166
+ app.exportContextFields('user');
167
+
168
+ ```
169
+
17
170
  ## Route
18
171
  Routes are the first thing that gets executed when your application receives a request. They are a mean for the developer to dictate what code gets executed depending on the URL. In addition to that, they allow capturing parts of the URL for use within the route.
19
- \
20
- \
172
+
173
+
174
+ You can add routes from your entry point using `app.request.on(RequestMethod, URLPattern, requestHandler)`, but you will never want to do that unless your entire application has a very few routes, in which case it would be acceptable.
175
+
21
176
  **Simple route:**
22
177
  ```
23
178
  app.request.on('GET', '/hello/world', async () => {
24
179
  return 'Hello, world!';
25
180
  });
26
181
  ```
27
- \
28
- **Capture URL segment:**
182
+
183
+
184
+ In a real life situation, you will likely have quite a few routes that you want to handle, and it usually makes sense to group them in multiple files, for example Auth.ts, Users.ts, Products.ts, etc...
185
+ When Application instance is created and initialized, it will load all routes from `conf.routes.path`.
186
+
187
+ All route files need to export a function that will receive the Application instance as the first argument:
188
+ ```
189
+ import { Application } from "structured-fw/Application";
190
+
191
+ export default function(app: Application) {
192
+ // all routes that belong to this file come here
193
+ app.request.on(...)
194
+ }
195
+ ```
196
+
197
+ Route file name has no effect on how the route (request handler) behaves, the only purpose of splitting your routes in separate files is making your code more maintainable.
198
+
199
+ ### RequestContext
200
+ All request handlers receive a `RequestContext` as the first argument.
201
+ ```
202
+ type RequestContext = {
203
+ request: IncomingMessage,
204
+ response: ServerResponse,
205
+ args: URIArguments,
206
+ handler: null|RequestHandler,
207
+
208
+ cookies: Record<string, string>,
209
+
210
+ // POSTed data, parsed to object
211
+ body?: PostedDataDecoded,
212
+
213
+ bodyRaw?: Buffer,
214
+
215
+ // files extracted from request body
216
+ files?: Record<string, RequestBodyRecordValue>,
217
+
218
+ // user defined data
219
+ data: RequestContextData,
220
+
221
+ // if session is started and user has visited any page
222
+ sessionId?: string,
223
+
224
+ // true if x-requested-with header is received and it equals 'xmlhttprequest'
225
+ isAjax: boolean,
226
+
227
+ // URL GET arguments
228
+ getArgs: PostedDataDecoded,
229
+
230
+ // send given data as a response
231
+ respondWith: (data: any) => void,
232
+
233
+ // redirect to given url, with given statusCode
234
+ redirect: (to: string, statusCode?: number) => void,
235
+
236
+ // show a 404 page
237
+ show404: () => Promise<void>
238
+ }
239
+ ```
240
+
241
+ **Capture URL segment:**\
242
+ Any URL segments in parenthesis will become available in ctx.args. For example:
29
243
  ```
30
244
  app.request.on('GET', '/greet/(name)', async (ctx) => {
31
245
  return `Hello, ${ctx.args.name}!`;
32
246
  });
33
247
  ```
248
+ You can capture any number of URL segments in this way.
249
+
250
+ **Capture group modifiers:**\
251
+ Capture group in URL pattern is (name) in above example. It makes data available within your route. Name will capture any string. Sometimes we know we expect a number in our URLs, in which case it is useful to use the modifier :num (which is the only modifier available), for example:
252
+ ```
253
+ app.request.on('GET', '/greet/(userId:num)', async (ctx) => {
254
+ const userId = ctx.args.userId as number;
255
+ // fetch user from DB
256
+ const user = await userModel.get(userId);
257
+ return `Hello, ${user.name}!`;
258
+ });
259
+ ```
260
+ It is safe to cast `ctx.args.userId` as `number` in above example because the route would not get executed if the second segment of the URL is not a numeric value, and in case :num modifier is used, URL-provided value is parsed to a number and you don't need to parseInt manually.
34
261
 
35
262
 
263
+ **Doing more with less code**\
264
+ You can have the same route be executed for multiple different request methods or URLs. Both request method (first argument) and URL pattern (second argument) can be an array.
265
+ ```
266
+ app.request.on(['GET', 'POST'], ['/greet/(name)', '/hello/(name)'], async (ctx) => {
267
+ return `Hello, ${ctx.args.name}!`;
268
+ });
269
+ ```
270
+ Above is equivalent of registering 4 request handlers one-by-one:\
271
+ GET '/greet/(name)'\
272
+ POST '/greet/(name)'\
273
+ GET '/hello/(name)'\
274
+ POST '/hello/(name)'
275
+
276
+ **RegExp as URLPatter**\
277
+ In some edge cases you may need more control of when a route is executed, in which case you can use a regular expression as URLPattern. If you use a RegExp, ctx.args will be `RegExpExecArray` so you can still capture data from the URL. This is very rarely needed because Structured router is versatile and covers almost all use cases.
36
278
 
37
279
  ## Document
38
280
  Document does not differ much from a component, in fact, it extends Component. It has a more user-firendly API than Component. Each Document represents a web page. It has a head and body. Structured intentionally does not differentiate between a page and a Component - page is just a component that loads many other components in a desired layout. DocumentHead (each document has one at Document.head) allows adding content to `<head>` section of the output HTML page.
package/app/Types.ts CHANGED
@@ -1 +1,7 @@
1
- export type RequestContextData = {}
1
+ export {}
2
+
3
+ declare global {
4
+ interface RequestContextData {
5
+ // definition for RequestContext.data here
6
+ }
7
+ }
@@ -1 +1,5 @@
1
- export type RequestContextData = {};
1
+ export {};
2
+ declare global {
3
+ interface RequestContextData {
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ export interface RequestContextData {
2
+ user: string;
3
+ }
@@ -0,0 +1 @@
1
+ export {};
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,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
+ }
@@ -1,7 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from "node:http";
2
2
  import { Application } from "./server/Application.js";
3
3
  import { symbolArrays } from "./Symbols.js";
4
- import { RequestContextData } from "../app/Types.js";
5
4
  import { Net } from './client/Net.js';
6
5
  import { ClientComponent } from './client/ClientComponent.js';
7
6
  import { Component } from "./server/Component.js";
@@ -1,11 +1,11 @@
1
1
  import { Server } from 'node:http';
2
- import { ApplicationEvents, LooseObject, RequestCallback, StructuredConfig } from '../Types';
2
+ import { ApplicationEvents, LooseObject, RequestContext, StructuredConfig } from '../Types';
3
+ import { Document } from './Document.js';
3
4
  import { Components } from './Components.js';
4
5
  import { Session } from './Session.js';
5
6
  import { Request } from './Request.js';
6
7
  import { Handlebars } from './Handlebars.js';
7
8
  import { Cookies } from './Cookies.js';
8
- import { RequestContextData } from '../../app/Types.js';
9
9
  export declare class Application {
10
10
  readonly config: StructuredConfig;
11
11
  server: null | Server;
@@ -19,8 +19,8 @@ export declare class Application {
19
19
  readonly exportedRequestContextData: Array<keyof RequestContextData>;
20
20
  constructor(config: StructuredConfig);
21
21
  init(): Promise<void>;
22
- start(): Promise<void>;
23
- on(evt: ApplicationEvents, callback: RequestCallback | ((payload?: any) => void)): void;
22
+ private start;
23
+ on<E extends ApplicationEvents>(evt: E, callback: (payload: E extends 'beforeRequestHandler' | 'afterRequestHandler' | 'beforeAssetAccess' | 'afterAssetAccess' | 'pageNotFound' ? RequestContext : E extends 'documentCreated' ? Document : undefined) => void): void;
24
24
  emit(eventName: ApplicationEvents, payload?: any): Promise<Array<any>>;
25
25
  importEnv<T extends LooseObject>(smartPrimitives?: boolean): T;
26
26
  exportContextFields(...fields: Array<keyof RequestContextData>): void;
@@ -9,6 +9,9 @@ export class Components {
9
9
  loadComponents(relativeToPath) {
10
10
  if (relativeToPath === undefined) {
11
11
  relativeToPath = path.resolve((this.config.runtime === 'Node.js' ? '../' : './') + this.config.components.path);
12
+ if (!existsSync(relativeToPath)) {
13
+ throw new Error(`Components path not found, expected to find:\n${relativeToPath}`);
14
+ }
12
15
  }
13
16
  const components = readdirSync(relativeToPath);
14
17
  components.forEach(async (component) => {
@@ -293,10 +293,13 @@ export class Request {
293
293
  else {
294
294
  routesPath = path.resolve((this.app.config.runtime === 'Node.js' ? '../build/' : './') + this.app.config.routes.path);
295
295
  }
296
+ if (!existsSync(routesPath)) {
297
+ throw new Error(`Routes path not found, expected to find:\n${routesPath}`);
298
+ }
296
299
  const files = readdirSync(routesPath);
297
300
  for (let i = 0; i < files.length; i++) {
298
301
  const file = files[i];
299
- if (!(file.endsWith('.js') || file.endsWith('.ts'))) {
302
+ if (!(file.endsWith('.js') || file.endsWith('.ts')) || file.endsWith('.d.ts')) {
300
303
  continue;
301
304
  }
302
305
  const filePath = path.resolve(routesPath + '/' + file);
@@ -0,0 +1 @@
1
+ {"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2021.d.ts","../node_modules/typescript/lib/lib.dom.d.ts","../node_modules/typescript/lib/lib.dom.iterable.d.ts","../node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../node_modules/typescript/lib/lib.scripthost.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.es2021.promise.d.ts","../node_modules/typescript/lib/lib.es2021.string.d.ts","../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../node_modules/typescript/lib/lib.es2021.intl.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../node_modules/typescript/lib/lib.es2021.full.d.ts","../node_modules/handlebars/types/index.d.ts","../node_modules/@types/mime-types/index.d.ts","../node_modules/ts-md5/dist/esm/md5.d.ts","../node_modules/ts-md5/dist/esm/md5_file_hasher.d.ts","../node_modules/ts-md5/dist/esm/parallel_hasher.d.ts","../node_modules/ts-md5/dist/esm/index.d.ts","../system/server/DocumentHead.ts","../system/server/dom/HTMLParser.ts","../system/server/dom/DOMNode.ts","../system/server/dom/DOMFragment.ts","../system/server/Component.ts","../system/server/Document.ts","../system/server/Components.ts","../system/server/Session.ts","../system/server/Request.ts","../system/server/Handlebars.ts","../system/server/Cookies.ts","../system/server/Application.ts","../system/Symbols.ts","../system/client/NetRequest.ts","../system/client/Net.ts","../system/client/DataStore.ts","../system/client/DataStoreView.ts","../system/client/EventEmitter.ts","../system/client/ClientComponent.ts","../system/Types.ts","../system/Util.ts","../system/Helpers.ts","../system/client/App.ts","../system/client/Client.ts","../system/server/FormValidation.ts","../app/Types.ts","../app/global.d.ts","../app/models/Users.ts","../app/routes/Auth.ts","../app/routes/Test.ts","../app/routes/Todo.ts","../app/routes/Upload.ts","../app/routes/Validation.ts","../assets/ts/Export.ts","../app/views/components/ClientImport/ClientImport.client.ts","../app/views/components/ClientImport/Export.ts","../app/views/components/Conditionals/Conditionals.client.ts","../app/views/components/FormTest/FormTestNested/FormTestNested.ts","../app/views/components/ModelsTest/ModelsTest.client.ts","../app/views/components/MultipartForm/MultipartForm.client.ts","../app/views/components/PassObject/PassObject.ts","../app/views/components/PassObject/ReceiveObj/ReceiveObj.ts","../app/views/components/RedrawAbort/RedrawAbort.client.ts","../app/views/components/RedrawAbort/RedrawAbort.ts","../app/views/components/ServerSideContext/ServerSideContext.ts","../Config.ts","../index.ts","../node_modules/@types/node/compatibility/disposable.d.ts","../node_modules/@types/node/compatibility/indexable.d.ts","../node_modules/@types/node/compatibility/iterators.d.ts","../node_modules/@types/node/compatibility/index.d.ts","../node_modules/@types/node/globals.typedarray.d.ts","../node_modules/@types/node/buffer.buffer.d.ts","../node_modules/undici-types/header.d.ts","../node_modules/undici-types/readable.d.ts","../node_modules/undici-types/file.d.ts","../node_modules/undici-types/fetch.d.ts","../node_modules/undici-types/formdata.d.ts","../node_modules/undici-types/connector.d.ts","../node_modules/undici-types/client.d.ts","../node_modules/undici-types/errors.d.ts","../node_modules/undici-types/dispatcher.d.ts","../node_modules/undici-types/global-dispatcher.d.ts","../node_modules/undici-types/global-origin.d.ts","../node_modules/undici-types/pool-stats.d.ts","../node_modules/undici-types/pool.d.ts","../node_modules/undici-types/handlers.d.ts","../node_modules/undici-types/balanced-pool.d.ts","../node_modules/undici-types/agent.d.ts","../node_modules/undici-types/mock-interceptor.d.ts","../node_modules/undici-types/mock-agent.d.ts","../node_modules/undici-types/mock-client.d.ts","../node_modules/undici-types/mock-pool.d.ts","../node_modules/undici-types/mock-errors.d.ts","../node_modules/undici-types/proxy-agent.d.ts","../node_modules/undici-types/env-http-proxy-agent.d.ts","../node_modules/undici-types/retry-handler.d.ts","../node_modules/undici-types/retry-agent.d.ts","../node_modules/undici-types/api.d.ts","../node_modules/undici-types/interceptors.d.ts","../node_modules/undici-types/util.d.ts","../node_modules/undici-types/cookies.d.ts","../node_modules/undici-types/patch.d.ts","../node_modules/undici-types/websocket.d.ts","../node_modules/undici-types/eventsource.d.ts","../node_modules/undici-types/filereader.d.ts","../node_modules/undici-types/diagnostics-channel.d.ts","../node_modules/undici-types/content-type.d.ts","../node_modules/undici-types/cache.d.ts","../node_modules/undici-types/index.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/dom-events.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/sea.d.ts","../node_modules/@types/node/sqlite.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/index.d.ts"],"fileIdsList":[[82,115,157],[115,157],[68,71,74,82,115,157],[68,74,87,115,157],[82,96,115,157],[82,83,115,157],[74,108,115,157],[115,154,157],[115,156,157],[157],[115,157,162,192],[115,157,158,163,169,170,177,189,200],[115,157,158,159,169,177],[110,111,112,115,157],[115,157,160,201],[115,157,161,162,170,178],[115,157,162,189,197],[115,157,163,165,169,177],[115,156,157,164],[115,157,165,166],[115,157,169],[115,157,167,169],[115,156,157,169],[115,157,169,170,171,189,200],[115,157,169,170,171,184,189,192],[115,152,157,205],[115,152,157,165,169,172,177,189,200],[115,157,169,170,172,173,177,189,197,200],[115,157,172,174,189,197,200],[113,114,115,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206],[115,157,169,175],[115,157,176,200,205],[115,157,165,169,177,189],[115,157,178],[115,157,179],[115,156,157,180],[115,154,155,156,157,158,159,160,161,162,163,164,165,166,167,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206],[115,157,182],[115,157,183],[115,157,169,184,185],[115,157,184,186,201,203],[115,157,169,189,190,191,192],[115,157,189,191],[115,157,189,190],[115,157,192],[115,157,193],[115,154,157,189],[115,157,169,195,196],[115,157,195,196],[115,157,162,177,189,197],[115,157,198],[115,157,177,199],[115,157,172,183,200],[115,157,162,201],[115,157,189,202],[115,157,176,203],[115,157,204],[115,157,162,169,171,180,189,200,203,205],[115,157,189,206],[59,60,61,115,157],[115,124,128,157,200],[115,124,157,189,200],[115,119,157],[115,121,124,157,197,200],[115,157,177,197],[115,157,207],[115,119,157,207],[115,121,124,157,177,200],[115,116,117,120,123,157,169,189,200],[115,124,131,157],[115,116,122,157],[115,124,145,146,157],[115,120,124,157,192,200,207],[115,145,157,207],[115,118,119,157,207],[115,124,157],[115,118,119,120,121,122,123,124,125,126,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,146,147,148,149,150,151,157],[115,124,139,157],[115,124,131,132,157],[115,122,124,132,133,157],[115,123,157],[115,116,119,124,157],[115,124,128,132,133,157],[115,128,157],[115,122,124,127,157,200],[115,116,121,124,131,157],[115,157,189],[115,119,124,145,157,205,207],[57,83,115,157],[67,74,75,77,81,115,157,172],[78,81,115,157],[77,85,115,157],[76,77,78,79,80,82,83,115,157],[81,82,83,115,157],[78,81,82,115,157],[76,82,115,157,172],[82,115,157,172],[58,68,69,70,71,72,73,82,83,115,157,169,170,172,179],[65,66,68,82,83,115,157],[74,82,115,157,170,179],[62,63,67,74,82,83,115,157,170,172,179],[57,82,115,157],[68,74,82,83,115,157,170,172,179],[74,82,83,115,157],[65,115,157],[64,115,157],[65,66,115,157]],"fileInfos":[{"version":"e41c290ef7dd7dab3493e6cbe5909e0148edf4a8dad0271be08edec368a0f7b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"4fd3f3422b2d2a3dfd5cdd0f387b3a8ec45f006c6ea896a4cb41264c2100bb2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"69e65d976bf166ce4a9e6f6c18f94d2424bf116e90837ace179610dbccad9b42","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7a3c8b952931daebdfc7a2897c53c0a1c73624593fa070e46bd537e64dcd20a","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"62bb211266ee48b2d0edf0d8d1b191f0c24fc379a82bd4c1692a082c540bc6b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"f1e2a172204962276504466a6393426d2ca9c54894b1ad0a6c9dad867a65f876","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"4a66df3ab5de5cfcda11538cffddd67ff6a174e003788e270914c1e0248483cf","impliedFormat":1},{"version":"f3a68054f682f21cec1eb6bc37d3c4c7f73b7723c7256f8a1ccc75873024aaa6","affectsGlobalScope":true,"impliedFormat":1},{"version":"169cc96316cacf8b489aaab4ac6bcef7b33e8779a8902bce57c737b4aa372d16","impliedFormat":1},{"version":"36f0847ebd70c7bec743c9f943ce72931975378f2c5fc18556fca46bf3b713ac","impliedFormat":1},{"version":"eb59adf5142bd260ebb26c1e4d83b8cbf40d8a2bcee936d2ec4afc74f213a4b0","impliedFormat":1},{"version":"7aae7e846d2ee8b1c5e89f1b7de9e92a13928ece1be66b87d872d758df19e42e","impliedFormat":1},{"version":"9329ffd96c23ec5b96f59f57f9a798eefe8d1565de7fadda3a2ea354d1455159","impliedFormat":1},{"version":"c308f25a99b75c29d2e348ed1e529c1e9495eb2d8927f8e9094d0979c82f5bd9","signature":"642edb9cd80f1d55bcf49297468b6c8894e9ab22d27044350b25424f8f3f014c"},{"version":"4ba362d1fe38784180b627b078876814bafaa3076b73962f98f3b1e836ec57e1","signature":"b72c48eccbc74d3070b67f35b24b69e7ba05a686d0f6f855a4ebe8912034f50b"},{"version":"779626da9442ffa6e585033f060017d1200a25fe9a5f288d90578145faa8340c","signature":"67dbb245db218ee4e82e0ae47415e87de3412657c6c4cab29a23057aca489350"},{"version":"98b1483ab31bb2d97ec02b2c11e546d347153725d559c5e409b43b86f2863a44","signature":"5f672ad8acddf3f5d683e2d8f40211a1c33209d7017d6a14cd779152642cbf9e"},{"version":"48cb7f00a111f467ad01fd7fc11e69fc5157e658d1143cfcedc1b826229dbf37","signature":"56c7a89a5c8a2cea05c1e4cd602127cfbb3103e1864fd042bd9835c5e7758fe1","affectsGlobalScope":true},{"version":"ea597e30a1ceedb0ee7cf973ac68a3a3dc619172d197345f770b0aff7d19758b","signature":"1ce43919aa8e605d6f8dd5b0c3a17411bbe0fc4ad895e49c207234110361e3bb"},{"version":"6e4cdd94bc4b5827a1da1b16ce518e25b32e391a1fcf1f4094cf3a6065432e17","signature":"72422a61710d7a245af730213ef18ebf3b54bd3b677990107e82778a379db64d"},{"version":"24c33d908546e10e2451ac244e9c27713d9dd7d6afc9b4e47d92f5eeded96aba","signature":"0f26d4e889dd2963e5b07e005ea10ed8a722e2591e999115be31220dc183e03a"},{"version":"92c4893bdb33aa38bd95782da34173eb213bff160e1902f2a75cc7e1ed7c4c45","signature":"ba9543dbc68854d0149ab3cdbdaaf5cd5ae18d8e0ed52e9ccb6870bf82407892","affectsGlobalScope":true},{"version":"5cb179976e0ccf15a6cd197bee534086f85c95e954eb1eabc0a110ec6f1e442c","signature":"646ba76176dd802bbd4699ac48140be1dc7263082cb75f24f8cbf85a6ed96a0a"},{"version":"2d3e6790fd9439d58b62d55817de54c36edfc2ff543c6153c71c5e9b8cc36f0d","signature":"edb0e91cfdb1d8a5ba365ac06a18d0e0a8bd2dc5b4e45f269164a6164f9371a6"},{"version":"8d4524132e2bda0cb337e3b7202defa277c4c59ba7fa1ac80de65b7357bdb1c0","signature":"e88b11abf97260f20ee6241dd9ca5c8b4dd59d8034f6d33bb5680e3d24d3014f","affectsGlobalScope":true},{"version":"4322880b08f97463c564ebd0d93e00bb47fb2d4f8047fe0b267035ee979a0779","signature":"3c8a0a0c7619f414e8d64ac805e4db68f42fe96ecac74a700b618d97e1281356"},{"version":"17f234ab67610f11c5fe892f49b80a3e3cc6bd4778305d288f81030f79632894","signature":"3a2966f108a65dd130f6968f2ff5f82e3e5dc42741bda5d4c5ada380fd05be74"},{"version":"685b0808444821f48b57fbefa36ae8fd6e5ffa104eb91389bc31f942db880f7c","signature":"b54dcf67a2cfa5d0ded5a496c82a12e149e8759af243d38083c48475022e9309"},{"version":"611852a4c1094600a51a2b4991fb0f9abb47f2f4363691ad90eeef07105bc5f7","signature":"3ea7a3af5ccf1828c07926e3b007a5ad67628672c59d3ccbf0c0cf6152397c31"},{"version":"3e75a9978ab23c9e06079aef200cd9812d905da89e41420a9e5b842888d65f42","signature":"4ae4a783f22e5cd9bbe95620d9e94918e3cdb5c50009ecc50d7bb4474679baf4"},{"version":"8f5ec0e46d58bf8980de66da4d774e6eee088d9b6d75817bbf00bb3d2b516011","signature":"2dbd18c28d9bfc22045eeb9a6b91664e1a8c6445729bb73b7dc7ebc4062eeed7"},{"version":"a9d405908aafd22ff4bfe82a4706a5dfb4e2b6a5d6db94a65f329c2a9ad6bc36","signature":"b8af56e95e2f7116f75a45e7982a8dd01697d25494c567c22483174f36cb652d","affectsGlobalScope":true},{"version":"6aa33b464089dc60552603f5960fc6ff1c14fd9753c1a6b8ebd4c437a2bfde54","signature":"d41977eed992e6fe8892f3d3b89e4aa7acd902c4f933b0739849431e413b8cd9"},{"version":"93b3114f6f2a01532d10d5f58f80be869074350ed0e88e7676c281d13467a066","signature":"9f084fcbe3839b8ebe9d0993ca4095768dc3342dffb5dfc11f171698e91ff98b"},{"version":"9fe47a0097954d4c4a3c9d67843bbc2fa07ecb411f867cfe8f721c7e75968563","signature":"289b69356c75e67867b2904b1ba7282169fea0f050ccacdbe0fe1bbe8c64daf6"},{"version":"3d0e5556187027a445f3637c45c757ce6fff7507bc3871d8a841e8dc9fd500bf","signature":"426defffb613aa20e788157a7b67bfd305cb9ee6aea981073eeeb1779caf986a"},{"version":"dad18aab1dfeeea0eb936ed3f756fc599ee109c89acef66bb9a636b44661f1e7","signature":"90065546c9f7e0e1959d7ee5a69512bff2b45a26d55130ed4f5047fd8d7724ce"},{"version":"5e3784751b46c7b1dd8b6a4088ad981d3d9706682dc04b794c62b2888bb59ccf","signature":"0ffb6159b5dd657d3aff31374033056864400c3894255bb066b712a4bdb524dd"},"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","2d009e4c4c91ff63daea2e4699fae228892a9fc9cb6821c7181e30d4e8df27bc",{"version":"86e90a7a43dfe2bb7f4e5bf4c41d9d8168f45d0f3c7950148cd610d5979f6add","signature":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},{"version":"dae0fd9dcbf0b5a443678d81c5eb994005198a74a57c4a375dad54725698d1d5","signature":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},{"version":"9f0a26da5f18fd5d9049f2b6c52a67df030b2dc17e442e4debeca01bcee70c48","signature":"995496801b1ee4457ed5e7df0d2c7a54846a5e6329df83f6996cd629d58c6fc7"},{"version":"c532cd069907c5d42cb36195fbb761bc7a041e0772c2682fb650a9ec3e9e7024","signature":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},{"version":"a826eb57af1c132871bd9ffbdd58844bb756fcd336bdceefe894cc59c1eb89b3","signature":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},{"version":"daf2d00217e38b280ac731d00f3b9a83c8d5ac80f9b9df88a90e3cef83879181","signature":"b5e731d837197e9f28319c5a91e2ebb6d53c4c86bef828dc35c5f7dc94ab503a"},{"version":"32a0983e424906d85c5c375d8af051adfa0b9d24a35816598c15775d0c8bf211","signature":"10ad70ee150c1e7e9731110e6679a5856003b01316adb3fc9f5249b93244d4bf"},{"version":"91bb28fcc8da60e83888c6227bb8396d1134fe1c7120ad1d4c899c42dab2396a","signature":"a9771789d0fd20e16a014136e45f6abf647ce81db8d0ffd19177db3dfe4f8ac4"},{"version":"e0c39155ffbd52f38f310cff6c161cfd694bbf73421a32bd14dee993bc3342fa","signature":"ba88f7af0374e466a7bf0736710e6f0efcd3f6af970523d30403bb225610f18c"},{"version":"c1254f2088a5b94f6b8ec9333fb01ad20f8e0d1f13bb423864131d0e86de5ac3","signature":"a9771789d0fd20e16a014136e45f6abf647ce81db8d0ffd19177db3dfe4f8ac4"},{"version":"562812d1b02e0d0487a0873be0c58d6650dc647d03554f768e3e7366988ef011","signature":"9c74956cd986a22189e6cf30050fbcfd30af673f2acda3e079097ecfbb95041c"},{"version":"6dca3348c0a381ee7faf298e5bff9113bf97f6750d19e161f226b5f0870d89bd","signature":"a9771789d0fd20e16a014136e45f6abf647ce81db8d0ffd19177db3dfe4f8ac4"},"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",{"version":"f01bd77de9f64275771216f8e63db40d60c4244597b5f16170446d2d5ed736d4","signature":"a9ceaa310406272646f45e4b636fcaa18c57ff87ae51cde9b7556bb3d060c22f"},{"version":"d5861f0d2037e92b0ee33b85324414c61186eaa13a6bf26017ad88e002de1f14","signature":"046601f48409cfe432ac58ded21ddaa6e44eda27eceec172b4b30c57bddb6246"},{"version":"b3bc68e909b6601cf3aada3bc2115ca48d9fbb40fe4d21e87b78dd0bba4d60c7","signature":"a9771789d0fd20e16a014136e45f6abf647ce81db8d0ffd19177db3dfe4f8ac4"},{"version":"f422586be24b2ef80184c4568c9d5cb2c6b4baf8c0a2bde96089444d251297db","signature":"6a01e9f8775e49819ad748033da026d95ce4719a5a0740c0fbe6e7ea117b0aa4"},{"version":"2ac0393bfc353575628757243f6d107a276260b132b2d85fd18ecc3a80d5e780","signature":"4ad310a41e254461390b7e7f113aaa12e1e0dd2c48625f53af8704ee48e419a7"},{"version":"a71099bf3b5128a83d45ff68899feac2f4dd6248d739b3770ffc37f7e14a4eb8","signature":"df768a0da6feea7c7f42cd7f7573cf47da0ea1a300c22850114e8d6ceedf9980"},{"version":"96d13fb47fa6f5467241cb34ba7727eb49bba8981da0da3b12ad1cf907cdd426","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"030e350db2525514580ed054f712ffb22d273e6bc7eddc1bb7eda1e0ba5d395e","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fd06258805d26c72f5997e07a23155d322d5f05387adb3744a791fe6a0b042d","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"24bd580b5743dc56402c440dc7f9a4f5d592ad7a419f25414d37a7bfe11e342b","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"6bdc71028db658243775263e93a7db2fd2abfce3ca569c3cca5aee6ed5eb186d","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"4d2b0eb911816f66abe4970898f97a2cfc902bcd743cbfa5017fad79f7ef90d8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"e53a3c2a9f624d90f24bf4588aacd223e7bec1b9d0d479b68d2f4a9e6011147f","impliedFormat":1},{"version":"24b8685c62562f5d98615c5a0c1d05f297cf5065f15246edfe99e81ec4c0e011","impliedFormat":1},{"version":"93507c745e8f29090efb99399c3f77bec07db17acd75634249dc92f961573387","impliedFormat":1},{"version":"339dc5265ee5ed92e536a93a04c4ebbc2128f45eeec6ed29f379e0085283542c","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"81184fe8e67d78ac4e5374650f0892d547d665d77da2b2f544b5d84729c4a15d","affectsGlobalScope":true,"impliedFormat":1},{"version":"f52e8dacc97d71dcc96af29e49584353f9c54cb916d132e3e768d8b8129c928d","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"76103716ba397bbb61f9fa9c9090dca59f39f9047cb1352b2179c5d8e7f4e8d0","impliedFormat":1},{"version":"53eac70430b30089a3a1959d8306b0f9cfaf0de75224b68ef25243e0b5ad1ca3","affectsGlobalScope":true,"impliedFormat":1},{"version":"4314c7a11517e221f7296b46547dbc4df047115b182f544d072bdccffa57fc72","impliedFormat":1},{"version":"115971d64632ea4742b5b115fb64ed04bcaae2c3c342f13d9ba7e3f9ee39c4e7","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","impliedFormat":1},{"version":"a76037255d4e7af8b20d191a4d3ad13236fba352239d3d9d54868a98dbb222f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"24642567d3729bcc545bacb65ee7c0db423400c7f1ef757cab25d05650064f98","impliedFormat":1},{"version":"e6f5a38687bebe43a4cef426b69d34373ef68be9a6b1538ec0a371e69f309354","impliedFormat":1},{"version":"a6bf63d17324010ca1fbf0389cab83f93389bb0b9a01dc8a346d092f65b3605f","impliedFormat":1},{"version":"e009777bef4b023a999b2e5b9a136ff2cde37dc3f77c744a02840f05b18be8ff","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true,"impliedFormat":1},{"version":"875928df2f3e9a3aed4019539a15d04ff6140a06df6cd1b2feb836d22a81eaca","affectsGlobalScope":true,"impliedFormat":1},{"version":"e9ad08a376ac84948fcca0013d6f1d4ae4f9522e26b91f87945b97c99d7cc30b","impliedFormat":1},{"version":"f65eecc63138013d13fefea9092e83c3043cb52a5e351d22ea194e81021c1cd5","impliedFormat":1},{"version":"4617299caf33afef24b5e074e6d20ce8f510dd212cebd75884ef27c64457a77b","impliedFormat":1},{"version":"fa56be9b96f747e93b895d8dc2aa4fb9f0816743e6e2abb9d60705e88d4743a2","impliedFormat":1},{"version":"4f80de3a11c0d2f1329a72e92c7416b2f7eab14f67e92cac63bb4e8d01c6edc8","impliedFormat":1},{"version":"6d386bc0d7f3afa1d401afc3e00ed6b09205a354a9795196caed937494a713e6","impliedFormat":1},{"version":"04296378d9636f6f9450a6e2b9889ea1d3b72a05b9270cb529ace09f04cda1f2","affectsGlobalScope":true,"impliedFormat":1},{"version":"94c4187083503a74f4544503b5a30e2bd7af0032dc739b0c9a7ce87f8bddc7b9","impliedFormat":1},{"version":"b1b6ee0d012aeebe11d776a155d8979730440082797695fc8e2a5c326285678f","impliedFormat":1},{"version":"45875bcae57270aeb3ebc73a5e3fb4c7b9d91d6b045f107c1d8513c28ece71c0","impliedFormat":1},{"version":"3eb62baae4df08c9173e6903d3ca45942ccec8c3659b0565684a75f3292cffbb","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f6abdaf8764ef01a552a958f45e795b5e79153b87ddad3af5264b86d2681b72","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"c6b4e0a02545304935ecbf7de7a8e056a31bb50939b5b321c9d50a405b5a0bba","impliedFormat":1},{"version":"fab29e6d649aa074a6b91e3bdf2bff484934a46067f6ee97a30fcd9762ae2213","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"e1120271ebbc9952fdc7b2dd3e145560e52e06956345e6fdf91d70ca4886464f","impliedFormat":1},{"version":"15c5e91b5f08be34a78e3d976179bf5b7a9cc28dc0ef1ffebffeb3c7812a2dca","impliedFormat":1},{"version":"a8f06c2382a30b7cb89ad2dfc48fc3b2b490f3dafcd839dadc008e4e5d57031d","impliedFormat":1},{"version":"553870e516f8c772b89f3820576152ebc70181d7994d96917bb943e37da7f8a7","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"93452d394fdd1dc551ec62f5042366f011a00d342d36d50793b3529bfc9bd633","impliedFormat":1},{"version":"745c4240220559bd340c8aeb6e3c5270a709d3565e934dc22a69c304703956bc","affectsGlobalScope":true,"impliedFormat":1},{"version":"2754d8221d77c7b382096651925eb476f1066b3348da4b73fe71ced7801edada","impliedFormat":1},{"version":"918d3b03a75858dcd5dbb275f19448b6b9a222aa8fc8471aca38c28a32ecb40f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bef91efa0baea5d0e0f0f27b574a8bc100ce62a6d7e70220a0d58af6acab5e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"282fd2a1268a25345b830497b4b7bf5037a5e04f6a9c44c840cb605e19fea841","impliedFormat":1},{"version":"5360a27d3ebca11b224d7d3e38e3e2c63f8290cb1fcf6c3610401898f8e68bc3","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"7d6ff413e198d25639f9f01f16673e7df4e4bd2875a42455afd4ecc02ef156da","affectsGlobalScope":true,"impliedFormat":1},{"version":"6bd91a2a356600dee28eb0438082d0799a18a974a6537c4410a796bab749813c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a5c09990a37469b0311a92ce8feeb8682e83918723aedbd445bd7a0f510eaaa3","impliedFormat":1},{"version":"ae25afbbf1ed5df63a177d67b9048bf7481067f1b8dc9c39212e59db94fc9fc6","impliedFormat":1},{"version":"ac5ed35e649cdd8143131964336ab9076937fa91802ec760b3ea63b59175c10a","impliedFormat":1},{"version":"89332fc3cc945c8df2bc0aead55230430a0dabd3277c39a43315e00330de97a6","affectsGlobalScope":true,"impliedFormat":1},{"version":"78dc0513cc4f1642906b74dda42146bcbd9df7401717d6e89ea6d72d12ecb539","impliedFormat":1},{"version":"ad90122e1cb599b3bc06a11710eb5489101be678f2920f2322b0ac3e195af78d","impliedFormat":1}],"root":[[63,109]],"options":{"allowSyntheticDefaultImports":true,"alwaysStrict":true,"composite":true,"declaration":true,"isolatedDeclarations":true,"module":6,"noImplicitAny":true,"noImplicitReturns":true,"noUnusedLocals":true,"outDir":"./","removeComments":true,"rootDir":"..","strictBindCallApply":true,"strictNullChecks":true,"strictPropertyInitialization":true,"target":8},"referencedMap":[[108,1],[88,2],[89,2],[90,2],[91,2],[92,3],[93,2],[94,2],[95,4],[97,5],[98,2],[99,1],[100,1],[101,1],[102,2],[103,6],[104,1],[105,1],[106,6],[107,1],[96,2],[109,7],[58,2],[154,8],[155,8],[156,9],[115,10],[157,11],[158,12],[159,13],[110,2],[113,14],[111,2],[112,2],[160,15],[161,16],[162,17],[163,18],[164,19],[165,20],[166,20],[168,21],[167,22],[169,23],[170,24],[171,25],[153,26],[114,2],[172,27],[173,28],[174,29],[207,30],[175,31],[176,32],[177,33],[178,34],[179,35],[180,36],[181,37],[182,38],[183,39],[184,40],[185,40],[186,41],[187,2],[188,2],[189,42],[191,43],[190,44],[192,45],[193,46],[194,47],[195,48],[196,49],[197,50],[198,51],[199,52],[200,53],[201,54],[202,55],[203,56],[204,57],[205,58],[206,59],[57,2],[62,60],[59,2],[60,2],[61,2],[54,2],[55,2],[11,2],[9,2],[10,2],[15,2],[14,2],[2,2],[16,2],[17,2],[18,2],[19,2],[20,2],[21,2],[22,2],[23,2],[3,2],[24,2],[25,2],[4,2],[26,2],[30,2],[27,2],[28,2],[29,2],[31,2],[32,2],[33,2],[5,2],[34,2],[35,2],[36,2],[37,2],[6,2],[41,2],[38,2],[39,2],[40,2],[42,2],[7,2],[43,2],[48,2],[49,2],[44,2],[45,2],[46,2],[47,2],[8,2],[56,2],[53,2],[50,2],[51,2],[52,2],[1,2],[13,2],[12,2],[131,61],[141,62],[130,61],[151,63],[122,64],[121,65],[150,66],[144,67],[149,68],[124,69],[138,70],[123,71],[147,72],[119,73],[118,66],[148,74],[120,75],[125,76],[126,2],[129,76],[116,2],[152,77],[142,78],[133,79],[134,80],[136,81],[132,82],[135,83],[145,66],[127,84],[128,85],[137,86],[117,87],[140,78],[139,76],[143,2],[146,88],[84,89],[75,2],[82,90],[83,1],[85,91],[86,92],[81,93],[78,94],[79,95],[80,1],[77,96],[76,97],[74,98],[67,99],[69,100],[73,97],[68,101],[63,1],[87,1],[72,102],[71,103],[70,104],[66,105],[65,106],[64,107]],"latestChangedDtsFile":"./index.d.ts","version":"5.7.2"}
package/package.json CHANGED
@@ -2,13 +2,19 @@
2
2
  "name": "structured-fw",
3
3
  "displayName": "Structured framework",
4
4
  "description": "Production-tested Node.js framework for creating performant server-side rendered web apps and APIs, with a sane amount of client side abstraction.",
5
+ "keywords": ["typescript", "framework", "ssr", "component"],
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/julijan/structured"
9
+ },
5
10
  "author": {
6
11
  "name": "Julijan Andjelic",
7
12
  "email": "julijan.andjelic@gmail.com"
8
13
  },
14
+ "license": "MIT",
9
15
  "type": "module",
10
16
  "main": "build/index",
11
- "version": "0.7.6",
17
+ "version": "0.7.8",
12
18
  "scripts": {
13
19
  "develop": "tsc --watch",
14
20
  "startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,css index.js",
package/system/Types.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from "node:http";
2
2
  import { Application } from "./server/Application.js";
3
3
  import { symbolArrays } from "./Symbols.js";
4
- import { RequestContextData } from "../app/Types.js";
5
4
  import { Net } from './client/Net.js';
6
5
  import { ClientComponent } from './client/ClientComponent.js';
7
6
  import { Component } from "./server/Component.js";
@@ -3,7 +3,7 @@ import { existsSync, readFileSync } from 'node:fs';
3
3
  import { createServer, Server } from 'node:http';
4
4
  import * as path from 'node:path';
5
5
  import * as mime from 'mime-types';
6
- import { ApplicationEvents, LooseObject, RequestBodyArguments, RequestCallback, RequestContext, StructuredConfig } from '../Types';
6
+ import { ApplicationEvents, LooseObject, RequestBodyArguments, RequestContext, StructuredConfig } from '../Types';
7
7
  import { Document } from './Document.js';
8
8
  import { Components } from './Components.js';
9
9
  import { Session } from './Session.js';
@@ -11,7 +11,6 @@ import { toSnakeCase } from '../Util.js';
11
11
  import { Request } from './Request.js';
12
12
  import { Handlebars } from './Handlebars.js';
13
13
  import { Cookies } from './Cookies.js';
14
- import { RequestContextData } from '../../app/Types.js';
15
14
 
16
15
  export class Application {
17
16
  readonly config: StructuredConfig;
@@ -100,7 +99,7 @@ export class Application {
100
99
  }
101
100
 
102
101
  // start the http server
103
- public start(): Promise<void> {
102
+ private start(): Promise<void> {
104
103
  return new Promise((resolve, reject) => {
105
104
  this.server = createServer((req, res) => {
106
105
  this.request.handle(req, res);
@@ -115,7 +114,15 @@ export class Application {
115
114
  }
116
115
 
117
116
  // add event listener
118
- public on(evt: ApplicationEvents, callback: RequestCallback|((payload?: any) => void)): void {
117
+ public on<E extends ApplicationEvents>(
118
+ evt: E,
119
+ callback: (
120
+ payload:
121
+ E extends 'beforeRequestHandler' | 'afterRequestHandler' | 'beforeAssetAccess' | 'afterAssetAccess' | 'pageNotFound' ? RequestContext :
122
+ E extends 'documentCreated' ? Document :
123
+ undefined
124
+ ) => void
125
+ ): void {
119
126
  this.eventEmitter.on(evt, callback);
120
127
  }
121
128
 
@@ -1,8 +1,6 @@
1
1
  import { Document } from './Document.js';
2
2
  import { attributeValueFromString, attributeValueToString, objectEach, toCamelCase } from '../Util.js';
3
3
  import { ComponentEntry, LooseObject } from '../Types.js';
4
-
5
- import { RequestContextData } from '../../app/Types.js';
6
4
  import { DOMFragment } from './dom/DOMFragment.js';
7
5
  import { DOMNode } from './dom/DOMNode.js';
8
6
 
@@ -18,6 +18,9 @@ export class Components {
18
18
  public loadComponents(relativeToPath?: string): void {
19
19
  if (relativeToPath === undefined) {
20
20
  relativeToPath = path.resolve((this.config.runtime === 'Node.js' ? '../' : './') + this.config.components.path);
21
+ if (! existsSync(relativeToPath)) {
22
+ throw new Error(`Components path not found, expected to find:\n${relativeToPath}`);
23
+ }
21
24
  }
22
25
  const components = readdirSync(relativeToPath);
23
26
 
@@ -1,7 +1,6 @@
1
1
  import { IncomingMessage, ServerResponse } from "node:http";
2
2
  import { PostedDataDecoded, RequestBodyFile, RequestCallback, RequestContext, RequestHandler, RequestMethod, URIArguments, URISegmentPattern } from "../Types.js";
3
3
  import { mergeDeep, queryStringDecode, queryStringDecodedSetValue } from "../Util.js";
4
- import { RequestContextData } from "../../app/Types.js";
5
4
  import { Application } from "./Application.js";
6
5
  import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
7
6
  import path from "node:path";
@@ -420,11 +419,16 @@ export class Request {
420
419
  } else {
421
420
  routesPath = path.resolve((this.app.config.runtime === 'Node.js' ? '../build/' : './') + this.app.config.routes.path);
422
421
  }
422
+
423
+ if (! existsSync(routesPath)) {
424
+ throw new Error(`Routes path not found, expected to find:\n${routesPath}`);
425
+ }
426
+
423
427
  const files = readdirSync(routesPath);
424
428
 
425
429
  for (let i = 0; i < files.length; i++) {
426
430
  const file = files[i];
427
- if (! (file.endsWith('.js') || file.endsWith('.ts'))) {
431
+ if (! (file.endsWith('.js') || file.endsWith('.ts')) || file.endsWith('.d.ts')) {
428
432
  continue;
429
433
  }
430
434
  const filePath = path.resolve(routesPath + '/' + file);