Full Code of liaisonjs/liaison for AI

master 10a7e9f521a6 cached
576 files
2.3 MB
644.0k tokens
1694 symbols
1 requests
Download .txt
Showing preview only (2,569K chars total). Download the full file or copy to clipboard to get everything.
Repository: liaisonjs/liaison
Branch: master
Commit: 10a7e9f521a6
Files: 576
Total size: 2.3 MB

Directory structure:
gitextract_vbywh81w/

├── .editorconfig
├── .gitignore
├── .npm-dev-registry.json
├── .prettierignore
├── .vscode/
│   └── extensions.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── assets/
│   ├── frontend-backend.excalidraw
│   ├── frontend-webapi-backend.excalidraw
│   ├── typical-stack-vs-layr-stack-light-mode.excalidraw
│   └── typical-stack-vs-layr-stack.excalidraw
├── docs/
│   ├── build.js
│   ├── contents/
│   │   ├── concepts/
│   │   │   └── coming-soon.md
│   │   ├── guides/
│   │   │   └── coming-soon.md
│   │   ├── index.json
│   │   └── introduction/
│   │       ├── handling-authorization.md
│   │       ├── hello-world/
│   │       │   └── hello-world.md
│   │       ├── introduction.md
│   │       └── storing-data.md
│   └── package.json
├── examples/
│   ├── v1/
│   │   ├── counter/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   ├── counter-with-create-react-app-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── package.json
│   │   │   │   ├── public/
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── manifest.json
│   │   │   │   │   └── robots.txt
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── react-app-env.d.ts
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── counter-with-esbuild-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── index.tsx
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── counter-with-http/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   ├── counter-with-parcel-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── babel.config.js
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── index.tsx
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── counter-with-rollup-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── babel.config.js
│   │   │   │   ├── package.json
│   │   │   │   ├── rollup.config.js
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── index.tsx
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── guestbook-cli-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   ├── guestbook-cli-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   └── frontend.ts
│   │   │   └── tsconfig.json
│   │   ├── guestbook-web-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.js
│   │   │   │   ├── frontend.js
│   │   │   │   └── index.html
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   ├── frontend.tsx
│   │   │   │   └── index.html
│   │   │   ├── tsconfig.json
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-authorization-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.js
│   │   │   │   ├── frontend.js
│   │   │   │   └── index.html
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-authorization-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   ├── frontend.tsx
│   │   │   │   └── index.html
│   │   │   ├── tsconfig.json
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-routes-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.js
│   │   │   │   ├── frontend.js
│   │   │   │   └── index.html
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-routes-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   ├── frontend.tsx
│   │   │   │   └── index.html
│   │   │   ├── tsconfig.json
│   │   │   └── webpack.config.js
│   │   ├── hello-world-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   └── hello-world-ts/
│   │       ├── README.md
│   │       ├── package.json
│   │       ├── src/
│   │       │   ├── backend.ts
│   │       │   └── frontend.ts
│   │       └── tsconfig.json
│   └── v2/
│       ├── hello-world-js/
│       │   ├── .editorconfig
│       │   ├── .gitignore
│       │   ├── .prettierignore
│       │   ├── .vscode/
│       │   │   ├── extensions.json
│       │   │   └── settings.json
│       │   ├── README.md
│       │   ├── backend/
│       │   │   ├── boostr.config.mjs
│       │   │   ├── boostr.config.private-example.mjs
│       │   │   ├── jsconfig.json
│       │   │   ├── package.json
│       │   │   └── src/
│       │   │       ├── components/
│       │   │       │   └── application.js
│       │   │       └── index.js
│       │   ├── boostr.config.mjs
│       │   ├── database/
│       │   │   ├── .gitignore
│       │   │   ├── boostr.config.mjs
│       │   │   └── boostr.config.private-example.mjs
│       │   ├── frontend/
│       │   │   ├── boostr.config.mjs
│       │   │   ├── jsconfig.json
│       │   │   ├── package.json
│       │   │   └── src/
│       │   │       ├── components/
│       │   │       │   └── application.jsx
│       │   │       └── index.js
│       │   └── package.json
│       └── hello-world-ts/
│           ├── .editorconfig
│           ├── .gitignore
│           ├── .prettierignore
│           ├── .vscode/
│           │   ├── extensions.json
│           │   └── settings.json
│           ├── README.md
│           ├── backend/
│           │   ├── boostr.config.mjs
│           │   ├── boostr.config.private-example.mjs
│           │   ├── package.json
│           │   ├── src/
│           │   │   ├── components/
│           │   │   │   └── application.ts
│           │   │   └── index.ts
│           │   └── tsconfig.json
│           ├── boostr.config.mjs
│           ├── database/
│           │   ├── .gitignore
│           │   ├── boostr.config.mjs
│           │   └── boostr.config.private-example.mjs
│           ├── frontend/
│           │   ├── boostr.config.mjs
│           │   ├── package.json
│           │   ├── src/
│           │   │   ├── components/
│           │   │   │   └── application.tsx
│           │   │   └── index.ts
│           │   └── tsconfig.json
│           └── package.json
├── lerna.json
├── nx.json
├── package.json
├── packages/
│   ├── aws-integration/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── lambda-execution-queue-sender.ts
│   │   │   └── lambda-handler.ts
│   │   └── tsconfig.json
│   ├── browser-navigator/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── browser-navigator.ts
│   │   │   ├── index.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── component/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── cloning.test.ts
│   │   │   ├── cloning.ts
│   │   │   ├── component.test.ts
│   │   │   ├── component.ts
│   │   │   ├── decorators.test.ts
│   │   │   ├── decorators.ts
│   │   │   ├── deserialization.test.ts
│   │   │   ├── deserialization.ts
│   │   │   ├── embedded-component.ts
│   │   │   ├── forking.test.ts
│   │   │   ├── forking.ts
│   │   │   ├── identifiable-component.test.ts
│   │   │   ├── identity-map.test.ts
│   │   │   ├── identity-map.ts
│   │   │   ├── index.ts
│   │   │   ├── js-parser.ts
│   │   │   ├── js-tests/
│   │   │   │   ├── decorators.test.js
│   │   │   │   └── jsconfig.json
│   │   │   ├── merging.test.ts
│   │   │   ├── merging.ts
│   │   │   ├── properties/
│   │   │   │   ├── attribute-selector.test.ts
│   │   │   │   ├── attribute-selector.ts
│   │   │   │   ├── attribute.test.ts
│   │   │   │   ├── attribute.ts
│   │   │   │   ├── identifier-attribute.test.ts
│   │   │   │   ├── identifier-attribute.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── method.test.ts
│   │   │   │   ├── method.ts
│   │   │   │   ├── primary-identifier-attribute.test.ts
│   │   │   │   ├── primary-identifier-attribute.ts
│   │   │   │   ├── property.test.ts
│   │   │   │   ├── property.ts
│   │   │   │   ├── secondary-identifier-attribute.test.ts
│   │   │   │   ├── secondary-identifier-attribute.ts
│   │   │   │   └── value-types/
│   │   │   │       ├── any-value-type.ts
│   │   │   │       ├── array-value-type.ts
│   │   │   │       ├── boolean-value-type.ts
│   │   │   │       ├── component-value-type.ts
│   │   │   │       ├── date-value-type.ts
│   │   │   │       ├── factory.test.ts
│   │   │   │       ├── factory.ts
│   │   │   │       ├── index.ts
│   │   │   │       ├── number-value-type.ts
│   │   │   │       ├── object-value-type.ts
│   │   │   │       ├── regexp-value-type.ts
│   │   │   │       ├── string-value-type.ts
│   │   │   │       ├── value-type.test.ts
│   │   │   │       └── value-type.ts
│   │   │   ├── sanitization/
│   │   │   │   ├── index.ts
│   │   │   │   ├── sanitizer-builders.test.ts
│   │   │   │   ├── sanitizer-builders.ts
│   │   │   │   ├── sanitizer.test.ts
│   │   │   │   ├── sanitizer.ts
│   │   │   │   ├── utilities.test.ts
│   │   │   │   └── utilities.ts
│   │   │   ├── serialization.test.ts
│   │   │   ├── serialization.ts
│   │   │   ├── utilities.test.ts
│   │   │   ├── utilities.ts
│   │   │   └── validation/
│   │   │       ├── index.ts
│   │   │       ├── utilities.test.ts
│   │   │       ├── utilities.ts
│   │   │       ├── validator-builders.test.ts
│   │   │       ├── validator-builders.ts
│   │   │       ├── validator.test.ts
│   │   │       └── validator.ts
│   │   └── tsconfig.json
│   ├── component-client/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-client.test.ts
│   │   │   ├── component-client.ts
│   │   │   ├── index.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── component-express-middleware/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-express-middleware.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-http-client/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-http-client.test.ts
│   │   │   ├── component-http-client.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-http-server/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-http-server.test.ts
│   │   │   ├── component-http-server.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-koa-middleware/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-koa-middleware.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-server/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-server.test.ts
│   │   │   ├── component-server.ts
│   │   │   ├── index.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── execution-queue/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── execution-queue.test.ts
│   │   │   ├── execution-queue.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── integration-testing/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── client-server.test.ts
│   │   │   ├── component-express-middleware.test.ts
│   │   │   ├── component-koa-middleware.test.ts
│   │   │   ├── counter.fixture.ts
│   │   │   ├── http-client-server.test.ts
│   │   │   ├── memory-navigator.test.ts
│   │   │   ├── navigator.test.ts
│   │   │   ├── storable.fixture.ts
│   │   │   └── storable.test.ts
│   │   └── tsconfig.json
│   ├── memory-navigator/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   └── memory-navigator.ts
│   │   └── tsconfig.json
│   ├── memory-store/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   └── memory-store.ts
│   │   └── tsconfig.json
│   ├── mongodb-store/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── mongodb-store.test.ts
│   │   │   └── mongodb-store.ts
│   │   └── tsconfig.json
│   ├── navigator/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── navigator.ts
│   │   │   ├── utilities.test.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── observable/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── observable.test.ts
│   │   │   └── observable.ts
│   │   └── tsconfig.json
│   ├── react-integration/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── components.tsx
│   │   │   ├── decorators.tsx
│   │   │   ├── hooks.ts
│   │   │   ├── index.ts
│   │   │   └── plugins.tsx
│   │   └── tsconfig.json
│   ├── routable/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── addressable.ts
│   │   │   ├── decorators.test.ts
│   │   │   ├── decorators.ts
│   │   │   ├── index.ts
│   │   │   ├── js-tests/
│   │   │   │   ├── decorators.test.js
│   │   │   │   └── jsconfig.json
│   │   │   ├── param.ts
│   │   │   ├── pattern.ts
│   │   │   ├── routable.test.ts
│   │   │   ├── routable.ts
│   │   │   ├── route.test.ts
│   │   │   ├── route.ts
│   │   │   ├── utilities.ts
│   │   │   └── wrapper.ts
│   │   └── tsconfig.json
│   ├── storable/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── decorators.test.ts
│   │   │   ├── decorators.ts
│   │   │   ├── index-class.test.ts
│   │   │   ├── index-class.ts
│   │   │   ├── index.ts
│   │   │   ├── js-tests/
│   │   │   │   ├── decorators.test.js
│   │   │   │   └── jsconfig.json
│   │   │   ├── operator.ts
│   │   │   ├── properties/
│   │   │   │   ├── index.ts
│   │   │   │   ├── storable-attribute.test.ts
│   │   │   │   ├── storable-attribute.ts
│   │   │   │   ├── storable-method.ts
│   │   │   │   ├── storable-primary-identifier-attribute.ts
│   │   │   │   ├── storable-property.ts
│   │   │   │   └── storable-secondary-identifier-attribute.ts
│   │   │   ├── query.ts
│   │   │   ├── storable.ts
│   │   │   ├── store-like.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── store/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── document.ts
│   │   │   ├── expression.ts
│   │   │   ├── index.ts
│   │   │   ├── path.ts
│   │   │   ├── store.test.ts
│   │   │   ├── store.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── utilities/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── error.test.ts
│   │   │   ├── error.ts
│   │   │   ├── index.ts
│   │   │   └── time.ts
│   │   └── tsconfig.json
│   └── with-roles/
│       ├── .gitignore
│       ├── README.md
│       ├── package.json
│       ├── src/
│       │   ├── decorators.test.ts
│       │   ├── decorators.ts
│       │   ├── index.ts
│       │   ├── role.test.ts
│       │   ├── role.ts
│       │   ├── utilities.ts
│       │   ├── with-roles.test.ts
│       │   └── with-roles.ts
│       └── tsconfig.json
└── website/
    ├── README.md
    ├── backend/
    │   ├── boostr.config.mjs
    │   ├── boostr.config.private-template.mjs
    │   ├── package.json
    │   ├── src/
    │   │   ├── components/
    │   │   │   ├── application.ts
    │   │   │   ├── article.ts
    │   │   │   ├── entity.ts
    │   │   │   ├── newsletter.ts
    │   │   │   ├── user.ts
    │   │   │   └── with-author.ts
    │   │   ├── index.ts
    │   │   └── jwt.ts
    │   └── tsconfig.json
    ├── boostr.config.mjs
    ├── database/
    │   ├── .gitignore
    │   ├── boostr.config.mjs
    │   └── boostr.config.private-template.mjs
    ├── frontend/
    │   ├── boostr.config.mjs
    │   ├── package.json
    │   ├── public/
    │   │   └── docs/
    │   │       ├── v1/
    │   │       │   ├── introduction/
    │   │       │   │   ├── authorization-6eooNLZnaLZk4eJNHNGwUp-edited.immutable.md
    │   │       │   │   ├── data-storage-1YDg3LGZPF09H3opJUEDSp-edited.immutable.md
    │   │       │   │   ├── hello-world-7F76XnjXXBB7eeZTpEZwEX-edited.immutable.md
    │   │       │   │   ├── introduction-1NNtkbXN0zHvG6VR0jvPRK-edited.immutable.md
    │   │       │   │   ├── routing-4ubaWloMHuNNs0foagYUwi-edited.immutable.md
    │   │       │   │   └── web-app-5okryUyuriFFHXtFK9uZNY-edited.immutable.md
    │   │       │   └── reference/
    │   │       │       ├── attribute-4P9dTivZ9HJ4Flr4Y8cTKv.immutable.md
    │   │       │       ├── attribute-selector-7FZWQpwLR7jpUHoBpvO9Et.immutable.md
    │   │       │       ├── aws-integration-3iPKbtjOS0uDgsZKk6Q0Kp.immutable.md
    │   │       │       ├── browser-router-6EIyPCgoPYsWmDmpyKMhce.immutable.md
    │   │       │       ├── component-6LvsJL2MA9RN6hmT0bBacd.immutable.md
    │   │       │       ├── component-client-1ISSjJNRL12I33addutRh4.immutable.md
    │   │       │       ├── component-express-middleware-6UieWJkEvLdXLYug4xuM16.immutable.md
    │   │       │       ├── component-http-client-6g8M9kRcBS4AQwFtAp7t9z.immutable.md
    │   │       │       ├── component-http-server-5VDR5fS2uD9iTkuHRSywjz.immutable.md
    │   │       │       ├── component-koa-middleware-402oMlpSmEIARQJLzn4qQg.immutable.md
    │   │       │       ├── component-server-e5RUuQXVcCIVLxHiNzCDO.immutable.md
    │   │       │       ├── embedded-component-4MiZBzspJQbUshU8Q93aJ8.immutable.md
    │   │       │       ├── identifier-attribute-6Jgrzmrlv4QJoBZVTYYDb9.immutable.md
    │   │       │       ├── identity-map-01fsjrVv6cSC6awmnNnn6c.immutable.md
    │   │       │       ├── index-1KeXILVBQNLQpRzBhIWjqB.immutable.md
    │   │       │       ├── memory-router-TGoBOhUXFPp3iDyKA9Sn0.immutable.md
    │   │       │       ├── memory-store-78uJRKSOEyr1WnXttCnd9u.immutable.md
    │   │       │       ├── method-3mc2TakviGDKFcdpxFaCIu.immutable.md
    │   │       │       ├── mongodb-store-1yTYtEyVy4ZLkF4A2QFaAh.immutable.md
    │   │       │       ├── observable-6JJJVlFHPe2kPQ4NhsJg7O.immutable.md
    │   │       │       ├── primary-identifier-attribute-6qTkOuHNN4Bq3EjC9JGVqr.immutable.md
    │   │       │       ├── property-5bbULbxC52tIPaMAcPEp27.immutable.md
    │   │       │       ├── query-Q04JuSZAcx8HGvYktmTlI.immutable.md
    │   │       │       ├── react-integration-3EgAB99IhnithzdqiytvwF.immutable.md
    │   │       │       ├── role-UodTLJi6Lg6UPXOKZdp8K.immutable.md
    │   │       │       ├── routable-3zt4vMLvzQR3aqOwoWd3xV.immutable.md
    │   │       │       ├── route-1rS9AS4eda7qe7lWTU4WKF.immutable.md
    │   │       │       ├── router-5zhzJL9MYM1yaHY6CXlkso.immutable.md
    │   │       │       ├── secondary-identifier-attribute-7BqK9EmnCMCHIAroYiQDth.immutable.md
    │   │       │       ├── storable-2maAYPX5kWufBfVolYVgdc.immutable.md
    │   │       │       ├── storable-attribute-7MiyqvA7PUf2E2YeoqA912.immutable.md
    │   │       │       ├── storable-method-1rnW3aKFlFYZ3kIJdCGXRv.immutable.md
    │   │       │       ├── storable-primary-identifier-attribute-74IwGTycdA7NVAybBly3t1.immutable.md
    │   │       │       ├── storable-property-5LuWR7uuQ1qdebK3iszZJO.immutable.md
    │   │       │       ├── storable-secondary-identifier-attribute-6CqhR0kLxoLhtWU85EcsZU.immutable.md
    │   │       │       ├── store-6BvlCSWkAb7smHsvoIGjv1.immutable.md
    │   │       │       ├── validator-2strlvnapeTZmbWT3o3VM1.immutable.md
    │   │       │       ├── value-type-23f3WjnZNDfFejs5ceJVcY.immutable.md
    │   │       │       └── with-roles-2PYi0037F3Mxg80b5YKb26.immutable.md
    │   │       └── v2/
    │   │           ├── concepts/
    │   │           │   └── coming-soon-38q4cuyCWekHuz36oHyMKG.immutable.md
    │   │           ├── guides/
    │   │           │   └── coming-soon-6TWZbDxh3EVysir57k1tga.immutable.md
    │   │           ├── introduction/
    │   │           │   ├── handling-authorization-1sLAebuD81FLlSvJbAuJmZ.immutable.md
    │   │           │   ├── hello-world/
    │   │           │   │   └── hello-world-2FHBCgFRhZX9qH9O1RkTlZ.immutable.md
    │   │           │   ├── introduction-1iLUBREWe2BB65qw9G4uzm.immutable.md
    │   │           │   └── storing-data-40jzWiVleR8ZE0fqfGTbO2.immutable.md
    │   │           └── reference/
    │   │               ├── addressable-6n5npS1cCoPKLkFrYU0Pk7.immutable.md
    │   │               ├── attribute-4IRansPGIm4E3gunH3Ztlq.immutable.md
    │   │               ├── attribute-selector-76ksImknctJspHLg12sRpR.immutable.md
    │   │               ├── aws-integration-3Rt2txpqioYQsmijgSqqwF.immutable.md
    │   │               ├── browser-navigator-eYIxYKNFdRYiKTxIWAjqd.immutable.md
    │   │               ├── component-1zBrZVglO2cjDP9aO87pOR.immutable.md
    │   │               ├── component-client-69HLk6gKzg5DfWcVC2bQWS.immutable.md
    │   │               ├── component-express-middleware-7KGBerWY9jB9r9eOjwLmPq.immutable.md
    │   │               ├── component-http-client-2rHYFMcsawI16EvGk8372w.immutable.md
    │   │               ├── component-http-server-5aWTLSzVvm0WohfP6af7OP.immutable.md
    │   │               ├── component-koa-middleware-6aVaQsSgkzWt35XyqSMuqx.immutable.md
    │   │               ├── component-server-i0AsOVFbGCJUrJ9mJyjPh.immutable.md
    │   │               ├── embedded-component-3YdGqfLNxl8c001AvWxHZ6.immutable.md
    │   │               ├── identifier-attribute-2w8hckqCKGHPurgIGY5vhT.immutable.md
    │   │               ├── identity-map-7sLdA5rsLvflf8T8OsZfGO.immutable.md
    │   │               ├── index-1Uz5JX1XB7V67nfM6tvnSV.immutable.md
    │   │               ├── memory-navigator-5wC9TEZn2cen7LuV4cGPOj.immutable.md
    │   │               ├── memory-store-3QHbAhGolblHx4OY17rEP.immutable.md
    │   │               ├── method-MAFTDipVXsOXj4o2CJLNQ.immutable.md
    │   │               ├── mongodb-store-37qsYI8A5ctkFlHTDVIc3O.immutable.md
    │   │               ├── navigator-5vNC9hp62PFUvxh0PLQcJ9.immutable.md
    │   │               ├── observable-7alzx5bqV1gD2Aj60hWQ0L.immutable.md
    │   │               ├── primary-identifier-attribute-5EqFynrkNUTa9DxYYmbmOl.immutable.md
    │   │               ├── property-bs5Xm31fCQXQkoZL24prZ.immutable.md
    │   │               ├── query-146gEiaHLp06V3LqhxRCzC.immutable.md
    │   │               ├── react-integration-4BgvR6gvTuqLdpNymyUYS1.immutable.md
    │   │               ├── role-3zJ3w6whE8RucN9kAhS5Hv.immutable.md
    │   │               ├── routable-7zjaksbkNa8sbNfqNnEKUu.immutable.md
    │   │               ├── route-3O1kMMGl4yZc9LGxH38Z3G.immutable.md
    │   │               ├── sanitizer-3hc34yGhzbK1cupoMtP6Dv.immutable.md
    │   │               ├── secondary-identifier-attribute-27lBtqHBopmgIAWwmeoLBg.immutable.md
    │   │               ├── storable-3UMrfeCfFVaVttjxtmCvVy.immutable.md
    │   │               ├── storable-attribute-1EYIvaUK2WvHmV3OxG5IzJ.immutable.md
    │   │               ├── storable-method-1o1egWUfiZzxO6y7Sda4rb.immutable.md
    │   │               ├── storable-primary-identifier-attribute-7qq06XjPnNRXumxcngJvZv.immutable.md
    │   │               ├── storable-property-6Ooq1wLy5pGx7Jb1qRrRyf.immutable.md
    │   │               ├── storable-secondary-identifier-attribute-1TKIxZX9JZ2aGFU5iEmUSv.immutable.md
    │   │               ├── store-1mGBVGCiO4K5X9dBakik9Z.immutable.md
    │   │               ├── validator-2aTKblcN30ADdXqrI3bHXv.immutable.md
    │   │               ├── value-type-FqKdGxNpEPIDVR56kq4NN.immutable.md
    │   │               ├── with-roles-CcLPnrWKVYxnZXgNTqVYi.immutable.md
    │   │               └── wrapper-4uhJFGS18pbZTt9qdtLnL2.immutable.md
    │   ├── src/
    │   │   ├── components/
    │   │   │   ├── application.tsx
    │   │   │   ├── article.tsx
    │   │   │   ├── blog.tsx
    │   │   │   ├── docs.tsx
    │   │   │   ├── home.tsx
    │   │   │   ├── newsletter.tsx
    │   │   │   └── user.tsx
    │   │   ├── custom.d.ts
    │   │   ├── docs.json
    │   │   ├── index.ts
    │   │   ├── markdown.tsx
    │   │   ├── styles.ts
    │   │   └── ui.tsx
    │   └── tsconfig.json
    ├── package.json
    └── redirection/
        ├── package.json
        ├── public/
        │   └── index.html
        └── simple-deployment.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false


================================================
FILE: .gitignore
================================================
.DS_Store
*.log
node_modules
.npmrc
package-lock.json
dist
build
_private
*.private.*


================================================
FILE: .npm-dev-registry.json
================================================
{
  "packages": ["./packages/*"]
}


================================================
FILE: .prettierignore
================================================
node_modules
dist
build


================================================
FILE: .vscode/extensions.json
================================================
{
  "recommendations": ["esbenp.prettier-vscode", "editorconfig.editorconfig"]
}


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

- The use of sexualized language or imagery, and sexual attention or
  advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
  address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
hello@layrjs.com.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Manuel Vila

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
<p align="center">
	<img src="assets/layr-logo-with-icon.svg" width="200" alt="Layr">
	<br>
	<br>
</p>

> Dramatically simplify full‑stack development.

## Documentation

Check out the [documentation](https://layrjs.com/docs) for a quick introduction and a comprehensive API description.

## Roadmap

### Components

- [x] Basic components
- [x] Controlled attributes
- [x] Component provision
- [x] Cross-layer inheritance
- [x] Remote method invocation
- [x] Optimized serialization
- [ ] Weak Identity Map
- [ ] Component subscriptions (realtime updates)
- [ ] HTTP Caching

### Storage

- [x] Basic storage (MongoDB)
- [x] Indexes
  - [x] Identifier attributes
  - [x] Regular attributes
  - [x] Compound attributes
  - [x] Referenced components
  - [x] Embedded components
- [ ] Automatic migrations
  - [x] Indexes
  - [ ] Default values
  - [ ] Renamed components
  - [ ] Renamed attributes
- [ ] Custom migrations
- [ ] Polymorphism
- [ ] Transactions
- [ ] Sugar to query reverse relationships
- [ ] Query subscriptions (realtime updates)
- [ ] Support for more databases (PostgreSQL, MySQL, DynamoDB,...)

### Routing

- [x] Basic routing
- [x] Nested routing

### Authorizations

- [x] Basic authorizations
- [x] Role-based authorizations

### Integrations

- [x] React integration
- [x] Basic AWS integration

## Contributing

Contributions are welcome.

Before contributing please read the [code of conduct](https://github.com/layrjs/layr/blob/master/CODE_OF_CONDUCT.md) and search the [issue tracker](https://github.com/layrjs/layr/issues) to find out if your issue has already been discussed before.

To contribute, [fork this repository](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo/), commit your changes, and [send a pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests).

## License

MIT


================================================
FILE: assets/frontend-backend.excalidraw
================================================
{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [
    {
      "id": "qmZPyH3vxEhjWDCfuvfXG",
      "type": "rectangle",
      "x": 473.40625,
      "y": -192.14453125,
      "width": 859.4531250000005,
      "height": 478.06640624999994,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "#263238",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1020737077,
      "version": 490,
      "versionNonce": 552337013,
      "isDeleted": false,
      "boundElementIds": null
    },
    {
      "type": "text",
      "version": 868,
      "versionNonce": 850464603,
      "isDeleted": false,
      "id": "pZqWf7TeaoVvLCg8jN1fw",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 629.6852678571429,
      "y": -62.34207589285717,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 110,
      "height": 35,
      "seed": 951595797,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Classes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "tzB0MO8qggda-Bt_Wm_TB",
      "type": "ellipse",
      "x": 518.53125,
      "y": -91.59375,
      "width": 328.45703124999994,
      "height": 328.45703124999994,
      "angle": 0,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1145563989,
      "version": 426,
      "versionNonce": 1479436245,
      "isDeleted": false,
      "boundElementIds": [
        "mO83jV49wubJCif3eCFF7"
      ]
    },
    {
      "type": "text",
      "version": 903,
      "versionNonce": 1445751803,
      "isDeleted": false,
      "id": "3XcH3jOWUovwndwQ5OWNZ",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 613.9001116071429,
      "y": -8.635044642857167,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 135,
      "height": 35,
      "seed": 1510068853,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Instances",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1064,
      "versionNonce": 1109173557,
      "isDeleted": false,
      "id": "jfBVn4_IY4-6kYgH4CLc2",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 541.4782366071429,
      "y": 44.08370535714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 145,
      "height": 35,
      "seed": 1265264027,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Attributes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1171,
      "versionNonce": 2001941659,
      "isDeleted": false,
      "id": "pbft6g1zEaKzjxE9qI4WH",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 713.2165178571429,
      "y": 43.12667410714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 109,
      "height": 35,
      "seed": 1694556846,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Methods",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1101,
      "versionNonce": 1109145237,
      "isDeleted": false,
      "id": "Ml8ehnX8s0BLj1BCSxw5v",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 602.6696428571429,
      "y": 101.35714285714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 479631835,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "References",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1129,
      "versionNonce": 634906939,
      "isDeleted": false,
      "id": "Lmij_syGf4Gxc0oIXhstt",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 608.6813616071429,
      "y": 157.23995535714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 622730715,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Exceptions",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 886,
      "versionNonce": 853711861,
      "isDeleted": false,
      "id": "g4v8TXu9aqJoc76AjvU5E",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1073.730189732143,
      "y": -65.31277901785715,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 110,
      "height": 35,
      "seed": 292264597,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Classes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "XS2Qi1--uR3zLQP7iXcp9",
      "type": "ellipse",
      "x": 962.576171875,
      "y": -92.56445312499999,
      "width": 328.45703124999994,
      "height": 328.45703124999994,
      "angle": 0,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1084278075,
      "version": 415,
      "versionNonce": 1461520859,
      "isDeleted": false,
      "boundElementIds": null
    },
    {
      "type": "text",
      "version": 923,
      "versionNonce": 2088064341,
      "isDeleted": false,
      "id": "2VgLJ7nXt0QOFYIBEIWAa",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1057.945033482143,
      "y": -13.605747767857153,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 135,
      "height": 35,
      "seed": 715489269,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Instances",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1083,
      "versionNonce": 808785531,
      "isDeleted": false,
      "id": "rOfltch3LXDrC9hL2pwbP",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 985.3278459821429,
      "y": 45.11300223214285,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 145,
      "height": 35,
      "seed": 1550476763,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Attributes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1190,
      "versionNonce": 1781129909,
      "isDeleted": false,
      "id": "woGF69RnnYqW_PttWeNeI",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1157.066127232143,
      "y": 44.15597098214285,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 109,
      "height": 35,
      "seed": 1111210325,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Methods",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1116,
      "versionNonce": 266506011,
      "isDeleted": false,
      "id": "vJWV-kfqxj7Mk8eWoWdTi",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1046.714564732143,
      "y": 104.45284598214283,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 1534521979,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "References",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1141,
      "versionNonce": 1084605461,
      "isDeleted": false,
      "id": "puaE8IFTDuN6P4YNxaFcX",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1052.726283482143,
      "y": 164.26925223214283,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 1904461493,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Exceptions",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "6iVlZb2OSireaYoyJCTfe",
      "type": "line",
      "x": 872.43359375,
      "y": 74.57421875,
      "width": 60.234375,
      "height": 0.82421875,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 298196123,
      "version": 294,
      "versionNonce": 1486353339,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          60.234375,
          -0.82421875
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "DKp1L9tGICjQBmD7WviKE",
      "type": "line",
      "x": 924,
      "y": 63.85156250000006,
      "width": 14.00390625,
      "height": 10.234375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 1899926395,
      "version": 295,
      "versionNonce": 333347189,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          14.00390625,
          10.234375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "2KOhHgB2-vgVjCIrzDoFC",
      "type": "line",
      "x": 938.40234375,
      "y": 73.69140625,
      "width": 19.35546875,
      "height": 14.65234375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 1385976021,
      "version": 289,
      "versionNonce": 2054669403,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          -19.35546875,
          14.65234375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "aMvlrbJ4JhavinX6IuIip",
      "type": "line",
      "x": 871.75,
      "y": 72.01171875,
      "width": 15.390625,
      "height": 8.05859375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 129732827,
      "version": 331,
      "versionNonce": 1561952981,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          15.390625,
          -8.05859375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "Heg0L7qNczN3uKd2rUc4H",
      "type": "line",
      "x": 869.2109375,
      "y": 74.93359375,
      "width": 20.64453125,
      "height": 12.38671875,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 592936059,
      "version": 337,
      "versionNonce": 1028948219,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          20.64453125,
          12.38671875
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "type": "text",
      "version": 1066,
      "versionNonce": 1357668405,
      "isDeleted": false,
      "id": "tGfMAIBrPStcxnXBLGc8q",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 605.6969866071429,
      "y": -156.91238839285717,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 152,
      "height": 45,
      "seed": 704809819,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Frontend",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1013,
      "versionNonce": 1253091739,
      "isDeleted": false,
      "id": "-eYtt3kyzRMtMkKUqbNJ1",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1053.138392857143,
      "y": -156.91238839285717,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 145,
      "height": 45,
      "seed": 553189045,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Backend",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    }
  ],
  "appState": {
    "viewBackgroundColor": "#000",
    "gridSize": null
  }
}

================================================
FILE: assets/frontend-webapi-backend.excalidraw
================================================
{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [
    {
      "id": "qmZPyH3vxEhjWDCfuvfXG",
      "type": "rectangle",
      "x": 284.2421875,
      "y": -189.6875,
      "width": 1237.3945312500002,
      "height": 478.06640624999994,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "#263238",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1020737077,
      "version": 359,
      "versionNonce": 815580763,
      "isDeleted": false,
      "boundElementIds": null
    },
    {
      "type": "text",
      "version": 677,
      "versionNonce": 1952969915,
      "isDeleted": false,
      "id": "pZqWf7TeaoVvLCg8jN1fw",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 439.0641741071429,
      "y": -59.88504464285717,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 110,
      "height": 35,
      "seed": 951595797,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Classes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "tzB0MO8qggda-Bt_Wm_TB",
      "type": "ellipse",
      "x": 327.91015625,
      "y": -89.13671875,
      "width": 328.45703124999994,
      "height": 328.45703124999994,
      "angle": 0,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1145563989,
      "version": 235,
      "versionNonce": 768854261,
      "isDeleted": false,
      "boundElementIds": [
        "mO83jV49wubJCif3eCFF7"
      ]
    },
    {
      "type": "text",
      "version": 712,
      "versionNonce": 1555921717,
      "isDeleted": false,
      "id": "3XcH3jOWUovwndwQ5OWNZ",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 423.2790178571429,
      "y": -6.178013392857167,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 135,
      "height": 35,
      "seed": 1510068853,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Instances",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 873,
      "versionNonce": 1655329909,
      "isDeleted": false,
      "id": "jfBVn4_IY4-6kYgH4CLc2",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 350.8571428571429,
      "y": 46.54073660714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 145,
      "height": 35,
      "seed": 1265264027,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Attributes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 980,
      "versionNonce": 858462555,
      "isDeleted": false,
      "id": "pbft6g1zEaKzjxE9qI4WH",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 522.5954241071429,
      "y": 45.58370535714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 109,
      "height": 35,
      "seed": 1694556846,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Methods",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 910,
      "versionNonce": 2116520635,
      "isDeleted": false,
      "id": "Ml8ehnX8s0BLj1BCSxw5v",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 412.0485491071429,
      "y": 103.81417410714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 479631835,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "References",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 938,
      "versionNonce": 402422619,
      "isDeleted": false,
      "id": "Lmij_syGf4Gxc0oIXhstt",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 418.0602678571429,
      "y": 159.69698660714283,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 622730715,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Exceptions",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 855,
      "versionNonce": 776023291,
      "isDeleted": false,
      "id": "g4v8TXu9aqJoc76AjvU5E",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1262.507533482143,
      "y": -62.85574776785715,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 110,
      "height": 35,
      "seed": 292264597,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Classes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "XS2Qi1--uR3zLQP7iXcp9",
      "type": "ellipse",
      "x": 1151.353515625,
      "y": -90.10742187499999,
      "width": 328.45703124999994,
      "height": 328.45703124999994,
      "angle": 0,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1084278075,
      "version": 384,
      "versionNonce": 863007797,
      "isDeleted": false,
      "boundElementIds": null
    },
    {
      "type": "text",
      "version": 892,
      "versionNonce": 1361565083,
      "isDeleted": false,
      "id": "2VgLJ7nXt0QOFYIBEIWAa",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1246.722377232143,
      "y": -11.148716517857153,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 135,
      "height": 35,
      "seed": 715489269,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Instances",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1052,
      "versionNonce": 291950453,
      "isDeleted": false,
      "id": "rOfltch3LXDrC9hL2pwbP",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1174.105189732143,
      "y": 47.57003348214285,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 145,
      "height": 35,
      "seed": 1550476763,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Attributes",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1159,
      "versionNonce": 952618587,
      "isDeleted": false,
      "id": "woGF69RnnYqW_PttWeNeI",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1345.843470982143,
      "y": 46.61300223214285,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 109,
      "height": 35,
      "seed": 1111210325,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Methods",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1085,
      "versionNonce": 785296117,
      "isDeleted": false,
      "id": "vJWV-kfqxj7Mk8eWoWdTi",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1235.491908482143,
      "y": 106.90987723214283,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 1534521979,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "References",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1110,
      "versionNonce": 1794992859,
      "isDeleted": false,
      "id": "puaE8IFTDuN6P4YNxaFcX",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1241.503627232143,
      "y": 166.72628348214283,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 148,
      "height": 35,
      "seed": 1904461493,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Exceptions",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "KHG3bd42lmlGY_6htw4yh",
      "type": "diamond",
      "x": 767.68359375,
      "y": -87.37890625,
      "width": 276.44140625000006,
      "height": 326.80859375,
      "angle": 0,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "seed": 1156814363,
      "version": 679,
      "versionNonce": 158888565,
      "isDeleted": false,
      "boundElementIds": null
    },
    {
      "type": "text",
      "version": 828,
      "versionNonce": 816995989,
      "isDeleted": false,
      "id": "PTJtBBiRYU7sirmpKXaaa",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 876.2438616071429,
      "y": -29.291294642857167,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 53,
      "height": 35,
      "seed": 1015869717,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Get",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 896,
      "versionNonce": 823673147,
      "isDeleted": false,
      "id": "Ui7ygay9V1Gwb_JPUnSoZ",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 835.4743303571429,
      "y": 21.189174107142833,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 64,
      "height": 35,
      "seed": 2081802805,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Post",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 1114,
      "versionNonce": 1014219765,
      "isDeleted": false,
      "id": "mCXJ_OIM1l6uuO5aerbPl",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 808.4547991071429,
      "y": 74.62667410714283,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 96,
      "height": 35,
      "seed": 872123483,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Delete",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 950,
      "versionNonce": 1217552859,
      "isDeleted": false,
      "id": "PvsMVeFX5yNreGLLR6cZl",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 929.6696428571429,
      "y": 23.579799107142833,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 48,
      "height": 35,
      "seed": 89552757,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Put",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 945,
      "versionNonce": 161578325,
      "isDeleted": false,
      "id": "wWagJGH0s7sy5ZggcAPSU",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 931.4508928571429,
      "y": 75.54464285714283,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 67,
      "height": 35,
      "seed": 1694554683,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "URLs",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 978,
      "versionNonce": 1301642165,
      "isDeleted": false,
      "id": "5uBcTnXeNlcF037DuFLt8",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 864.4860491071429,
      "y": 130.73604910714283,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 76,
      "height": 35,
      "seed": 989301691,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "JSON",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "id": "6iVlZb2OSireaYoyJCTfe",
      "type": "line",
      "x": 681.8125,
      "y": 77.03125,
      "width": 60.234375,
      "height": 0.82421875,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 298196123,
      "version": 103,
      "versionNonce": 1469817205,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          60.234375,
          -0.82421875
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "DKp1L9tGICjQBmD7WviKE",
      "type": "line",
      "x": 733.37890625,
      "y": 66.30859375000006,
      "width": 14.00390625,
      "height": 10.234375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 1899926395,
      "version": 104,
      "versionNonce": 981539931,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          14.00390625,
          10.234375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "2KOhHgB2-vgVjCIrzDoFC",
      "type": "line",
      "x": 747.78125,
      "y": 76.1484375,
      "width": 19.35546875,
      "height": 14.65234375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 1385976021,
      "version": 98,
      "versionNonce": 2129767125,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          -19.35546875,
          14.65234375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "aMvlrbJ4JhavinX6IuIip",
      "type": "line",
      "x": 681.12890625,
      "y": 74.46875,
      "width": 15.390625,
      "height": 8.05859375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 129732827,
      "version": 140,
      "versionNonce": 1651693819,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          15.390625,
          -8.05859375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "Heg0L7qNczN3uKd2rUc4H",
      "type": "line",
      "x": 678.58984375,
      "y": 77.390625,
      "width": 20.64453125,
      "height": 12.38671875,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 592936059,
      "version": 146,
      "versionNonce": 1434421301,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          20.64453125,
          12.38671875
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "MziFM0bqQkfptvWC6js9V",
      "type": "line",
      "x": 1065.697265625,
      "y": 81.41796874999997,
      "width": 60.234375,
      "height": 0.82421875,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 194372437,
      "version": 241,
      "versionNonce": 1782841755,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          60.234375,
          -0.82421875
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "1K59ruDxOFEs38bKS3wOR",
      "type": "line",
      "x": 1117.263671875,
      "y": 70.69531250000003,
      "width": 14.00390625,
      "height": 10.234375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 195848315,
      "version": 248,
      "versionNonce": 1294645653,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          14.00390625,
          10.234375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "HsDXwOGJ1sjxaRJXDDZvp",
      "type": "line",
      "x": 1131.666015625,
      "y": 80.53515624999997,
      "width": 19.35546875,
      "height": 14.65234375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 570994869,
      "version": 236,
      "versionNonce": 2066159163,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          -19.35546875,
          14.65234375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "0pX2lORYW_GourTAVS2dY",
      "type": "line",
      "x": 1065.013671875,
      "y": 78.85546874999997,
      "width": 15.390625,
      "height": 8.05859375,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 1688183067,
      "version": 278,
      "versionNonce": 2133376757,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          15.390625,
          -8.05859375
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "id": "V7OyGddYwmngOBKRWiOir",
      "type": "line",
      "x": 1062.474609375,
      "y": 81.77734374999997,
      "width": 20.64453125,
      "height": 12.38671875,
      "angle": 0,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "groupIds": [],
      "strokeSharpness": "round",
      "seed": 1870320149,
      "version": 284,
      "versionNonce": 1946064603,
      "isDeleted": false,
      "boundElementIds": null,
      "points": [
        [
          0,
          0
        ],
        [
          20.64453125,
          12.38671875
        ]
      ],
      "lastCommittedPoint": null,
      "startBinding": null,
      "endBinding": null
    },
    {
      "type": "text",
      "version": 875,
      "versionNonce": 1438821333,
      "isDeleted": false,
      "id": "tGfMAIBrPStcxnXBLGc8q",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 415.0758928571429,
      "y": -154.45535714285717,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 152,
      "height": 45,
      "seed": 704809819,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Frontend",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 932,
      "versionNonce": 1294663739,
      "isDeleted": false,
      "id": "D4N_3rWoMa0_PDwOF4QG4",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 829.7399553571429,
      "y": -150.45535714285717,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 149,
      "height": 45,
      "seed": 1200951285,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Web API",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 982,
      "versionNonce": 1744068155,
      "isDeleted": false,
      "id": "-eYtt3kyzRMtMkKUqbNJ1",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 1241.915736607143,
      "y": -154.45535714285717,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 145,
      "height": 45,
      "seed": 553189045,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Backend",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    }
  ],
  "appState": {
    "viewBackgroundColor": "#000",
    "gridSize": null
  }
}

================================================
FILE: assets/typical-stack-vs-layr-stack-light-mode.excalidraw
================================================
{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [
    {
      "type": "rectangle",
      "version": 518,
      "versionNonce": 1142497202,
      "isDeleted": false,
      "id": "78pcPSx_TrkBrqMvVMUaS",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 314.42578125,
      "y": -47.8984375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 250.83482142857142,
      "height": 67.28515625,
      "seed": 132882798,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": []
    },
    {
      "type": "text",
      "version": 203,
      "versionNonce": 2102357102,
      "isDeleted": false,
      "id": "Tg35xQQF7BB9-_T5IlAPi",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 345.87890625,
      "y": -31.755859375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 187,
      "height": 35,
      "seed": 74600110,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Data Access",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 722,
      "versionNonce": 1392400754,
      "isDeleted": false,
      "id": "isBhZDRkcIoWGbySBsLEy",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 51.353515625,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 252.4587053571429,
      "height": 67.28515625,
      "seed": 298779118,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": []
    },
    {
      "type": "text",
      "version": 403,
      "versionNonce": 633581230,
      "isDeleted": false,
      "id": "j7kpflnVnuaDP-1F5MCcc",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 340.42578125,
      "y": 67.49609375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 199,
      "height": 35,
      "seed": 11834414,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Backend Model",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 812,
      "versionNonce": 1284922162,
      "isDeleted": false,
      "id": "zk1Tzfs7TN7NuvV9nUrkK",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 150.568359375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 253.4743303571429,
      "height": 67.28515625,
      "seed": 1135815662,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "_q_pfShbWagNPeqr2Cw4q",
        "CzbKjuh5LlBF8vEsdGoYs",
        "euFzlspcyBdei7ZjDGsTE"
      ]
    },
    {
      "type": "text",
      "version": 429,
      "versionNonce": 854960366,
      "isDeleted": false,
      "id": "pbft6g1zEaKzjxE9qI4WH",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 366.1735491071429,
      "y": 166.48214285714283,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 152,
      "height": 35,
      "seed": 1694556846,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "API Server",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 837,
      "versionNonce": 1598563570,
      "isDeleted": false,
      "id": "G_sH-_BODgjExxHFIJUO7",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 313.0546875,
      "y": 251.623046875,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 251.515625,
      "height": 67.28515625,
      "seed": 2087476462,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "P-5Se_P31c9YU_W_jiyRL",
        "CzbKjuh5LlBF8vEsdGoYs"
      ]
    },
    {
      "type": "text",
      "version": 467,
      "versionNonce": 879647534,
      "isDeleted": false,
      "id": "FWR6GQyMu_VgSTbgtdktG",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 369.21205357142856,
      "y": 268.20647321428567,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 144,
      "height": 35,
      "seed": 82743086,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "API Client",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 813,
      "versionNonce": 1419425458,
      "isDeleted": false,
      "id": "RxupO9IzGSd0WgL0ECubS",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 355.587890625,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 253.07812500000003,
      "height": 67.28515625,
      "seed": 290532466,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "GNYre13yKH_YUl3IHWLJV",
        "f72O2kwJb9RVWZ6WUwfn-",
        "tcnX3h7U3Y7nCrYotIHRV",
        "P-5Se_P31c9YU_W_jiyRL"
      ]
    },
    {
      "type": "text",
      "version": 516,
      "versionNonce": 1620493678,
      "isDeleted": false,
      "id": "UJ8QgwFB2cterDA5_P1XR",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 337.83761160714283,
      "y": 370.9436383928572,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 205,
      "height": 35,
      "seed": 2132201010,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "uGtob-oyCnRKt3cM6Pyg_"
      ],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Frontend Model",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 900,
      "versionNonce": 758452338,
      "isDeleted": false,
      "id": "I5x5Y1aUFonRrUCGi6_jw",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 458.373046875,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 252.57421875000006,
      "height": 67.28515625,
      "seed": 1935830894,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "GNYre13yKH_YUl3IHWLJV",
        "f72O2kwJb9RVWZ6WUwfn-",
        "qDACPeHQipsh0zAP-atrl"
      ]
    },
    {
      "type": "text",
      "version": 591,
      "versionNonce": 951576494,
      "isDeleted": false,
      "id": "Ozy5i1Z2EEzX3kAVJ5IY9",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 335.1579241071429,
      "y": 474.50446428571445,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 207,
      "height": 35,
      "seed": 1037108850,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "uGtob-oyCnRKt3cM6Pyg_"
      ],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "User Interface",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 1078,
      "versionNonce": 1083733508,
      "isDeleted": false,
      "id": "BK5gVfRenINsXjknIgSxf",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "dotted",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 695.0412946428572,
      "y": 153.30106026785717,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 195.533482142857,
      "height": 67.28515625,
      "seed": 544079922,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "xQNTkIrt5bvAXhVmKvBxM",
        "hTkLQGX8fKKkms2V_vm0r",
        "CzbKjuh5LlBF8vEsdGoYs",
        "mnKhSKUhk7EFCekLtz1fQ"
      ]
    },
    {
      "type": "text",
      "version": 787,
      "versionNonce": 198499388,
      "isDeleted": false,
      "id": "iQoD1G_MsPZm4xfuufUxe",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 734.5055803571429,
      "y": 168.5563616071429,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 113,
      "height": 35,
      "seed": 48441842,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Backend",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 1220,
      "versionNonce": 1839404420,
      "isDeleted": false,
      "id": "pCkj2Qaeh9PDMAzSCWPM9",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "dotted",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 694.9520089285714,
      "y": 252.49637276785717,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 193.7477678571429,
      "height": 67.28515625,
      "seed": 374338158,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "xQNTkIrt5bvAXhVmKvBxM",
        "hTkLQGX8fKKkms2V_vm0r",
        "mnKhSKUhk7EFCekLtz1fQ"
      ]
    },
    {
      "type": "text",
      "version": 810,
      "versionNonce": 31847612,
      "isDeleted": false,
      "id": "-CvZWfngqmHMBLZxpCqri",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 732.0145089285714,
      "y": 269.67131696428584,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 119,
      "height": 35,
      "seed": 415462574,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Frontend",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 1501,
      "versionNonce": 1865270532,
      "isDeleted": false,
      "id": "MSfRFHL5NGAG-wZc7hZub",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 664.8816964285714,
      "y": 117.36356026785717,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 252.3643973214285,
      "height": 231.47656249999994,
      "seed": 153297006,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "CzbKjuh5LlBF8vEsdGoYs",
        "euFzlspcyBdei7ZjDGsTE"
      ]
    },
    {
      "type": "text",
      "version": 347,
      "versionNonce": 1710969860,
      "isDeleted": false,
      "id": "HblX02yOmNDLcQXmIx14_",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 318.7762276785714,
      "y": -124.638671875,
      "strokeColor": "#607d8b",
      "backgroundColor": "transparent",
      "width": 244,
      "height": 45,
      "seed": 1398208946,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Typical Stack",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 666,
      "versionNonce": 152493628,
      "isDeleted": false,
      "id": "oi9Jo0SrqAcTWeuWmDnFT",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 670.4157366071428,
      "y": 42.34793526785717,
      "strokeColor": "#607d8b",
      "backgroundColor": "transparent",
      "width": 241,
      "height": 45,
      "seed": 1175668722,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Layr Stack",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 864,
      "versionNonce": 459154052,
      "isDeleted": false,
      "id": "snrOZbuQdOfsbwfDVsvOh",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 259.15066964285734,
      "y": -163.32142857142867,
      "strokeColor": "#607d8b",
      "backgroundColor": "transparent",
      "width": 711.9587053571425,
      "height": 743.0351562500001,
      "seed": 2001414322,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": []
    },
    {
      "type": "arrow",
      "version": 746,
      "versionNonce": 926940476,
      "isDeleted": false,
      "id": "mnKhSKUhk7EFCekLtz1fQ",
      "fillStyle": "solid",
      "strokeWidth": 1,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 795.6113691236103,
      "y": 251.49637276785717,
      "strokeColor": "#ff4081",
      "backgroundColor": "transparent",
      "width": 0.5444303450863117,
      "height": 29.553292410714278,
      "seed": 1730055982,
      "groupIds": [],
      "strokeSharpness": "round",
      "boundElementIds": [],
      "startBinding": {
        "elementId": "pCkj2Qaeh9PDMAzSCWPM9",
        "focus": 0.032282012887604794,
        "gap": 1
      },
      "endBinding": {
        "elementId": "BK5gVfRenINsXjknIgSxf",
        "focus": -0.040579986296433085,
        "gap": 1.3568638392857224
      },
      "points": [
        [
          0,
          0
        ],
        [
          0.5444303450863117,
          -29.553292410714278
        ]
      ],
      "lastCommittedPoint": null
    },
    {
      "type": "arrow",
      "version": 55,
      "versionNonce": 1268233916,
      "isDeleted": false,
      "id": "euFzlspcyBdei7ZjDGsTE",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 583.1283482142857,
      "y": 234.59709821428572,
      "strokeColor": "#607d8b",
      "backgroundColor": "transparent",
      "width": 62.05624021153369,
      "height": 0.7102786712734144,
      "seed": 1376797106,
      "groupIds": [],
      "strokeSharpness": "round",
      "boundElementIds": [],
      "startBinding": {
        "elementId": "zk1Tzfs7TN7NuvV9nUrkK",
        "focus": 1.4825585590033774,
        "gap": 16.743582589285722
      },
      "endBinding": {
        "elementId": "MSfRFHL5NGAG-wZc7hZub",
        "focus": 0.0075499005148347426,
        "gap": 19.697108002752145
      },
      "points": [
        [
          0,
          0
        ],
        [
          62.05624021153369,
          -0.7102786712734144
        ]
      ],
      "lastCommittedPoint": null
    }
  ],
  "appState": {
    "viewBackgroundColor": "#ffffff",
    "gridSize": null
  }
}


================================================
FILE: assets/typical-stack-vs-layr-stack.excalidraw
================================================
{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [
    {
      "type": "rectangle",
      "version": 518,
      "versionNonce": 1142497202,
      "isDeleted": false,
      "id": "78pcPSx_TrkBrqMvVMUaS",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 314.42578125,
      "y": -47.8984375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 250.83482142857142,
      "height": 67.28515625,
      "seed": 132882798,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": []
    },
    {
      "type": "text",
      "version": 203,
      "versionNonce": 2102357102,
      "isDeleted": false,
      "id": "Tg35xQQF7BB9-_T5IlAPi",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 345.87890625,
      "y": -31.755859375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 187,
      "height": 35,
      "seed": 74600110,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Data Access",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 722,
      "versionNonce": 1392400754,
      "isDeleted": false,
      "id": "isBhZDRkcIoWGbySBsLEy",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 51.353515625,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 252.4587053571429,
      "height": 67.28515625,
      "seed": 298779118,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": []
    },
    {
      "type": "text",
      "version": 403,
      "versionNonce": 633581230,
      "isDeleted": false,
      "id": "j7kpflnVnuaDP-1F5MCcc",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 340.42578125,
      "y": 67.49609375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 199,
      "height": 35,
      "seed": 11834414,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Backend Model",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 812,
      "versionNonce": 1284922162,
      "isDeleted": false,
      "id": "zk1Tzfs7TN7NuvV9nUrkK",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 150.568359375,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 253.4743303571429,
      "height": 67.28515625,
      "seed": 1135815662,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "_q_pfShbWagNPeqr2Cw4q",
        "CzbKjuh5LlBF8vEsdGoYs",
        "euFzlspcyBdei7ZjDGsTE"
      ]
    },
    {
      "type": "text",
      "version": 429,
      "versionNonce": 854960366,
      "isDeleted": false,
      "id": "pbft6g1zEaKzjxE9qI4WH",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 366.1735491071429,
      "y": 166.48214285714283,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 152,
      "height": 35,
      "seed": 1694556846,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "API Server",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 837,
      "versionNonce": 1598563570,
      "isDeleted": false,
      "id": "G_sH-_BODgjExxHFIJUO7",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 313.0546875,
      "y": 251.623046875,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 251.515625,
      "height": 67.28515625,
      "seed": 2087476462,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "P-5Se_P31c9YU_W_jiyRL",
        "CzbKjuh5LlBF8vEsdGoYs"
      ]
    },
    {
      "type": "text",
      "version": 467,
      "versionNonce": 879647534,
      "isDeleted": false,
      "id": "FWR6GQyMu_VgSTbgtdktG",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 369.21205357142856,
      "y": 268.20647321428567,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 144,
      "height": 35,
      "seed": 82743086,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "API Client",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 813,
      "versionNonce": 1419425458,
      "isDeleted": false,
      "id": "RxupO9IzGSd0WgL0ECubS",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 355.587890625,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 253.07812500000003,
      "height": 67.28515625,
      "seed": 290532466,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "GNYre13yKH_YUl3IHWLJV",
        "f72O2kwJb9RVWZ6WUwfn-",
        "tcnX3h7U3Y7nCrYotIHRV",
        "P-5Se_P31c9YU_W_jiyRL"
      ]
    },
    {
      "type": "text",
      "version": 516,
      "versionNonce": 1620493678,
      "isDeleted": false,
      "id": "UJ8QgwFB2cterDA5_P1XR",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 337.83761160714283,
      "y": 370.9436383928572,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 205,
      "height": 35,
      "seed": 2132201010,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "uGtob-oyCnRKt3cM6Pyg_"
      ],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Frontend Model",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 900,
      "versionNonce": 758452338,
      "isDeleted": false,
      "id": "I5x5Y1aUFonRrUCGi6_jw",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 312.97265625,
      "y": 458.373046875,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 252.57421875000006,
      "height": 67.28515625,
      "seed": 1935830894,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "GNYre13yKH_YUl3IHWLJV",
        "f72O2kwJb9RVWZ6WUwfn-",
        "qDACPeHQipsh0zAP-atrl"
      ]
    },
    {
      "type": "text",
      "version": 591,
      "versionNonce": 951576494,
      "isDeleted": false,
      "id": "Ozy5i1Z2EEzX3kAVJ5IY9",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 335.1579241071429,
      "y": 474.50446428571445,
      "strokeColor": "#03a9f4",
      "backgroundColor": "transparent",
      "width": 207,
      "height": 35,
      "seed": 1037108850,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "uGtob-oyCnRKt3cM6Pyg_"
      ],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "User Interface",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 1077,
      "versionNonce": 1021194802,
      "isDeleted": false,
      "id": "BK5gVfRenINsXjknIgSxf",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "dotted",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 695.0412946428572,
      "y": 153.30106026785717,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 195.533482142857,
      "height": 67.28515625,
      "seed": 544079922,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "xQNTkIrt5bvAXhVmKvBxM",
        "hTkLQGX8fKKkms2V_vm0r",
        "CzbKjuh5LlBF8vEsdGoYs",
        "mnKhSKUhk7EFCekLtz1fQ"
      ]
    },
    {
      "type": "text",
      "version": 786,
      "versionNonce": 754631150,
      "isDeleted": false,
      "id": "iQoD1G_MsPZm4xfuufUxe",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 734.5055803571429,
      "y": 168.5563616071429,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 113,
      "height": 35,
      "seed": 48441842,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Backend",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 1219,
      "versionNonce": 1182604274,
      "isDeleted": false,
      "id": "pCkj2Qaeh9PDMAzSCWPM9",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "dotted",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 694.9520089285714,
      "y": 252.49637276785717,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 193.7477678571429,
      "height": 67.28515625,
      "seed": 374338158,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "xQNTkIrt5bvAXhVmKvBxM",
        "hTkLQGX8fKKkms2V_vm0r",
        "mnKhSKUhk7EFCekLtz1fQ"
      ]
    },
    {
      "type": "text",
      "version": 809,
      "versionNonce": 1080579118,
      "isDeleted": false,
      "id": "-CvZWfngqmHMBLZxpCqri",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 732.0145089285714,
      "y": 269.67131696428584,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 119,
      "height": 35,
      "seed": 415462574,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 28,
      "fontFamily": 1,
      "text": "Frontend",
      "baseline": 25,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 1500,
      "versionNonce": 404278706,
      "isDeleted": false,
      "id": "MSfRFHL5NGAG-wZc7hZub",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 664.8816964285714,
      "y": 117.36356026785717,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 252.3643973214285,
      "height": 231.47656249999994,
      "seed": 153297006,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [
        "CzbKjuh5LlBF8vEsdGoYs",
        "euFzlspcyBdei7ZjDGsTE"
      ]
    },
    {
      "type": "text",
      "version": 346,
      "versionNonce": 1998441774,
      "isDeleted": false,
      "id": "HblX02yOmNDLcQXmIx14_",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 318.7762276785714,
      "y": -124.638671875,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 244,
      "height": 45,
      "seed": 1398208946,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Typical Stack",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "text",
      "version": 665,
      "versionNonce": 848204036,
      "isDeleted": false,
      "id": "oi9Jo0SrqAcTWeuWmDnFT",
      "fillStyle": "hachure",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 670.4157366071428,
      "y": 42.34793526785717,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 241,
      "height": 45,
      "seed": 1175668722,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": [],
      "fontSize": 36,
      "fontFamily": 1,
      "text": "Layr Stack",
      "baseline": 32,
      "textAlign": "center",
      "verticalAlign": "top"
    },
    {
      "type": "rectangle",
      "version": 863,
      "versionNonce": 1082652526,
      "isDeleted": false,
      "id": "snrOZbuQdOfsbwfDVsvOh",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 259.15066964285734,
      "y": -163.32142857142867,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 711.9587053571425,
      "height": 743.0351562500001,
      "seed": 2001414322,
      "groupIds": [],
      "strokeSharpness": "sharp",
      "boundElementIds": []
    },
    {
      "type": "arrow",
      "version": 745,
      "versionNonce": 1705508466,
      "isDeleted": false,
      "id": "mnKhSKUhk7EFCekLtz1fQ",
      "fillStyle": "solid",
      "strokeWidth": 1,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 795.6113691236103,
      "y": 251.49637276785717,
      "strokeColor": "#aeea00",
      "backgroundColor": "transparent",
      "width": 0.5444303450863117,
      "height": 29.553292410714278,
      "seed": 1730055982,
      "groupIds": [],
      "strokeSharpness": "round",
      "boundElementIds": [],
      "startBinding": {
        "elementId": "pCkj2Qaeh9PDMAzSCWPM9",
        "focus": 0.032282012887604794,
        "gap": 1
      },
      "endBinding": {
        "elementId": "BK5gVfRenINsXjknIgSxf",
        "focus": -0.040579986296433085,
        "gap": 1.3568638392857224
      },
      "points": [
        [
          0,
          0
        ],
        [
          0.5444303450863117,
          -29.553292410714278
        ]
      ],
      "lastCommittedPoint": null
    },
    {
      "type": "arrow",
      "version": 54,
      "versionNonce": 79913010,
      "isDeleted": false,
      "id": "euFzlspcyBdei7ZjDGsTE",
      "fillStyle": "solid",
      "strokeWidth": 2,
      "strokeStyle": "solid",
      "roughness": 1,
      "opacity": 100,
      "angle": 0,
      "x": 583.1283482142857,
      "y": 234.59709821428572,
      "strokeColor": "#eceff1",
      "backgroundColor": "transparent",
      "width": 62.05624021153369,
      "height": 0.7102786712734144,
      "seed": 1376797106,
      "groupIds": [],
      "strokeSharpness": "round",
      "boundElementIds": [],
      "startBinding": {
        "elementId": "zk1Tzfs7TN7NuvV9nUrkK",
        "focus": 1.4825585590033774,
        "gap": 16.743582589285722
      },
      "endBinding": {
        "elementId": "MSfRFHL5NGAG-wZc7hZub",
        "focus": 0.0075499005148347426,
        "gap": 19.697108002752145
      },
      "points": [
        [
          0,
          0
        ],
        [
          62.05624021153369,
          -0.7102786712734144
        ]
      ],
      "lastCommittedPoint": null
    }
  ],
  "appState": {
    "viewBackgroundColor": "#000",
    "gridSize": null
  }
}


================================================
FILE: docs/build.js
================================================
const {buildDocumentation, freezeDocumentation} = require('@mvila/simple-doc');
const {copySync, removeSync, readJsonSync, writeJSONSync} = require('fs-extra');
const path = require('path');

const VERSION = 'v2';

const SOURCE_DIRECTORY = './contents';
const BUILD_DIRECTORY = './build';
const WEBSITE_DIRECTORY = '../website/frontend/public/docs';
const WEBSITE_INDEX_FILE = '../website/frontend/src/docs.json';

const sourceDirectory = path.resolve(__dirname, SOURCE_DIRECTORY);
const buildDirectory = path.resolve(__dirname, BUILD_DIRECTORY);
const websiteDirectory = path.resolve(__dirname, WEBSITE_DIRECTORY);
const websiteIndexFile = path.resolve(__dirname, WEBSITE_INDEX_FILE);

buildDocumentation(sourceDirectory, buildDirectory);

freezeDocumentation(buildDirectory);

console.log(`Writing index file to '${path.relative(process.cwd(), websiteIndexFile)}'...`);

const builtIndexFile = path.join(buildDirectory, 'index.json');

const builtIndex = readJsonSync(builtIndexFile);
const websiteIndex = readJsonSync(websiteIndexFile);

websiteIndex.versions[VERSION] = builtIndex;

writeJSONSync(websiteIndexFile, websiteIndex, {spaces: 2});

const websiteDirectoryWithVersion = path.join(websiteDirectory, VERSION);

console.log(
  `Copying contents to '${path.relative(process.cwd(), websiteDirectoryWithVersion)}'...`
);

removeSync(websiteDirectoryWithVersion);

copySync(buildDirectory, websiteDirectoryWithVersion, {
  filter(source) {
    return source !== builtIndexFile;
  }
});


================================================
FILE: docs/contents/concepts/coming-soon.md
================================================
### Concepts

#### Coming Soon

This section will introduce the basic concepts of Layr, such as:

- Components
- Controlled attributes and methods
- Cross-layer inheritance
- Storage
- Routes and wrappers

Unfortunately, writing documentation takes a lot of time, and the Layr project is currently handled by a [single person](https://mvila.me) who has to work for customers to make a living and is also starting a new [ambitious project](https://1place.app), which will be based on Layr.

More documentation will come for sure, but please be patient.

If you cannot wait and feel adventurous, you can figure out how to build an app with Layr by checking out:

- The ["Hello, World!"](https://layrjs.com/docs/v2/introduction/hello-world) introductory app.
- The pretty exhaustive ["Reference"](https://layrjs.com/docs/v2/reference) section.
- Some [examples](https://layrjs.com/docs/v2/introduction/introduction#examples) of simple full-stack apps built with Layr.


================================================
FILE: docs/contents/guides/coming-soon.md
================================================
### Guides

#### Coming Soon

This section will contain some guides explaining how to achieve the most common tasks and features with Layr, such as:

- Local development
- Layouts and pages
- Data fetching and storage
- Authentication
- Testing
- Deployment

Unfortunately, writing documentation takes a lot of time, and the Layr project is currently handled by a [single person](https://mvila.me) who has to work for customers to make a living and is also starting a new [ambitious project](https://1place.app), which will be based on Layr.

More documentation will come for sure, but please be patient.

If you cannot wait and feel adventurous, you can figure out how to build an app with Layr by checking out:

- The ["Hello, World!"](https://layrjs.com/docs/v2/introduction/hello-world) introductory app.
- The pretty exhaustive ["Reference"](https://layrjs.com/docs/v2/reference) section.
- Some [examples](https://layrjs.com/docs/v2/introduction/introduction#examples) of simple full-stack apps built with Layr.


================================================
FILE: docs/contents/index.json
================================================
{
  "books": [
    {
      "title": "Getting Started",
      "slug": "introduction",
      "chapters": [
        {
          "title": "Introduction",
          "slug": "introduction",
          "file": "introduction/introduction.md"
        },
        {
          "title": "Hello, World!",
          "slug": "hello-world",
          "file": "introduction/hello-world/hello-world.md",
          "assets": "introduction/hello-world/assets"
        },
        {
          "title": "Storing Data",
          "slug": "storing-data",
          "file": "introduction/storing-data.md"
        },
        {
          "title": "Handling Authorization",
          "slug": "handling-authorization",
          "file": "introduction/handling-authorization.md"
        }
      ]
    },
    {
      "title": "Concepts",
      "slug": "concepts",
      "chapters": [
        {
          "title": "Coming Soon",
          "slug": "coming-soon",
          "file": "concepts/coming-soon.md"
        }
      ]
    },
    {
      "title": "Guides",
      "slug": "guides",
      "chapters": [
        {
          "title": "Coming Soon",
          "slug": "coming-soon",
          "file": "guides/coming-soon.md"
        }
      ]
    },
    {
      "title": "Reference",
      "slug": "reference",
      "chapters": [
        {
          "title": "Component",
          "slug": "component",
          "file": "reference/component.md",
          "source": [
            "../../packages/component/src/component.ts",
            "../../packages/component/src/cloning.ts",
            "../../packages/component/src/forking.ts",
            "../../packages/component/src/merging.ts",
            "../../packages/component/src/serialization.ts",
            "../../packages/component/src/deserialization.ts",
            "../../packages/component/src/decorators.ts",
            "../../packages/component/src/utilities.ts"
          ],
          "category": "Basics"
        },
        {
          "title": "EmbeddedComponent",
          "slug": "embedded-component",
          "file": "reference/embedded-component.md",
          "source": "../../packages/component/src/embedded-component.ts",
          "category": "Basics"
        },
        {
          "title": "Property",
          "slug": "property",
          "file": "reference/property.md",
          "source": "../../packages/component/src/properties/property.ts",
          "category": "Basics"
        },
        {
          "title": "Attribute",
          "slug": "attribute",
          "file": "reference/attribute.md",
          "source": "../../packages/component/src/properties/attribute.ts",
          "category": "Basics"
        },
        {
          "title": "IdentifierAttribute",
          "slug": "identifier-attribute",
          "file": "reference/identifier-attribute.md",
          "source": "../../packages/component/src/properties/identifier-attribute.ts",
          "category": "Basics"
        },
        {
          "title": "PrimaryIdentifierAttribute",
          "slug": "primary-identifier-attribute",
          "file": "reference/primary-identifier-attribute.md",
          "source": "../../packages/component/src/properties/primary-identifier-attribute.ts",
          "category": "Basics"
        },
        {
          "title": "SecondaryIdentifierAttribute",
          "slug": "secondary-identifier-attribute",
          "file": "reference/secondary-identifier-attribute.md",
          "source": "../../packages/component/src/properties/secondary-identifier-attribute.ts",
          "category": "Basics"
        },
        {
          "title": "Method",
          "slug": "method",
          "file": "reference/method.md",
          "source": "../../packages/component/src/properties/method.ts",
          "category": "Basics"
        },
        {
          "title": "ValueType",
          "slug": "value-type",
          "file": "reference/value-type.md",
          "source": "../../packages/component/src/properties/value-types/value-type.ts",
          "category": "Basics"
        },
        {
          "title": "Sanitizer",
          "slug": "sanitizer",
          "file": "reference/sanitizer.md",
          "source": "../../packages/component/src/sanitization/sanitizer.ts",
          "category": "Basics"
        },
        {
          "title": "Validator",
          "slug": "validator",
          "file": "reference/validator.md",
          "source": "../../packages/component/src/validation/validator.ts",
          "category": "Basics"
        },
        {
          "title": "AttributeSelector",
          "slug": "attribute-selector",
          "file": "reference/attribute-selector.md",
          "source": "../../packages/component/src/properties/attribute-selector.ts",
          "category": "Basics"
        },
        {
          "title": "IdentityMap",
          "slug": "identity-map",
          "file": "reference/identity-map.md",
          "source": "../../packages/component/src/identity-map.ts",
          "category": "Basics"
        },
        {
          "title": "ComponentClient",
          "slug": "component-client",
          "file": "reference/component-client.md",
          "source": "../../packages/component-client/src/component-client.ts",
          "category": "Communication"
        },
        {
          "title": "ComponentServer",
          "slug": "component-server",
          "file": "reference/component-server.md",
          "source": "../../packages/component-server/src/component-server.ts",
          "category": "Communication"
        },
        {
          "title": "ComponentHTTPClient",
          "slug": "component-http-client",
          "file": "reference/component-http-client.md",
          "source": "../../packages/component-http-client/src/component-http-client.ts",
          "category": "Communication"
        },
        {
          "title": "ComponentHTTPServer",
          "slug": "component-http-server",
          "file": "reference/component-http-server.md",
          "source": "../../packages/component-http-server/src/component-http-server.ts",
          "category": "Communication"
        },
        {
          "title": "component-express-middleware",
          "slug": "component-express-middleware",
          "file": "reference/component-express-middleware.md",
          "source": "../../packages/component-express-middleware/src/component-express-middleware.ts",
          "category": "Communication"
        },
        {
          "title": "component-koa-middleware",
          "slug": "component-koa-middleware",
          "file": "reference/component-koa-middleware.md",
          "source": "../../packages/component-koa-middleware/src/component-koa-middleware.ts",
          "category": "Communication"
        },
        {
          "title": "Storable()",
          "slug": "storable",
          "file": "reference/storable.md",
          "source": [
            "../../packages/storable/src/storable.ts",
            "../../packages/storable/src/decorators.ts",
            "../../packages/storable/src/utilities.ts"
          ],
          "category": "Storage"
        },
        {
          "title": "StorableProperty",
          "slug": "storable-property",
          "file": "reference/storable-property.md",
          "source": ["../../packages/storable/src/properties/storable-property.ts"],
          "category": "Storage"
        },
        {
          "title": "StorableAttribute",
          "slug": "storable-attribute",
          "file": "reference/storable-attribute.md",
          "source": ["../../packages/storable/src/properties/storable-attribute.ts"],
          "category": "Storage"
        },
        {
          "title": "StorablePrimaryIdentifierAttribute",
          "slug": "storable-primary-identifier-attribute",
          "file": "reference/storable-primary-identifier-attribute.md",
          "source": [
            "../../packages/storable/src/properties/storable-primary-identifier-attribute.ts"
          ],
          "category": "Storage"
        },
        {
          "title": "StorableSecondaryIdentifierAttribute",
          "slug": "storable-secondary-identifier-attribute",
          "file": "reference/storable-secondary-identifier-attribute.md",
          "source": [
            "../../packages/storable/src/properties/storable-secondary-identifier-attribute.ts"
          ],
          "category": "Storage"
        },
        {
          "title": "StorableMethod",
          "slug": "storable-method",
          "file": "reference/storable-method.md",
          "source": ["../../packages/storable/src/properties/storable-method.ts"],
          "category": "Storage"
        },
        {
          "title": "Query",
          "slug": "query",
          "file": "reference/query.md",
          "source": "../../packages/storable/src/query.ts",
          "category": "Storage"
        },
        {
          "title": "Index",
          "slug": "index",
          "file": "reference/index.md",
          "source": "../../packages/storable/src/index-class.ts",
          "category": "Storage"
        },
        {
          "title": "Store",
          "slug": "store",
          "file": "reference/store.md",
          "source": "../../packages/store/src/store.ts",
          "category": "Storage"
        },
        {
          "title": "MongoDBStore",
          "slug": "mongodb-store",
          "file": "reference/mongodb-store.md",
          "source": "../../packages/mongodb-store/src/mongodb-store.ts",
          "category": "Storage"
        },
        {
          "title": "MemoryStore",
          "slug": "memory-store",
          "file": "reference/memory-store.md",
          "source": "../../packages/memory-store/src/memory-store.ts",
          "category": "Storage"
        },
        {
          "title": "Routable()",
          "slug": "routable",
          "file": "reference/routable.md",
          "source": [
            "../../packages/routable/src/routable.ts",
            "../../packages/routable/src/decorators.ts",
            "../../packages/routable/src/utilities.ts"
          ],
          "category": "Routing"
        },
        {
          "title": "Addressable",
          "slug": "addressable",
          "file": "reference/addressable.md",
          "source": "../../packages/routable/src/addressable.ts",
          "category": "Routing"
        },
        {
          "title": "Route",
          "slug": "route",
          "file": "reference/route.md",
          "source": "../../packages/routable/src/route.ts",
          "category": "Routing"
        },
        {
          "title": "Wrapper",
          "slug": "wrapper",
          "file": "reference/wrapper.md",
          "source": "../../packages/routable/src/wrapper.ts",
          "category": "Routing"
        },
        {
          "title": "Navigator",
          "slug": "navigator",
          "file": "reference/navigator.md",
          "source": [
            "../../packages/navigator/src/navigator.ts",
            "../../packages/navigator/src/utilities.ts"
          ],
          "category": "Routing"
        },
        {
          "title": "BrowserNavigator",
          "slug": "browser-navigator",
          "file": "reference/browser-navigator.md",
          "source": "../../packages/browser-navigator/src/browser-navigator.ts",
          "category": "Routing"
        },
        {
          "title": "MemoryNavigator",
          "slug": "memory-navigator",
          "file": "reference/memory-navigator.md",
          "source": "../../packages/memory-navigator/src/memory-navigator.ts",
          "category": "Routing"
        },
        {
          "title": "WithRoles()",
          "slug": "with-roles",
          "file": "reference/with-roles.md",
          "source": [
            "../../packages/with-roles/src/with-roles.ts",
            "../../packages/with-roles/src/decorators.ts",
            "../../packages/with-roles/src/utilities.ts"
          ],
          "category": "Authorization"
        },
        {
          "title": "Role",
          "slug": "role",
          "file": "reference/role.md",
          "source": "../../packages/with-roles/src/role.ts",
          "category": "Authorization"
        },
        {
          "title": "aws-integration",
          "slug": "aws-integration",
          "file": "reference/aws-integration.md",
          "source": [
            "../../packages/aws-integration/src/index.ts",
            "../../packages/aws-integration/src/lambda-handler.ts"
          ],
          "category": "Integrations"
        },
        {
          "title": "react-integration",
          "slug": "react-integration",
          "file": "reference/react-integration.md",
          "source": [
            "../../packages/react-integration/src/index.ts",
            "../../packages/react-integration/src/components.tsx",
            "../../packages/react-integration/src/decorators.tsx",
            "../../packages/react-integration/src/hooks.ts"
          ],
          "category": "Integrations"
        },
        {
          "title": "Observable()",
          "slug": "observable",
          "file": "reference/observable.md",
          "source": "../../packages/observable/src/observable.ts",
          "category": "Utilities"
        }
      ]
    }
  ]
}


================================================
FILE: docs/contents/introduction/handling-authorization.md
================================================
### Handling Authorization

#### Coming Soon

This tutorial will expand the ["Hello, World!"](https://layrjs.com/docs/v2/introduction/hello-world) app to show you how Layr handles user authorization.

Unfortunately, writing tutorials takes a lot of time, and the Layr project is currently handled by a [single person](https://mvila.me) who has to work for customers to make a living and is also starting a new [ambitious project](https://1place.app), which will be based on Layr.

This tutorial will come for sure, but please be patient.

If you cannot wait and feel adventurous, you can figure out how to handle authorization with Layr by checking out:

- The [`WithRoles()`](https://layrjs.com/docs/v2/reference/with-roles) mixin in the "Reference" section.
- Some examples of simple full-stack apps handling authorization with Layr:
  - [Layr Website (TS)](https://github.com/layrjs/layr/tree/master/website)
  - [CodebaseShow (TS)](https://github.com/codebaseshow/codebaseshow)
  - [RealWorld Example App (JS)](https://github.com/layrjs/react-layr-realworld-example-app)


================================================
FILE: docs/contents/introduction/hello-world/hello-world.md
================================================
### Hello, World!

Let's start our journey into Layr by implementing the mandatory ["Hello, World!"](https://en.wikipedia.org/wiki/%22Hello,_World!%22_program) app, and let's make it object-oriented and full-stack!

> **Note**: Layr supports both [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) and [TypeScript](https://www.typescriptlang.org/). To select your language of choice, use the drop-down menu on the left.

> **TLDR**: The completed app is available in the <!-- <if language="js"> -->[Layr repository](https://github.com/layrjs/layr/tree/master/examples/v2/hello-world-js)<!-- </if> --><!-- <if language="ts"> -->[Layr repository](https://github.com/layrjs/layr/tree/master/examples/v2/hello-world-ts)<!-- </if> -->.

#### Prerequisites

- You use a Mac with a recent version of macOS. Everything should work fine on Linux, but we haven't tested it yet. It may work on Windows, but we haven't tested it and don't plan to provide support for now.
- You have [Node.js](https://nodejs.org/) v16 or newer installed.
- You are familiar with [React](https://reactjs.org/), which is used in this tutorial.

#### Creating the App

To make things easier, we'll use [Boostr](https://boostr.dev) to create the app and manage the local development environment.

Boostr is a companion tool for Layr that takes care of everything you need to build and deploy a Layr app so you can focus on what really matters — the app's code.

So, first of all, we have to install Boostr. Run the following command in your terminal:

```sh
npm install --global boostr
```

> **Notes**:
>
> - Depending on your Node.js installation, you may have to prefix the command with `sudo` so the package can be installed globally.
> - Installing an NPM package globally is usually not recommended. But it's not a problem in this case because each app managed by Boostr uses a local Boostr package which is automatically installed. So the global Boostr package can be seen as a shortcut to the local Boostr packages installed in your apps, and, therefore, you can have different apps using different versions of Boostr.

Then, run the following commands to create a directory for the app and initialize it:

<!-- <if language="js"> -->

```sh
mkdir hello-world
cd hello-world
boostr initialize @boostr/web-app-js
```

<!-- </if> -->

<!-- <if language="ts"> -->

```sh
mkdir hello-world
cd hello-world
boostr initialize @boostr/web-app-ts
```

<!-- </if> -->

Finally, you can open the `hello-world` directory in your favorite [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) to explore the initial codebase.

> **Note**: You can use any IDE you want, but if you use [Visual Studio Code](https://code.visualstudio.com/), you can profit from the VS Code configuration included in the [Boostr app templates](https://boostr.dev/docs#boostr-initialize-template-options). Otherwise, you may have to set up your IDE to get a suitable configuration.

We will not detail all directories and files created by Boostr because it would be out of the scope of this tutorial. If you are the kind of person who needs to understand everything, please check out the [Boostr documentation](https://boostr.dev/docs) to find out more.

So, we will only focus on two files:

<!-- <if language="js"> -->

- `frontend/src/components/application.jsx`: The root [component](https://layrjs.com/docs/v2/reference/component) of the app frontend.
- `backend/src/components/application.js`: The root [component](https://layrjs.com/docs/v2/reference/component) of the app backend.

<!-- </if> -->

<!-- <if language="ts"> -->

- `frontend/src/components/application.tsx`: The root [component](https://layrjs.com/docs/v2/reference/component) of the app frontend.
- `backend/src/components/application.ts`: The root [component](https://layrjs.com/docs/v2/reference/component) of the app backend.

<!-- </if> -->

#### Starting the App

Start the app in development mode with the following command:

```sh
boostr start
```

The terminal should output something like this:

```txt
[database] MongoDB server started at mongodb://localhost:18160/
[backend] Build succeeded (bundle size: 2.06MB)
[backend] Component HTTP server started at http://localhost:18159/
[frontend] Build succeeded (bundle size: 1.34MB)
[frontend] Single-page application server started at http://localhost:18158/
```

> **Notes**:
>
> - The TCP ports used for each [local development URL](https://boostr.dev/docs#local-development-urls) were randomly set when the Boostr `initialize` command was executed to create the app in the [previous section](https://layrjs.com/docs/v2/introduction/hello-world#creating-the-app). So, it's normal if the TCP ports are different for you.
> - Don't be freaked out by the size of the generated bundles in development mode. When you deploy your apps, the generated bundles are a lot smaller.

The last line in the terminal output should include an URL you can open in a browser to display the app.

At this point, you should see something like this in your browser:

<p>
	<img src="https://layrjs.com/docs/v2/introduction/hello-world/assets/screenshot-001.immutable.png" alt="Screenshot of the app initialized by Boostr" style="width: 100%; margin-top: .5rem">
</p>

#### Taking a Look at the Initial App

Let's see what we have for now.

When we bootstrapped the app with the Boostr `initialize` command, we got a minimal app which does one thing: displaying the result of a backend method in the frontend.

##### Frontend

Here's what the initial frontend root [component](https://layrjs.com/docs/v2/reference/component) (`Application`) looks like:

```js
// JS

// frontend/src/components/application.jsx

import {Routable} from '@layr/routable';
import React from 'react';
import {layout, page, useData} from '@layr/react-integration';

export const extendApplication = (Base) => {
  class Application extends Routable(Base) {
    @layout('/') static MainLayout({children}) {
      return (
        <>
          <this.MainPage.Link>
            <h1>{process.env.APPLICATION_NAME}</h1>
          </this.MainPage.Link>
          {children()}
        </>
      );
    }

    @page('[/]') static MainPage() {
      return useData(
        async () => await this.isHealthy(),

        (isHealthy) => <p>The app is {isHealthy ? 'healthy' : 'unhealthy'}.</p>
      );
    }

    @page('[/]*') static NotFoundPage() {
      return (
        <>
          <h2>Page not found</h2>
          <p>Sorry, there is nothing here.</p>
        </>
      );
    }
  }

  return Application;
};
```

```ts
// TS

// frontend/src/components/application.tsx

import {Routable} from '@layr/routable';
import React, {Fragment} from 'react';
import {layout, page, useData} from '@layr/react-integration';

import type {Application as BackendApplication} from '../../../backend/src/components/application';

export const extendApplication = (Base: typeof BackendApplication) => {
  class Application extends Routable(Base) {
    declare ['constructor']: typeof Application;

    @layout('/') static MainLayout({children}: {children: () => any}) {
      return (
        <>
          <this.MainPage.Link>
            <h1>{process.env.APPLICATION_NAME}</h1>
          </this.MainPage.Link>
          {children()}
        </>
      );
    }

    @page('[/]') static MainPage() {
      return useData(
        async () => await this.isHealthy(),

        (isHealthy) => <p>The app is {isHealthy ? 'healthy' : 'unhealthy'}.</p>
      );
    }

    @page('[/]*') static NotFoundPage() {
      return (
        <>
          <h2>Page not found</h2>
          <p>Sorry, there is nothing here.</p>
        </>
      );
    }
  }

  return Application;
};

export declare const Application: ReturnType<typeof extendApplication>;

export type Application = InstanceType<typeof Application>;
```

If we put aside the [mixin mechanism](https://www.typescriptlang.org/docs/handbook/mixins.html) that allows the frontend `Application` component to "inherit" from the backend `Application` component, we can see three class methods.

`MainLayout()` implements a layout for all the pages of the app:

- It is decorated with [`@layout('/')`](https://layrjs.com/docs/v2/reference/react-integration#layout-decorator), which makes the method acts as a layout and defines an URL path (`'/'`) for it.
- It renders the name of the app (using the `APPLICATION_NAME` [environment variable](https://github.com/boostrjs/boostr#environment-variables)) in an `<h1>` HTML tag, which is nested into a link pointing to the app's main page (using the [`<this.MainPage.Link>`](https://layrjs.com/docs/v2/reference/routable#route-decorator) React element).
- It calls the `children` prop to render the content of the pages using this layout.

`MainPage()` implements the main page of the app:

- It is decorated with [`@page('[/]')`](https://layrjs.com/docs/v2/reference/react-integration#page-decorator), which makes the method acts as a page associated with the `'/'` URL path and specifies that the main layout (`'/'` enclosed in square brackets `'[]'`) should be used.
- It returns the result of the [`useData()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) React hook, which calls a backend method (with `await this.isHealthy()`) and renders its result (with `<p>The app is {isHealthy ? 'healthy' : 'unhealthy'}.</p>`).

`NotFoundPage()` implements a page that is displayed when a user goes to an URL that is not handled by the app:

- It is decorated with [`@page('[/]*')`](https://layrjs.com/docs/v2/reference/react-integration#page-decorator), which makes the method acts as a page associated with any unhandled URL path starting with `'/'` and specifies that the main layout (`'/'` enclosed in square brackets `'[]'`) should be used.
- It renders some simple HTML tags and texts indicating that the page cannot be found.

##### Backend

Here's what the initial backend root [component](https://layrjs.com/docs/v2/reference/component) (`Application`) looks like:

```js
// JS

// backend/src/components/application.js

import {Component, method, expose} from '@layr/component';

export class Application extends Component {
  @expose({call: true}) @method() static async isHealthy() {
    return true;
  }
}
```

```ts
// TS

// backend/src/components/application.ts

import {Component, method, expose} from '@layr/component';

export class Application extends Component {
  @expose({call: true}) @method() static async isHealthy() {
    return true;
  }
}
```

This component is straightforward.

`isHealthy()` implements a class method that the frontend can call to check whether the app is healthy:

- It is decorated with [`@expose({call: true})`](https://layrjs.com/docs/v2/reference/component#expose-decorator), which exposes the method to the frontend.
- It is also decorated with [`@method()`](https://layrjs.com/docs/v2/reference/component#method-decorator), which is required so that the `@expose()` decorator can be used.
- It always returns `true`, which is rather pointless. An actual `isHealthy()` method would, for example, check whether a database responds correctly.

#### Displaying "Hello, World!" in the Frontend

It's about time to write some code.

We'll start gently by modifying the frontend to display "Hello, World!" instead of "The app is healthy.".

Modify the `MainPage()` class method in the <!-- <if language="js"> -->`frontend/src/components/application.jsx`<!-- </if> --><!-- <if language="ts"> -->`frontend/src/components/application.tsx`<!-- </if> --> file as follows:

```ts
@page('[/]') static MainPage() {
  return <p>Hello, World!</p>;
}
```

Save the file, and your browser should automatically refresh the page with the following contents:

<p>
	<img src="https://layrjs.com/docs/v2/introduction/hello-world/assets/screenshot-002.immutable.png" alt="Screenshot of the app displaying 'Hello, World!'" style="width: 100%; margin-top: .5rem">
</p>

#### Adding a Page in the Frontend

So the frontend is now displaying "Hello, World!" and we could call it a day.

But that was a bit too easy, don't you think?

Let's spice this tutorial a little by adding a page in charge of displaying the "Hello, World!" message.

Add the following class method in the <!-- <if language="js"> -->`frontend/src/components/application.jsx`<!-- </if> --><!-- <if language="ts"> -->`frontend/src/components/application.tsx`<!-- </if> --> file:

```ts
@page('[/]hello-world') static HelloWorldPage() {
  return <p>Hello, World!</p>;
}
```

That's it. The app just got a new page. You could view it by changing the URL path to `/hello-world` in your browser, but adding a link to the new page inside the main page would be better in terms of user experience.

Let's do so by modifying the `MainPage()` class method as follows:

```ts
@page('[/]') static MainPage() {
  return (
    <p>
      <this.HelloWorldPage.Link>
        See the "Hello, World!" page
      </this.HelloWorldPage.Link>
    </p>
  );
}
```

Hold on. What's going on here? Is it how we create links with Layr? Where is the URL path (`'/hello-world'`) of the "Hello, World!" page? Well, in a Layr app, except in the `@page()` decorators, you should never encounter any URL path.

We hope it doesn't sound too magical because it is not. Any method decorated with [`@page()`](https://layrjs.com/docs/v2/reference/react-integration#page-decorator) automatically gets some attached [shortcut functions](https://layrjs.com/docs/v2/reference/routable#route-decorator), such as `Link()`, which implements a React component rendering a `<a>` tag referencing the URL path of the page.

Your browser should now display the following page:

<p>
	<img src="https://layrjs.com/docs/v2/introduction/hello-world/assets/screenshot-003.immutable.png" alt="Screenshot of the app displaying a link to the 'Hello, World!' page" style="width: 100%; margin-top: .5rem">
</p>

#### Getting the "Hello, World" Message from the Backend

At the beginning of this tutorial, we promised to create a full-stack app, but currently, the backend is not involved, and everything happens in the frontend.

Let's fix that by moving the "business logic" generating the "Hello, World!" message to the backend.

First, add the following class method in the <!-- <if language="js"> -->`backend/src/components/application.js`<!-- </if> --><!-- <if language="ts"> -->`backend/src/components/application.ts`<!-- </if> --> file:

```ts
@expose({call: true}) @method() static async getHelloWorld() {
  return 'Hello, World!';
}
```

This method will be callable from the frontend (thanks to the [`@expose()`](https://layrjs.com/docs/v2/reference/component#expose-decorator) and [`@method()`](https://layrjs.com/docs/v2/reference/component#method-decorator) decorators) and will return the `'Hello, World!'` string.

> **Note**: Since the `isHealthy()` class method is not used anymore, you can remove it if you want.

Save the file to restart the backend, and then modify the `HelloWorldPage()` class method in the <!-- <if language="js"> -->`frontend/src/components/application.jsx`<!-- </if> --><!-- <if language="ts"> -->`frontend/src/components/application.tsx`<!-- </if> --> file as follows:

```ts
@page('[/]hello-world') static HelloWorldPage() {
  return useData(
    async () => await this.getHelloWorld(),

    (helloWorld) => <p>{helloWorld}</p>
  );
}
```

As seen in the initial [`MainPage()`](https://layrjs.com/docs/v2/introduction/hello-world#frontend) method, we use the [`useData()`](https://layrjs.com/docs/v2/reference/react-integration#use-data-react-hook) React hook to call a backend method (with `await this.getHelloWorld()`) and render its result (with `<p>{helloWorld}</p>`).

If you refresh the "Hello, World!" page in your browser, you should not see any difference. However, if you inspect the network requests via the browser's developer tools, you should see that the `'Hello, World'` string displayed in the frontend comes from the backend.

#### One Last Thing

Technically, we now have a full-stack app involving a frontend and a backend.

But the app is a bit static. The backend always returns the same `'Hello, World'` string, which is rather boring.

Let's make the app more dynamic by modifying the `getHelloWorld()` class method in the <!-- <if language="js"> -->`backend/src/components/application.js`<!-- </if> --><!-- <if language="ts"> -->`backend/src/components/application.ts`<!-- </if> --> file as follows:

```ts
@expose({call: true}) @method() static async getHelloWorld() {
  const translations = ['Hello, World!', 'Bonjour le monde !', 'こんにちは世界!'];

  const translation = translations[Math.round(Math.random() * (translations.length - 1))];

  return translation;
}
```

Save the file to restart the backend, and now, when you refresh the "Hello, World!" page several times in your browser, you should see some translations randomly picked up.

Here's an example showing the Japanese translation:

<p>
	<img src="https://layrjs.com/docs/v2/introduction/hello-world/assets/screenshot-004.immutable.png" alt="Screenshot of the app displaying 'Hello, World!' in Japanese" style="width: 100%; margin-top: .5rem">
</p>

We hardcoded the translations in the `getHelloWorld()` class method, which is OK for this tutorial. But in a real-world app, storing the translations in a database would be better so an admin can edit them. We'll see how to achieve that in [another tutorial](https://layrjs.com/docs/v2/introduction/storing-data) that remains to be written.

#### Wrapping Up

In this first tutorial, we saw how to build a basic full-stack app with Layr:

- We [created an app](https://layrjs.com/docs/v2/introduction/hello-world#creating-the-app) and [started it](https://layrjs.com/docs/v2/introduction/hello-world#starting-the-app) in development mode with a few [Boostr](https://boostr.dev) commands.
- We discovered how to implement [layouts](https://layrjs.com/docs/v2/introduction/hello-world#taking-a-look-at-the-initial-app), [pages](https://layrjs.com/docs/v2/introduction/hello-world#adding-a-page-in-the-frontend), and [links](https://layrjs.com/docs/v2/introduction/hello-world#adding-a-page-in-the-frontend) encapsulated in a Layr [component](https://layrjs.com/docs/v2/reference/component).
- We found out how [a backend method could be called from the frontend](https://layrjs.com/docs/v2/introduction/hello-world#getting-the-hello-world-message-from-the-backend) thanks to the cross-layer class inheritance ability of Layr.


================================================
FILE: docs/contents/introduction/introduction.md
================================================
### Introduction

> **Note**: Layr v2 is published on NPM, but the documentation is still a work in progress.

#### Overview

Layr is a set of JavaScript/TypeScript libraries that dramatically simplify the development of highly dynamic full-stack apps.

Typically, a highly dynamic full-stack app comprises a frontend and a backend running in two different environments connected through a web API (REST, GraphQL, etc.)

Separating the frontend and the backend is a good thing. Still, the problem is that building a web API usually leads to a lot of code scattering, knowledge duplication, boilerplate, and accidental complexity.

Layr removes the need to build a web API and [reunites the frontend and backend](https://dev.to/mvila/good-bye-web-apis-2bel) so that you can experience them as a single entity.

On the frontend side, Layr gives you [routing capabilities](https://layrjs.com/docs/v2/reference/routable) and [object observability](https://layrjs.com/docs/v2/reference/observable) so that you don't need to add an external router or a state manager.

On the backend side, Layr offers an [ORM](https://layrjs.com/docs/v2/reference/storable) (which can be exposed to the frontend) to make data storage as easy as possible.

#### Made for Highly Dynamic Apps

Layr stands out for building apps that offer rich user interfaces, such as the good old desktop apps.

Even if they both run in a browser, we should clearly differentiate "websites" and "web apps".

##### Websites

Websites provide fast load time, good [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization), and a few dynamic parts.

Some examples fitting in this category are e-commerce websites (e.g., [Amazon](https://www.amazon.com/)), marketplace platforms (e.g., [Airbnb](https://www.airbnb.com/)), or online newspapers (e.g., [The New York Times](https://www.nytimes.com/)).

Layr is inappropriate for building these kinds of websites because it relies on a [Single-page application](https://en.wikipedia.org/wiki/Single-page_application) architecture and doesn't provide server-side rendering.

So, instead of Layr, you should use some frameworks such as [Next.js](https://nextjs.org/), [Nuxt.js](https://nextjs.org/), or [Remix](https://remix.run/).

##### Web Apps

Web apps provide rich user interfaces and are all made of dynamic parts.

Some examples fitting in this category are productivity apps (e.g., [Notion](https://www.notion.so/)), communication apps (e.g., [Slack](https://slack.com/)), or design apps (e.g., [Figma](https://www.figma.com/)).

Layr is made for building these kinds of apps with a straightforward architecture:

- The frontend exposes an interface for _humans_.
- The backend exposes an interface for _computers_.

Note that the frontend can obviously run in a browser, but it can also run on mobile and desktop with the help of frameworks such as [React Native](https://reactnative.dev/) or [Electron](https://www.electronjs.org/).

#### Core Features

Layr provides everything you need to build an app from start to finish:

- **Cross-layer inheritance**: A frontend class can "inherit" from a backend class, so some exposed [attributes](https://layrjs.com/docs/v2/reference/attribute) are automatically transported between the frontend and the backend. Also, you can call some exposed backend [methods](https://layrjs.com/docs/v2/reference/method) directly from the frontend.
- **Controlled attributes**: An attribute can be [type-checked](https://layrjs.com/docs/v2/reference/value-type), [sanitized](https://layrjs.com/docs/v2/reference/sanitizer), [validated](https://layrjs.com/docs/v2/reference/validator), [serialized](https://layrjs.com/docs/v2/reference/component#serialization), and [observed](https://layrjs.com/docs/v2/reference/observable) at runtime.
- **Storage**: A class instance can be [persisted](https://layrjs.com/docs/v2/reference/storable) in a database. Currently, only [MongoDB](https://www.mongodb.com/) is supported, but we plan to support more databases in the future.
- **Routing**: A method can be [associated with an URL](https://layrjs.com/docs/v2/reference/routable) and controlled by a [navigator](https://layrjs.com/docs/v2/reference/navigator) so that this method is automatically called when the user navigates.
- **Layouts**: A method can act as a [wrapper](https://layrjs.com/docs/v2/reference/wrapper) for other methods with a shared URL path prefix. This way, you can easily create [layouts](https://layrjs.com/docs/v2/reference/react-integration#layout-decorator) for your [pages](https://layrjs.com/docs/v2/reference/react-integration#page-decorator).
- **Authorization**: [User-role-based](https://layrjs.com/docs/v2/reference/with-roles) authorizations can be set to restrict some attributes or methods.
- **Integrations**: Integration helpers are provided to facilitate the integration of the most popular libraries or services. Currently, two integration helpers are available: [react-integration](https://layrjs.com/docs/v2/reference/react-integration) and [aws-integration](https://layrjs.com/docs/v2/reference/aws-integration). But more should come shortly.
- **Interoperability**: The backend is automatically exposed through a [Deepr API](https://deepr.io), so you can consume it from any frontend even though it's not built with Layr. And if you want to bring a more standard API (e.g., REST) to your backend, it's straightforward to add such an API in your Layr backend.

#### Core Principles

Here's a quick taste of the core principles upon which Layr is built:

- **Object-oriented**: Layr embraces the object-oriented paradigm in all aspects of an app and allows you to organize your code in a way that is as cohesive as possible.
- **End-to-end type safety**: When you use TypeScript, from the frontend to the database (which goes through the backend), every single piece of a Layr app can be type-safe.
- **100% DRY**: A Layr app can be fully [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) (i.e., zero knowledge duplication).
- **Low-level**: Layr is designed to be as closest to the language as possible and can be seen as a [language extension](https://layrjs.com/blog/articles/Getting-the-Right-Level-of-Generalization-7xpk37) in many ways.
- **Unopinionated**: Layr has strong opinions about itself but doesn't force you to use any external library, service, or tool.

#### Command-Line Interface

Layr is just a set of low-level JavaScript/TypeScript libraries and does not come with a CLI.

So, you can use Layr with any development and deployment tools.

However, we know that setting up a development environment and a deployment mechanism can be challenging.

So, we created [Boostr](https://boostr.dev), a companion tool that takes care of everything you need to build and deploy a Layr app.

Check out the [Boostr documentation](https://boostr.dev/docs) to find out more.

#### Compatibility

Layr is implemented in [TypeScript](https://www.typescriptlang.org/), but you can use either JavaScript or TypeScript to build your app.

If you are using JavaScript, you'll need to compile your code with [Babel](https://babeljs.io/) to take advantage of some novel JavaScript features such as "decorators".

If you are using TypeScript, all you need is the TypeScript compiler ([`tsc`](https://www.typescriptlang.org/docs/handbook/compiler-options.html)).

> **Note**: If you use [Boostr](https://boostr.dev) to manage your app's development and deployment, you don't have to worry about compiling your code because it is automatically handled.

To run your app, you'll need a JavaScript runtime for both the frontend and the backend.

##### Frontend

###### Web

Any modern browser should work fine.

Here are the minimum versions with which Layr is tested:

- Chrome v55
- Safari v11
- Firefox v54
- Edge Chromium

###### Mobile and Desktop

Any mobile or desktop app framework using JavaScript or TypeScript (such as [React Native](https://reactnative.dev/) or [Electron](https://www.electronjs.org/)) should work fine.

##### Backend

Any environment running [Node.js](https://nodejs.org/) v16 or later is supported.

#### Examples

Here are some examples of simple full-stack apps that you can check out:

- [CRUD Example App (JS)](https://github.com/layrjs/crud-example-app-js-boostr)
- [CRUD Example App (TS)](https://github.com/layrjs/crud-example-app-ts-boostr)
- [Layr Website (TS)](https://github.com/layrjs/layr/tree/master/website)
- [CodebaseShow (TS)](https://github.com/codebaseshow/codebaseshow)
- [RealWorld Example App (JS)](https://github.com/layrjs/react-layr-realworld-example-app)


================================================
FILE: docs/contents/introduction/storing-data.md
================================================
### Storing Data

#### Coming Soon

This tutorial will expand the ["Hello, World!"](https://layrjs.com/docs/v2/introduction/hello-world) app to show you how Layr handles database storage.

Unfortunately, writing tutorials takes a lot of time, and the Layr project is currently handled by a [single person](https://mvila.me) who has to work for customers to make a living and is also starting a new [ambitious project](https://1place.app), which will be based on Layr.

This tutorial will come for sure, but please be patient.

If you cannot wait and feel adventurous, you can figure out how to store data with Layr by checking out:

- The [`Storable()`](https://layrjs.com/docs/v2/reference/storable) mixin in the "Reference" section.
- Some [examples](https://layrjs.com/docs/v2/introduction/introduction#examples) of simple full-stack apps built with Layr.


================================================
FILE: docs/package.json
================================================
{
  "name": "@layr/docs",
  "version": "1.0.0",
  "private": true,
  "description": "Layr documentation",
  "keywords": [],
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "repository": "https://github.com/layrjs/layr/tree/master/docs",
  "scripts": {
    "build": "node ./build.js"
  },
  "dependencies": {
    "@mvila/simple-doc": "^0.1.138",
    "fs-extra": "^11.1.0"
  }
}


================================================
FILE: examples/v1/counter/README.md
================================================
# Counter

A simple example to introduce the core concepts of Layr.

## Usage

Install the npm dependencies with:

```sh
npm install
```

Run the example with:

```sh
npx babel-node ./src/frontend.js
```


================================================
FILE: examples/v1/counter/babel.config.json
================================================
{
  "presets": [["@babel/preset-env", {"targets": {"node": "10"}}]],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-proposal-class-properties"]
  ]
}


================================================
FILE: examples/v1/counter/jsconfig.json
================================================
{
  "compilerOptions": {
  "target": "ES2017",
    "module": "CommonJS",
    "checkJs": false,
    "experimentalDecorators": true
  }
}


================================================
FILE: examples/v1/counter/package.json
================================================
{
  "name": "counter",
  "version": "1.0.0",
  "description": "A simple example to introduce the core concepts of Layr",
  "private": true,
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-client": "^1.0.0",
    "@layr/component-server": "^1.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/node": "^7.10.5",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.10.5",
    "@babel/preset-env": "^7.11.0"
  }
}


================================================
FILE: examples/v1/counter/src/backend.js
================================================
import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';
import {ComponentServer} from '@layr/component-server';

class Counter extends Component {
  // We need a primary identifier so a Counter instance
  // can be transported between the frontend and the backend
  // while keeping it's identity
  @expose({get: true, set: true}) @primaryIdentifier() id;

  // The counter's value is exposed to the frontend
  @expose({get: true, set: true}) @attribute('number') value = 0;

  // And the "business logic" is exposed as well
  @expose({call: true}) @method() increment() {
    this.value++;
  }
}

// We serve the Counter through a ComponentServer
export const server = new ComponentServer(Counter);


================================================
FILE: examples/v1/counter/src/frontend.js
================================================
import {ComponentClient} from '@layr/component-client';

import {server} from './backend';

// We create a client that is connected to the backend's server
const client = new ComponentClient(server);

// We get the backend's Counter component
const BackendCounter = client.getComponent();

// We extends the backend's Counter component so we can override the increment() method
class Counter extends BackendCounter {
  increment() {
    super.increment(); // The backend's `increment()` method is invoked
    console.log(this.value); // Some additional code is executed in the frontend
  }
}

// Lastly, we consume the Counter
const counter = new Counter();
counter.increment();


================================================
FILE: examples/v1/counter-with-create-react-app-ts/README.md
================================================
# Counter with CreateReactApp (TS)

A simple example to introduce the core concepts of Layr.

## Install

Install the npm dependencies with:

```sh
npm install
```

## Usage

### Running the app in development mode

Execute the following command:

```sh
npm run start
```

The app should then be available at http://localhost:3000.

### Debugging

#### Client

Add the following entry in the local storage of your browser:

```
| Key   | Value     |
| ----- | --------- |
| debug | layr:* |
```

#### Server

Add the following environment variables when starting the app:

```sh
DEBUG=layr:* DEBUG_DEPTH=10
```


================================================
FILE: examples/v1/counter-with-create-react-app-ts/backend/package.json
================================================
{
  "name": "counter-with-create-react-app-ts-backend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "start": "nodemon --watch ./src --exec ts-node ./src/http-server.ts"
  },
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-server": "^1.0.0",
    "tslib": "^2.0.3"
  },
  "devDependencies": {
    "@layr/component-http-server": "^1.0.0",
    "@types/node": "^14.11.8",
    "nodemon": "^2.0.5",
    "ts-node": "^9.0.0",
    "typescript": "^4.0.3"
  }
}


================================================
FILE: examples/v1/counter-with-create-react-app-ts/backend/src/components/counter.ts
================================================
import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';

export class Counter extends Component {
  @expose({get: true, set: true}) @primaryIdentifier() id!: string;

  @expose({get: true, set: true}) @attribute('number') value = 0;

  @expose({call: true}) @method() async increment() {
    this.value++;
  }
}


================================================
FILE: examples/v1/counter-with-create-react-app-ts/backend/src/http-server.ts
================================================
import {ComponentHTTPServer} from '@layr/component-http-server';

import {server} from './server';

const httpServer = new ComponentHTTPServer(server, {port: 3001});
httpServer.start();


================================================
FILE: examples/v1/counter-with-create-react-app-ts/backend/src/server.ts
================================================
import {ComponentServer} from '@layr/component-server';

import {Counter} from './components/counter';

export const server = new ComponentServer(Counter);


================================================
FILE: examples/v1/counter-with-create-react-app-ts/backend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true
  }
}


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/package.json
================================================
{
  "name": "counter-with-create-react-app-ts-frontend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "dependencies": {
    "@layr/component": "^1.0.6",
    "@layr/component-http-client": "^1.0.3",
    "@layr/react-integration": "^1.0.3",
    "@types/node": "^14.11.8",
    "@types/react": "^16.9.52",
    "@types/react-dom": "^16.9.8",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.3",
    "typescript": "^4.0.3"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/public/manifest.json
================================================
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/src/components/counter.tsx
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';
import React from 'react';
import {view} from '@layr/react-integration';

import type {Counter as BackendCounter} from '../../../backend/src/components/counter';

export const getCounter = async () => {
  const client = new ComponentHTTPClient('http://localhost:3001');

  const BackendCounterProxy = (await client.getComponent()) as typeof BackendCounter;

  class Counter extends BackendCounterProxy {
    @view() Main() {
      return (
        <div>
          <input value={this.value} readOnly />
          <button
            onClick={async () => {
              await this.increment();
            }}
          >
            +
          </button>
        </div>
      );
    }
  }

  return Counter;
};


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/src/index.tsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';

import {getCounter} from './components/counter';

(async () => {
  const Counter = await getCounter();

  const counter = new Counter();

  ReactDOM.render(
    <React.StrictMode>
      <counter.Main />
    </React.StrictMode>,
    document.getElementById('root')
  );
})();


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/src/react-app-env.d.ts
================================================
/// <reference types="react-scripts" />


================================================
FILE: examples/v1/counter-with-create-react-app-ts/frontend/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "experimentalDecorators": true,
    "skipLibCheck": true
  },
  "include": [
    "src"
  ]
}


================================================
FILE: examples/v1/counter-with-create-react-app-ts/package.json
================================================
{
  "name": "counter-with-create-react-app-ts",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "postinstall": "(cd ./frontend && npm install) && (cd ./backend && npm install)",
    "start": "concurrently --names=frontend,backend --prefix-colors=green,blue --kill-others \"(cd ./frontend && npm run start)\" \"(cd ./backend && npm run start)\"",
    "update": "(cd ./frontend && npm update) && (cd ./backend && npm update)"
  },
  "devDependencies": {
    "concurrently": "^5.3.0"
  }
}


================================================
FILE: examples/v1/counter-with-esbuild-ts/README.md
================================================
# Counter with esbuild (TS)

A simple example to introduce the core concepts of Layr.

## Install

Install the npm dependencies with:

```sh
npm install
```

## Usage

### Running the app in development mode

Execute the following command:

```sh
npm run start
```

The app should then be available at http://localhost:3000.

### Debugging

#### Client

Add the following entry in the local storage of your browser:

```
| Key   | Value     |
| ----- | --------- |
| debug | layr:* |
```

#### Server

Add the following environment variables when starting the app:

```sh
DEBUG=layr:* DEBUG_DEPTH=10
```


================================================
FILE: examples/v1/counter-with-esbuild-ts/backend/package.json
================================================
{
  "name": "counter-with-esbuild-ts-backend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "build": "esbuild ./src/http-server.ts --bundle --target=node12 --sourcemap --platform=node --external:koa --outfile=./build/bundle.js",
    "start": "nodemon --watch ./src --ext ts --exec 'npm run build && node -r source-map-support/register ./build/bundle.js'"
  },
  "dependencies": {
    "@layr/component": "^1.1.2",
    "@layr/component-server": "^1.1.2",
    "tslib": "^2.1.0"
  },
  "devDependencies": {
    "@layr/component-http-server": "^1.1.2",
    "@types/node": "^14.14.20",
    "esbuild": "^0.9.2",
    "nodemon": "^2.0.7",
    "source-map-support": "^0.5.19",
    "typescript": "^4.1.3"
  }
}


================================================
FILE: examples/v1/counter-with-esbuild-ts/backend/src/components/counter.ts
================================================
import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';

export class Counter extends Component {
  @expose({get: true, set: true}) @primaryIdentifier() id!: string;

  @expose({get: true, set: true}) @attribute('number') value = 0;

  @expose({call: true}) @method() async increment() {
    this.value++;
  }
}


================================================
FILE: examples/v1/counter-with-esbuild-ts/backend/src/http-server.ts
================================================
import {ComponentHTTPServer} from '@layr/component-http-server';

import {server} from './server';

const httpServer = new ComponentHTTPServer(server, {port: 3001});
httpServer.start();


================================================
FILE: examples/v1/counter-with-esbuild-ts/backend/src/server.ts
================================================
import {ComponentServer} from '@layr/component-server';

import {Counter} from './components/counter';

export const server = new ComponentServer(Counter);


================================================
FILE: examples/v1/counter-with-esbuild-ts/backend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true,
    "isolatedModules": true
  }
}


================================================
FILE: examples/v1/counter-with-esbuild-ts/frontend/package.json
================================================
{
  "name": "counter-with-esbuild-ts-frontend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "copy": "mkdir -p ./build && cp ./src/index.html ./build/index.html",
    "watch": "npm run copy && esbuild ./src/index.tsx --bundle --target=es2017 --watch --minify --keep-names --sourcemap --define:process.env.NODE_ENV=\\\"development\\\" --outfile=./build/bundle.js",
    "serve": "serve --listen 3000 ./build",
    "start": "npm-run-all --parallel watch serve"
  },
  "dependencies": {
    "@layr/component": "^1.1.2",
    "@layr/component-http-client": "^1.1.1",
    "@layr/react-integration": "^1.0.22",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@types/node": "^14.14.20",
    "@types/react": "^16.14.2",
    "@types/react-dom": "^16.9.10",
    "esbuild": "^0.9.2",
    "npm-run-all": "^4.1.5",
    "serve": "^11.3.2"
  }
}


================================================
FILE: examples/v1/counter-with-esbuild-ts/frontend/src/components/counter.tsx
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';
import React from 'react';
import {view} from '@layr/react-integration';

import type {Counter as BackendCounter} from '../../../backend/src/components/counter';

export const getCounter = async () => {
  const client = new ComponentHTTPClient('http://localhost:3001');

  const BackendCounterProxy = (await client.getComponent()) as typeof BackendCounter;

  class Counter extends BackendCounterProxy {
    @view() Main() {
      return (
        <div>
          <input value={this.value} readOnly />
          <button
            onClick={async () => {
              await this.increment();
            }}
          >
            +
          </button>
        </div>
      );
    }
  }

  return Counter;
};


================================================
FILE: examples/v1/counter-with-esbuild-ts/frontend/src/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>My Rollup Project</title>
  </head>

  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>


================================================
FILE: examples/v1/counter-with-esbuild-ts/frontend/src/index.tsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';

import {getCounter} from './components/counter';

(async () => {
  const Counter = await getCounter();

  const counter = new Counter();

  ReactDOM.render(
    <React.StrictMode>
      <counter.Main />
    </React.StrictMode>,
    document.getElementById('root')
  );
})();


================================================
FILE: examples/v1/counter-with-esbuild-ts/frontend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true,
    "isolatedModules": true
  }
}


================================================
FILE: examples/v1/counter-with-esbuild-ts/package.json
================================================
{
  "name": "counter-with-rollup-ts",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "postinstall": "(cd ./frontend && npm install) && (cd ./backend && npm install)",
    "start": "concurrently --names=frontend,backend --prefix-colors=green,blue --kill-others \"(cd ./frontend && npm run start)\" \"(cd ./backend && npm run start)\"",
    "update": "(cd ./frontend && npm update) && (cd ./backend && npm update)"
  },
  "devDependencies": {
    "concurrently": "^5.3.0"
  }
}


================================================
FILE: examples/v1/counter-with-http/README.md
================================================
# Counter with HTTP

A simple example to introduce the core concepts of Layr.

## Usage

Install the npm dependencies with:

```sh
npm install
```

Run the backend with:

```sh
npx babel-node ./src/backend.js
```

Then, in another terminal, run the frontend with:

```sh
npx babel-node ./src/frontend.js
```


================================================
FILE: examples/v1/counter-with-http/babel.config.json
================================================
{
  "presets": [["@babel/preset-env", {"targets": {"node": "10"}}]],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-proposal-class-properties"]
  ]
}


================================================
FILE: examples/v1/counter-with-http/jsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "checkJs": false,
    "experimentalDecorators": true
  }
}


================================================
FILE: examples/v1/counter-with-http/package.json
================================================
{
  "name": "counter-with-http",
  "version": "1.0.0",
  "description": "A simple example to introduce the core concepts of Layr",
  "private": true,
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-http-client": "^1.0.0",
    "@layr/component-http-server": "^1.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/node": "^7.10.5",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.10.5",
    "@babel/preset-env": "^7.11.0"
  }
}


================================================
FILE: examples/v1/counter-with-http/src/backend.js
================================================
import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';
import {ComponentHTTPServer} from '@layr/component-http-server';

class Counter extends Component {
  // We need a primary identifier so a Counter instance
  // can be transported between the frontend and the backend
  // while keeping it's identity
  @expose({get: true, set: true}) @primaryIdentifier() id;

  // The counter's value is exposed to the frontend
  @expose({get: true, set: true}) @attribute('number') value = 0;

  // And the "business logic" is exposed as well
  @expose({call: true}) @method() increment() {
    this.value++;
  }
}

// We serve the Counter through a ComponentHTTPServer
const server = new ComponentHTTPServer(Counter, {port: 3210});
server.start();


================================================
FILE: examples/v1/counter-with-http/src/frontend.js
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';

(async () => {
  // We create a client that is connected to the backend's server
  const client = new ComponentHTTPClient('http://localhost:3210');

  // We get the backend's Counter component
  const BackendCounter = await client.getComponent();

  // We extends the backend's Counter component so we can override the increment() method
  class Counter extends BackendCounter {
    async increment() {
      await super.increment(); // The backend's `increment()` method is invoked
      console.log(this.value); // Some additional code is executed in the frontend
    }
  }

  // Lastly, we consume the Counter
  const counter = new Counter();
  await counter.increment();
})();


================================================
FILE: examples/v1/counter-with-parcel-ts/README.md
================================================
# Counter with Parcel (TS)

A simple example to introduce the core concepts of Layr.

## Install

Install the npm dependencies with:

```sh
npm install
```

## Usage

### Running the app in development mode

Execute the following command:

```sh
npm run start
```

The app should then be available at http://localhost:1234.

### Debugging

#### Client

Add the following entry in the local storage of your browser:

```
| Key   | Value     |
| ----- | --------- |
| debug | layr:* |
```

#### Server

Add the following environment variables when starting the app:

```sh
DEBUG=layr:* DEBUG_DEPTH=10
```


================================================
FILE: examples/v1/counter-with-parcel-ts/backend/package.json
================================================
{
  "name": "counter-with-parcel-ts-backend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "start": "nodemon --watch ./src --exec ts-node ./src/http-server.ts"
  },
  "dependencies": {
    "@layr/component": "^1.1.2",
    "@layr/component-server": "^1.1.2",
    "tslib": "^2.1.0"
  },
  "devDependencies": {
    "@layr/component-http-server": "^1.1.2",
    "@types/node": "^14.14.20",
    "nodemon": "^2.0.5",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}


================================================
FILE: examples/v1/counter-with-parcel-ts/backend/src/components/counter.ts
================================================
import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';

export class Counter extends Component {
  @expose({get: true, set: true}) @primaryIdentifier() id!: string;

  @expose({get: true, set: true}) @attribute('number') value = 0;

  @expose({call: true}) @method() async increment() {
    this.value++;
  }
}


================================================
FILE: examples/v1/counter-with-parcel-ts/backend/src/http-server.ts
================================================
import {ComponentHTTPServer} from '@layr/component-http-server';

import {server} from './server';

const httpServer = new ComponentHTTPServer(server, {port: 1235});
httpServer.start();


================================================
FILE: examples/v1/counter-with-parcel-ts/backend/src/server.ts
================================================
import {ComponentServer} from '@layr/component-server';

import {Counter} from './components/counter';

export const server = new ComponentServer(Counter);


================================================
FILE: examples/v1/counter-with-parcel-ts/backend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true
  }
}


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/.gitignore
================================================
/.parcel-cache


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/babel.config.js
================================================
module.exports = (api) => {
  api.cache(true);

  const presets = [
    ['@babel/preset-typescript'],
    [
      '@babel/preset-env',
      {
        targets: {chrome: '55', safari: '11', firefox: '54'},
        loose: true,
        modules: false
      }
    ],
    ['@babel/preset-react']
  ];

  const plugins = [
    ['@babel/plugin-proposal-decorators', {legacy: true}],
    ['@babel/plugin-proposal-class-properties', {loose: true}]
  ];

  return {presets, plugins};
};


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/package.json
================================================
{
  "name": "counter-with-parcel-ts-frontend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "start": "parcel serve ./src/index.html"
  },
  "dependencies": {
    "@layr/component": "^1.1.2",
    "@layr/component-http-client": "^1.1.1",
    "@layr/react-integration": "^1.0.22",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.12.12",
    "@babel/preset-env": "^7.12.11",
    "@babel/preset-react": "^7.12.10",
    "@babel/preset-typescript": "^7.12.7",
    "@types/node": "^14.14.20",
    "@types/react": "^16.14.2",
    "@types/react-dom": "^16.9.10",
    "parcel": "next"
  }
}


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/src/components/counter.tsx
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';
import React from 'react';
import {view} from '@layr/react-integration';

import type {Counter as BackendCounter} from '../../../backend/src/components/counter';

export const getCounter = async () => {
  const client = new ComponentHTTPClient('http://localhost:1235');

  const BackendCounterProxy = (await client.getComponent()) as typeof BackendCounter;

  class Counter extends BackendCounterProxy {
    @view() Main() {
      return (
        <div>
          <input value={this.value} readOnly />
          <button
            onClick={async () => {
              await this.increment();
            }}
          >
            +
          </button>
        </div>
      );
    }
  }

  return Counter;
};


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/src/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>My Parcel Project</title>
  </head>

  <body>
    <div id="root"></div>
    <script src="./index.tsx"></script>
  </body>
</html>


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/src/index.tsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';

import {getCounter} from './components/counter';

(async () => {
  const Counter = await getCounter();

  const counter = new Counter();

  ReactDOM.render(
    <React.StrictMode>
      <counter.Main />
    </React.StrictMode>,
    document.getElementById('root')
  );
})();


================================================
FILE: examples/v1/counter-with-parcel-ts/frontend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true
  }
}


================================================
FILE: examples/v1/counter-with-parcel-ts/package.json
================================================
{
  "name": "counter-with-parcel-ts",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "postinstall": "(cd ./frontend && npm install) && (cd ./backend && npm install)",
    "start": "concurrently --names=frontend,backend --prefix-colors=green,blue --kill-others \"(cd ./frontend && npm run start)\" \"(cd ./backend && npm run start)\"",
    "update": "(cd ./frontend && npm update) && (cd ./backend && npm update)"
  },
  "devDependencies": {
    "concurrently": "^5.3.0"
  }
}


================================================
FILE: examples/v1/counter-with-rollup-ts/README.md
================================================
# Counter with Rollup (TS)

A simple example to introduce the core concepts of Layr.

## Install

Install the npm dependencies with:

```sh
npm install
```

## Usage

### Running the app in development mode

Execute the following command:

```sh
npm run start
```

The app should then be available at http://localhost:3000.

### Debugging

#### Client

Add the following entry in the local storage of your browser:

```
| Key   | Value     |
| ----- | --------- |
| debug | layr:* |
```

#### Server

Add the following environment variables when starting the app:

```sh
DEBUG=layr:* DEBUG_DEPTH=10
```


================================================
FILE: examples/v1/counter-with-rollup-ts/backend/package.json
================================================
{
  "name": "counter-with-rollup-ts-backend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "start": "nodemon --watch ./src --exec ts-node ./src/http-server.ts"
  },
  "dependencies": {
    "@layr/component": "^1.1.2",
    "@layr/component-server": "^1.1.2",
    "tslib": "^2.1.0"
  },
  "devDependencies": {
    "@layr/component-http-server": "^1.1.2",
    "@types/node": "^14.14.20",
    "nodemon": "^2.0.5",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}


================================================
FILE: examples/v1/counter-with-rollup-ts/backend/src/components/counter.ts
================================================
import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';

export class Counter extends Component {
  @expose({get: true, set: true}) @primaryIdentifier() id!: string;

  @expose({get: true, set: true}) @attribute('number') value = 0;

  @expose({call: true}) @method() async increment() {
    this.value++;
  }
}


================================================
FILE: examples/v1/counter-with-rollup-ts/backend/src/http-server.ts
================================================
import {ComponentHTTPServer} from '@layr/component-http-server';

import {server} from './server';

const httpServer = new ComponentHTTPServer(server, {port: 3001});
httpServer.start();


================================================
FILE: examples/v1/counter-with-rollup-ts/backend/src/server.ts
================================================
import {ComponentServer} from '@layr/component-server';

import {Counter} from './components/counter';

export const server = new ComponentServer(Counter);


================================================
FILE: examples/v1/counter-with-rollup-ts/backend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true
  }
}


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/babel.config.js
================================================
module.exports = (api) => {
  api.cache(true);

  const presets = [
    ['@babel/preset-typescript'],
    [
      '@babel/preset-env',
      {
        targets: {chrome: '55', safari: '11', firefox: '54'},
        loose: true,
        modules: false
      }
    ],
    ['@babel/preset-react']
  ];

  const plugins = [
    ['@babel/plugin-proposal-decorators', {legacy: true}],
    ['@babel/plugin-proposal-class-properties', {loose: true}]
  ];

  return {presets, plugins};
};


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/package.json
================================================
{
  "name": "counter-with-rollup-ts-frontend",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "copy": "mkdir -p ./build && cp ./src/index.html ./build/index.html",
    "build": "npm run copy && rollup --config",
    "watch": "npm run copy && rollup --config --watch",
    "serve": "serve --listen 3000 ./build",
    "start": "npm-run-all --parallel watch serve"
  },
  "dependencies": {
    "@layr/component": "^1.1.2",
    "@layr/component-http-client": "^1.1.1",
    "@layr/react-integration": "^1.0.22",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.12.12",
    "@babel/preset-env": "^7.12.11",
    "@babel/preset-react": "^7.12.10",
    "@babel/preset-typescript": "^7.12.7",
    "@rollup/plugin-babel": "^5.2.2",
    "@rollup/plugin-commonjs": "^15.1.0",
    "@rollup/plugin-node-resolve": "^9.0.0",
    "@types/node": "^14.14.20",
    "@types/react": "^16.14.2",
    "@types/react-dom": "^16.9.10",
    "npm-run-all": "^4.1.5",
    "rollup": "^2.36.0",
    "rollup-plugin-node-globals": "^1.4.0",
    "serve": "^11.3.2"
  }
}


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/rollup.config.js
================================================
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import globals from 'rollup-plugin-node-globals';

export default {
  input: 'src/index.tsx',
  output: {
    file: 'build/bundle.js',
    format: 'iife',
    sourcemap: true
  },
  plugins: [
    resolve({browser: true, extensions: ['.mjs', '.js', '.json', '.node', '.ts', '.tsx']}),
    commonjs(),
    globals(),
    babel({extensions: ['ts', 'tsx'], babelHelpers: 'bundled'})
  ]
};


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/src/components/counter.tsx
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';
import React from 'react';
import {view} from '@layr/react-integration';

import type {Counter as BackendCounter} from '../../../backend/src/components/counter';

export const getCounter = async () => {
  const client = new ComponentHTTPClient('http://localhost:3001');

  const BackendCounterProxy = (await client.getComponent()) as typeof BackendCounter;

  class Counter extends BackendCounterProxy {
    @view() Main() {
      return (
        <div>
          <input value={this.value} readOnly />
          <button
            onClick={async () => {
              await this.increment();
            }}
          >
            +
          </button>
        </div>
      );
    }
  }

  return Counter;
};


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/src/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>My Rollup Project</title>
  </head>

  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/src/index.tsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';

import {getCounter} from './components/counter';

(async () => {
  const Counter = await getCounter();

  const counter = new Counter();

  ReactDOM.render(
    <React.StrictMode>
      <counter.Main />
    </React.StrictMode>,
    document.getElementById('root')
  );
})();


================================================
FILE: examples/v1/counter-with-rollup-ts/frontend/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "importHelpers": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "stripInternal": true,
    "skipLibCheck": true
  }
}


================================================
FILE: examples/v1/counter-with-rollup-ts/package.json
================================================
{
  "name": "counter-with-rollup-ts",
  "version": "1.0.0",
  "private": true,
  "author": "Manuel Vila <hi@mvila.me>",
  "license": "MIT",
  "scripts": {
    "postinstall": "(cd ./frontend && npm install) && (cd ./backend && npm install)",
    "start": "concurrently --names=frontend,backend --prefix-colors=green,blue --kill-others \"(cd ./frontend && npm run start)\" \"(cd ./backend && npm run start)\"",
    "update": "(cd ./frontend && npm update) && (cd ./backend && npm update)"
  },
  "devDependencies": {
    "concurrently": "^5.3.0"
  }
}


================================================
FILE: examples/v1/guestbook-cli-js/README.md
================================================
# Guestbook CLI (JS)

A simple CLI app to introduce data storage with Layr.

See the [corresponding guide](https://layrjs.com/docs/v1/introduction/data-storage?language=js).


================================================
FILE: examples/v1/guestbook-cli-js/babel.config.json
================================================
{
  "presets": [["@babel/preset-env", {"targets": {"node": "10"}}]],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-proposal-class-properties"]
  ]
}


================================================
FILE: examples/v1/guestbook-cli-js/jsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "checkJs": false,
    "experimentalDecorators": true
  }
}


================================================
FILE: examples/v1/guestbook-cli-js/package.json
================================================
{
  "name": "guestbook-cli",
  "version": "1.0.0",
  "description": "A simple CLI app to introduce data storage with Layr",
  "private": true,
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-http-client": "^1.0.0",
    "@layr/component-http-server": "^1.0.0",
    "@layr/memory-store": "^1.0.0",
    "@layr/storable": "^1.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/node": "^7.10.5",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.10.5",
    "@babel/preset-env": "^7.11.0"
  }
}


================================================
FILE: examples/v1/guestbook-cli-js/src/backend.js
================================================
import {Component, expose, validators} from '@layr/component';
import {Storable, primaryIdentifier, attribute} from '@layr/storable';
import {MemoryStore} from '@layr/memory-store';
import {ComponentHTTPServer} from '@layr/component-http-server';

const {notEmpty, maxLength} = validators;

@expose({
  find: {call: true},
  prototype: {
    load: {call: true},
    save: {call: true}
  }
})
export class Message extends Storable(Component) {
  @expose({get: true, set: true}) @primaryIdentifier() id;

  @expose({get: true, set: true})
  @attribute('string', {validators: [notEmpty(), maxLength(300)]})
  text = '';

  @expose({get: true}) @attribute('Date') createdAt = new Date();
}

const store = new MemoryStore();

store.registerStorable(Message);

const server = new ComponentHTTPServer(Message, {port: 3210});

server.start();


================================================
FILE: examples/v1/guestbook-cli-js/src/frontend.js
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';
import {Storable} from '@layr/storable';

(async () => {
  const client = new ComponentHTTPClient('http://localhost:3210', {
    mixins: [Storable]
  });

  const Message = await client.getComponent();

  const text = process.argv[2];

  if (text) {
    addMessage(text);
  } else {
    showMessages();
  }

  async function addMessage(text) {
    const message = new Message({text});
    await message.save();
    console.log(`Message successfully added`);
  }

  async function showMessages() {
    const messages = await Message.find(
      {},
      {text: true, createdAt: true},
      {sort: {createdAt: 'desc'}, limit: 30}
    );

    for (const message of messages) {
      console.log(`[${message.createdAt.toISOString()}] ${message.text}`);
    }
  }
})();


================================================
FILE: examples/v1/guestbook-cli-ts/README.md
================================================
# Guestbook CLI (TS)

A simple CLI app to introduce data storage with Layr.

See the [corresponding guide](https://layrjs.com/docs/v1/introduction/data-storage?language=ts).


================================================
FILE: examples/v1/guestbook-cli-ts/package.json
================================================
{
  "name": "guestbook-cli",
  "version": "1.0.0",
  "description": "A simple CLI app to introduce data storage with Layr",
  "private": true,
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-http-client": "^1.0.0",
    "@layr/component-http-server": "^1.0.0",
    "@layr/memory-store": "^1.0.0",
    "@layr/storable": "^1.0.0"
  },
  "devDependencies": {
    "ts-node": "^8.10.2",
    "typescript": "^3.9.7"
  }
}


================================================
FILE: examples/v1/guestbook-cli-ts/src/backend.ts
================================================
import {Component, expose, validators} from '@layr/component';
import {Storable, primaryIdentifier, attribute} from '@layr/storable';
import {MemoryStore} from '@layr/memory-store';
import {ComponentHTTPServer} from '@layr/component-http-server';

const {notEmpty, maxLength} = validators;

@expose({
  find: {call: true},
  prototype: {
    load: {call: true},
    save: {call: true}
  }
})
export class Message extends Storable(Component) {
  @expose({get: true, set: true}) @primaryIdentifier() id!: string;

  @expose({get: true, set: true})
  @attribute('string', {validators: [notEmpty(), maxLength(300)]})
  text = '';

  @expose({get: true}) @attribute('Date') createdAt = new Date();
}

const store = new MemoryStore();

store.registerStorable(Message);

const server = new ComponentHTTPServer(Message, {port: 3210});

server.start();


================================================
FILE: examples/v1/guestbook-cli-ts/src/frontend.ts
================================================
import {ComponentHTTPClient} from '@layr/component-http-client';
import {Storable} from '@layr/storable';

import type {Message as MessageType} from './backend';

(async () => {
  const client = new ComponentHTTPClient('http://localhost:3210', {
    mixins: [Storable]
  });

  const Message = (await client.getComponent()) as typeof MessageType;

  const text = process.argv[2];

  if (text) {
    addMessage(text);
  } else {
    showMessages();
  }

  async function addMessage(text: string) {
    const message = new Message({text});
    await message.save();
    console.log(`Message successfully added`);
  }

  async function showMessages() {
    const messages = await Message.find(
      {},
      {text: true, createdAt: true},
      {sort: {createdAt: 'desc'}, limit: 30}
    );

    for (const message of messages) {
      console.log(`[${message.createdAt.toISOString()}] ${message.text}`);
    }
  }
})();


================================================
FILE: examples/v1/guestbook-cli-ts/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "sourceMap": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "experimentalDecorators": true,
    "skipLibCheck": true
  }
}


================================================
FILE: examples/v1/guestbook-web-js/README.md
================================================
# Guestbook Web (JS)

A simple web app showing how to build a web frontend with Layr.

See the [corresponding guide](https://layrjs.com/docs/v1/introduction/web-app?language=js).


================================================
FILE: examples/v1/guestbook-web-js/babel.config.json
================================================
{
  "presets": [["@babel/preset-env", {"targets": {"node": "10"}}], "@babel/preset-react"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-proposal-class-properties"]
  ]
}


================================================
FILE: examples/v1/guestbook-web-js/jsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "checkJs": false,
    "experimentalDecorators": true
  }
}


================================================
FILE: examples/v1/guestbook-web-js/package.json
================================================
{
  "name": "guestbook-web",
  "version": "1.0.0",
  "description": "A simple web app showing how to build a web frontend with Layr",
  "private": true,
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-http-client": "^1.0.0",
    "@layr/component-http-server": "^1.0.0",
    "@layr/memory-store": "^1.0.0",
    "@layr/react-integration": "^1.0.0",
    "@layr/storable": "^1.0.0",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/core": "^7.11.5",
    "@babel/node": "^7.10.5",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/plugin-proposal-decorators": "^7.10.5",
    "@babel/preset-env": "^7.11.5",
    "@babel/preset-react": "^7.10.4",
    "babel-loader": "^8.1.0",
    "html-webpack-plugin": "^4.4.1",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  }
}


================================================
FILE: examples/v1/guestbook-web-js/src/backend.js
================================================
import {Component, expose, validators} from '@layr/component';
import {Storable, primaryIdentifier, attribute} from '@layr/storable';
import {MemoryStore} from '@layr/memory-store';
import {ComponentHTTPServer} from '@layr/component-http-server';

const {notEmpty, maxLength} = validators;

@expose({
  find: {call: true},
  prototype: {
    load: {call: true},
    save: {call: true}
  }
})
export class Message extends Storable(Component) {
  @expose({get: true, set: true}) @primaryIdentifier() id;

  @expose({get: true, set: true})
  @attribute('string', {validators: [notEmpty(), maxLength(300)]})
  text = '';

  @expose({get: true}) @attribute('Date') createdAt = new Date();
}

const store = new MemoryStore();

store.registerStorable(Message);

const server = new ComponentHTTPServer(Message, {port: 3210});

server.start();


================================================
FILE: examples/v1/guestbook-web-js/src/frontend.js
================================================
import React, {useCallback} from 'react';
import ReactDOM from 'react-dom';
import {Component, attribute, provide} from '@layr/component';
import {Storable} from '@layr/storable';
import {ComponentHTTPClient} from '@layr/component-http-client';
import {view, useAsyncCall, useAsyncCallback, useRecomputableMemo} from '@layr/react-integration';

async function main() {
  const client = new ComponentHTTPClient('http://localhost:3210', {
    mixins: [Storable]
  });

  const BackendMessage = await client.getComponent();

  class Message extends BackendMessage {
    @view() Viewer() {
      return (
        <div>
          <small>{this.createdAt.toLocaleString()}</small>
          <br />
          <strong>{this.text}</strong>
        </div>
      );
    }

    @view() Form({onSubmit}) {
      const [handleSubmit, isSubmitting, submitError] = useAsyncCallback(async (event) => {
        event.preventDefault();
        await onSubmit();
      });

      return (
        <form onSubmit={handleSubmit}>
          <div>
            <textarea
              value={this.text}
              onChange={(event) => {
                this.text = event.target.value;
              }}
              required
              style={{width: '100%', height: '80px'}}
            />
          </div>

          <p>
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
          </p>

          {submitError && (
            <p style={{color: 'red'}}>Sorry, an error occurred while submitting your message.</p>
          )}
        </form>
      );
    }
  }

  class Guestbook extends Component {
    @provide() static Message = Message;

    @attribute('Message[]') static existingMessages = [];

    @view() static Home() {
      return (
        <div style={{maxWidth: '700px', margin: '40px auto'}}>
          <h1>Guestbook</h1>
          <this.MessageList />
          <this.MessageCreator />
        </div>
      );
    }

    @view() static MessageList() {
      const {Message} = this;

      const [isLoading, loadingError] = useAsyncCall(async () => {
        this.existingMessages = await Message.find(
          {},
          {text: true, createdAt: true},
          {sort: {createdAt: 'desc'}, limit: 30}
        );
      });

      if (isLoading) {
        return null;
      }

      if (loadingError) {
        return (
          <p style={{color: 'red'}}>
            Sorry, an error occurred while loading the guestbook’s messages.
          </p>
        );
      }

      return (
        <div>
          <h2>All Messages</h2>
          {this.existingMessages.length > 0 ? (
            this.existingMessages.map((message) => (
              <div key={message.id} style={{marginTop: '15px'}}>
                <message.Viewer />
              </div>
            ))
          ) : (
            <p>No messages yet.</p>
          )}
        </div>
      );
    }

    @view() static MessageCreator() {
      const {Message} = this;

      const [createdMessage, resetCreatedMessage] = useRecomputableMemo(() => new Message());

      const saveMessage = useCallback(async () => {
        await createdMessage.save();
        this.existingMessages = [createdMessage, ...this.existingMessages];
        resetCreatedMessage();
      }, [createdMessage]);

      return (
        <div>
          <h2>Add a Message</h2>
          <createdMessage.Form onSubmit={saveMessage} />
        </div>
      );
    }
  }

  ReactDOM.render(<Guestbook.Home />, document.getElementById('root'));
}

main().catch((error) => console.error(error));


================================================
FILE: examples/v1/guestbook-web-js/src/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Guestbook</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <%= htmlWebpackPlugin.tags.headTags %>
  </head>
  <body>
    <noscript><p>Sorry, this site requires JavaScript to be enabled.</p></noscript>
    <div id="root"></div>
    <%= htmlWebpackPlugin.tags.bodyTags %>
  </body>
</html>


================================================
FILE: examples/v1/guestbook-web-js/webpack.config.js
================================================
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = (env, argv) => {
  return {
    // The entry point of the app is './src/frontend.js'
    entry: './src/frontend.js',
    output: {
      // Specify '/' as the base path for all the assets
      // This is required for a single-page application
      publicPath: '/'
    },
    module: {
      rules: [
        {
          // Use 'babel-loader' to compile the JS files
          test: /\.js$/,
          include: path.join(__dirname, 'src'),
          loader: 'babel-loader'
        }
      ]
    },
    plugins: [
      // Use 'html-webpack-plugin' to generate the 'index.html' file
      // from the './src/index.html' template
      new HtmlWebPackPlugin({
        template: './src/index.html',
        inject: false
      })
    ],
    // Generate source maps to make debugging easier
    devtool: 'eval-cheap-module-source-map',
    devServer: {
      // Fallback to 'index.html' in case of 404 responses
      // This is required for a single-page application
      historyApiFallback: true
    }
  };
};


================================================
FILE: examples/v1/guestbook-web-ts/README.md
================================================
# Guestbook Web (TS)

A simple web app showing how to build a web frontend with Layr.

See the [corresponding guide](https://layrjs.com/docs/v1/introduction/web-app?language=ts).


================================================
FILE: examples/v1/guestbook-web-ts/package.json
================================================
{
  "name": "guestbook-web",
  "version": "1.0.0",
  "description": "A simple web app showing how to build a web frontend with Layr",
  "private": true,
  "dependencies": {
    "@layr/component": "^1.0.0",
    "@layr/component-http-client": "^1.0.0",
    "@layr/component-http-server": "^1.0.0",
    "@layr/memory-store": "^1.0.0",
    "@layr/react-integration": "^1.0.0",
    "@layr/storable": "^1.0.0",
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@types/react": "^16.9.49",
    "@types/react-dom": "^16.9.8",
    "html-webpack-plugin": "^4.3.0",
    "ts-loader": "^7.0.5",
    "ts-node": "^8.10.2",
    "typescript": "^3.9.7",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  }
}


================================================
FILE: examples/v1/guestbook-web-ts/src/backend.ts
================================================
import {Component, expose, validators} from '@layr/component';
import {Storable, primaryIdentifier, attribute} from '@layr/storable';
import {MemoryStore} from '@layr/memory-store';
import {ComponentHTTPServer} from '@layr/component-http-server';

const {notEmpty, maxLength} = validators;

@expose({
  find: {call: true},
  prototype: {
    load: {call: true},
    save: {call: true}
  }
})
export class Message extends Storable(Component) {
  @expose({get: true, set: true}) @primaryIdentifier() id!: string;

  @expose({get: true, set: true})
  @attribute('string', {validators: [notEmpty(), maxLength(300)]})
  text = '';

  @expose({get: true}) @attribute('Date') createdAt = new Date();
}

const store = new MemoryStore();

store.registerStorable(Message);

const server = new ComponentHTTPServer(Message, {port: 3210});

server.start();


================================================
FILE: examples/v1/guestbook-web-ts/src/frontend.tsx
================================================
import React, {useCallback} from 'react';
import ReactDOM from 'react-dom';
import {Component, attribute, provide} from '@layr/component';
import {Storable} from '@layr/storable';
import {ComponentHTTPClient} from '@layr/component-http-client';
import {
  view,
  useAsyncCall,
  useAsyncCallback,
  useRecomputableMemo
} from '@layr/react-integration';

import type {Message as MessageType} from './backend';

async function main() {
  const client = new ComponentHTTPClient('http://localhost:3210', {
    mixins: [Storable]
  });

  const BackendMessage = (await client.getComponent()) as typeof MessageType;

  class Message extends BackendMessage {
    @view() Viewer() {
      return (
        <div>
          <small>{this.createdAt.toLocaleString()}</small>
          <br />
          <strong>{this.text}</strong>
        </div>
      );
    }

    @view() Form({onSubmit}: {onSubmit: () => Promise<void>}) {
      const [handleSubmit, isSubmitting, submitError] = useAsyncCallback(async (event) => {
        event.preventDefault();
        await onSubmit();
      });

      return (
        <form onSubmit={handleSubmit}>
          <div>
            <textarea
              value={this.text}
              onChange={(event) => {
                this.text = event.target.value;
              }}
              required
              style={{width: '100%', height: '80px'}}
            />
          </div>

          <p>
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
          </p>

          {submitError && (
            <p style={{color: 'red'}}>Sorry, an error occurred while submitting your message.</p>
          )}
        </form>
      );
    }
  }

  class Guestbook extends Component {
    @provide() static Message = Message;

    @attribute('Message[]') static existingMessages: Message[] = [];

    @view() static Home() {
      return (
        <div style={{maxWidth: '700px', margin: '40px auto'}}>
          <h1>Guestbook</h1>
          <this.MessageList />
          <this.MessageCreator />
        </div>
      );
    }

    @view() static MessageList() {
      const {Message} = this;

      const [isLoading, loadingError] = useAsyncCall(async () => {
        this.existingMessages = await Message.find(
          {},
          {text: true, createdAt: true},
          {sort: {createdAt: 'desc'}, limit: 30}
        );
      });

      if (isLoading) {
        return null;
      }

      if (loadingError) {
        return (
          <p style={{color: 'red'}}>
            Sorry, an error occurred while loading the guestbook’s messages.
          </p>
        );
      }

      return (
        <div>
          <h2>All Messages</h2>
          {this.existingMessages.length > 0 ? (
            this.existingMessages.map((message) => (
              <div key={message.id} style={{marginTop: '15px'}}>
                <message.Viewer />
              </div>
            ))
          ) : (
            <p>No messages yet.</p>
          )}
        </div>
      );
    }

    @view() static MessageCreator() {
      const {Message} = this;

      const [createdMessage, resetCreatedMessage] = useRecomputableMemo(() => new Message());

      const saveMessage = useCallback(async () => {
        await createdMessage.save();
        this.existingMessages = [createdMessage, ...this.existingMessages];
        resetCreatedMessage();
      }, [createdMessage]);

      return (
        <div>
          <h2>Add a Message</h2>
          <createdMessage.Form onSubmit={saveMessage} />
        </div>
      );
    }
  }

  ReactDOM.render(<Guestbook.Home />, document.getElementById('root'));
}

main().catch((error) => console.error(error));


================================================
FILE: examples/v1/guestbook-web-ts/src/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Guestbook</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta http-equiv="x-ua-compatible" content="ie=edge" />
    <%= htmlWebpackPlugin.tags.headTags %>
  </head>
  <body>
    <noscript><p>Sorry, this site requires JavaScript to be enabled.</p></noscript>
    <div id="root"></div>
    <%= htmlWebpackPlugin.tags.bodyTags %>
  </body>
</html>


================================================
FILE: examples/v1/guestbook-web-ts/tsconfig.json
================================================
{
  "include": ["src/**/*"],
  "compilerOptions": {
    "target": "ES2017",
    "module": "CommonJS",
    "lib": ["ESNext", "DOM"],
    "jsx": "react",
    "sourceMap": true,
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "noUnusedLocals": true,
    
Download .txt
gitextract_vbywh81w/

├── .editorconfig
├── .gitignore
├── .npm-dev-registry.json
├── .prettierignore
├── .vscode/
│   └── extensions.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── assets/
│   ├── frontend-backend.excalidraw
│   ├── frontend-webapi-backend.excalidraw
│   ├── typical-stack-vs-layr-stack-light-mode.excalidraw
│   └── typical-stack-vs-layr-stack.excalidraw
├── docs/
│   ├── build.js
│   ├── contents/
│   │   ├── concepts/
│   │   │   └── coming-soon.md
│   │   ├── guides/
│   │   │   └── coming-soon.md
│   │   ├── index.json
│   │   └── introduction/
│   │       ├── handling-authorization.md
│   │       ├── hello-world/
│   │       │   └── hello-world.md
│   │       ├── introduction.md
│   │       └── storing-data.md
│   └── package.json
├── examples/
│   ├── v1/
│   │   ├── counter/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   ├── counter-with-create-react-app-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── package.json
│   │   │   │   ├── public/
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── manifest.json
│   │   │   │   │   └── robots.txt
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── react-app-env.d.ts
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── counter-with-esbuild-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── index.tsx
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── counter-with-http/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   ├── counter-with-parcel-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── babel.config.js
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── index.tsx
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── counter-with-rollup-ts/
│   │   │   ├── README.md
│   │   │   ├── backend/
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.ts
│   │   │   │   │   ├── http-server.ts
│   │   │   │   │   └── server.ts
│   │   │   │   └── tsconfig.json
│   │   │   ├── frontend/
│   │   │   │   ├── babel.config.js
│   │   │   │   ├── package.json
│   │   │   │   ├── rollup.config.js
│   │   │   │   ├── src/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── counter.tsx
│   │   │   │   │   ├── index.html
│   │   │   │   │   └── index.tsx
│   │   │   │   └── tsconfig.json
│   │   │   └── package.json
│   │   ├── guestbook-cli-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   ├── guestbook-cli-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   └── frontend.ts
│   │   │   └── tsconfig.json
│   │   ├── guestbook-web-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.js
│   │   │   │   ├── frontend.js
│   │   │   │   └── index.html
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   ├── frontend.tsx
│   │   │   │   └── index.html
│   │   │   ├── tsconfig.json
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-authorization-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.js
│   │   │   │   ├── frontend.js
│   │   │   │   └── index.html
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-authorization-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   ├── frontend.tsx
│   │   │   │   └── index.html
│   │   │   ├── tsconfig.json
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-routes-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.js
│   │   │   │   ├── frontend.js
│   │   │   │   └── index.html
│   │   │   └── webpack.config.js
│   │   ├── guestbook-web-with-routes-ts/
│   │   │   ├── README.md
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   │   ├── backend.ts
│   │   │   │   ├── frontend.tsx
│   │   │   │   └── index.html
│   │   │   ├── tsconfig.json
│   │   │   └── webpack.config.js
│   │   ├── hello-world-js/
│   │   │   ├── README.md
│   │   │   ├── babel.config.json
│   │   │   ├── jsconfig.json
│   │   │   ├── package.json
│   │   │   └── src/
│   │   │       ├── backend.js
│   │   │       └── frontend.js
│   │   └── hello-world-ts/
│   │       ├── README.md
│   │       ├── package.json
│   │       ├── src/
│   │       │   ├── backend.ts
│   │       │   └── frontend.ts
│   │       └── tsconfig.json
│   └── v2/
│       ├── hello-world-js/
│       │   ├── .editorconfig
│       │   ├── .gitignore
│       │   ├── .prettierignore
│       │   ├── .vscode/
│       │   │   ├── extensions.json
│       │   │   └── settings.json
│       │   ├── README.md
│       │   ├── backend/
│       │   │   ├── boostr.config.mjs
│       │   │   ├── boostr.config.private-example.mjs
│       │   │   ├── jsconfig.json
│       │   │   ├── package.json
│       │   │   └── src/
│       │   │       ├── components/
│       │   │       │   └── application.js
│       │   │       └── index.js
│       │   ├── boostr.config.mjs
│       │   ├── database/
│       │   │   ├── .gitignore
│       │   │   ├── boostr.config.mjs
│       │   │   └── boostr.config.private-example.mjs
│       │   ├── frontend/
│       │   │   ├── boostr.config.mjs
│       │   │   ├── jsconfig.json
│       │   │   ├── package.json
│       │   │   └── src/
│       │   │       ├── components/
│       │   │       │   └── application.jsx
│       │   │       └── index.js
│       │   └── package.json
│       └── hello-world-ts/
│           ├── .editorconfig
│           ├── .gitignore
│           ├── .prettierignore
│           ├── .vscode/
│           │   ├── extensions.json
│           │   └── settings.json
│           ├── README.md
│           ├── backend/
│           │   ├── boostr.config.mjs
│           │   ├── boostr.config.private-example.mjs
│           │   ├── package.json
│           │   ├── src/
│           │   │   ├── components/
│           │   │   │   └── application.ts
│           │   │   └── index.ts
│           │   └── tsconfig.json
│           ├── boostr.config.mjs
│           ├── database/
│           │   ├── .gitignore
│           │   ├── boostr.config.mjs
│           │   └── boostr.config.private-example.mjs
│           ├── frontend/
│           │   ├── boostr.config.mjs
│           │   ├── package.json
│           │   ├── src/
│           │   │   ├── components/
│           │   │   │   └── application.tsx
│           │   │   └── index.ts
│           │   └── tsconfig.json
│           └── package.json
├── lerna.json
├── nx.json
├── package.json
├── packages/
│   ├── aws-integration/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── lambda-execution-queue-sender.ts
│   │   │   └── lambda-handler.ts
│   │   └── tsconfig.json
│   ├── browser-navigator/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── browser-navigator.ts
│   │   │   ├── index.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── component/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── cloning.test.ts
│   │   │   ├── cloning.ts
│   │   │   ├── component.test.ts
│   │   │   ├── component.ts
│   │   │   ├── decorators.test.ts
│   │   │   ├── decorators.ts
│   │   │   ├── deserialization.test.ts
│   │   │   ├── deserialization.ts
│   │   │   ├── embedded-component.ts
│   │   │   ├── forking.test.ts
│   │   │   ├── forking.ts
│   │   │   ├── identifiable-component.test.ts
│   │   │   ├── identity-map.test.ts
│   │   │   ├── identity-map.ts
│   │   │   ├── index.ts
│   │   │   ├── js-parser.ts
│   │   │   ├── js-tests/
│   │   │   │   ├── decorators.test.js
│   │   │   │   └── jsconfig.json
│   │   │   ├── merging.test.ts
│   │   │   ├── merging.ts
│   │   │   ├── properties/
│   │   │   │   ├── attribute-selector.test.ts
│   │   │   │   ├── attribute-selector.ts
│   │   │   │   ├── attribute.test.ts
│   │   │   │   ├── attribute.ts
│   │   │   │   ├── identifier-attribute.test.ts
│   │   │   │   ├── identifier-attribute.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── method.test.ts
│   │   │   │   ├── method.ts
│   │   │   │   ├── primary-identifier-attribute.test.ts
│   │   │   │   ├── primary-identifier-attribute.ts
│   │   │   │   ├── property.test.ts
│   │   │   │   ├── property.ts
│   │   │   │   ├── secondary-identifier-attribute.test.ts
│   │   │   │   ├── secondary-identifier-attribute.ts
│   │   │   │   └── value-types/
│   │   │   │       ├── any-value-type.ts
│   │   │   │       ├── array-value-type.ts
│   │   │   │       ├── boolean-value-type.ts
│   │   │   │       ├── component-value-type.ts
│   │   │   │       ├── date-value-type.ts
│   │   │   │       ├── factory.test.ts
│   │   │   │       ├── factory.ts
│   │   │   │       ├── index.ts
│   │   │   │       ├── number-value-type.ts
│   │   │   │       ├── object-value-type.ts
│   │   │   │       ├── regexp-value-type.ts
│   │   │   │       ├── string-value-type.ts
│   │   │   │       ├── value-type.test.ts
│   │   │   │       └── value-type.ts
│   │   │   ├── sanitization/
│   │   │   │   ├── index.ts
│   │   │   │   ├── sanitizer-builders.test.ts
│   │   │   │   ├── sanitizer-builders.ts
│   │   │   │   ├── sanitizer.test.ts
│   │   │   │   ├── sanitizer.ts
│   │   │   │   ├── utilities.test.ts
│   │   │   │   └── utilities.ts
│   │   │   ├── serialization.test.ts
│   │   │   ├── serialization.ts
│   │   │   ├── utilities.test.ts
│   │   │   ├── utilities.ts
│   │   │   └── validation/
│   │   │       ├── index.ts
│   │   │       ├── utilities.test.ts
│   │   │       ├── utilities.ts
│   │   │       ├── validator-builders.test.ts
│   │   │       ├── validator-builders.ts
│   │   │       ├── validator.test.ts
│   │   │       └── validator.ts
│   │   └── tsconfig.json
│   ├── component-client/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-client.test.ts
│   │   │   ├── component-client.ts
│   │   │   ├── index.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── component-express-middleware/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-express-middleware.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-http-client/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-http-client.test.ts
│   │   │   ├── component-http-client.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-http-server/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-http-server.test.ts
│   │   │   ├── component-http-server.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-koa-middleware/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-koa-middleware.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── component-server/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── component-server.test.ts
│   │   │   ├── component-server.ts
│   │   │   ├── index.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── execution-queue/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── execution-queue.test.ts
│   │   │   ├── execution-queue.ts
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   ├── integration-testing/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── client-server.test.ts
│   │   │   ├── component-express-middleware.test.ts
│   │   │   ├── component-koa-middleware.test.ts
│   │   │   ├── counter.fixture.ts
│   │   │   ├── http-client-server.test.ts
│   │   │   ├── memory-navigator.test.ts
│   │   │   ├── navigator.test.ts
│   │   │   ├── storable.fixture.ts
│   │   │   └── storable.test.ts
│   │   └── tsconfig.json
│   ├── memory-navigator/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   └── memory-navigator.ts
│   │   └── tsconfig.json
│   ├── memory-store/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   └── memory-store.ts
│   │   └── tsconfig.json
│   ├── mongodb-store/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── mongodb-store.test.ts
│   │   │   └── mongodb-store.ts
│   │   └── tsconfig.json
│   ├── navigator/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── navigator.ts
│   │   │   ├── utilities.test.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── observable/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── observable.test.ts
│   │   │   └── observable.ts
│   │   └── tsconfig.json
│   ├── react-integration/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── components.tsx
│   │   │   ├── decorators.tsx
│   │   │   ├── hooks.ts
│   │   │   ├── index.ts
│   │   │   └── plugins.tsx
│   │   └── tsconfig.json
│   ├── routable/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── addressable.ts
│   │   │   ├── decorators.test.ts
│   │   │   ├── decorators.ts
│   │   │   ├── index.ts
│   │   │   ├── js-tests/
│   │   │   │   ├── decorators.test.js
│   │   │   │   └── jsconfig.json
│   │   │   ├── param.ts
│   │   │   ├── pattern.ts
│   │   │   ├── routable.test.ts
│   │   │   ├── routable.ts
│   │   │   ├── route.test.ts
│   │   │   ├── route.ts
│   │   │   ├── utilities.ts
│   │   │   └── wrapper.ts
│   │   └── tsconfig.json
│   ├── storable/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── decorators.test.ts
│   │   │   ├── decorators.ts
│   │   │   ├── index-class.test.ts
│   │   │   ├── index-class.ts
│   │   │   ├── index.ts
│   │   │   ├── js-tests/
│   │   │   │   ├── decorators.test.js
│   │   │   │   └── jsconfig.json
│   │   │   ├── operator.ts
│   │   │   ├── properties/
│   │   │   │   ├── index.ts
│   │   │   │   ├── storable-attribute.test.ts
│   │   │   │   ├── storable-attribute.ts
│   │   │   │   ├── storable-method.ts
│   │   │   │   ├── storable-primary-identifier-attribute.ts
│   │   │   │   ├── storable-property.ts
│   │   │   │   └── storable-secondary-identifier-attribute.ts
│   │   │   ├── query.ts
│   │   │   ├── storable.ts
│   │   │   ├── store-like.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── store/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── document.ts
│   │   │   ├── expression.ts
│   │   │   ├── index.ts
│   │   │   ├── path.ts
│   │   │   ├── store.test.ts
│   │   │   ├── store.ts
│   │   │   └── utilities.ts
│   │   └── tsconfig.json
│   ├── utilities/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── error.test.ts
│   │   │   ├── error.ts
│   │   │   ├── index.ts
│   │   │   └── time.ts
│   │   └── tsconfig.json
│   └── with-roles/
│       ├── .gitignore
│       ├── README.md
│       ├── package.json
│       ├── src/
│       │   ├── decorators.test.ts
│       │   ├── decorators.ts
│       │   ├── index.ts
│       │   ├── role.test.ts
│       │   ├── role.ts
│       │   ├── utilities.ts
│       │   ├── with-roles.test.ts
│       │   └── with-roles.ts
│       └── tsconfig.json
└── website/
    ├── README.md
    ├── backend/
    │   ├── boostr.config.mjs
    │   ├── boostr.config.private-template.mjs
    │   ├── package.json
    │   ├── src/
    │   │   ├── components/
    │   │   │   ├── application.ts
    │   │   │   ├── article.ts
    │   │   │   ├── entity.ts
    │   │   │   ├── newsletter.ts
    │   │   │   ├── user.ts
    │   │   │   └── with-author.ts
    │   │   ├── index.ts
    │   │   └── jwt.ts
    │   └── tsconfig.json
    ├── boostr.config.mjs
    ├── database/
    │   ├── .gitignore
    │   ├── boostr.config.mjs
    │   └── boostr.config.private-template.mjs
    ├── frontend/
    │   ├── boostr.config.mjs
    │   ├── package.json
    │   ├── public/
    │   │   └── docs/
    │   │       ├── v1/
    │   │       │   ├── introduction/
    │   │       │   │   ├── authorization-6eooNLZnaLZk4eJNHNGwUp-edited.immutable.md
    │   │       │   │   ├── data-storage-1YDg3LGZPF09H3opJUEDSp-edited.immutable.md
    │   │       │   │   ├── hello-world-7F76XnjXXBB7eeZTpEZwEX-edited.immutable.md
    │   │       │   │   ├── introduction-1NNtkbXN0zHvG6VR0jvPRK-edited.immutable.md
    │   │       │   │   ├── routing-4ubaWloMHuNNs0foagYUwi-edited.immutable.md
    │   │       │   │   └── web-app-5okryUyuriFFHXtFK9uZNY-edited.immutable.md
    │   │       │   └── reference/
    │   │       │       ├── attribute-4P9dTivZ9HJ4Flr4Y8cTKv.immutable.md
    │   │       │       ├── attribute-selector-7FZWQpwLR7jpUHoBpvO9Et.immutable.md
    │   │       │       ├── aws-integration-3iPKbtjOS0uDgsZKk6Q0Kp.immutable.md
    │   │       │       ├── browser-router-6EIyPCgoPYsWmDmpyKMhce.immutable.md
    │   │       │       ├── component-6LvsJL2MA9RN6hmT0bBacd.immutable.md
    │   │       │       ├── component-client-1ISSjJNRL12I33addutRh4.immutable.md
    │   │       │       ├── component-express-middleware-6UieWJkEvLdXLYug4xuM16.immutable.md
    │   │       │       ├── component-http-client-6g8M9kRcBS4AQwFtAp7t9z.immutable.md
    │   │       │       ├── component-http-server-5VDR5fS2uD9iTkuHRSywjz.immutable.md
    │   │       │       ├── component-koa-middleware-402oMlpSmEIARQJLzn4qQg.immutable.md
    │   │       │       ├── component-server-e5RUuQXVcCIVLxHiNzCDO.immutable.md
    │   │       │       ├── embedded-component-4MiZBzspJQbUshU8Q93aJ8.immutable.md
    │   │       │       ├── identifier-attribute-6Jgrzmrlv4QJoBZVTYYDb9.immutable.md
    │   │       │       ├── identity-map-01fsjrVv6cSC6awmnNnn6c.immutable.md
    │   │       │       ├── index-1KeXILVBQNLQpRzBhIWjqB.immutable.md
    │   │       │       ├── memory-router-TGoBOhUXFPp3iDyKA9Sn0.immutable.md
    │   │       │       ├── memory-store-78uJRKSOEyr1WnXttCnd9u.immutable.md
    │   │       │       ├── method-3mc2TakviGDKFcdpxFaCIu.immutable.md
    │   │       │       ├── mongodb-store-1yTYtEyVy4ZLkF4A2QFaAh.immutable.md
    │   │       │       ├── observable-6JJJVlFHPe2kPQ4NhsJg7O.immutable.md
    │   │       │       ├── primary-identifier-attribute-6qTkOuHNN4Bq3EjC9JGVqr.immutable.md
    │   │       │       ├── property-5bbULbxC52tIPaMAcPEp27.immutable.md
    │   │       │       ├── query-Q04JuSZAcx8HGvYktmTlI.immutable.md
    │   │       │       ├── react-integration-3EgAB99IhnithzdqiytvwF.immutable.md
    │   │       │       ├── role-UodTLJi6Lg6UPXOKZdp8K.immutable.md
    │   │       │       ├── routable-3zt4vMLvzQR3aqOwoWd3xV.immutable.md
    │   │       │       ├── route-1rS9AS4eda7qe7lWTU4WKF.immutable.md
    │   │       │       ├── router-5zhzJL9MYM1yaHY6CXlkso.immutable.md
    │   │       │       ├── secondary-identifier-attribute-7BqK9EmnCMCHIAroYiQDth.immutable.md
    │   │       │       ├── storable-2maAYPX5kWufBfVolYVgdc.immutable.md
    │   │       │       ├── storable-attribute-7MiyqvA7PUf2E2YeoqA912.immutable.md
    │   │       │       ├── storable-method-1rnW3aKFlFYZ3kIJdCGXRv.immutable.md
    │   │       │       ├── storable-primary-identifier-attribute-74IwGTycdA7NVAybBly3t1.immutable.md
    │   │       │       ├── storable-property-5LuWR7uuQ1qdebK3iszZJO.immutable.md
    │   │       │       ├── storable-secondary-identifier-attribute-6CqhR0kLxoLhtWU85EcsZU.immutable.md
    │   │       │       ├── store-6BvlCSWkAb7smHsvoIGjv1.immutable.md
    │   │       │       ├── validator-2strlvnapeTZmbWT3o3VM1.immutable.md
    │   │       │       ├── value-type-23f3WjnZNDfFejs5ceJVcY.immutable.md
    │   │       │       └── with-roles-2PYi0037F3Mxg80b5YKb26.immutable.md
    │   │       └── v2/
    │   │           ├── concepts/
    │   │           │   └── coming-soon-38q4cuyCWekHuz36oHyMKG.immutable.md
    │   │           ├── guides/
    │   │           │   └── coming-soon-6TWZbDxh3EVysir57k1tga.immutable.md
    │   │           ├── introduction/
    │   │           │   ├── handling-authorization-1sLAebuD81FLlSvJbAuJmZ.immutable.md
    │   │           │   ├── hello-world/
    │   │           │   │   └── hello-world-2FHBCgFRhZX9qH9O1RkTlZ.immutable.md
    │   │           │   ├── introduction-1iLUBREWe2BB65qw9G4uzm.immutable.md
    │   │           │   └── storing-data-40jzWiVleR8ZE0fqfGTbO2.immutable.md
    │   │           └── reference/
    │   │               ├── addressable-6n5npS1cCoPKLkFrYU0Pk7.immutable.md
    │   │               ├── attribute-4IRansPGIm4E3gunH3Ztlq.immutable.md
    │   │               ├── attribute-selector-76ksImknctJspHLg12sRpR.immutable.md
    │   │               ├── aws-integration-3Rt2txpqioYQsmijgSqqwF.immutable.md
    │   │               ├── browser-navigator-eYIxYKNFdRYiKTxIWAjqd.immutable.md
    │   │               ├── component-1zBrZVglO2cjDP9aO87pOR.immutable.md
    │   │               ├── component-client-69HLk6gKzg5DfWcVC2bQWS.immutable.md
    │   │               ├── component-express-middleware-7KGBerWY9jB9r9eOjwLmPq.immutable.md
    │   │               ├── component-http-client-2rHYFMcsawI16EvGk8372w.immutable.md
    │   │               ├── component-http-server-5aWTLSzVvm0WohfP6af7OP.immutable.md
    │   │               ├── component-koa-middleware-6aVaQsSgkzWt35XyqSMuqx.immutable.md
    │   │               ├── component-server-i0AsOVFbGCJUrJ9mJyjPh.immutable.md
    │   │               ├── embedded-component-3YdGqfLNxl8c001AvWxHZ6.immutable.md
    │   │               ├── identifier-attribute-2w8hckqCKGHPurgIGY5vhT.immutable.md
    │   │               ├── identity-map-7sLdA5rsLvflf8T8OsZfGO.immutable.md
    │   │               ├── index-1Uz5JX1XB7V67nfM6tvnSV.immutable.md
    │   │               ├── memory-navigator-5wC9TEZn2cen7LuV4cGPOj.immutable.md
    │   │               ├── memory-store-3QHbAhGolblHx4OY17rEP.immutable.md
    │   │               ├── method-MAFTDipVXsOXj4o2CJLNQ.immutable.md
    │   │               ├── mongodb-store-37qsYI8A5ctkFlHTDVIc3O.immutable.md
    │   │               ├── navigator-5vNC9hp62PFUvxh0PLQcJ9.immutable.md
    │   │               ├── observable-7alzx5bqV1gD2Aj60hWQ0L.immutable.md
    │   │               ├── primary-identifier-attribute-5EqFynrkNUTa9DxYYmbmOl.immutable.md
    │   │               ├── property-bs5Xm31fCQXQkoZL24prZ.immutable.md
    │   │               ├── query-146gEiaHLp06V3LqhxRCzC.immutable.md
    │   │               ├── react-integration-4BgvR6gvTuqLdpNymyUYS1.immutable.md
    │   │               ├── role-3zJ3w6whE8RucN9kAhS5Hv.immutable.md
    │   │               ├── routable-7zjaksbkNa8sbNfqNnEKUu.immutable.md
    │   │               ├── route-3O1kMMGl4yZc9LGxH38Z3G.immutable.md
    │   │               ├── sanitizer-3hc34yGhzbK1cupoMtP6Dv.immutable.md
    │   │               ├── secondary-identifier-attribute-27lBtqHBopmgIAWwmeoLBg.immutable.md
    │   │               ├── storable-3UMrfeCfFVaVttjxtmCvVy.immutable.md
    │   │               ├── storable-attribute-1EYIvaUK2WvHmV3OxG5IzJ.immutable.md
    │   │               ├── storable-method-1o1egWUfiZzxO6y7Sda4rb.immutable.md
    │   │               ├── storable-primary-identifier-attribute-7qq06XjPnNRXumxcngJvZv.immutable.md
    │   │               ├── storable-property-6Ooq1wLy5pGx7Jb1qRrRyf.immutable.md
    │   │               ├── storable-secondary-identifier-attribute-1TKIxZX9JZ2aGFU5iEmUSv.immutable.md
    │   │               ├── store-1mGBVGCiO4K5X9dBakik9Z.immutable.md
    │   │               ├── validator-2aTKblcN30ADdXqrI3bHXv.immutable.md
    │   │               ├── value-type-FqKdGxNpEPIDVR56kq4NN.immutable.md
    │   │               ├── with-roles-CcLPnrWKVYxnZXgNTqVYi.immutable.md
    │   │               └── wrapper-4uhJFGS18pbZTt9qdtLnL2.immutable.md
    │   ├── src/
    │   │   ├── components/
    │   │   │   ├── application.tsx
    │   │   │   ├── article.tsx
    │   │   │   ├── blog.tsx
    │   │   │   ├── docs.tsx
    │   │   │   ├── home.tsx
    │   │   │   ├── newsletter.tsx
    │   │   │   └── user.tsx
    │   │   ├── custom.d.ts
    │   │   ├── docs.json
    │   │   ├── index.ts
    │   │   ├── markdown.tsx
    │   │   ├── styles.ts
    │   │   └── ui.tsx
    │   └── tsconfig.json
    ├── package.json
    └── redirection/
        ├── package.json
        ├── public/
        │   └── index.html
        └── simple-deployment.config.js
Download .txt
SYMBOL INDEX (1694 symbols across 195 files)

FILE: docs/build.js
  constant VERSION (line 5) | const VERSION = 'v2';
  constant SOURCE_DIRECTORY (line 7) | const SOURCE_DIRECTORY = './contents';
  constant BUILD_DIRECTORY (line 8) | const BUILD_DIRECTORY = './build';
  constant WEBSITE_DIRECTORY (line 9) | const WEBSITE_DIRECTORY = '../website/frontend/public/docs';
  constant WEBSITE_INDEX_FILE (line 10) | const WEBSITE_INDEX_FILE = '../website/frontend/src/docs.json';
  method filter (line 41) | filter(source) {

FILE: examples/v1/counter-with-create-react-app-ts/backend/src/components/counter.ts
  class Counter (line 3) | class Counter extends Component {
    method increment (line 8) | async increment() {

FILE: examples/v1/counter-with-create-react-app-ts/frontend/src/components/counter.tsx
  class Counter (line 12) | class Counter extends BackendCounterProxy {
    method Main (line 13) | Main() {

FILE: examples/v1/counter-with-esbuild-ts/backend/src/components/counter.ts
  class Counter (line 3) | class Counter extends Component {
    method increment (line 8) | async increment() {

FILE: examples/v1/counter-with-esbuild-ts/frontend/src/components/counter.tsx
  class Counter (line 12) | class Counter extends BackendCounterProxy {
    method Main (line 13) | Main() {

FILE: examples/v1/counter-with-http/src/backend.js
  class Counter (line 4) | class Counter extends Component {
    method increment (line 14) | @expose({call: true}) @method() increment() {

FILE: examples/v1/counter-with-http/src/frontend.js
  class Counter (line 11) | class Counter extends BackendCounter {
    method increment (line 12) | async increment() {

FILE: examples/v1/counter-with-parcel-ts/backend/src/components/counter.ts
  class Counter (line 3) | class Counter extends Component {
    method increment (line 8) | async increment() {

FILE: examples/v1/counter-with-parcel-ts/frontend/src/components/counter.tsx
  class Counter (line 12) | class Counter extends BackendCounterProxy {
    method Main (line 13) | Main() {

FILE: examples/v1/counter-with-rollup-ts/backend/src/components/counter.ts
  class Counter (line 3) | class Counter extends Component {
    method increment (line 8) | async increment() {

FILE: examples/v1/counter-with-rollup-ts/frontend/src/components/counter.tsx
  class Counter (line 12) | class Counter extends BackendCounterProxy {
    method Main (line 13) | Main() {

FILE: examples/v1/counter/src/backend.js
  class Counter (line 4) | class Counter extends Component {
    method increment (line 14) | @expose({call: true}) @method() increment() {

FILE: examples/v1/counter/src/frontend.js
  class Counter (line 12) | class Counter extends BackendCounter {
    method increment (line 13) | increment() {

FILE: examples/v1/guestbook-cli-js/src/backend.js
  class Message (line 15) | class Message extends Storable(Component) {

FILE: examples/v1/guestbook-cli-js/src/frontend.js
  function addMessage (line 19) | async function addMessage(text) {
  function showMessages (line 25) | async function showMessages() {

FILE: examples/v1/guestbook-cli-ts/src/backend.ts
  class Message (line 15) | class Message extends Storable(Component) {

FILE: examples/v1/guestbook-cli-ts/src/frontend.ts
  function addMessage (line 21) | async function addMessage(text: string) {
  function showMessages (line 27) | async function showMessages() {

FILE: examples/v1/guestbook-web-js/src/backend.js
  class Message (line 15) | class Message extends Storable(Component) {

FILE: examples/v1/guestbook-web-js/src/frontend.js
  function main (line 8) | async function main() {

FILE: examples/v1/guestbook-web-ts/src/backend.ts
  class Message (line 15) | class Message extends Storable(Component) {

FILE: examples/v1/guestbook-web-ts/src/frontend.tsx
  function main (line 15) | async function main() {

FILE: examples/v1/guestbook-web-with-authorization-js/src/backend.js
  class Session (line 9) | class Session extends Component {
    method isAdmin (line 14) | static isAdmin() {
  class Message (line 26) | class Message extends WithRoles(Storable(Component)) {
    method creatorRoleResolver (line 37) | @role('creator') creatorRoleResolver() {
    method adminRoleResolver (line 41) | @role('admin') static adminRoleResolver() {

FILE: examples/v1/guestbook-web-with-authorization-js/src/frontend.js
  function main (line 16) | async function main() {

FILE: examples/v1/guestbook-web-with-authorization-ts/src/backend.ts
  class Session (line 9) | class Session extends Component {
    method isAdmin (line 14) | static isAdmin() {
  class Message (line 26) | class Message extends WithRoles(Storable(Component)) {
    method creatorRoleResolver (line 37) | creatorRoleResolver() {
    method adminRoleResolver (line 41) | static adminRoleResolver() {

FILE: examples/v1/guestbook-web-with-authorization-ts/src/frontend.tsx
  function main (line 18) | async function main() {

FILE: examples/v1/guestbook-web-with-routes-js/src/backend.js
  class Message (line 15) | class Message extends Storable(Component) {

FILE: examples/v1/guestbook-web-with-routes-js/src/frontend.js
  function main (line 16) | async function main() {

FILE: examples/v1/guestbook-web-with-routes-ts/src/backend.ts
  class Message (line 15) | class Message extends Storable(Component) {

FILE: examples/v1/guestbook-web-with-routes-ts/src/frontend.tsx
  function main (line 18) | async function main() {

FILE: examples/v1/hello-world-js/src/backend.js
  class Greeter (line 4) | class Greeter extends Component {
    method hello (line 7) | @expose({call: true}) @method() async hello() {

FILE: examples/v1/hello-world-js/src/frontend.js
  class Greeter (line 8) | class Greeter extends BackendGreeter {
    method hello (line 9) | async hello() {

FILE: examples/v1/hello-world-ts/src/backend.ts
  class Greeter (line 4) | class Greeter extends Component {
    method hello (line 7) | async hello() {

FILE: examples/v1/hello-world-ts/src/frontend.ts
  class Greeter (line 10) | class Greeter extends BackendGreeter {
    method hello (line 11) | async hello() {

FILE: examples/v2/hello-world-js/backend/src/components/application.js
  class Application (line 3) | class Application extends Component {
    method getHelloWorld (line 4) | @expose({call: true}) @method() static async getHelloWorld() {

FILE: examples/v2/hello-world-js/frontend/src/components/application.jsx
  class Application (line 6) | class Application extends Routable(Base) {
    method MainLayout (line 7) | @layout('/') static MainLayout({children}) {
    method MainPage (line 18) | @page('[/]') static MainPage() {
    method HelloWorldPage (line 26) | @page('[/]hello-world') static HelloWorldPage() {
    method NotFoundPage (line 34) | @page('[/]*') static NotFoundPage() {

FILE: examples/v2/hello-world-js/frontend/src/index.js
  method retryFailedRequests (line 9) | async retryFailedRequests() {

FILE: examples/v2/hello-world-ts/backend/src/components/application.ts
  class Application (line 3) | class Application extends Component {
    method getHelloWorld (line 4) | static async getHelloWorld() {

FILE: examples/v2/hello-world-ts/frontend/src/components/application.tsx
  class Application (line 8) | class Application extends Routable(Base) {
    method MainLayout (line 11) | static MainLayout({children}: {children: () => any}) {
    method MainPage (line 22) | static MainPage() {
    method HelloWorldPage (line 30) | static HelloWorldPage() {
    method NotFoundPage (line 38) | static NotFoundPage() {
  type Application (line 53) | type Application = InstanceType<typeof Application>;
    method MainLayout (line 11) | static MainLayout({children}: {children: () => any}) {
    method MainPage (line 22) | static MainPage() {
    method HelloWorldPage (line 30) | static HelloWorldPage() {
    method NotFoundPage (line 38) | static NotFoundPage() {

FILE: examples/v2/hello-world-ts/frontend/src/index.ts
  method retryFailedRequests (line 10) | async retryFailedRequests() {

FILE: packages/aws-integration/src/lambda-execution-queue-sender.ts
  function createAWSLambdaExecutionQueueSender (line 4) | function createAWSLambdaExecutionQueueSender({

FILE: packages/aws-integration/src/lambda-handler.ts
  type CustomHandler (line 9) | type CustomHandler = (
  function createAWSLambdaHandler (line 44) | function createAWSLambdaHandler(

FILE: packages/browser-navigator/src/browser-navigator.ts
  type BrowserNavigatorLinkProps (line 4) | type BrowserNavigatorLinkProps = {
  type BrowserNavigatorOptions (line 12) | type BrowserNavigatorOptions = NavigatorOptions;
  class BrowserNavigator (line 25) | class BrowserNavigator extends Navigator {
    method constructor (line 33) | constructor(options: BrowserNavigatorOptions = {}) {
    method mount (line 44) | mount() {
    method unmount (line 92) | unmount() {
    method _getCurrentURL (line 122) | _getCurrentURL() {
    method _navigate (line 134) | _navigate(url: URL) {
    method _redirect (line 139) | _redirect(url: URL) {
    method _fixScrollPosition (line 144) | _fixScrollPosition() {
    method _reload (line 155) | _reload(url: URL | undefined) {
    method _go (line 163) | _go(delta: number) {
    method _getHistoryLength (line 180) | _getHistoryLength() {
    method _getHistoryIndex (line 184) | _getHistoryIndex() {

FILE: packages/browser-navigator/src/utilities.ts
  function isInternalURL (line 1) | function isInternalURL(url: URL | string) {

FILE: packages/component-client/src/component-client.test.ts
  method receive (line 9) | receive({query, components, version: clientVersion}) {
  method isStorable (line 257) | static isStorable() {}
  method isStorable (line 258) | isStorable() {}
  class BaseSession (line 340) | class BaseSession extends Component {
  class BaseMovie (line 344) | class BaseMovie extends Component {
    method find (line 348) | static find({limit}: {limit?: number} = {}): BaseMovie[] {}
    method play (line 354) | play() {}
    method validateTitle (line 356) | validateTitle(): boolean {}
  class BaseBackend (line 359) | class BaseBackend extends Component {

FILE: packages/component-client/src/component-client.ts
  type SendOperation (line 24) | interface SendOperation extends Operation {
  type ComponentClientOptions (line 29) | type ComponentClientOptions = {
  class ComponentClient (line 41) | class ComponentClient {
    method constructor (line 95) | constructor(componentServer: ComponentServerLike, options: ComponentCl...
    method getComponent (line 132) | getComponent() {
    method _createComponent (line 143) | _createComponent() {
    method _createMethodProxy (line 154) | _createMethodProxy(name: string) {
    method _introspectComponentServer (line 171) | _introspectComponentServer() {
    method send (line 189) | send(query: PlainObject, options: {rootComponent?: typeof Component} =...
    method _sendOne (line 197) | _sendOne(query: PlainObject, options: {rootComponent?: typeof Componen...
    method _sendMany (line 237) | async _sendMany(operations: SendOperation[]) {
    method _serializeQuery (line 299) | _serializeQuery(query: PlainObject) {
    method isComponentClient (line 370) | static isComponentClient(value: any): value is ComponentClient {
  function debugRequest (line 375) | function debugRequest({
  function debugResponse (line 393) | function debugResponse({
  function debugRequests (line 411) | function debugRequests({
  function debugResponses (line 429) | function debugResponses({

FILE: packages/component-client/src/utilities.ts
  function isComponentClientClass (line 3) | function isComponentClientClass(value: any): value is typeof ComponentCl...
  function isComponentClientInstance (line 7) | function isComponentClientInstance(value: any): value is ComponentClient {

FILE: packages/component-express-middleware/src/component-express-middleware.ts
  constant DEFAULT_LIMIT (line 39) | const DEFAULT_LIMIT = '8mb';
  type ServeComponentOptions (line 41) | type ServeComponentOptions = ComponentServerOptions & {
  function serveComponent (line 57) | function serveComponent(

FILE: packages/component-http-client/src/component-http-client.test.ts
  constant SERVER_PORT (line 11) | const SERVER_PORT = Math.floor(Math.random() * (60000 - 50000 + 1) + 500...

FILE: packages/component-http-client/src/component-http-client.ts
  constant DEFAULT_MAXIMUM_REQUEST_RETRIES (line 6) | const DEFAULT_MAXIMUM_REQUEST_RETRIES = 10;
  constant DEFAULT_MINIMUM_TIME_BETWEEN_REQUEST_RETRIES (line 7) | const DEFAULT_MINIMUM_TIME_BETWEEN_REQUEST_RETRIES = 3000;
  type ComponentHTTPClientOptions (line 9) | type ComponentHTTPClientOptions = ComponentClientOptions & {
  type RetryFailedRequests (line 15) | type RetryFailedRequests =
  class ComponentHTTPClient (line 110) | class ComponentHTTPClient extends ComponentClient {
    method constructor (line 125) | constructor(url: string, options: ComponentHTTPClientOptions = {}) {
  function createComponentServer (line 156) | function createComponentServer(

FILE: packages/component-http-server/src/component-http-server.test.ts
  constant SERVER_PORT (line 6) | const SERVER_PORT = Math.floor(Math.random() * (60000 - 50000 + 1) + 500...
  class Movie (line 12) | class Movie extends Component {
  function get (line 53) | async function get() {
  function postJSON (line 61) | async function postJSON(json: object) {
  function handleFetchResponse (line 73) | async function handleFetchResponse(response: Response) {

FILE: packages/component-http-server/src/component-http-server.ts
  constant DEFAULT_PORT (line 16) | const DEFAULT_PORT = 3333;
  type ComponentHTTPServerOptions (line 18) | type ComponentHTTPServerOptions = {port?: number} & ServeComponentOptions;
  class ComponentHTTPServer (line 31) | class ComponentHTTPServer {
    method constructor (line 47) | constructor(
    method start (line 75) | start() {
    method stop (line 108) | stop() {

FILE: packages/component-koa-middleware/src/component-koa-middleware.ts
  constant DEFAULT_LIMIT (line 48) | const DEFAULT_LIMIT = '8mb';
  type ServeComponentOptions (line 50) | type ServeComponentOptions = ComponentServerOptions & {
  function serveComponent (line 66) | function serveComponent(

FILE: packages/component-server/src/component-server.test.ts
  class Session (line 18) | class Session extends Component {
  class Movie (line 22) | class Movie extends Component {
    method find (line 25) | static find() {}
    method count (line 26) | static count() {}
    method play (line 34) | play() {}
    method delete (line 35) | delete() {}
    method exposedClassMethod (line 284) | static exposedClassMethod() {
    method exposedAsyncClassMethod (line 288) | static async exposedAsyncClassMethod() {
    method unexposedClassMethod (line 292) | static unexposedClassMethod() {
    method exposedInstanceMethod (line 296) | exposedInstanceMethod() {
    method exposedAsyncInstanceMethod (line 300) | async exposedAsyncInstanceMethod() {
    method unexposedInstanceMethod (line 304) | unexposedInstanceMethod() {
    method exposedInstanceMethodWithParameters (line 308) | exposedInstanceMethodWithParameters(
  class Backend (line 38) | class Backend extends Component {
  function trimSerializedFunctions (line 122) | function trimSerializedFunctions(object: PlainObject) {
  class Movie (line 132) | class Movie extends Component {
    method find (line 25) | static find() {}
    method count (line 26) | static count() {}
    method play (line 34) | play() {}
    method delete (line 35) | delete() {}
    method exposedClassMethod (line 284) | static exposedClassMethod() {
    method exposedAsyncClassMethod (line 288) | static async exposedAsyncClassMethod() {
    method unexposedClassMethod (line 292) | static unexposedClassMethod() {
    method exposedInstanceMethod (line 296) | exposedInstanceMethod() {
    method exposedAsyncInstanceMethod (line 300) | async exposedAsyncInstanceMethod() {
    method unexposedInstanceMethod (line 304) | unexposedInstanceMethod() {
    method exposedInstanceMethodWithParameters (line 308) | exposedInstanceMethodWithParameters(
  class Movie (line 283) | class Movie extends Component {
    method find (line 25) | static find() {}
    method count (line 26) | static count() {}
    method play (line 34) | play() {}
    method delete (line 35) | delete() {}
    method exposedClassMethod (line 284) | static exposedClassMethod() {
    method exposedAsyncClassMethod (line 288) | static async exposedAsyncClassMethod() {
    method unexposedClassMethod (line 292) | static unexposedClassMethod() {
    method exposedInstanceMethod (line 296) | exposedInstanceMethod() {
    method exposedAsyncInstanceMethod (line 300) | async exposedAsyncInstanceMethod() {
    method unexposedInstanceMethod (line 304) | unexposedInstanceMethod() {
    method exposedInstanceMethodWithParameters (line 308) | exposedInstanceMethodWithParameters(

FILE: packages/component-server/src/component-server.ts
  type ComponentServerLike (line 29) | interface ComponentServerLike {
  type ComponentServerOptions (line 33) | type ComponentServerOptions = {
  class ComponentServer (line 43) | class ComponentServer {
    method constructor (line 61) | constructor(component: typeof Component, options: ComponentServerOptio...
    method getComponent (line 74) | getComponent() {
    method receive (line 78) | receive(
    method _deserializeRequest (line 189) | _deserializeRequest(
    method _serializeResponse (line 223) | _serializeResponse(
    method validateVersion (line 297) | validateVersion(clientVersion: number | undefined) {
    method getDeeprRoot (line 312) | getDeeprRoot() {
    method isComponentServer (line 325) | static isComponentServer(value: any): value is ComponentServer {
  function ensureComponentServer (line 330) | function ensureComponentServer(
  function debugRequest (line 341) | function debugRequest({
  function debugResponse (line 359) | function debugResponse({

FILE: packages/component-server/src/utilities.ts
  function isComponentServerClass (line 5) | function isComponentServerClass(value: any): value is typeof ComponentSe...
  function isComponentServerInstance (line 9) | function isComponentServerInstance(value: any): value is ComponentServer {
  function assertIsComponentServerInstance (line 13) | function assertIsComponentServerInstance(value: any): asserts value is C...

FILE: packages/component/src/cloning.test.ts
  class Movie (line 6) | class Movie extends Component {
  class Movie (line 41) | class Movie extends Component {
  class Director (line 45) | class Director extends Component {
  class Movie (line 64) | class Movie extends Component {
  class Director (line 77) | class Director extends Component {
  class Movie (line 82) | class Movie extends Component {

FILE: packages/component/src/cloning.ts
  function clone (line 33) | function clone(value: any, options: CloneOptions = {}): any {

FILE: packages/component/src/component.test.ts
  class Movie (line 20) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 60) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 82) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 98) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 117) | class Movie extends Component {}
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class MovieDetails (line 145) | class MovieDetails extends Component {}
  class Movie (line 147) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class App (line 151) | class App extends Component {
  class Movie (line 161) | class Movie extends Component {}
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 175) | class Movie extends Component {}
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 193) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 213) | class Film extends Movie {}
    method delete (line 1143) | delete() {}
  class Movie (line 250) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 263) | class Movie extends Component {}
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 293) | class Film extends Movie {}
    method delete (line 1143) | delete() {}
  class Movie (line 310) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 335) | class Film extends Movie {
    method delete (line 1143) | delete() {}
  method filter (line 353) | filter(property) {
  class Movie (line 369) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 385) | class Film extends Movie {
    method delete (line 1143) | delete() {}
  class Movie (line 397) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 415) | class Film extends Movie {}
    method delete (line 1143) | delete() {}
  class Movie (line 446) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 462) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 483) | class Film extends Movie {}
    method delete (line 1143) | delete() {}
  class Movie (line 504) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 528) | class Film extends Movie {
    method delete (line 1143) | delete() {}
  method filter (line 559) | filter(property) {
  class Article (line 572) | class Article extends EmbeddedComponent {
  class Blog (line 576) | class Blog extends Component {
  class Person (line 664) | class Person extends EmbeddedComponent {
  class Movie (line 668) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class UserDetails (line 741) | class UserDetails extends EmbeddedComponent {
  class User (line 745) | class User extends Component {
  class Article (line 783) | class Article extends EmbeddedComponent {
  class Blog (line 787) | class Blog extends Component {
  class Person (line 883) | class Person extends EmbeddedComponent {
  class Movie (line 888) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Cinema (line 986) | class Cinema extends Component {
  class Movie (line 1015) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 1033) | class Film extends Movie {}
    method delete (line 1143) | delete() {}
  class Movie (line 1064) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Movie (line 1080) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 1101) | class Film extends Movie {}
    method delete (line 1143) | delete() {}
  class Movie (line 1122) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Film (line 1142) | class Film extends Movie {
    method delete (line 1143) | delete() {}
  method filter (line 1158) | filter(property) {
  class Movie (line 1171) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Director (line 1175) | class Director extends Component {
  class App (line 1179) | class App extends Component {
  class Movie (line 1209) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Director (line 1215) | class Director extends Component {}
  class Actor (line 1217) | class Actor extends Component {}
  class Producer (line 1219) | class Producer extends Component {}
  class Root (line 1271) | class Root extends Component {}
  class Film (line 1284) | class Film extends Component {}
    method delete (line 1143) | delete() {}
  class OtherComponent (line 1290) | class OtherComponent extends Component {}
  class Movie (line 1306) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Director (line 1311) | class Director extends Component {
  class Producer (line 1315) | class Producer extends Component {}
  class App (line 1317) | class App extends Component {
  class Movie (line 1385) | class Movie extends Component {}
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class App (line 1387) | class App extends Component {
  class Movie (line 1486) | class Movie extends Component {}
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class App (line 1488) | class App extends Component {
  class Movie (line 1508) | class Movie extends EmbeddedComponent {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Cinema (line 1520) | class Cinema extends Component {
  class Film (line 1658) | class Film extends Storable(Component) {
    method delete (line 1143) | delete() {}
  method storableMethod (line 1751) | static storableMethod() {}
  class MovieDetails (line 1789) | class MovieDetails extends EmbeddedComponent {
  class Movie (line 1793) | class Movie extends Component {
    method initializer (line 85) | static initializer() {
    method initializer (line 101) | static async initializer() {
    method find (line 196) | static find() {}
    method find (line 253) | static find() {}
    method load (line 314) | load() {}
    method save (line 315) | save() {}
    method load (line 373) | load() {}
    method save (line 374) | save() {}
    method find (line 400) | static find() {}
    method find (line 449) | static find() {}
    method find (line 463) | static find() {}
    method load (line 508) | load() {}
    method save (line 509) | save() {}
    method find (line 1018) | static find() {}
    method load (line 1020) | load() {}
    method find (line 1067) | static find() {}
    method load (line 1126) | load() {}
    method save (line 1127) | save() {}
    method find (line 1513) | static find() {}
    method load (line 1517) | load() {}
  class Cinema (line 1804) | class Cinema extends Component {

FILE: packages/component/src/component.ts
  type ComponentSet (line 68) | type ComponentSet = Set<typeof Component | Component>;
  type ComponentMixin (line 70) | type ComponentMixin = (Base: typeof Component) => typeof Component;
  type TraverseAttributesIteratee (line 72) | type TraverseAttributesIteratee = (attribute: Attribute) => void;
  type TraverseAttributesOptions (line 74) | type TraverseAttributesOptions = {
  type IdentifierDescriptor (line 79) | type IdentifierDescriptor = NormalizedIdentifierDescriptor | IdentifierV...
  type NormalizedIdentifierDescriptor (line 81) | type NormalizedIdentifierDescriptor = {[name: string]: IdentifierValue};
  type IdentifierSelector (line 83) | type IdentifierSelector = NormalizedIdentifierSelector | IdentifierValue;
  type NormalizedIdentifierSelector (line 85) | type NormalizedIdentifierSelector = {[name: string]: IdentifierValue};
  type ResolveAttributeSelectorOptions (line 87) | type ResolveAttributeSelectorOptions = {
  type MethodBuilder (line 102) | type MethodBuilder = (name: string) => Function;
  type ExecutionMode (line 104) | type ExecutionMode = 'foreground' | 'background';
  type IntrospectedComponent (line 106) | type IntrospectedComponent = {
  type IntrospectedComponentMap (line 118) | type IntrospectedComponentMap = Map<typeof Component, IntrospectedCompon...
  class Component (line 251) | class Component extends Observable(Object) {
    method constructor (line 295) | constructor(object: PlainObject = {}) {
    method instantiate (line 319) | static instantiate<T extends typeof Component>(
    method initialize (line 381) | static initialize() {
    method getBaseComponentName (line 393) | static getBaseComponentName() {
    method getComponentName (line 409) | static getComponentName() {
    method setComponentName (line 433) | static setComponentName(name: string) {
    method getComponentPath (line 461) | static getComponentPath() {
    method getBaseComponentType (line 482) | static getBaseComponentType() {
    method getBaseComponentType (line 486) | getBaseComponentType() {
    method getComponentType (line 504) | static getComponentType() {
    method getComponentType (line 525) | getComponentType() {
    method getIsNewMark (line 548) | getIsNewMark() {
    method setIsNewMark (line 567) | setIsNewMark(isNew: boolean) {
    method isNew (line 584) | isNew() {
    method markAsNew (line 595) | markAsNew() {
    method markAsNotNew (line 606) | markAsNotNew() {
    method isEmbedded (line 627) | static isEmbedded() {
    method getPropertyClass (line 633) | static getPropertyClass(type: string) {
    method getProperty (line 672) | static get getProperty() {
    method getProperty (line 691) | getProperty(name: string, options: {autoFork?: boolean} = {}) {
    method hasProperty (line 719) | static get hasProperty() {
    method hasProperty (line 739) | hasProperty(name: string) {
    method __getProperty (line 743) | static get __getProperty() {
    method __getProperty (line 747) | __getProperty(name: string, options: {autoFork: boolean}) {
    method setProperty (line 782) | static get setProperty() {
    method setProperty (line 807) | setProperty(name: string, PropertyClass: typeof Property, propertyOpti...
    method deleteProperty (line 848) | static get deleteProperty() {
    method deleteProperty (line 861) | deleteProperty(name: string) {
    method getProperties (line 897) | static get getProperties() {
    method getProperties (line 925) | getProperties<PropertyType extends Property = Property>(
    method getPropertyNames (line 978) | static get getPropertyNames() {
    method getPropertyNames (line 994) | getPropertyNames() {
    method __getProperties (line 1009) | static get __getProperties() {
    method __getProperties (line 1013) | __getProperties({autoCreateOrFork = true} = {}) {
    method normalizePropertyOperationSetting (line 1027) | static normalizePropertyOperationSetting(
    method resolvePropertyOperationSetting (line 1046) | static get resolvePropertyOperationSetting() {
    method resolvePropertyOperationSetting (line 1050) | resolvePropertyOperationSetting(
    method getAttribute (line 1079) | static get getAttribute() {
    method getAttribute (line 1098) | getAttribute(name: string, options: {autoFork?: boolean} = {}) {
    method hasAttribute (line 1126) | static get hasAttribute() {
    method hasAttribute (line 1146) | hasAttribute(name: string) {
    method __getAttribute (line 1150) | static get __getAttribute() {
    method __getAttribute (line 1154) | __getAttribute(name: string, options: {autoFork: boolean}) {
    method setAttribute (line 1187) | static get setAttribute() {
    method setAttribute (line 1206) | setAttribute(name: string, attributeOptions: AttributeOptions = {}) {
    method getAttributes (line 1231) | static get getAttributes() {
    method getAttributes (line 1256) | getAttributes<AttributeType extends Attribute = Attribute>(
    method traverseAttributes (line 1273) | static get traverseAttributes() {
    method traverseAttributes (line 1277) | traverseAttributes(
    method __traverseAttributes (line 1304) | static get __traverseAttributes() {
    method __traverseAttributes (line 1308) | __traverseAttributes(
    method getIdentifierAttribute (line 1348) | getIdentifierAttribute(name: string, options: {autoFork?: boolean} = {...
    method hasIdentifierAttribute (line 1379) | hasIdentifierAttribute(name: string) {
    method __getIdentifierAttribute (line 1383) | __getIdentifierAttribute(name: string, options: {autoFork: boolean}) {
    method getPrimaryIdentifierAttribute (line 1413) | getPrimaryIdentifierAttribute(options: {autoFork?: boolean} = {}) {
    method hasPrimaryIdentifierAttribute (line 1439) | hasPrimaryIdentifierAttribute() {
    method __getPrimaryIdentifierAttribute (line 1443) | __getPrimaryIdentifierAttribute(options: {autoFork: boolean}) {
    method setPrimaryIdentifierAttribute (line 1475) | setPrimaryIdentifierAttribute(name: string, attributeOptions: Attribut...
    method getSecondaryIdentifierAttribute (line 1494) | getSecondaryIdentifierAttribute(name: string, options: {autoFork?: boo...
    method hasSecondaryIdentifierAttribute (line 1524) | hasSecondaryIdentifierAttribute(name: string) {
    method __getSecondaryIdentifierAttribute (line 1528) | __getSecondaryIdentifierAttribute(name: string, options: {autoFork: bo...
    method setSecondaryIdentifierAttribute (line 1561) | setSecondaryIdentifierAttribute(name: string, attributeOptions: Attrib...
    method getIdentifierAttributes (line 1587) | getIdentifierAttributes(
    method getSecondaryIdentifierAttributes (line 1641) | getSecondaryIdentifierAttributes(
    method getIdentifiers (line 1686) | getIdentifiers() {
    method hasIdentifiers (line 1710) | hasIdentifiers() {
    method __getIdentifiers (line 1714) | __getIdentifiers() {
    method generateId (line 1746) | static generateId() {
    method __getMinimumAttributeCount (line 1750) | __getMinimumAttributeCount() {
    method getIdentifierDescriptor (line 1772) | getIdentifierDescriptor() {
    method hasIdentifierDescriptor (line 1796) | hasIdentifierDescriptor() {
    method __getIdentifierDescriptor (line 1800) | __getIdentifierDescriptor(): NormalizedIdentifierDescriptor | undefined {
    method normalizeIdentifierDescriptor (line 1822) | static normalizeIdentifierDescriptor(
    method describeIdentifierDescriptor (line 1860) | static describeIdentifierDescriptor(identifierDescriptor: IdentifierDe...
    method normalizeIdentifierSelector (line 1870) | static normalizeIdentifierSelector(
    method __createIdentifierSelectorFromObject (line 1908) | __createIdentifierSelectorFromObject(object: PlainObject) {
    method assign (line 1950) | static assign<T extends typeof Component>(
    method assign (line 2017) | assign<T extends Component>(
    method __assignAttributes (line 2031) | static get __assignAttributes() {
    method __assignAttributes (line 2035) | __assignAttributes(object: PlainObject, {source}: {source: ValueSource...
    method getIdentityMap (line 2052) | static getIdentityMap() {
    method attach (line 2071) | static attach<T extends typeof Component>(this: T) {
    method detach (line 2084) | static detach<T extends typeof Component>(this: T) {
    method isAttached (line 2097) | static isAttached() {
    method isDetached (line 2124) | static isDetached() {
    method attach (line 2137) | attach() {
    method detach (line 2155) | detach() {
    method isAttached (line 2173) | isAttached() {
    method isDetached (line 2188) | isDetached() {
    method resolveAttributeSelector (line 2194) | static get resolveAttributeSelector() {
    method resolveAttributeSelector (line 2198) | resolveAttributeSelector(
    method __resolveAttributeSelector (line 2239) | static get __resolveAttributeSelector() {
    method __resolveAttributeSelector (line 2243) | __resolveAttributeSelector(
    method validate (line 2396) | static get validate() {
    method validate (line 2447) | validate(attributeSelector: AttributeSelector = true) {
    method isValid (line 2496) | static get isValid() {
    method isValid (line 2519) | isValid(attributeSelector: AttributeSelector = true) {
    method runValidators (line 2544) | static get runValidators() {
    method runValidators (line 2567) | runValidators(attributeSelector: AttributeSelector = true) {
    method getMethod (line 2608) | static get getMethod() {
    method getMethod (line 2627) | getMethod(name: string, options: {autoFork?: boolean} = {}) {
    method hasMethod (line 2655) | static get hasMethod() {
    method hasMethod (line 2675) | hasMethod(name: string) {
    method __getMethod (line 2679) | static get __getMethod() {
    method __getMethod (line 2683) | __getMethod(name: string, options: {autoFork: boolean}) {
    method setMethod (line 2716) | static get setMethod() {
    method setMethod (line 2735) | setMethod(name: string, methodOptions: MethodOptions = {}) {
    method getMethods (line 2758) | static get getMethods() {
    method getMethods (line 2781) | getMethods(options: {filter?: PropertyFilterSync; autoFork?: boolean} ...
    method getComponent (line 2810) | static getComponent(name: string) {
    method hasComponent (line 2842) | static hasComponent(name: string) {
    method __getComponent (line 2846) | static __getComponent(name: string): typeof Component | undefined {
    method getComponentOfType (line 2889) | static getComponentOfType(type: string) {
    method hasComponentOfType (line 2924) | static hasComponentOfType(type: string) {
    method __getComponentOfType (line 2928) | static __getComponentOfType(type: string) {
    method traverseComponents (line 2944) | static traverseComponents(options: {filter?: (component: typeof Compon...
    method getProvidedComponent (line 2982) | static getProvidedComponent(name: string) {
    method provideComponent (line 3022) | static provideComponent(component: typeof Component) {
    method getProvidedComponents (line 3089) | static getProvidedComponents(
    method getComponentProvider (line 3137) | static getComponentProvider() {
    method __getComponentProvider (line 3161) | static __getComponentProvider() {
    method __setComponentProvider (line 3165) | static __setComponentProvider(componentProvider: typeof Component) {
    method __getProvidedComponents (line 3171) | static __getProvidedComponents() {
    method getConsumedComponent (line 3238) | static getConsumedComponent(name: string) {
    method consumeComponent (line 3275) | static consumeComponent(name: string) {
    method getConsumedComponents (line 3311) | static getConsumedComponents(
    method __getConsumedComponents (line 3335) | static __getConsumedComponents(autoFork = false) {
    method clone (line 3351) | static clone() {
    method clone (line 3374) | clone<T extends Component>(this: T, options: CloneOptions = {}): T {
    method fork (line 3410) | static fork<T extends typeof Component>(this: T, options: ForkOptions ...
    method fork (line 3449) | fork<T extends Component>(this: T, options: ForkOptions = {}) {
    method isForkOf (line 3494) | static isForkOf(component: typeof Component) {
    method isForkOf (line 3517) | isForkOf(component: Component) {
    method getGhost (line 3540) | static getGhost<T extends typeof Component>(this: T) {
    method getGhost (line 3593) | getGhost<T extends Component>(this: T): T {
    method merge (line 3632) | static merge<T extends typeof Component>(
    method merge (line 3668) | merge(
    method __mergeAttributes (line 3683) | static get __mergeAttributes() {
    method __mergeAttributes (line 3687) | __mergeAttributes(
    method serialize (line 3736) | static serialize(options: SerializeOptions = {}) {
    method __serialize (line 3767) | static __serialize(options: SerializeOptions) {
    method serialize (line 3829) | serialize(options: SerializeOptions = {}) {
    method __serialize (line 3862) | __serialize(options: SerializeOptions) {
    method __serializeAttributes (line 3922) | static get __serializeAttributes() {
    method __serializeAttributes (line 3926) | __serializeAttributes(
    method deserialize (line 3987) | static deserialize<T extends typeof Component>(
    method deserialize (line 4037) | deserialize<T extends Component>(
    method __deserializeAttributes (line 4071) | static get __deserializeAttributes() {
    method __deserializeAttributes (line 4075) | __deserializeAttributes(
    method getExecutionMode (line 4102) | static getExecutionMode() {
    method setExecutionMode (line 4122) | static setExecutionMode(executionMode: ExecutionMode) {
    method introspect (line 4128) | static introspect({
    method __introspectMixins (line 4192) | static __introspectMixins() {
    method __introspectProperties (line 4212) | static get __introspectProperties() {
    method __introspectProperties (line 4216) | __introspectProperties() {
    method __introspectProvidedComponents (line 4230) | static __introspectProvidedComponents({
    method __introspectConsumedComponents (line 4248) | static __introspectConsumedComponents({
    method unintrospect (line 4266) | static unintrospect(
    method __unintrospectMixins (line 4336) | static __unintrospectMixins(introspectedMixins: string[], {mixins}: {m...
    method __unintrospectProperties (line 4354) | static get __unintrospectProperties() {
    method __unintrospectProperties (line 4358) | __unintrospectProperties(
    method __unintrospectProvidedComponents (line 4390) | static __unintrospectProvidedComponents(
    method __unintrospectConsumedComponents (line 4404) | static __unintrospectConsumedComponents(introspectedConsumedComponents...
    method getRemoteComponent (line 4414) | static getRemoteComponent() {
    method getRemoteComponent (line 4418) | getRemoteComponent() {
    method __setRemoteComponent (line 4422) | static __setRemoteComponent(remoteComponent: typeof Component) {
    method hasRemoteMethod (line 4428) | static get hasRemoteMethod() {
    method hasRemoteMethod (line 4432) | hasRemoteMethod(name: string) {
    method callRemoteMethod (line 4444) | static get callRemoteMethod() {
    method callRemoteMethod (line 4448) | callRemoteMethod(name: string, ...args: any[]): any {
    method __setRemoteMethodBuilder (line 4462) | static __setRemoteMethodBuilder(methodBuilder: MethodBuilder) {
    method isComponent (line 4468) | static isComponent(value: any): value is Component {
    method toObject (line 4472) | static get toObject() {
    method toObject (line 4476) | toObject(options: {minimize?: boolean} = {}) {
    method describeComponent (line 4516) | static get describeComponent() {
    method describeComponent (line 4520) | describeComponent(options: {componentPrefix?: string} = {}) {
    method describeComponentProperty (line 4530) | static describeComponentProperty(name: string) {
    method describeComponentProperty (line 4534) | describeComponentProperty(name: string) {
  type CreatePropertyFilterOptions (line 4549) | type CreatePropertyFilterOptions = {
  type CreatePropertyFilterOptionsForAttributes (line 4554) | type CreatePropertyFilterOptionsForAttributes = {
  function createPropertyFilter (line 4559) | function createPropertyFilter(

FILE: packages/component/src/decorators.test.ts
  class Movie (line 22) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Film (line 105) | class Film extends Movie {
  class MotionPicture (line 164) | class MotionPicture extends Component {
  class MotionPicture (line 174) | class MotionPicture extends Component {
  class MotionPicture (line 184) | class MotionPicture extends Component {
  class Movie1 (line 195) | class Movie1 extends Component {
  class Movie2 (line 207) | class Movie2 extends Component {
  class Movie3 (line 219) | class Movie3 extends Component {
  class Movie (line 236) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Movie (line 246) | class Movie {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Movie (line 254) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class User (line 264) | class User extends Component {
  class Movie (line 287) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Movie (line 347) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Movie (line 359) | @expose({
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Movie (line 379) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class ExposedMovie (line 387) | @expose({
  class Movie (line 402) | class Movie extends Component {}
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Backend (line 404) | class Backend extends Component {
  class Movie (line 411) | class Movie extends BackendMovie {}
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Frontend (line 413) | class Frontend extends Backend {
  class Movie (line 424) | class Movie extends Component {}
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Backend (line 426) | class Backend extends Component {
  class Movie (line 437) | class Movie {}
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Backend (line 439) | class Backend extends Component {
  class Movie (line 450) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Director (line 454) | class Director extends Component {
  class Backend (line 458) | class Backend extends Component {
  class Movie (line 469) | class Movie extends BackendMovie {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Director (line 473) | class Director extends BackendDirector {
  class Frontend (line 477) | class Frontend extends Backend {
  class Movie (line 497) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}
  class Director (line 502) | class Director extends Component {}
  class Director (line 510) | class Director extends Component {}
  class Movie (line 512) | class Movie extends Component {
    method find (line 288) | static find() {}
    method load (line 290) | load() {}
    method find (line 349) | static find() {}
    method load (line 352) | load() {}
    method find (line 369) | static find() {}
    method load (line 372) | load() {}
    method find (line 381) | static find() {}
    method load (line 384) | load() {}

FILE: packages/component/src/decorators.ts
  type AttributeDecoratorOptions (line 20) | type AttributeDecoratorOptions = Omit<AttributeOptions, 'value' | 'defau...
  function attribute (line 82) | function attribute(
  function primaryIdentifier (line 142) | function primaryIdentifier(
  function secondaryIdentifier (line 198) | function secondaryIdentifier(
  function createAttributeDecorator (line 210) | function createAttributeDecorator(
  function getAttributeInitializer (line 277) | function getAttributeInitializer(
  function method (line 326) | function method(options: MethodOptions = {}) {
  function createMethodDecorator (line 330) | function createMethodDecorator(
  type PropertyClassMap (line 361) | type PropertyClassMap = Map<(value: any) => boolean, typeof Property>;
  function getPropertyClass (line 363) | function getPropertyClass(
  type ClassExposure (line 379) | type ClassExposure = {
  function expose (line 459) | function expose(exposure: ClassExposure | PropertyExposure = {}) {
  function provide (line 559) | function provide() {
  function consume (line 593) | function consume() {
  function determineCompiler (line 625) | function determineCompiler(descriptor: PropertyDescriptor | undefined) {

FILE: packages/component/src/deserialization.test.ts
  class Movie (line 8) | class Movie extends Component {
  class Application (line 13) | class Application extends Component {
  class Movie (line 93) | class Movie extends Component {
  class Application (line 98) | class Application extends Component {
  method attributeFilter (line 138) | attributeFilter(attribute) {
  class Person (line 221) | class Person extends EmbeddedComponent {
  class Movie (line 225) | class Movie extends Component {
  class Application (line 233) | class Application extends Component {
  class Person (line 285) | class Person extends Component {
  class Movie (line 290) | class Movie extends Component {
  class Application (line 298) | class Application extends Component {

FILE: packages/component/src/deserialization.ts
  type DeserializeOptions (line 14) | type DeserializeOptions = SimpleDeserializeOptions & {
  function deserialize (line 85) | function deserialize(value: any, options: DeserializeOptions = {}) {
  function deserializeFunction (line 200) | function deserializeFunction(functionCode: string): Function {

FILE: packages/component/src/embedded-component.ts
  class EmbeddedComponent (line 94) | class EmbeddedComponent extends Component {
    method isEmbedded (line 116) | static isEmbedded() {

FILE: packages/component/src/forking.test.ts
  class Movie (line 6) | class Movie extends Component {
  class MovieDetails (line 76) | class MovieDetails extends Component {}
  class Movie (line 78) | class Movie extends Component {
  class App (line 82) | class App extends Component {
  class Director (line 109) | class Director extends Component {
  class Movie (line 113) | class Movie extends Component {

FILE: packages/component/src/forking.ts
  type ForkOptions (line 6) | type ForkOptions = SimpleForkOptions & {
  function fork (line 37) | function fork(value: any, options: ForkOptions = {}) {

FILE: packages/component/src/identifiable-component.test.ts
  class User (line 12) | class User extends Component {
  class User (line 42) | class User extends Component {
  class User (line 86) | class User extends Component {
  class User (line 110) | class User extends Component {
  class User (line 126) | class User extends Component {
  class Movie (line 136) | class Movie extends Component {
  class User (line 146) | class User extends Component {
  class Movie (line 152) | class Movie extends Component {
  class User (line 160) | class User extends Component {}
  class User (line 181) | class User extends Component {
  class User (line 198) | class User extends Component {
  class User (line 216) | class User extends Component {}
  class User (line 237) | class User extends Component {
  class User (line 255) | class User extends Component {
  class User (line 271) | class User extends Component {
  class User (line 290) | class User extends Component {
  class User (line 313) | class User extends Component {
  class User (line 369) | class User extends Component {
  class Person (line 384) | class Person extends Component {
  class Movie (line 389) | class Movie extends Component {
  class Movie (line 453) | class Movie extends Component {}
  class User (line 468) | class User extends Component {
  class Article (line 492) | class Article extends Component {
  class User (line 561) | class User extends Component {
  class App (line 565) | class App extends Component {
  class User (line 581) | class User extends Component {
  class Director (line 607) | class Director extends Component {
  class Movie (line 612) | class Movie extends Component {

FILE: packages/component/src/identity-map.test.ts
  class User (line 7) | class User extends Component {
  class User (line 17) | class User extends Component {
  class User (line 35) | class User extends Component {
  class User (line 58) | class User extends Component {
  class User (line 121) | class User extends Component {
  class User (line 148) | class User extends Component {

FILE: packages/component/src/identity-map.ts
  class IdentityMap (line 57) | class IdentityMap {
    method constructor (line 60) | constructor(parent: typeof Component) {
    method getParent (line 64) | getParent() {
    method fork (line 68) | fork(newParent: typeof Component) {
    method getComponent (line 123) | getComponent(identifiers: IdentifierSelector = {}) {
    method addComponent (line 159) | addComponent(component: Component) {
    method updateComponent (line 185) | updateComponent(
    method removeComponent (line 220) | removeComponent(component: Component) {
    method getComponents (line 237) | getComponents() {
    method _getIndex (line 267) | _getIndex(name: string) {
    method _getIndexes (line 281) | _getIndexes() {

FILE: packages/component/src/js-parser.ts
  function getConstructorSourceCode (line 3) | function getConstructorSourceCode(classSourceCode: string) {
  function getAttributeInitializerFromConstructorSourceCode (line 23) | function getAttributeInitializerFromConstructorSourceCode(
  function getIndexAfterTerminator (line 58) | function getIndexAfterTerminator(
  function getIndexAfterStringTerminator (line 137) | function getIndexAfterStringTerminator(

FILE: packages/component/src/js-tests/decorators.test.js
  class Movie (line 22) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Film (line 105) | class Film extends Movie {
  class MotionPicture (line 164) | class MotionPicture extends Component {
  class MotionPicture (line 174) | class MotionPicture extends Component {
  class MotionPicture (line 184) | class MotionPicture extends Component {
  class Movie1 (line 195) | class Movie1 extends Component {
  class Movie2 (line 207) | class Movie2 extends Component {
  class Movie3 (line 219) | class Movie3 extends Component {
  class Movie (line 236) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Movie (line 246) | class Movie {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Movie (line 254) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class User (line 264) | class User extends Component {
  class Movie (line 287) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Movie (line 347) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Movie (line 359) | @expose({
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Movie (line 379) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class ExposedMovie (line 387) | @expose({
  class Movie (line 402) | class Movie extends Component {}
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Backend (line 404) | class Backend extends Component {
  class Movie (line 411) | class Movie extends BackendMovie {}
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Frontend (line 413) | class Frontend extends Backend {
  class Movie (line 424) | class Movie extends Component {}
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Backend (line 426) | class Backend extends Component {
  class Movie (line 437) | class Movie {}
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Backend (line 439) | class Backend extends Component {
  class Movie (line 450) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Director (line 454) | class Director extends Component {
  class Backend (line 458) | class Backend extends Component {
  class Movie (line 469) | class Movie extends BackendMovie {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Director (line 473) | class Director extends BackendDirector {
  class Frontend (line 477) | class Frontend extends Backend {
  class Movie (line 497) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}
  class Director (line 502) | class Director extends Component {}
  class Director (line 510) | class Director extends Component {}
  class Movie (line 512) | class Movie extends Component {
    method find (line 288) | @method() static find() {}
    method load (line 290) | @method() load() {}
    method find (line 349) | @expose({call: true}) @method() static find() {}
    method load (line 352) | @expose({call: true}) @method() load() {}
    method find (line 369) | @method() static find() {}
    method load (line 372) | @method() load() {}
    method find (line 381) | @method() static find() {}
    method load (line 384) | @method() load() {}

FILE: packages/component/src/merging.test.ts
  class Movie (line 6) | class Movie extends Component {
  class Director (line 62) | class Director extends Component {
  class Movie (line 66) | class Movie extends Component {

FILE: packages/component/src/merging.ts
  function merge (line 39) | function merge(value: any, valueFork: any, options: MergeOptions = {}) {

FILE: packages/component/src/properties/attribute-selector.test.ts
  class Organization (line 297) | class Organization extends Component {
  class Organization (line 424) | class Organization extends Component {
  class Movie (line 643) | class Movie {}

FILE: packages/component/src/properties/attribute-selector.ts
  type AttributeSelector (line 15) | type AttributeSelector = boolean | PlainObject;
  function createAttributeSelectorFromNames (line 75) | function createAttributeSelectorFromNames(names: string[]) {
  function createAttributeSelectorFromAttributes (line 100) | function createAttributeSelectorFromAttributes(attributes: Iterable<Attr...
  function getFromAttributeSelector (line 138) | function getFromAttributeSelector(
  function setWithinAttributeSelector (line 177) | function setWithinAttributeSelector(
  function cloneAttributeSelector (line 218) | function cloneAttributeSelector(attributeSelector: AttributeSelector) {
  function attributeSelectorsAreEqual (line 244) | function attributeSelectorsAreEqual(
  function attributeSelectorIncludes (line 277) | function attributeSelectorIncludes(
  function mergeAttributeSelectors (line 329) | function mergeAttributeSelectors(
  function intersectAttributeSelectors (line 384) | function intersectAttributeSelectors(
  function removeFromAttributeSelector (line 437) | function removeFromAttributeSelector(
  function iterateOverAttributeSelector (line 475) | function iterateOverAttributeSelector(attributeSelector: AttributeSelect...
  type PickFromAttributeSelectorResult (line 489) | type PickFromAttributeSelectorResult<Value> = Value extends Array<infer ...
  function pickFromAttributeSelector (line 500) | function pickFromAttributeSelector(
  function _pick (line 518) | function _pick(
  type TraverseIteratee (line 570) | type TraverseIteratee = (
  type TraverseContext (line 576) | type TraverseContext = {name?: string; object?: object; isArray?: boolean};
  type TraverseOptions (line 578) | type TraverseOptions = {includeSubtrees?: boolean; includeLeafs?: boolean};
  function traverseAttributeSelector (line 580) | function traverseAttributeSelector(
  function _traverse (line 604) | function _traverse(
  function trimAttributeSelector (line 670) | function trimAttributeSelector(attributeSelector: AttributeSelector): At...
  function normalizeAttributeSelector (line 692) | function normalizeAttributeSelector(attributeSelector: any): AttributeSe...

FILE: packages/component/src/properties/attribute.test.ts
  class Movie (line 12) | class Movie extends Component {}
  class Movie (line 23) | class Movie extends Component {}
  class Movie (line 53) | class Movie extends Component {}
  class Movie (line 69) | class Movie extends Component {}
  method getter (line 75) | getter() {
  method setter (line 79) | setter(title) {
  method setter (line 95) | setter(title) {
  class Movie (line 105) | class Movie extends Component {}
  method getter (line 121) | getter() {
  class Movie (line 131) | class Movie extends Component {}
  method getter (line 160) | getter() {
  class Movie (line 170) | class Movie extends Component {}
  class Movie (line 192) | class Movie extends Component {}
  class Movie (line 235) | class Movie extends Component {}
  class Movie (line 295) | class Movie extends Component {}
  class UserDetails (line 389) | class UserDetails extends EmbeddedComponent {}
  class User (line 395) | class User extends Component {}
  class Organization (line 426) | class Organization extends EmbeddedComponent {}
  class Blog (line 467) | class Blog extends Component {}
  class Article (line 473) | class Article extends Component {}
  class Comment (line 504) | class Comment extends Component {}
  class Movie (line 543) | class Movie extends Component {}
  class Movie (line 564) | class Movie extends Component {}
  class Movie (line 693) | class Movie extends Component {}

FILE: packages/component/src/properties/attribute.ts
  type AttributeOptions (line 35) | type AttributeOptions = PropertyOptions & {
  type AttributeItemsOptions (line 46) | type AttributeItemsOptions = {
  type ValueSource (line 52) | type ValueSource = 'server' | 'store' | 'local' | 'client';
  type IntrospectedAttribute (line 54) | type IntrospectedAttribute = IntrospectedProperty & {
  type UnintrospectedAttribute (line 59) | type UnintrospectedAttribute = UnintrospectedProperty & {
  class Attribute (line 148) | class Attribute extends Observable(Property) {
    method constructor (line 182) | constructor(name: string, parent: typeof Component | Component, option...
    method _initialize (line 186) | _initialize() {
    method setOptions (line 195) | setOptions(options: AttributeOptions = {}) {
    method getValueType (line 282) | getValueType() {
    method getValue (line 309) | getValue(options: {throwIfUnset?: boolean; autoFork?: boolean} = {}) {
    method setValue (line 367) | setValue(value: unknown, {source = 'local'}: {source?: ValueSource} = ...
    method unsetValue (line 434) | unsetValue() {
    method isSet (line 473) | isSet() {
    method checkValue (line 477) | checkValue(value: unknown) {
    method sanitizeValue (line 481) | sanitizeValue(value: unknown) {
    method getValueSource (line 502) | getValueSource() {
    method setValueSource (line 521) | setValueSource(source: ValueSource) {
    method getDefault (line 560) | getDefault() {
    method evaluateDefault (line 577) | evaluateDefault() {
    method _fixDecoration (line 589) | _fixDecoration() {
    method isControlled (line 599) | isControlled() {
    method markAsControlled (line 603) | markAsControlled() {
    method _onChange (line 609) | _onChange(payload: ObserverPayload & {source?: ValueSource}) {
    method _traverseAttributes (line 621) | _traverseAttributes(iteratee: TraverseAttributesIteratee, options: Tra...
    method _resolveAttributeSelector (line 631) | _resolveAttributeSelector(
    method serialize (line 649) | serialize(options: SerializeOptions = {}): unknown {
    method deserialize (line 659) | deserialize(
    method validate (line 732) | validate(attributeSelector: AttributeSelector = true) {
    method isValid (line 779) | isValid(attributeSelector: AttributeSelector = true) {
    method runValidators (line 804) | runValidators(attributeSelector: AttributeSelector = true) {
    method introspect (line 824) | introspect() {
    method unintrospect (line 852) | static unintrospect(introspectedAttribute: IntrospectedAttribute) {
    method isAttribute (line 882) | static isAttribute(value: any): value is Attribute {
    method describeType (line 886) | describeType() {
  function isAttributeClass (line 900) | function isAttributeClass(value: any): value is typeof Attribute {
  function isAttributeInstance (line 913) | function isAttributeInstance(value: any): value is Attribute {

FILE: packages/component/src/properties/identifier-attribute.test.ts
  class Movie (line 7) | class Movie extends Component {}

FILE: packages/component/src/properties/identifier-attribute.ts
  type IdentifierValue (line 7) | type IdentifierValue = string | number;
  class IdentifierAttribute (line 14) | class IdentifierAttribute extends Attribute {
    method constructor (line 15) | constructor(name: string, parent: Component, options: AttributeOptions...
    method getParent (line 25) | getParent() {
    method setOptions (line 31) | setOptions(options: AttributeOptions = {}) {
    method getValue (line 51) | getValue(options: {throwIfUnset?: boolean; autoFork?: boolean} = {}) {
    method setValue (line 55) | setValue(value: IdentifierValue, {source = 'local'}: {source?: ValueSo...
    method unsetValue (line 73) | unsetValue() {
    method isIdentifierAttribute (line 89) | static isIdentifierAttribute(value: any): value is IdentifierAttribute {
  function isIdentifierAttributeClass (line 103) | function isIdentifierAttributeClass(value: any): value is typeof Identif...
  function isIdentifierAttributeInstance (line 116) | function isIdentifierAttributeInstance(value: any): value is IdentifierA...

FILE: packages/component/src/properties/method.test.ts
  class Movie (line 8) | class Movie extends Component {}
  class Movie (line 18) | class Movie extends Component {}
  class Movie (line 34) | class Movie extends Component {}
  class Movie (line 50) | class Movie extends Component {}

FILE: packages/component/src/properties/method.ts
  type IntrospectedMethod (line 5) | type IntrospectedMethod = IntrospectedProperty;
  type MethodOptions (line 7) | type MethodOptions = PropertyOptions & {
  type MethodScheduling (line 13) | type MethodScheduling = {rate: number} | false;
  type MethodQueueing (line 15) | type MethodQueueing = boolean;
  class Method (line 104) | class Method extends Property {
    method constructor (line 134) | constructor(name: string, parent: typeof Component | Component, option...
    method setOptions (line 140) | setOptions(options: MethodOptions = {}) {
    method getScheduling (line 183) | getScheduling() {
    method setScheduling (line 199) | setScheduling(scheduling: MethodScheduling | undefined) {
    method getQueueing (line 239) | getQueueing() {
    method setQueueing (line 255) | setQueueing(queueing: MethodQueueing | undefined) {
    method getMaximumDuration (line 276) | getMaximumDuration() {
    method setMaximumDuration (line 292) | setMaximumDuration(maximumDuration: number | undefined) {
    method isMethod (line 298) | static isMethod(value: any): value is Method {
    method describeType (line 302) | describeType() {
  function isMethodClass (line 316) | function isMethodClass(value: any): value is typeof Method {
  function isMethodInstance (line 329) | function isMethodInstance(value: any): value is Method {

FILE: packages/component/src/properties/primary-identifier-attribute.test.ts
  class Movie (line 11) | class Movie extends Component {}
  class Movie (line 31) | class Movie extends Component {}
  class Movie (line 51) | class Movie extends Component {}
  class Movie (line 62) | class Movie extends Component {}

FILE: packages/component/src/properties/primary-identifier-attribute.ts
  class PrimaryIdentifierAttribute (line 105) | class PrimaryIdentifierAttribute extends IdentifierAttribute {
    method constructor (line 134) | constructor(name: string, parent: Component, options: AttributeOptions...
    method setOptions (line 152) | setOptions(options: AttributeOptions = {}) {
    method setValue (line 180) | setValue(value: IdentifierValue, {source = 'local'}: {source?: ValueSo...
    method isPrimaryIdentifierAttribute (line 207) | static isPrimaryIdentifierAttribute(value: any): value is PrimaryIdent...
  function isPrimaryIdentifierAttributeClass (line 221) | function isPrimaryIdentifierAttributeClass(
  function isPrimaryIdentifierAttributeInstance (line 236) | function isPrimaryIdentifierAttributeInstance(

FILE: packages/component/src/properties/property.test.ts
  class Movie (line 6) | class Movie extends Component {}
    method normalizePropertyOperationSetting (line 115) | static normalizePropertyOperationSetting(
  class Movie (line 36) | class Movie extends Component {}
    method normalizePropertyOperationSetting (line 115) | static normalizePropertyOperationSetting(
  class Film (line 58) | class Film extends Component {
    method normalizePropertyOperationSetting (line 59) | static normalizePropertyOperationSetting(
  class Movie (line 99) | class Movie extends Component {}
    method normalizePropertyOperationSetting (line 115) | static normalizePropertyOperationSetting(
  class Movie (line 114) | class Movie extends Component {
    method normalizePropertyOperationSetting (line 115) | static normalizePropertyOperationSetting(

FILE: packages/component/src/properties/property.ts
  type PropertyOptions (line 8) | type PropertyOptions = {
  type PropertyExposure (line 12) | type PropertyExposure = Partial<Record<PropertyOperation, PropertyOperat...
  type PropertyOperation (line 14) | type PropertyOperation = 'get' | 'set' | 'call';
  type PropertyOperationSetting (line 16) | type PropertyOperationSetting = boolean | string | string[];
  type PropertyFilter (line 18) | type PropertyFilter = (property: any) => boolean | PromiseLike<boolean>;
  type PropertyFilterSync (line 19) | type PropertyFilterSync = (property: any) => boolean;
  type PropertyFilterAsync (line 20) | type PropertyFilterAsync = (property: any) => PromiseLike<boolean>;
  type IntrospectedProperty (line 22) | type IntrospectedProperty = {
  type IntrospectedExposure (line 28) | type IntrospectedExposure = Partial<Record<PropertyOperation, boolean>>;
  type UnintrospectedProperty (line 30) | type UnintrospectedProperty = {
  type UnintrospectedExposure (line 37) | type UnintrospectedExposure = Partial<Record<PropertyOperation, true>>;
  class Property (line 42) | class Property {
    method constructor (line 69) | constructor(name: string, parent: typeof Component | Component, option...
    method _initialize (line 81) | _initialize() {}
    method getName (line 95) | getName() {
    method getParent (line 111) | getParent() {
    method setOptions (line 117) | setOptions(options: PropertyOptions = {}) {
    method getExposure (line 143) | getExposure() {
    method setExposure (line 159) | setExposure(exposure = {}) {
    method _normalizeExposure (line 163) | _normalizeExposure(exposure: PropertyExposure) {
    method operationIsAllowed (line 205) | operationIsAllowed(operation: PropertyOperation) {
    method fork (line 241) | fork<T extends Property>(this: T, parent: typeof Component | Component) {
    method introspect (line 253) | introspect() {
    method introspectExposure (line 267) | introspectExposure() {
    method unintrospect (line 281) | static unintrospect(introspectedProperty: IntrospectedProperty) {
    method isProperty (line 289) | static isProperty(value: any): value is Property {
    method describeType (line 293) | describeType() {
    method describe (line 297) | describe() {
  function isPropertyClass (line 304) | function isPropertyClass(value: any): value is typeof Property {
  function isPropertyInstance (line 308) | function isPropertyInstance(value: any): value is Property {

FILE: packages/component/src/properties/secondary-identifier-attribute.test.ts
  class Movie (line 10) | class Movie extends Component {}
  class Movie (line 21) | class Movie extends Component {}
  class Movie (line 39) | class Movie extends Component {}

FILE: packages/component/src/properties/secondary-identifier-attribute.ts
  class SecondaryIdentifierAttribute (line 84) | class SecondaryIdentifierAttribute extends IdentifierAttribute {
    method constructor (line 114) | constructor(name: string, parent: Component, options: AttributeOptions...
    method isSecondaryIdentifierAttribute (line 144) | static isSecondaryIdentifierAttribute(value: any): value is SecondaryI...
  function isSecondaryIdentifierAttributeClass (line 158) | function isSecondaryIdentifierAttributeClass(
  function isSecondaryIdentifierAttributeInstance (line 173) | function isSecondaryIdentifierAttributeInstance(

FILE: packages/component/src/properties/value-types/any-value-type.ts
  class AnyValueType (line 4) | class AnyValueType extends ValueType {
    method isOptional (line 5) | isOptional() {
    method toString (line 9) | toString() {
    method _checkValue (line 13) | _checkValue(_value: any, _attribute: Attribute) {
    method isAnyValueType (line 17) | static isAnyValueType(value: any): value is AnyValueType {
  function isAnyValueTypeInstance (line 22) | function isAnyValueTypeInstance(value: any): value is AnyValueType {

FILE: packages/component/src/properties/value-types/array-value-type.ts
  class ArrayValueType (line 19) | class ArrayValueType extends ValueType {
    method constructor (line 22) | constructor(itemType: ValueType, attribute: Attribute, options: ValueT...
    method getItemType (line 28) | getItemType() {
    method toString (line 32) | toString() {
    method getScalarType (line 36) | getScalarType() {
    method checkValue (line 40) | checkValue(values: unknown[], attribute: Attribute) {
    method _checkValue (line 55) | _checkValue(values: unknown, attribute: Attribute) {
    method _traverseAttributes (line 59) | _traverseAttributes(
    method _resolveAttributeSelector (line 81) | _resolveAttributeSelector(
    method sanitizeValue (line 129) | sanitizeValue(values: any[] | undefined) {
    method runValidators (line 138) | runValidators(values: unknown[] | undefined, attributeSelector?: Attri...
    method serializeValue (line 156) | serializeValue(items: unknown, attribute: Attribute, options: Serializ...
    method introspect (line 166) | introspect() {
    method isArrayValueType (line 179) | static isArrayValueType(value: any): value is ArrayValueType {
  function isArrayValueTypeInstance (line 184) | function isArrayValueTypeInstance(value: any): value is ArrayValueType {

FILE: packages/component/src/properties/value-types/boolean-value-type.ts
  class BooleanValueType (line 4) | class BooleanValueType extends ValueType {
    method toString (line 5) | toString() {
    method _checkValue (line 9) | _checkValue(value: unknown, attribute: Attribute) {
    method isBooleanValueType (line 13) | static isBooleanValueType(value: any): value is BooleanValueType {
  function isBooleanValueTypeInstance (line 18) | function isBooleanValueTypeInstance(value: any): value is BooleanValueTy...

FILE: packages/component/src/properties/value-types/component-value-type.ts
  class ComponentValueType (line 18) | class ComponentValueType extends ValueType {
    method constructor (line 21) | constructor(componentType: string, attribute: Attribute, options: Valu...
    method getComponentType (line 29) | getComponentType() {
    method getComponent (line 33) | getComponent(attribute: Attribute) {
    method toString (line 37) | toString() {
    method _checkValue (line 41) | _checkValue(value: unknown, attribute: Attribute) {
    method _traverseAttributes (line 65) | _traverseAttributes(
    method _resolveAttributeSelector (line 82) | _resolveAttributeSelector(
    method runValidators (line 105) | runValidators(value: unknown, attributeSelector?: AttributeSelector) {
    method serializeValue (line 116) | serializeValue(value: unknown, attribute: Attribute, options: Serializ...
    method canDeserializeInPlace (line 124) | canDeserializeInPlace(attribute: Attribute) {
    method isComponentValueType (line 128) | static isComponentValueType(value: any): value is ComponentValueType {
  function isComponentValueTypeInstance (line 133) | function isComponentValueTypeInstance(value: any): value is ComponentVal...

FILE: packages/component/src/properties/value-types/date-value-type.ts
  class DateValueType (line 4) | class DateValueType extends ValueType {
    method toString (line 5) | toString() {
    method _checkValue (line 9) | _checkValue(value: unknown, attribute: Attribute) {
    method isDateValueType (line 13) | static isDateValueType(value: any): value is DateValueType {
  function isDateValueTypeInstance (line 18) | function isDateValueTypeInstance(value: any): value is DateValueType {

FILE: packages/component/src/properties/value-types/factory.test.ts
  class TestComponent (line 12) | class TestComponent extends Component {}

FILE: packages/component/src/properties/value-types/factory.ts
  constant VALUE_TYPE_MAP (line 16) | const VALUE_TYPE_MAP = new Map(
  type UnintrospectedValueType (line 28) | type UnintrospectedValueType = {
  type CreateValueTypeOptions (line 34) | type CreateValueTypeOptions = {
  function createValueType (line 40) | function createValueType(
  function unintrospectValueType (line 88) | function unintrospectValueType({

FILE: packages/component/src/properties/value-types/number-value-type.ts
  class NumberValueType (line 4) | class NumberValueType extends ValueType {
    method toString (line 5) | toString() {
    method _checkValue (line 9) | _checkValue(value: unknown, attribute: Attribute) {
    method isNumberValueType (line 13) | static isNumberValueType(value: any): value is NumberValueType {
  function isNumberValueTypeInstance (line 18) | function isNumberValueTypeInstance(value: any): value is NumberValueType {

FILE: packages/component/src/properties/value-types/object-value-type.ts
  class ObjectValueType (line 6) | class ObjectValueType extends ValueType {
    method toString (line 7) | toString() {
    method _checkValue (line 11) | _checkValue(value: unknown, attribute: Attribute) {
    method isObjectValueType (line 15) | static isObjectValueType(value: any): value is ObjectValueType {
  function isObjectValueTypeInstance (line 20) | function isObjectValueTypeInstance(value: any): value is ObjectValueType {

FILE: packages/component/src/properties/value-types/regexp-value-type.ts
  class RegExpValueType (line 4) | class RegExpValueType extends ValueType {
    method toString (line 5) | toString() {
    method _checkValue (line 9) | _checkValue(value: unknown, attribute: Attribute) {
    method isRegExpValueType (line 13) | static isRegExpValueType(value: any): value is RegExpValueType {
  function isRegExpValueTypeInstance (line 18) | function isRegExpValueTypeInstance(value: any): value is RegExpValueType {

FILE: packages/component/src/properties/value-types/string-value-type.ts
  class StringValueType (line 4) | class StringValueType extends ValueType {
    method toString (line 5) | toString() {
    method _checkValue (line 9) | _checkValue(value: unknown, attribute: Attribute) {
    method isStringValueType (line 13) | static isStringValueType(value: any): value is StringValueType {
  function isStringValueTypeInstance (line 18) | function isStringValueTypeInstance(value: any): value is StringValueType {

FILE: packages/component/src/properties/value-types/value-type.test.ts
  class TestComponent (line 15) | class TestComponent extends Component {}
  class Movie (line 129) | class Movie extends Component {}
  class Movie (line 267) | class Movie extends Component {}
  class Actor (line 269) | class Actor extends Component {}
  class App (line 271) | class App extends Component {

FILE: packages/component/src/properties/value-types/value-type.ts
  type IntrospectedValueType (line 14) | type IntrospectedValueType = {
  type ValueTypeOptions (line 20) | type ValueTypeOptions = {
  class ValueType (line 168) | class ValueType {
    method constructor (line 173) | constructor(attribute: Attribute, options: ValueTypeOptions = {}) {
    method isOptional (line 205) | isOptional() {
    method getSanitizers (line 209) | getSanitizers() {
    method getValidators (line 226) | getValidators() {
    method toString (line 259) | toString(): string {
    method getScalarType (line 263) | getScalarType() {
    method checkValue (line 267) | checkValue(value: unknown, attribute: Attribute) {
    method _checkValue (line 277) | _checkValue(value: unknown, _attribute: Attribute) {
    method _traverseAttributes (line 281) | _traverseAttributes(
    method _resolveAttributeSelector (line 290) | _resolveAttributeSelector(
    method sanitizeValue (line 299) | sanitizeValue(value: any) {
    method isValidValue (line 303) | isValidValue(value: unknown) {
    method runValidators (line 309) | runValidators(value: unknown, _attributeSelector?: AttributeSelector) {
    method serializeValue (line 320) | serializeValue(value: unknown, _attribute: Attribute, options: Seriali...
    method canDeserializeInPlace (line 324) | canDeserializeInPlace(_attribute: Attribute) {
    method introspect (line 328) | introspect() {

FILE: packages/component/src/sanitization/sanitizer-builders.ts
  type SanitizerBuilder (line 16) | type SanitizerBuilder = (...args: any[]) => Sanitizer;
  function createSanitizer (line 24) | function createSanitizer(name: string, func: SanitizerFunction, args: an...

FILE: packages/component/src/sanitization/sanitizer.ts
  type SanitizerFunction (line 3) | type SanitizerFunction = (value: any, ...args: any[]) => any;
  type SanitizerOptions (line 5) | type SanitizerOptions = {
  class Sanitizer (line 114) | class Sanitizer {
    method constructor (line 119) | constructor(func: SanitizerFunction, options: SanitizerOptions = {}) {
    method getFunction (line 131) | getFunction() {
    method getName (line 135) | getName() {
    method getArguments (line 139) | getArguments() {
    method run (line 143) | run(value: any) {
    method isSanitizer (line 147) | static isSanitizer(value: any): value is Sanitizer {
  function isSanitizerInstance (line 152) | function isSanitizerInstance(value: any): value is Sanitizer {
  function runSanitizers (line 156) | function runSanitizers(sanitizers: Sanitizer[], value: any) {

FILE: packages/component/src/sanitization/utilities.test.ts
  class TestComponent (line 9) | class TestComponent extends Component {}

FILE: packages/component/src/sanitization/utilities.ts
  function normalizeSanitizer (line 5) | function normalizeSanitizer(sanitizer: Sanitizer | SanitizerFunction, at...

FILE: packages/component/src/serialization.test.ts
  class BaseMovie (line 8) | class BaseMovie extends Component {}
  class Movie (line 12) | class Movie extends BaseMovie {
  class Cinema (line 54) | class Cinema extends Component {
  class Person (line 86) | class Person extends EmbeddedComponent {
  class Director (line 91) | class Director extends Person {}
  class Actor (line 92) | class Actor extends Person {}
  class Movie (line 94) | class Movie extends Component {
  method attributeFilter (line 195) | attributeFilter(attribute) {
  method attributeFilter (line 208) | async attributeFilter(attribute) {
  class Movie (line 279) | class Movie extends Component {
  class Cinema (line 346) | class Cinema extends Component {
  function sum (line 423) | function sum(a: number, b: number) {
  function trimSerializedFunction (line 440) | function trimSerializedFunction(serializedFunction: any) {

FILE: packages/component/src/serialization.ts
  type SerializeOptions (line 14) | type SerializeOptions = SimpleSerializeOptions & {
  function serialize (line 61) | function serialize(value: any, options: SerializeOptions = {}) {
  function serializeFunction (line 123) | function serializeFunction(func: Function) {

FILE: packages/component/src/utilities.test.ts
  class Movie (line 18) | class Movie extends Component {}
  class Movie (line 35) | class Movie extends Component {}
  class Movie (line 51) | class Movie extends Component {}

FILE: packages/component/src/utilities.ts
  function isComponentClass (line 15) | function isComponentClass(value: any): value is typeof Component {
  function isComponentInstance (line 28) | function isComponentInstance(value: any): value is Component {
  function isComponentClassOrInstance (line 41) | function isComponentClassOrInstance(value: any): value is typeof Compone...
  function assertIsComponentClass (line 55) | function assertIsComponentClass(value: any): asserts value is typeof Com...
  function assertIsComponentInstance (line 70) | function assertIsComponentInstance(value: any): asserts value is Compone...
  function assertIsComponentClassOrInstance (line 85) | function assertIsComponentClassOrInstance(
  function ensureComponentClass (line 111) | function ensureComponentClass(component: any) {
  function ensureComponentInstance (line 141) | function ensureComponentInstance(component: any) {
  constant COMPONENT_NAME_PATTERN (line 155) | const COMPONENT_NAME_PATTERN = /^[A-Z][A-Za-z0-9_]*$/;
  function isComponentName (line 176) | function isComponentName(name: string) {
  function assertIsComponentName (line 187) | function assertIsComponentName(name: string) {
  function getComponentNameFromComponentClassType (line 211) | function getComponentNameFromComponentClassType(type: string) {
  function getComponentNameFromComponentInstanceType (line 231) | function getComponentNameFromComponentInstanceType(type: string) {
  constant COMPONENT_CLASS_TYPE_PATTERN (line 237) | const COMPONENT_CLASS_TYPE_PATTERN = /^typeof [A-Z][A-Za-z0-9_]*$/;
  constant COMPONENT_INSTANCE_TYPE_PATTERN (line 238) | const COMPONENT_INSTANCE_TYPE_PATTERN = /^[A-Z][A-Za-z0-9_]*$/;
  function isComponentType (line 261) | function isComponentType(type: string, {allowClasses = true, allowInstan...
  function assertIsComponentType (line 282) | function assertIsComponentType(
  function getComponentClassTypeFromComponentName (line 313) | function getComponentClassTypeFromComponentName(name: string) {
  function getComponentInstanceTypeFromComponentName (line 333) | function getComponentInstanceTypeFromComponentName(name: string) {
  type ComponentMap (line 339) | type ComponentMap = {[name: string]: typeof Component};
  function createComponentMap (line 341) | function createComponentMap(components: typeof Component[] = []) {
  function getComponentFromComponentMap (line 353) | function getComponentFromComponentMap(componentMap: ComponentMap, name: ...
  function isComponentMixin (line 365) | function isComponentMixin(value: any): value is ComponentMixin {
  function assertIsComponentMixin (line 369) | function assertIsComponentMixin(value: any): asserts value is ComponentM...
  function composeDescription (line 377) | function composeDescription(description: string[]) {
  function joinAttributePath (line 387) | function joinAttributePath(path: [string?, string?]) {

FILE: packages/component/src/validation/utilities.test.ts
  class TestComponent (line 9) | class TestComponent extends Component {}

FILE: packages/component/src/validation/utilities.ts
  function normalizeValidator (line 5) | function normalizeValidator(validator: Validator | ValidatorFunction, at...

FILE: packages/component/src/validation/validator-builders.ts
  type ValidatorBuilder (line 62) | type ValidatorBuilder = (...args: any[]) => Validator;
  function createValidator (line 70) | function createValidator(name: string, func: ValidatorFunction, args: an...

FILE: packages/component/src/validation/validator.ts
  type ValidatorFunction (line 3) | type ValidatorFunction = (value: any, ...args: any[]) => boolean;
  type ValidatorOptions (line 5) | type ValidatorOptions = {
  class Validator (line 172) | class Validator {
    method constructor (line 178) | constructor(func: ValidatorFunction, options: ValidatorOptions = {}) {
    method getFunction (line 204) | getFunction() {
    method getName (line 220) | getName() {
    method getArguments (line 236) | getArguments() {
    method getSignature (line 240) | getSignature(): string {
    method getMessage (line 256) | getMessage({generateIfMissing = true}: {generateIfMissing?: boolean} =...
    method run (line 280) | run(value: any) {
    method serialize (line 284) | serialize(serializer: Function) {
    method recreate (line 307) | static recreate(serializedValidator: any, deserializer: Function) {
    method isValidator (line 320) | static isValidator(value: any): value is Validator {
  function isValidatorInstance (line 325) | function isValidatorInstance(value: any): value is Validator {
  function isSerializedValidator (line 329) | function isSerializedValidator(object: object) {
  function runValidators (line 333) | function runValidators(validators: Validator[], value: any) {
  function stringifyArguments (line 345) | function stringifyArguments(args: any[]) {

FILE: packages/execution-queue/src/execution-queue.test.ts
  class Application (line 11) | class Application extends Component {
    method task (line 12) | static async task() {
  class Movie (line 42) | class Movie extends Component {
    method play (line 47) | async play() {
  class Application (line 54) | class Application extends Component {
    method task (line 12) | static async task() {

FILE: packages/execution-queue/src/execution-queue.ts
  type ExecutionQueueSender (line 4) | type ExecutionQueueSender = (query: PlainObject) => Promise<any>;
  class ExecutionQueue (line 6) | class ExecutionQueue {
    method constructor (line 9) | constructor(sender: ExecutionQueueSender) {
    method registerRootComponent (line 13) | registerRootComponent(rootComponent: typeof Component) {

FILE: packages/integration-testing/src/component-express-middleware.test.ts
  constant SERVER_PORT (line 9) | const SERVER_PORT = 6666;

FILE: packages/integration-testing/src/component-koa-middleware.test.ts
  constant SERVER_PORT (line 10) | const SERVER_PORT = 5555;

FILE: packages/integration-testing/src/counter.fixture.ts
  class Counter (line 5) | class Counter extends Routable(Component) {
    method increment (line 10) | increment() {
    method ping (line 14) | static ping() {
    method input (line 20) | input(_, {headers, body}) {
    method echo (line 35) | static echo({data}: {data: any}) {

FILE: packages/integration-testing/src/http-client-server.test.ts
  constant SERVER_PORT (line 6) | const SERVER_PORT = Math.floor(Math.random() * (60000 - 50000 + 1) + 500...

FILE: packages/integration-testing/src/memory-navigator.test.ts
  class Home (line 9) | class Home extends Routable(Component) {
    method HomePage (line 10) | static HomePage() {
  class Movie (line 15) | class Movie extends Routable(Component) {
    method ListPage (line 18) | static ListPage() {
    method ItemLayout (line 22) | ItemLayout({children}: {children: () => any}) {
    method ItemPage (line 26) | ItemPage() {
    method DetailsPage (line 30) | DetailsPage() {
  class Application (line 35) | class Application extends Routable(Component) {
    method RootLayout (line 39) | static RootLayout({children}: {children: () => any}) {
    method MainLayout (line 43) | static MainLayout({children}: {children: () => any}) {

FILE: packages/integration-testing/src/navigator.test.ts
  class MockNavigator (line 6) | class MockNavigator extends Navigator {
    method _getCurrentURL (line 7) | _getCurrentURL() {
    method _navigate (line 11) | _navigate(_url: URL) {}
    method _redirect (line 13) | _redirect(_url: URL) {}
    method _reload (line 15) | _reload(_url: URL | undefined) {}
    method _go (line 17) | _go(_delta: number) {}
    method _getHistoryLength (line 19) | _getHistoryLength(): number {
    method _getHistoryIndex (line 23) | _getHistoryIndex(): number {
  class Profile (line 41) | class Profile extends Routable(Component) {}
  class User (line 43) | class User extends Routable(Component) {
  class Movie (line 47) | class Movie extends Routable(Component) {}
    method ItemPage (line 75) | ItemPage({
  class Application (line 49) | class Application extends Routable(Component) {
    method MainLayout (line 92) | static MainLayout({children}: {children: () => any}) {
    method filter (line 97) | filter(request) {
    method ping (line 101) | static ping() {
    method NotFoundPage (line 105) | static NotFoundPage() {
  class Movie (line 72) | class Movie extends Routable(Component) {
    method ItemPage (line 75) | ItemPage({
  class Actor (line 82) | class Actor extends Routable(Component) {
    method TopPage (line 83) | static TopPage() {
  class Application (line 88) | class Application extends Routable(Component) {
    method MainLayout (line 92) | static MainLayout({children}: {children: () => any}) {
    method filter (line 97) | filter(request) {
    method ping (line 101) | static ping() {
    method NotFoundPage (line 105) | static NotFoundPage() {

FILE: packages/integration-testing/src/storable.fixture.ts
  constant CREATED_ON (line 4) | const CREATED_ON = new Date('2020-03-22T01:27:42.612Z');
  constant UPDATED_ON (line 5) | const UPDATED_ON = new Date('2020-03-22T01:29:33.673Z');
  function getInitialCollections (line 7) | function getInitialCollections() {
  function seedMongoDB (line 101) | async function seedMongoDB(connectionString: string) {

FILE: packages/integration-testing/src/storable.test.ts
  class BasePicture (line 35) | class BasePicture extends EmbeddedComponent {
  class BaseOrganization (line 40) | class BaseOrganization extends Storable(Component) {
  class BaseUser (line 46) | class BaseUser extends Storable(Component) {
  class Picture (line 68) | class Picture extends BasePicture {}
  class Organization (line 70) | class Organization extends BaseOrganization {}
  class User (line 72) | class User extends BaseUser {
  class Picture (line 88) | class Picture extends BasePicture {}
  class Organization (line 90) | class Organization extends BaseOrganization {}
  class User (line 92) | class User extends BaseUser {
  class Picture (line 116) | class Picture extends BasePicture {}
  class Organization (line 118) | class Organization extends BaseOrganization {}
  class User (line 120) | class User extends BaseUser {
  class Picture (line 146) | class Picture extends BasePicture {}
  class Organization (line 148) | class Organization extends BaseOrganization {}
  class User (line 150) | class User extends BaseUser {
  class Picture (line 171) | class Picture extends BasePicture {}
  class Organization (line 173) | class Organization extends BaseOrganization {}
  class User (line 175) | class User extends BaseUser {
  class Picture (line 213) | @expose({
  class Organization (line 221) | @expose({
  class User (line 234) | @expose({
  class Picture (line 283) | class Picture extends BasePicture {}
  class Organization (line 285) | class Organization extends BaseOrganization {}
  class User (line 287) | class User extends BaseUser {
  function testOperations (line 297) | function testOperations(userClassProvider: () => typeof BaseUser | Promi...
  function getUserClass (line 1922) | function getUserClass() {
  function getUserClass (line 1991) | function getUserClass() {
  function getUserClass (line 2163) | function getUserClass() {
  method get (line 2263) | get(target: object, name: string) {
  method set (line 2266) | set(target: object, name: string, value: any) {

FILE: packages/memory-navigator/src/memory-navigator.ts
  type MemoryNavigatorOptions (line 3) | type MemoryNavigatorOptions = NavigatorOptions & {
  class MemoryNavigator (line 17) | class MemoryNavigator extends Navigator {
    method constructor (line 31) | constructor(options: MemoryNavigatorOptions = {}) {
    method _getCurrentURL (line 48) | _getCurrentURL() {
    method _navigate (line 64) | _navigate(url: URL) {
    method _redirect (line 70) | _redirect(url: URL) {
    method _reload (line 79) | _reload(_url: URL | undefined): void {
    method _go (line 83) | _go(delta: number) {
    method _getHistoryLength (line 95) | _getHistoryLength() {
    method _getHistoryIndex (line 99) | _getHistoryIndex() {

FILE: packages/memory-store/src/memory-store.ts
  type Collection (line 23) | type Collection = Document[];
  type CollectionMap (line 25) | type CollectionMap = {[name: string]: Collection};
  class MemoryStore (line 38) | class MemoryStore extends Store {
    method constructor (line 72) | constructor(options: {initialCollections?: CollectionMap} = {}) {
    method _getCollection (line 92) | _getCollection(name: string) {
    method createDocument (line 105) | async createDocument({collectionName, identifierDescriptor, document}:...
    method readDocument (line 119) | async readDocument({
    method _readDocument (line 130) | async _readDocument({
    method updateDocument (line 144) | async updateDocument({
    method deleteDocument (line 176) | async deleteDocument({collectionName, identifierDescriptor}: DeleteDoc...
    method findDocuments (line 190) | async findDocuments({
    method _findDocuments (line 204) | async _findDocuments({
    method countDocuments (line 228) | async countDocuments({collectionName, expressions}: CountDocumentsPara...
    method migrateCollection (line 238) | async migrateCollection({collectionName}: MigrateCollectionParams) {
  function filterDocuments (line 249) | function filterDocuments(documents: Document[], expressions: Expression[...
  function documentIsMatchingExpressions (line 257) | function documentIsMatchingExpressions(document: Document, expressions: ...
  function evaluateExpression (line 269) | function evaluateExpression(
  function sortDocuments (line 412) | function sortDocuments(documents: Document[], sort: SortDescriptor | und...
  function skipDocuments (line 430) | function skipDocuments(documents: Document[], skip: number | undefined) {
  function limitDocuments (line 438) | function limitDocuments(documents: Document[], limit: number | undefined) {

FILE: packages/mongodb-store/src/mongodb-store.test.ts
  class Person (line 20) | class Person extends Storable(Component) {
  class Movie (line 26) | class Movie extends Storable(Component) {

FILE: packages/mongodb-store/src/mongodb-store.ts
  constant MONGODB_PRIMARY_IDENTIFIER_ATTRIBUTE_NAME (line 38) | const MONGODB_PRIMARY_IDENTIFIER_ATTRIBUTE_NAME = '_id';
  constant MONGODB_PRIMARY_IDENTIFIER_ATTRIBUTE_INDEX_NAME (line 39) | const MONGODB_PRIMARY_IDENTIFIER_ATTRIBUTE_INDEX_NAME = '_id_';
  class MongoDBStore (line 124) | class MongoDBStore extends Store {
    method constructor (line 143) | constructor(connectionString: string, options: {poolSize?: number} = {...
    method getURL (line 164) | getURL() {
    method connect (line 185) | async connect() {
    method disconnect (line 194) | async disconnect() {
    method createDocument (line 200) | async createDocument({collectionName, document}: CreateDocumentParams) {
    method readDocument (line 242) | async readDocument({
    method updateDocument (line 267) | async updateDocument({
    method deleteDocument (line 312) | async deleteDocument({collectionName, identifierDescriptor}: DeleteDoc...
    method findDocuments (line 331) | async findDocuments({
    method countDocuments (line 375) | async countDocuments({collectionName, expressions}: CountDocumentsPara...
    method toDocument (line 396) | toDocument<Value>(storable: typeof StorableComponent | StorableCompone...
    method fromDocument (line 412) | fromDocument(
    method migrateCollection (line 439) | async migrateCollection({
    method _getClient (line 551) | private async _getClient() {
    method _connectClient (line 559) | private _connectClient() {
    method _fixConnectionString (line 588) | private _fixConnectionString(connectionString: string) {
    method _disconnectClient (line 606) | private async _disconnectClient() {
    method _getDatabase (line 633) | private async _getDatabase() {
    method _getCollection (line 644) | private async _getCollection(name: string) {
  function buildMongoQuery (line 658) | function buildMongoQuery(expressions: Expression[]) {
  function handleOperator (line 683) | function handleOperator(
  function buildMongoSort (line 790) | function buildMongoSort(sort: SortDescriptor | undefined) {
  function debugCall (line 800) | async function debugCall<Result>(
  type FindOneOperation (line 827) | interface FindOneOperation extends Operation {
  function batchableFindOne (line 831) | function batchableFindOne(

FILE: packages/navigator/src/navigator.ts
  type Function (line 8) | interface Function {
  type URLOptions (line 21) | type URLOptions = {hash?: string};
  type NavigationOptions (line 23) | type NavigationOptions = {silent?: boolean; defer?: boolean};
  type NavigatorPlugin (line 25) | type NavigatorPlugin = (navigator: Navigator) => void;
  type AddressableMethodWrapper (line 27) | type AddressableMethodWrapper = (receiver: any, method: Function, params...
  type CustomRouteDecorator (line 29) | type CustomRouteDecorator = (method: Function) => void;
  type NavigatorOptions (line 31) | type NavigatorOptions = {
  method constructor (line 41) | constructor(options: NavigatorOptions = {}) {
  method mount (line 55) | mount() {
  method unmount (line 59) | unmount() {
  method getCurrentURL (line 80) | getCurrentURL() {
  method getCurrentPath (line 101) | getCurrentPath() {
  method getCurrentQuery (line 122) | getCurrentQuery<T extends object = object>() {
  method getCurrentHash (line 150) | getCurrentHash() {
  method navigate (line 190) | navigate(url: string | URL, options: NavigationOptions = {}) {
  method redirect (line 230) | redirect(url: string | URL, options: NavigationOptions = {}) {
  method reload (line 263) | reload(url?: string | URL) {
  method go (line 294) | go(delta: number, options: NavigationOptions = {}) {
  method goBack (line 323) | goBack(options: NavigationOptions = {}) {
  method goBackToRoot (line 338) | goBackToRoot(options: NavigationOptions = {}) {
  method goForward (line 361) | goForward(options: NavigationOptions = {}) {
  method getHistoryLength (line 370) | getHistoryLength() {
  method getHistoryIndex (line 381) | getHistoryIndex() {
  method applyPlugins (line 397) | applyPlugins(plugins: NavigatorPlugin[]) {
  method addAddressableMethodWrapper (line 405) | addAddressableMethodWrapper(methodWrapper: AddressableMethodWrapper) {
  method callAddressableMethodWrapper (line 415) | callAddressableMethodWrapper(receiver: any, method: Function, params: an...
  method addCustomRouteDecorator (line 428) | addCustomRouteDecorator(decorator: CustomRouteDecorator) {
  method applyCustomRouteDecorators (line 432) | applyCustomRouteDecorators(routable: any, method: Function) {
  method isNavigator (line 442) | static isNavigator(value: any): value is Navigator {
  function possiblyDeferred (line 447) | function possiblyDeferred(defer: boolean, func: Function) {

FILE: packages/navigator/src/utilities.ts
  constant INTERNAL_LAYR_BASE_URL (line 6) | const INTERNAL_LAYR_BASE_URL = 'http://internal.layr';
  function isNavigatorClass (line 17) | function isNavigatorClass(value: any): value is typeof Navigator {
  function isNavigatorInstance (line 30) | function isNavigatorInstance(value: any): value is Navigator {
  function assertIsNavigatorInstance (line 34) | function assertIsNavigatorInstance(value: any): asserts value is Navigat...
  function normalizeURL (line 42) | function normalizeURL(url: URL | string) {
  function fixCapacitorURL (line 60) | function fixCapacitorURL(url: URL) {
  function stringifyURL (line 71) | function stringifyURL(url: URL) {
  function parseQuery (line 85) | function parseQuery<T extends object = object>(queryString: string) {
  function stringifyQuery (line 93) | function stringifyQuery(query: object | undefined) {

FILE: packages/observable/src/observable.test.ts
  class BaseCustomObservable (line 482) | class BaseCustomObservable extends Observable(Object) {
    method constructor (line 485) | constructor({id}: {id?: number} = {}) {
    method limit (line 492) | static get limit() {
    method limit (line 496) | static set limit(limit) {
    method id (line 501) | get id() {
    method id (line 505) | set id(id) {
  class NonEmbeddable (line 634) | class NonEmbeddable extends Observable(Object) {
    method isEmbedded (line 635) | static isEmbedded() {

FILE: packages/observable/src/observable.ts
  type ObservableType (line 3) | type ObservableType = {
  type Observer (line 10) | type Observer = ObserverFunction | ObservableType;
  type ObserverFunction (line 12) | type ObserverFunction = (...args: any[]) => void;
  type ObserverPayload (line 14) | type ObserverPayload = {[key: string]: unknown};
  function Observable (line 109) | function Observable<T extends Constructor>(Base: T) {
  function createObservable (line 377) | function createObservable<T extends object>(target: T) {
  class ObserverSet (line 531) | class ObserverSet {
    method constructor (line 534) | constructor() {
    method add (line 538) | add(observer: Observer) {
    method remove (line 546) | remove(observer: Observer) {
    method call (line 558) | call({
  function isObservable (line 591) | function isObservable(value: any): value is ObservableType {
  function canBeObserved (line 595) | function canBeObserved(value: any): value is object {
  function isEmbeddable (line 602) | function isEmbeddable(value: any) {

FILE: packages/react-integration/src/components.tsx
  function BrowserRootView (line 27) | function BrowserRootView({
  function BrowserNavigatorView (line 161) | function BrowserNavigatorView({rootComponent}: {rootComponent: RoutableC...
  function useNavigator (line 225) | function useNavigator() {
  type Customization (line 237) | type Customization = {
  function useCustomization (line 246) | function useCustomization() {
  function Customizer (line 297) | function Customizer({
  class BrowserActionView (line 310) | class BrowserActionView extends React.Component<
    method open (line 319) | open() {
    method close (line 337) | close() {
    method render (line 357) | render() {

FILE: packages/react-integration/src/decorators.tsx
  type ViewOption (line 14) | type ViewOption = {observe?: boolean};
  function view (line 50) | function view(options: ViewOption = {}) {
  function page (line 117) | function page(pattern: Pattern, options: ViewOption & RouteOptions = {}) {
  function layout (line 142) | function layout(pattern: Pattern, options: ViewOption & WrapperOptions =...

FILE: packages/react-integration/src/hooks.ts
  function useData (line 54) | function useData<Result>(
  function useAction (line 130) | function useAction<Args extends any[] = any[], Result = any>(
  function useObserve (line 185) | function useObserve(observable: ObservableType) {
  function useAsyncCallback (line 243) | function useAsyncCallback<Args extends any[] = any[], Result = any>(
  function useAsyncMemo (line 328) | function useAsyncMemo<Result>(asyncFunc: () => Promise<Result>, deps: De...
  function useRecomputableMemo (line 413) | function useRecomputableMemo<Result>(func: () => Result, deps: Dependenc...
  function useAsyncCall (line 526) | function useAsyncCall(asyncFunc: () => Promise<void>, deps: DependencyLi...
  function useIsMounted (line 532) | function useIsMounted() {
  function useForceUpdate (line 550) | function useForceUpdate() {
  function useDelay (line 563) | function useDelay(duration = 100) {

FILE: packages/react-integration/src/plugins.tsx
  function BrowserNavigatorPlugin (line 6) | function BrowserNavigatorPlugin() {

FILE: packages/routable/src/addressable.ts
  type AddressableOptions (line 14) | type AddressableOptions = {
  type Filter (line 21) | type Filter = (request: any) => boolean;
  type Transformers (line 23) | type Transformers = {
  method constructor (line 77) | constructor(name: string, pattern: Pattern, options: AddressableOptions ...
  method getName (line 128) | getName() {
  method getPattern (line 146) | getPattern() {
  method isCatchAll (line 150) | isCatchAll() {
  method getParams (line 154) | getParams() {
  method getAliases (line 178) | getAliases() {
  method getFilter (line 182) | getFilter() {
  method getTransformers (line 186) | getTransformers() {
  method transformMethod (line 190) | transformMethod(method: Function, request: any) {
  method matchURL (line 247) | matchURL(url: URL | string, request?: any) {
  method matchPath (line 268) | matchPath(path: string, request?: any) {
  method generateURL (line 316) | generateURL(
  method generatePath (line 336) | generatePath(identifiers?: Record<string, any>) {
  method generateQueryString (line 340) | generateQueryString(params: Record<string, any> = {}) {
  method isAddressable (line 403) | static isAddressable(value: any): value is Addressable {
  function isAddressableClass (line 417) | function isAddressableClass(value: any): value is typeof Addressable {
  function isAddressableInstance (line 430) | function isAddressableInstance(value: any): value is Addressable {

FILE: packages/routable/src/decorators.test.ts
  class Studio (line 11) | class Studio extends Component {
  class Movie (line 15) | class Movie extends Routable(Component) {
    method ListPage (line 22) | static ListPage() {
    method ItemPage (line 27) | get ItemPage() {
    method ItemWithStudioPage (line 34) | get ItemWithStudioPage() {
    method MainLayout (line 134) | static MainLayout() {}
    method ItemLayout (line 136) | ItemLayout() {}
    method getMovie (line 160) | async getMovie() {
    method routeNotFound (line 171) | static routeNotFound() {
    method trace (line 204) | static trace() {}
  class Movie (line 133) | class Movie extends Routable(Component) {
    method ListPage (line 22) | static ListPage() {
    method ItemPage (line 27) | get ItemPage() {
    method ItemWithStudioPage (line 34) | get ItemWithStudioPage() {
    method MainLayout (line 134) | static MainLayout() {}
    method ItemLayout (line 136) | ItemLayout() {}
    method getMovie (line 160) | async getMovie() {
    method routeNotFound (line 171) | static routeNotFound() {
    method trace (line 204) | static trace() {}
  class Movie (line 157) | class Movie extends Routable(Component) {
    method ListPage (line 22) | static ListPage() {
    method ItemPage (line 27) | get ItemPage() {
    method ItemWithStudioPage (line 34) | get ItemWithStudioPage() {
    method MainLayout (line 134) | static MainLayout() {}
    method ItemLayout (line 136) | ItemLayout() {}
    method getMovie (line 160) | async getMovie() {
    method routeNotFound (line 171) | static routeNotFound() {
    method trace (line 204) | static trace() {}
  class Movie (line 202) | class Movie extends Routable(Component) {
    method ListPage (line 22) | static ListPage() {
    method ItemPage (line 27) | get ItemPage() {
    method ItemWithStudioPage (line 34) | get ItemWithStudioPage() {
    method MainLayout (line 134) | static MainLayout() {}
    method ItemLayout (line 136) | ItemLayout() {}
    method getMovie (line 160) | async getMovie() {
    method routeNotFound (line 171) | static routeNotFound() {
    method trace (line 204) | static trace() {}

FILE: packages/routable/src/decorators.ts
  function route (line 42) | function route(pattern: Pattern, options: RouteOptions = {}) {
  function wrapper (line 173) | function wrapper(pattern: Pattern, options: WrapperOptions = {}) {
  constant HTTP_METHODS (line 199) | const HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const;
  constant ANY_HTTP_METHOD (line 200) | const ANY_HTTP_METHOD = '*';
  type HTTPMethod (line 202) | type HTTPMethod = typeof HTTP_METHODS[number];
  type AnyHTTPMethod (line 203) | type AnyHTTPMethod = typeof ANY_HTTP_METHOD;
  function basicHTTPRouteInputTransformer (line 205) | function basicHTTPRouteInputTransformer(params: any, _request: any) {
  function basicHTTPRouteOutputTransformer (line 209) | function basicHTTPRouteOutputTransformer(result: any, request: any) {
  function basicHTTPRouteErrorTransformer (line 233) | function basicHTTPRouteErrorTransformer(error: any, _request: any) {
  function httpRoute (line 271) | function httpRoute(

FILE: packages/routable/src/js-tests/decorators.test.js
  class Studio (line 11) | class Studio extends Component {
  class Movie (line 15) | class Movie extends Routable(Component) {
    method ListPage (line 22) | @route('/movies', {aliases: ['/films']}) static ListPage() {
    method ItemPage (line 27) | @route('/movies/:id', {aliases: ['/films/:id']}) get ItemPage() {
    method ItemWithStudioPage (line 34) | @route('/studios/:studio.id/movies/:id') get ItemWithStudioPage() {
    method MainLayout (line 134) | @wrapper('/movies') static MainLayout() {}
    method ItemLayout (line 136) | @wrapper('[/movies]/:id') ItemLayout() {}
    method getMovie (line 160) | @httpRoute('GET', '/movies/:id') async getMovie() {
    method routeNotFound (line 171) | @httpRoute('*', '/*') static routeNotFound() {
    method trace (line 203) | @httpRoute('TRACE', '/trace') static trace() {}
  class Movie (line 133) | class Movie extends Routable(Component) {
    method ListPage (line 22) | @route('/movies', {aliases: ['/films']}) static ListPage() {
    method ItemPage (line 27) | @route('/movies/:id', {aliases: ['/films/:id']}) get ItemPage() {
    method ItemWithStudioPage (line 34) | @route('/studios/:studio.id/movies/:id') get ItemWithStudioPage() {
    method MainLayout (line 134) | @wrapper('/movies') static MainLayout() {}
    method ItemLayout (line 136) | @wrapper('[/movies]/:id') ItemLayout() {}
    method getMovie (line 160) | @httpRoute('GET', '/movies/:id') async getMovie() {
    method routeNotFound (line 171) | @httpRoute('*', '/*') static routeNotFound() {
    method trace (line 203) | @httpRoute('TRACE', '/trace') static trace() {}
  class Movie (line 157) | class Movie extends Routable(Component) {
    method ListPage (line 22) | @route('/movies', {aliases: ['/films']}) static ListPage() {
    method ItemPage (line 27) | @route('/movies/:id', {aliases: ['/films/:id']}) get ItemPage() {
    method ItemWithStudioPage (line 34) | @route('/studios/:studio.id/movies/:id') get ItemWithStudioPage() {
    method MainLayout (line 134) | @wrapper('/movies') static MainLayout() {}
    method ItemLayout (line 136) | @wrapper('[/movies]/:id') ItemLayout() {}
    method getMovie (line 160) | @httpRoute('GET', '/movies/:id') async getMovie() {
    method routeNotFound (line 171) | @httpRoute('*', '/*') static routeNotFound() {
    method trace (line 203) | @httpRoute('TRACE', '/trace') static trace() {}
  class Movie (line 201) | class Movie extends Routable(Component) {
    method ListPage (line 22) | @route('/movies', {aliases: ['/films']}) static ListPage() {
    method ItemPage (line 27) | @route('/movies/:id', {aliases: ['/films/:id']}) get ItemPage() {
    method ItemWithStudioPage (line 34) | @route('/studios/:studio.id/movies/:id') get ItemWithStudioPage() {
    method MainLayout (line 134) | @wrapper('/movies') static MainLayout() {}
    method ItemLayout (line 136) | @wrapper('[/movies]/:id') ItemLayout() {}
    method getMovie (line 160) | @httpRoute('GET', '/movies/:id') async getMovie() {
    method routeNotFound (line 171) | @httpRoute('*', '/*') static routeNotFound() {
    method trace (line 203) | @httpRoute('TRACE', '/trace') static trace() {}

FILE: packages/routable/src/param.ts
  type Params (line 3) | type Params = Record<string, TypeSpecifier>;
  constant PARAM_TYPE (line 5) | const PARAM_TYPE = ['boolean', 'number', 'string', 'Date'] as const;
  type ParamType (line 7) | type ParamType = typeof PARAM_TYPE[number];
  type TypeSpecifier (line 9) | type TypeSpecifier = `${ParamType}${'' | '?'}`;
  type ParamTypeDescriptor (line 11) | type ParamTypeDescriptor = {
  function serializeParam (line 17) | function serializeParam(name: string, value: any, typeDescriptor: ParamT...
  function deserializeParam (line 61) | function deserializeParam(
  function parseParamTypeSpecifier (line 113) | function parseParamTypeSpecifier(typeSpecifier: TypeSpecifier) {

FILE: packages/routable/src/pattern.ts
  type Pattern (line 5) | type Pattern = string;
  type PathMatcher (line 7) | type PathMatcher = (path: string) => Record<string, any> | undefined;
  type PathGenerator (line 8) | type PathGenerator = (identifiers?: Record<string, any>) => string | und...
  constant PATH_CHARACTER_REGEXP (line 10) | const PATH_CHARACTER_REGEXP = /[A-Za-z0-9.\-_@/]/;
  constant IDENTIFIER_NAME_CHARACTER_REGEXP (line 11) | const IDENTIFIER_NAME_CHARACTER_REGEXP = /[A-Za-z0-9.]/;
  constant IDENTIFIER_VALUE_GROUP_PATTERN (line 12) | const IDENTIFIER_VALUE_GROUP_PATTERN = '([^/]+)';
  function parsePattern (line 14) | function parsePattern(pattern: Pattern) {
  function splitPattern (line 95) | function splitPattern(pattern: Pattern) {

FILE: packages/routable/src/routable.test.ts
  class Movie (line 8) | class Movie extends Routable(Component) {}
    method ListPage (line 170) | static ListPage() {
    method ItemPage (line 174) | ItemPage({showDetails = false}) {
    method ItemWithStudioPage (line 178) | ItemWithStudioPage() {
  class Movie (line 15) | class Movie extends Routable(Component) {}
    method ListPage (line 170) | static ListPage() {
    method ItemPage (line 174) | ItemPage({showDetails = false}) {
    method ItemWithStudioPage (line 178) | ItemWithStudioPage() {
  class Movie (line 41) | class Movie extends Routable(Component) {}
    method ListPage (line 170) | static ListPage() {
    method ItemPage (line 174) | ItemPage({showDetails = false}) {
    method ItemWithStudioPage (line 178) | ItemWithStudioPage() {
  class ExtendedMovie (line 43) | class ExtendedMovie extends Movie {}
  class Movie (line 83) | class Movie extends Routable(Component) {}
    method ListPage (line 170) | static ListPage() {
    method ItemPage (line 174) | ItemPage({showDetails = false}) {
    method ItemWithStudioPage (line 178) | ItemWithStudioPage() {
  class Studio (line 161) | class Studio extends Routable(Component) {
  class Movie (line 165) | class Movie extends Routable(Component) {
    method ListPage (line 170) | static ListPage() {
    method ItemPage (line 174) | ItemPage({showDetails = false}) {
    method ItemWithStudioPage (line 178) | ItemWithStudioPage() {
  class Application (line 183) | class Application extends Routable(Component) {
    method MainLayout (line 187) | static MainLayout({children}: {children: () => any}) {
    method echo (line 191) | static echo({message = ''}: {message?: string}) {
    method echoAsync (line 199) | static async echoAsync({message = ''}: {message?: string}) {
  method input (line 242) | input({message = ''}: {message?: string}, {method}: {method: string}) {
  method output (line 245) | output(result: string) {
  method error (line 252) | error(error: Error) {

FILE: packages/routable/src/routable.ts
  function Routable (line 39) | function Routable<T extends Constructor<typeof Component>>(Base: T) {
  class RoutableComponent (line 683) | class RoutableComponent extends Routable(Component) {}
  function findRouteByURL (line 687) | function findRouteByURL(rootComponent: typeof Component, url: URL | stri...
  function callRouteByURL (line 731) | function callRouteByURL(rootComponent: typeof Component, url: URL | stri...
  function findWrapperByPath (line 743) | function findWrapperByPath(rootComponent: typeof Component, path: string...
  function callWrapperByPath (line 771) | function callWrapperByPath(
  function instantiateComponent (line 795) | function instantiateComponent(

FILE: packages/routable/src/route.test.ts
  method filter (line 243) | filter(request: any) {

FILE: packages/routable/src/route.ts
  type RouteOptions (line 3) | type RouteOptions = AddressableOptions;
  class Route (line 16) | class Route extends Addressable {
    method isRoute (line 41) | static isRoute(value: any): value is Route {
  function isRouteClass (line 55) | function isRouteClass(value: any): value is typeof Route {
  function isRouteInstance (line 68) | function isRouteInstance(value: any): value is Route {

FILE: packages/routable/src/utilities.ts
  function isRoutableClass (line 14) | function isRoutableClass(value: any): value is typeof RoutableComponent {
  function isRoutableInstance (line 27) | function isRoutableInstance(value: any): value is RoutableComponent {
  function isRoutableClassOrInstance (line 40) | function isRoutableClassOrInstance(
  function assertIsRoutableClass (line 55) | function assertIsRoutableClass(value: any): asserts value is typeof Rout...
  function assertIsRoutableInstance (line 70) | function assertIsRoutableInstance(value: any): asserts value is Routable...
  function assertIsRoutableClassOrInstance (line 85) | function assertIsRoutableClassOrInstance(

FILE: packages/routable/src/wrapper.ts
  type WrapperOptions (line 4) | type WrapperOptions = AddressableOptions;
  class Wrapper (line 17) | class Wrapper extends Addressable {
    method constructor (line 26) | constructor(name: string, pattern: Pattern, options: WrapperOptions = ...
    method isWrapper (line 50) | static isWrapper(value: any): value is Wrapper {
  function isWrapperClass (line 64) | function isWrapperClass(value: any): value is typeof Wrapper {
  function isWrapperInstance (line 77) | function isWrapperInstance(value: any): value is Wrapper {

FILE: packages/storable/src/decorators.test.ts
  class Movie (line 13) | class Movie extends Storable(Component) {
    method hasAccessLevel (line 75) | hasAccessLevel() {}
  class Movie (line 42) | class Movie extends Storable(Component) {
    method hasAccessLevel (line 75) | hasAccessLevel() {}
  class Movie (line 73) | class Movie extends Storable(Component) {
    method hasAccessLevel (line 75) | hasAccessLevel() {}
  class Movie (line 96) | @index({year: 'desc', title: 'asc'}, {isUnique: true})
    method hasAccessLevel (line 75) | hasAccessLevel() {}

FILE: packages/storable/src/decorators.ts
  type StorableAttributeDecoratorOptions (line 26) | type StorableAttributeDecoratorOptions = Omit<StorableAttributeOptions, ...
  function attribute (line 44) | function attribute(
  function primaryIdentifier (line 73) | function primaryIdentifier(
  function secondaryIdentifier (line 102) | function secondaryIdentifier(
  function method (line 127) | function method(options: StorableMethodOptions = {}) {
  function loader (line 148) | function loader(loader: StorableAttributeLoader) {
  function finder (line 179) | function finder(finder: StorablePropertyFinder) {
  type ClassIndexParam (line 200) | type ClassIndexParam = IndexAttributes;
  type ClassIndexOptions (line 201) | type ClassIndexOptions = {isUnique?: boolean};
  type AttributeIndexParam (line 202) | type AttributeIndexParam = {direction?: SortDirection; isUnique?: boolean};
  function index (line 275) | function index(

FILE: packages/storable/src/index-class.test.ts
  class Person (line 9) | class Person extends Storable(Component) {
  class MovieDetails (line 15) | class MovieDetails extends Storable(EmbeddedComponent) {
  class Movie (line 21) | class Movie extends Storable(Component) {
    method play (line 52) | play() {}

FILE: packages/storable/src/index-class.ts
  type IndexAttributes (line 13) | type IndexAttributes = {[name: string]: SortDirection};
  type IndexOptions (line 15) | type IndexOptions = {isUnique?: boolean};
  class Index (line 150) | class Index {
    method constructor (line 166) | constructor(attributes: IndexAttributes, parent: StorableComponent, op...
    method getAttributes (line 244) | getAttributes() {
    method getParent (line 255) | getParent() {
    method getOptions (line 261) | getOptions() {
    method setOptions (line 265) | setOptions(options: IndexOptions = {}) {
    method fork (line 275) | fork(parent: StorableComponent) {
    method isIndex (line 285) | static isIndex(value: any): value is Index {
    method _buildIndexKey (line 289) | static _buildIndexKey(attributes: IndexAttributes) {
  function isIndexClass (line 303) | function isIndexClass(value: any): value is typeof Index {
  function isIndexInstance (line 316) | function isIndexInstance(value: any): value is Index {

FILE: packages/storable/src/js-tests/decorators.test.js
  class Movie (line 13) | class Movie extends Storable(Component) {
    method hasAccessLevel (line 75) | @finder(hasAccessLevelFinder) @method() hasAccessLevel() {}
  class Movie (line 42) | class Movie extends Storable(Component) {
    method hasAccessLevel (line 75) | @finder(hasAccessLevelFinder) @method() hasAccessLevel() {}
  class Movie (line 73) | class Movie extends Storable(Component) {
    method hasAccessLevel (line 75) | @finder(hasAccessLevelFinder) @method() hasAccessLevel() {}
  class Movie (line 96) | @index({year: 'desc', title: 'asc'}, {isUnique: true})
    method hasAccessLevel (line 75) | @finder(hasAccessLevelFinder) @method() hasAccessLevel() {}

FILE: packages/storable/src/operator.ts
  type Operator (line 5) | type Operator = string;
  function looksLikeOperator (line 25) | function looksLikeOperator(string: string): string is Operator {
  function normalizeOperatorForValue (line 29) | function normalizeOperatorForValue(
  function normalizeBasicOperatorForValue (line 63) | function normalizeBasicOperatorForValue(
  function normalizeStringOperatorForValue (line 91) | function normalizeStringOperatorForValue(
  function normalizeArrayOperatorForValue (line 119) | function normalizeArrayOperatorForValue(
  function normalizeLogicalOperatorForValue (line 139) | function normalizeLogicalOperatorForValue(

FILE: packages/storable/src/properties/storable-attribute.test.ts
  class Movie (line 8) | class Movie extends Storable(Component) {}
  method loader (line 16) | async loader() {
  method finder (line 20) | async finder() {
  method beforeLoad (line 24) | async beforeLoad() {
  class Movie (line 72) | class Movie extends Storable(Component) {}

FILE: packages/storable/src/properties/storable-attribute.ts
  type StorableAttributeOptions (line 13) | type StorableAttributeOptions = StorablePropertyOptions &
  type StorableAttributeLoader (line 24) | type StorableAttributeLoader = () => PromiseLikeable<unknown>;
  type StorableAttributeHook (line 26) | type StorableAttributeHook = (attribute: StorableAttribute) => PromiseLi...
  type StorableAttributeHookName (line 28) | type StorableAttributeHookName =
  method setOptions (line 350) | setOptions(options: StorableAttributeOptions = {}) {
  method isControlled (line 395) | isControlled() {
  method getLoader (line 426) | getLoader() {
  method hasLoader (line 437) | hasLoader() {
  method setLoader (line 448) | setLoader(loader: StorableAttributeLoader) {
  method callLoader (line 452) | async callLoader() {
  method isComputed (line 484) | isComputed() {
  method getHook (line 499) | getHook(name: StorableAttributeHookName) {
  method hasHook (line 512) | hasHook(name: StorableAttributeHookName) {
  method setHook (line 524) | setHook(name: StorableAttributeHookName, hook: StorableAttributeHook) {
  method callHook (line 528) | async callHook(name: StorableAttributeHookName) {
  method _getHooks (line 540) | _getHooks(autoFork = false) {
  method isStorableAttribute (line 578) | static isStorableAttribute(value: any): value is StorableAttribute {
  function isStorableAttributeClass (line 583) | function isStorableAttributeClass(value: any): value is typeof StorableA...
  function isStorableAttributeInstance (line 587) | function isStorableAttributeInstance(value: any): value is StorableAttri...
  class StorableAttribute (line 591) | class StorableAttribute extends StorableAttributeMixin(Attribute) {
    method constructor (line 592) | constructor(

FILE: packages/storable/src/properties/storable-method.ts
  type StorableMethodOptions (line 13) | type StorableMethodOptions = StorablePropertyOptions & MethodOptions;
  method isStorableMethod (line 209) | static isStorableMethod(value: any): value is StorableMethod {
  function isStorableMethodClass (line 214) | function isStorableMethodClass(value: any): value is typeof StorableMeth...
  function isStorableMethodInstance (line 218) | function isStorableMethodInstance(value: any): value is StorableMethod {
  class StorableMethod (line 222) | class StorableMethod extends StorableMethodMixin(Method) {
    method constructor (line 223) | constructor(

FILE: packages/storable/src/properties/storable-primary-identifier-attribute.ts
  class StorablePrimaryIdentifierAttribute (line 47) | class StorablePrimaryIdentifierAttribute extends StorableAttributeMixin(

FILE: packages/storable/src/properties/storable-property.ts
  type StorablePropertyOptions (line 8) | type StorablePropertyOptions = PropertyOptions & {
  type StorablePropertyFinder (line 12) | type StorablePropertyFinder = (value: unknown) => PromiseLikeable<Query>;
  method setOptions (line 40) | setOptions(options: StorablePropertyOptions = {}) {
  method getFinder (line 67) | getFinder() {
  method hasFinder (line 78) | hasFinder() {
  method setFinder (line 89) | setFinder(finder: StorablePropertyFinder) {
  method callFinder (line 93) | async callFinder(value: unknown) {
  method isStorableProperty (line 123) | static isStorableProperty(value: any): value is StorableProperty {
  function isStorablePropertyClass (line 128) | function isStorablePropertyClass(value: any): value is typeof StorablePr...
  function isStorablePropertyInstance (line 132) | function isStorablePropertyInstance(value: any): value is StorableProper...
  class StorableProperty (line 136) | class StorableProperty extends StorablePropertyMixin(Property) {
    method constructor (line 137) | constructor(

FILE: packages/storable/src/properties/storable-secondary-identifier-attribute.ts
  class StorableSecondaryIdentifierAttribute (line 51) | class StorableSecondaryIdentifierAttribute extends StorableAttributeMixin(

FILE: packages/storable/src/query.ts
  type Query (line 310) | type Query = PlainObject;

FILE: packages/storable/src/storable.ts
  type SortDescriptor (line 49) | type SortDescriptor = {[name: string]: SortDirection};
  type SortDirection (line 51) | type SortDirection = 'asc' | 'desc';
  function Storable (line 153) | function Storable<T extends Constructor<typeof Component>>(Base: T) {
  class StorableComponent (line 1836) | class StorableComponent extends Storable(Component) {}
  function describeCaller (line 1838) | function describeCaller(callerMethodName: string | undefined) {

FILE: packages/storable/src/store-like.ts
  class StoreLike (line 7) | class StoreLike {

FILE: packages/storable/src/utilities.ts
  function isStorableClass (line 14) | function isStorableClass(value: any): value is typeof StorableComponent {
  function isStorableInstance (line 27) | function isStorableInstance(value: any): value is StorableComponent {
  function isStorableClassOrInstance (line 40) | function isStorableClassOrInstance(
  function isStorable (line 46) | function isStorable(value: any): value is typeof StorableComponent | Sto...
  function assertIsStorableClass (line 57) | function assertIsStorableClass(value: any): asserts value is typeof Stor...
  function assertIsStorableInstance (line 72) | function assertIsStorableInstance(value: any): asserts value is Storable...
  function assertIsStorableClassOrInstance (line 87) | function assertIsStorableClassOrInstance(
  function ensureStorableClass (line 115) | function ensureStorableClass(storable: typeof StorableComponent | Storab...
  function ensureStorableInstance (line 147) | function ensureStorableInstance(component: typeof StorableComponent | St...

FILE: packages/store/src/document.ts
  type Document (line 6) | type Document = PlainObject;
  type AttributeValue (line 8) | type AttributeValue = undefined | null | boolean | number | string | Date;
  type Projection (line 10) | type Projection = {[path: string]: 1};
  type DocumentPatch (line 12) | type DocumentPatch = {$set?: {[path: string]: any}; $unset?: {[path: str...
  function buildProjection (line 15) | function buildProjection(attributeSelector: AttributeSelector) {
  function buildDocumentPatch (line 47) | function buildDocumentPatch(document: Document) {

FILE: packages/store/src/expression.ts
  type Expression (line 6) | type Expression = [Path, Operator, Operand];
  type Operand (line 8) | type Operand = AttributeValue | Expression[] | Expression[][];

FILE: packages/store/src/path.ts
  type Path (line 1) | type Path = string;

FILE: packages/store/src/store.test.ts
  class MockStore (line 8) | class MockStore extends Store {
    method createDocument (line 9) | async createDocument() {
    method readDocument (line 13) | async readDocument() {
    method updateDocument (line 17) | async updateDocument() {
    method deleteDocument (line 21) | async deleteDocument() {
    method findDocuments (line 25) | async findDocuments() {
    method countDocuments (line 29) | async countDocuments() {
    method migrateCollection (line 33) | async migrateCollection() {
  class Profile (line 53) | class Profile extends Storable(Component) {}
  class User (line 55) | class User extends Storable(Component) {
  class MovieDetails (line 59) | class MovieDetails extends Storable(EmbeddedComponent) {}
  class Movie (line 61) | class Movie extends Storable(Component) {
  class Root (line 65) | class Root extends Component {
  class User (line 80) | class User extends Storable(Component) {}
  class User (line 96) | class User extends Storable(Component) {}
  class User (line 111) | class User extends Storable(Component) {}
  class UserDetails (line 124) | class UserDetails extends Storable(EmbeddedComponent) {}
  class NotAStorable (line 130) | class NotAStorable {}
  class User2 (line 143) | class User2 extends Storable(Component) {}
  class User (line 153) | class User extends Storable(Component) {}
  class Movie (line 155) | class Movie extends Storable(Component) {}
  class Person (line 171) | class Person extends Storable(Component) {
  class MovieDetails (line 177) | class MovieDetails extends Storable(EmbeddedComponent) {
  class Movie (line 183) | @index({year: 'desc', title: 'asc'})

FILE: packages/store/src/store.ts
  type CreateDocumentParams (line 52) | type CreateDocumentParams = {
  type ReadDocumentParams (line 58) | type ReadDocumentParams = {
  type UpdateDocumentParams (line 64) | type UpdateDocumentParams = {
  type DeleteDocumentParams (line 70) | type DeleteDocumentParams = {
  type FindDocumentsParams (line 75) | type FindDocumentsParams = {
  type CountDocumentsParams (line 84) | type CountDocumentsParams = {
  type MigrateCollectionParams (line 89) | type MigrateCollectionParams = {
  type MigrateCollectionResult (line 95) | type MigrateCollectionResult = {
  type CollectionSchema (line 101) | type CollectionSchema = {
  type CollectionIndex (line 105) | type CollectionIndex = {
  type TraceEntry (line 111) | type TraceEntry = {
  method constructor (line 122) | constructor(options = {}) {
  method getURL (line 126) | getURL(): string | undefined {
  method registerRootComponent (line 165) | registerRootComponent(rootComponent: typeof Component) {
  method getRootComponents (line 184) | getRootComponents() {
  method getStorable (line 210) | getStorable(name: string) {
  method hasStorable (line 238) | hasStorable(name: string) {
  method _getStorable (line 242) | _getStorable(name: string) {
  method getStorableOfType (line 246) | getStorableOfType(type: string) {
  method _getStorableOfType (line 256) | _getStorableOfType(type: string) {
  method registerStorable (line 290) | registerStorable(storable: typeof StorableComponent) {
  method getStorables (line 331) | getStorables() {
  method _getCollectionNameFromStorable (line 337) | _getCollectionNameFromStorable(storable: typeof StorableComponent | Stor...
  method load (line 343) | async load(
  method save (line 397) | async save(
  method delete (line 506) | async delete(storable: StorableComponent, options: {throwIfMissing?: boo...
  method find (line 539) | async find(
  method count (line 595) | async count(storable: typeof StorableComponent, query: Query = {}) {
  method _runOperation (line 613) | async _runOperation<
  method getTrace (line 640) | getTrace() {
  method startTrace (line 650) | startTrace() {
  method stopTrace (line 654) | stopTrace() {
  method toDocument (line 704) | toDocument<Value>(_storable: typeof StorableComponent | StorableComponen...
  method toDocumentExpressions (line 709) | toDocumentExpressions(storable: typeof StorableComponent | StorableCompo...
  method fromDocument (line 832) | fromDocument(
  method migrateStorables (line 852) | async migrateStorables(options: {silent?: boolean} = {}) {
  method migrateStorable (line 867) | async migrateStorable(storable: typeof StorableComponent, options: {sile...
  method getCollectionSchema (line 882) | getCollectionSchema(storable: StorableComponent) {
  method _getCollectionIndexes (line 890) | _getCollectionIndexes(storable: StorableComponent) {
  method isStore (line 981) | static isStore(value: any): value is Store {

FILE: packages/store/src/utilities.ts
  function isStoreClass (line 3) | function isStoreClass(value: any): value is typeof Store {
  function isStoreInstance (line 7) | function isStoreInstance(value: any): value is Store {

FILE: packages/utilities/src/error.ts
  constant DEFAULT_DISPLAY_MESSAGE (line 1) | const DEFAULT_DISPLAY_MESSAGE = 'Sorry, something went wrong.';
  type ExtendedError (line 3) | type ExtendedError = Error & ExtendedErrorAttributes;
  type ExtendedErrorAttributes (line 5) | type ExtendedErrorAttributes = Record<string, any> & {
  function createError (line 10) | function createError(message?: string, attributes: ExtendedErrorAttribut...
  function throwError (line 22) | function throwError(message?: string, attributes: ExtendedErrorAttribute...
  function formatError (line 26) | function formatError(

FILE: packages/utilities/src/time.ts
  constant MILLISECOND (line 1) | const MILLISECOND = 1;
  constant SECOND (line 2) | const SECOND = 1000 * MILLISECOND;
  constant MINUTE (line 3) | const MINUTE = 60 * SECOND;
  constant HOUR (line 4) | const HOUR = 60 * MINUTE;
  constant DAY (line 5) | const DAY = 24 * HOUR;
  constant WEEK (line 6) | const WEEK = 7 * DAY;
  constant MONTH (line 7) | const MONTH = 30.4375 * DAY;
  constant YEAR (line 8) | const YEAR = 12 * MONTH;
  function sleep (line 10) | function sleep(milliseconds: number) {

FILE: packages/with-roles/src/decorators.test.ts
  class Movie (line 9) | class Movie extends WithRoles(Component) {
    method anyoneRoleResolver (line 10) | static anyoneRoleResolver() {
    method authorRoleResolver (line 14) | authorRoleResolver() {

FILE: packages/with-roles/src/decorators.ts
  function role (line 16) | function role(name: string) {

FILE: packages/with-roles/src/role.test.ts
  class Movie (line 8) | class Movie extends WithRoles(Component) {}
  class Movie (line 22) | class Movie extends WithRoles(Component) {}
  class Movie (line 47) | class Movie extends WithRoles(Component) {}

FILE: packages/with-roles/src/role.ts
  type RoleResolver (line 14) | type RoleResolver = () => PromiseLikeable<boolean | undefined>;
  class Role (line 31) | class Role {
    method constructor (line 56) | constructor(
    method getName (line 77) | getName() {
    method getParent (line 88) | getParent() {
    method getResolver (line 99) | getResolver() {
    method resolve (line 118) | resolve(): PromiseLikeable<boolean | undefined> {
    method fork (line 130) | fork(parent: typeof ComponentWithRoles | ComponentWithRoles) {
    method isForkOf (line 138) | isForkOf(role: Role) {
    method isRole (line 144) | static isRole(value: any): value is Role {
  method [inspect.custom] (line 148) | [inspect.custom]() {
  function isRoleInstance (line 162) | function isRoleInstance(value: any): value is Role {
  function assertIsRoleInstance (line 173) | function assertIsRoleInstance(value: any): asserts value is Role {

FILE: packages/with-roles/src/utilities.ts
  function isComponentWithRolesClassOrInstance (line 14) | function isComponentWithRolesClassOrInstance(
  function assertIsComponentWithRolesClassOrInstance (line 27) | function assertIsComponentWithRolesClassOrInstance(

FILE: packages/with-roles/src/with-roles.test.ts
  class Movie (line 7) | class Movie extends WithRoles(Component) {}
  class Movie (line 42) | class Movie extends WithRoles(Component) {}
  class Movie (line 63) | class Movie extends WithRoles(Component) {}
  class Movie (line 85) | class Movie extends WithRoles(Component) {}
  class Film (line 92) | class Film extends Movie {}
  class Movie (line 103) | class Movie extends WithRoles(Component) {}
  class Movie (line 115) | class Movie extends WithRoles(Component) {}

FILE: packages/with-roles/src/with-roles.ts
  function WithRoles (line 56) | function WithRoles<T extends Constructor<typeof Component>>(Base: T) {
  class ComponentWithRoles (line 391) | class ComponentWithRoles extends WithRoles(Component) {}

FILE: website/backend/src/components/application.ts
  class Application (line 8) | class Application extends Routable(Component) {

FILE: website/backend/src/components/article.ts
  class Article (line 23) | class Article extends Routable(WithAuthor(Entity)) {
    method generateSlug (line 40) | generateSlug() {
    method output (line 53) | output(result) {
    method getRSSFeed (line 64) | static async getRSSFeed() {

FILE: website/backend/src/components/entity.ts
  class Entity (line 7) | class Entity extends WithRoles(Storable(Component)) {
    method userRoleResolver (line 16) | static async userRoleResolver() {
    method guestRoleResolver (line 20) | static async guestRoleResolver() {
    method beforeSave (line 24) | async beforeSave(attributeSelector: AttributeSelector) {

FILE: website/backend/src/components/newsletter.ts
  constant MAILER_LITE_API_URL (line 4) | const MAILER_LITE_API_URL = 'https://connect.mailerlite.com/api/';
  class Newsletter (line 11) | class Newsletter extends Component {
    method subscribe (line 12) | static async subscribe({email}: {email: string}) {

FILE: website/backend/src/components/user.ts
  constant TOKEN_DURATION (line 11) | const TOKEN_DURATION = 31536000000;
  constant INVITE_TOKEN_DURATION (line 12) | const INVITE_TOKEN_DURATION = 604800000;
  constant BCRYPT_SALT_ROUNDS (line 13) | const BCRYPT_SALT_ROUNDS = 5;
  class User (line 18) | class User extends Entity {
    method beforeSave (line 25) | async beforeSave(this: User) {
    method beforeSave (line 43) | async beforeSave(this: User) {
    method creatorRoleResolver (line 76) | creatorRoleResolver() {
    method selfRoleResolver (line 80) | async selfRoleResolver() {
    method getAuthenticatedUser (line 88) | static async getAuthenticatedUser(
    method verifyToken (line 114) | static verifyToken(token: string) {
    method generateToken (line 121) | static generateToken(userId: string, {expiresIn = TOKEN_DURATION} = {}) {
    method signUp (line 130) | async signUp({inviteToken}: {inviteToken?: string} = {}) {
    method signIn (line 153) | async signIn() {
    method hashPassword (line 175) | static async hashPassword(password: string) {
    method verifyPassword (line 179) | async verifyPassword(existingUser: User) {
    method generateInviteToken (line 183) | static generateInviteToken({
    method verifyInviteToken (line 192) | static verifyInviteToken(token: string) {

FILE: website/backend/src/components/with-author.ts
  class WithAuthor (line 9) | class WithAuthor extends Base {
    method authorRoleResolver (line 14) | async authorRoleResolver() {

FILE: website/backend/src/jwt.ts
  function generateJWT (line 8) | function generateJWT(payload: object) {
  function verifyJWT (line 12) | function verifyJWT(token: string) {

FILE: website/frontend/src/components/application.tsx
  class Application (line 24) | class Application extends Routable(Base) {
    method RootLayout (line 32) | static RootLayout({children}: {children: () => any}) {
    method MainLayout (line 53) | static MainLayout({children}: {children: () => any}) {
    method HeaderView (line 84) | static HeaderView() {
    method FooterView (line 121) | static FooterView() {
    method FrontendPlusBackendEqualsLoveView (line 201) | static FrontendPlusBackendEqualsLoveView() {
    method NotFoundPage (line 240) | static NotFoundPage() {
    method NotFoundView (line 244) | static NotFoundView() {

FILE: website/frontend/src/components/article.tsx
  class Article (line 17) | class Article extends Routable(Base) {
    method ItemLayout (line 23) | ItemLayout({children}: {children: () => any}) {
    method ItemPage (line 40) | ItemPage() {
    method ListItemView (line 51) | ListItemView() {
    method MetaView (line 64) | MetaView({...props}) {
    method EditPage (line 83) | EditPage() {
    method FormView (line 102) | FormView({onSubmit}: {onSubmit: Function}) {

FILE: website/frontend/src/components/blog.tsx
  class Blog (line 12) | class Blog extends Routable(Component) {
    method MainLayout (line 19) | static MainLayout({children}: {children: () => any}) {
    method MainPage (line 33) | static MainPage() {
    method AddArticlePage (line 62) | static AddArticlePage() {

FILE: website/frontend/src/components/docs.tsx
  constant VERSIONS (line 16) | const VERSIONS = [
  constant LAST_VERSION (line 21) | const LAST_VERSION = VERSIONS[VERSIONS.length - 1].value;
  constant LANGUAGES (line 23) | const LANGUAGES = [
  constant BASE_URL (line 28) | const BASE_URL = '/docs';
  type URLParams (line 30) | type URLParams = {
  type Contents (line 37) | type Contents = {books: Book[]};
  type Book (line 39) | type Book = {title: string; slug: string; chapters: Chapter[]};
  type Chapter (line 41) | type Chapter = {
  type Category (line 50) | type Category = {
  class Docs (line 55) | class Docs extends Routable(Component) {
    method MainPage (line 60) | static MainPage() {
    method ContentsView (line 124) | static ContentsView({version, bookSlug, chapterSlug, language}: URLPar...
    method OptionsView (line 214) | static OptionsView({version, bookSlug, chapterSlug, language}: URLPara...
    method ChapterView (line 274) | static ChapterView({version, bookSlug, chapterSlug, language}: URLPara...
    method getContents (line 318) | static getContents({version}: {version: string}) {
    method getChapter (line 340) | static async getChapter({
    method resolveURL (line 384) | static resolveURL() {
    method resolvePath (line 396) | static resolvePath(path: string) {
    method resolveVersion (line 440) | static resolveVersion(version: string | undefined) {
    method resolveQuery (line 452) | static resolveQuery(query: {language?: string}) {
    method resolveLanguage (line 458) | static resolveLanguage(language: string | undefined) {
    method generateURL (line 470) | static generateURL({
    method generatePath (line 498) | static generatePath({
    method generateQuery (line 520) | static generateQuery({language}: {language: string}) {
  function getBookCategories (line 525) | function getBookCategories(book: Book) {

FILE: website/frontend/src/components/home.tsx
  constant NO_WEB_API_BACKEND_EXAMPLE (line 16) | const NO_WEB_API_BACKEND_EXAMPLE = `
  constant NO_WEB_API_FRONTEND_EXAMPLE (line 35) | const NO_WEB_API_FRONTEND_EXAMPLE = `
  constant ORM_DATA_MODELING_EXAMPLE (line 55) | const ORM_DATA_MODELING_EXAMPLE = `
  constant ORM_STORE_REGISTRATION_EXAMPLE (line 69) | const ORM_STORE_REGISTRATION_EXAMPLE = `
  constant ORM_STORE_CRUD_OPERATIONS_EXAMPLE (line 79) | const ORM_STORE_CRUD_OPERATIONS_EXAMPLE = `
  constant ORM_STORE_FINDING_DATA_EXAMPLE (line 102) | const ORM_STORE_FINDING_DATA_EXAMPLE = `
  constant ENCAPSULATED_USER_INTERFACE_EXAMPLE (line 115) | const ENCAPSULATED_USER_INTERFACE_EXAMPLE = `
  class Home (line 161) | class Home extends Routable(Component) {
    method MainPage (line 166) | static MainPage() {
    method HeroView (line 212) | static HeroView({...props}) {
    method ScrollerView (line 273) | static ScrollerView({id}: {id: string}) {
    method NoWebAPIView (line 298) | static NoWebAPIView() {
    method ORMView (line 314) | static ORMView() {
    method UserInterfaceView (line 336) | static UserInterfaceView() {
    method FindOutMoreView (line 351) | static FindOutMoreView() {

FILE: website/frontend/src/components/newsletter.tsx
  class Newsletter (line 10) | class Newsletter extends Base {
    method SubscriptionView (line 11) | static SubscriptionView() {

FILE: website/frontend/src/components/user.tsx
  class User (line 15) | class User extends Routable(Base) {
    method getter (line 21) | getter() {
    method setter (line 24) | setter(token) {
    method initializer (line 36) | static async initializer() {
    method SignUpPage (line 40) | static SignUpPage() {
    method SignUpView (line 53) | SignUpView() {
    method SignInPage (line 152) | static SignInPage() {
    method SignInView (line 165) | SignInView() {
    method signOutPage (line 218) | static signOutPage() {
    method InvitePage (line 227) | static InvitePage() {

FILE: website/frontend/src/index.ts
  method retryFailedRequests (line 10) | async retryFailedRequests() {

FILE: website/frontend/src/markdown.tsx
  function Markdown (line 24) | function Markdown({languageFilter, children}: {languageFilter?: string; ...
  function InlineMarkdown (line 107) | function InlineMarkdown({children: markdown}: {children: string}) {

FILE: website/frontend/src/styles.ts
  function getGlobalStyles (line 4) | function getGlobalStyles(theme: Theme) {
  function useStyles (line 232) | function useStyles() {

FILE: website/frontend/src/ui.tsx
  function FullHeight (line 11) | function FullHeight({
  function FeatureSection (line 29) | function FeatureSection({
  function Title (line 73) | function Title({children: title}: {children?: string}) {
  function ErrorMessage (line 87) | function ErrorMessage({children}: {children: string | Error}) {
  function LoadingSpinner (line 106) | function LoadingSpinner({delay}: {delay?: number}) {
  function Delayed (line 140) | function Delayed({
Condensed preview — 576 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,585K chars).
[
  {
    "path": ".editorconfig",
    "chars": 207,
    "preview": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_"
  },
  {
    "path": ".gitignore",
    "chars": 86,
    "preview": ".DS_Store\n*.log\nnode_modules\n.npmrc\npackage-lock.json\ndist\nbuild\n_private\n*.private.*\n"
  },
  {
    "path": ".npm-dev-registry.json",
    "chars": 35,
    "preview": "{\n  \"packages\": [\"./packages/*\"]\n}\n"
  },
  {
    "path": ".prettierignore",
    "chars": 24,
    "preview": "node_modules\ndist\nbuild\n"
  },
  {
    "path": ".vscode/extensions.json",
    "chars": 81,
    "preview": "{\n  \"recommendations\": [\"esbenp.prettier-vscode\", \"editorconfig.editorconfig\"]\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5217,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2020 Manuel Vila\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "README.md",
    "chars": 1895,
    "preview": "<p align=\"center\">\n\t<img src=\"assets/layr-logo-with-icon.svg\" width=\"200\" alt=\"Layr\">\n\t<br>\n\t<br>\n</p>\n\n> Dramatically s"
  },
  {
    "path": "assets/frontend-backend.excalidraw",
    "chars": 16380,
    "preview": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"id\": \"qmZPy"
  },
  {
    "path": "assets/frontend-webapi-backend.excalidraw",
    "chars": 26189,
    "preview": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"id\": \"qmZPy"
  },
  {
    "path": "assets/typical-stack-vs-layr-stack-light-mode.excalidraw",
    "chars": 16564,
    "preview": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"rec"
  },
  {
    "path": "assets/typical-stack-vs-layr-stack.excalidraw",
    "chars": 16562,
    "preview": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"rec"
  },
  {
    "path": "docs/build.js",
    "chars": 1493,
    "preview": "const {buildDocumentation, freezeDocumentation} = require('@mvila/simple-doc');\nconst {copySync, removeSync, readJsonSyn"
  },
  {
    "path": "docs/contents/concepts/coming-soon.md",
    "chars": 965,
    "preview": "### Concepts\n\n#### Coming Soon\n\nThis section will introduce the basic concepts of Layr, such as:\n\n- Components\n- Control"
  },
  {
    "path": "docs/contents/guides/coming-soon.md",
    "chars": 1018,
    "preview": "### Guides\n\n#### Coming Soon\n\nThis section will contain some guides explaining how to achieve the most common tasks and "
  },
  {
    "path": "docs/contents/index.json",
    "chars": 13304,
    "preview": "{\n  \"books\": [\n    {\n      \"title\": \"Getting Started\",\n      \"slug\": \"introduction\",\n      \"chapters\": [\n        {\n     "
  },
  {
    "path": "docs/contents/introduction/handling-authorization.md",
    "chars": 1075,
    "preview": "### Handling Authorization\n\n#### Coming Soon\n\nThis tutorial will expand the [\"Hello, World!\"](https://layrjs.com/docs/v2"
  },
  {
    "path": "docs/contents/introduction/hello-world/hello-world.md",
    "chars": 18501,
    "preview": "### Hello, World!\n\nLet's start our journey into Layr by implementing the mandatory [\"Hello, World!\"](https://en.wikipedi"
  },
  {
    "path": "docs/contents/introduction/introduction.md",
    "chars": 8602,
    "preview": "### Introduction\n\n> **Note**: Layr v2 is published on NPM, but the documentation is still a work in progress.\n\n#### Over"
  },
  {
    "path": "docs/contents/introduction/storing-data.md",
    "chars": 859,
    "preview": "### Storing Data\n\n#### Coming Soon\n\nThis tutorial will expand the [\"Hello, World!\"](https://layrjs.com/docs/v2/introduct"
  },
  {
    "path": "docs/package.json",
    "chars": 392,
    "preview": "{\n  \"name\": \"@layr/docs\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"description\": \"Layr documentation\",\n  \"keywords\": "
  },
  {
    "path": "examples/v1/counter/README.md",
    "chars": 204,
    "preview": "# Counter\n\nA simple example to introduce the core concepts of Layr.\n\n## Usage\n\nInstall the npm dependencies with:\n\n```sh"
  },
  {
    "path": "examples/v1/counter/babel.config.json",
    "chars": 199,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}]],\n  \"plugins\": [\n    [\"@babel/plugin-proposal-decorat"
  },
  {
    "path": "examples/v1/counter/jsconfig.json",
    "chars": 136,
    "preview": "{\n  \"compilerOptions\": {\n  \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecorato"
  },
  {
    "path": "examples/v1/counter/package.json",
    "chars": 511,
    "preview": "{\n  \"name\": \"counter\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple example to introduce the core concepts of Layr\","
  },
  {
    "path": "examples/v1/counter/src/backend.js",
    "chars": 733,
    "preview": "import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';\nimport {ComponentServer} from '"
  },
  {
    "path": "examples/v1/counter/src/frontend.js",
    "chars": 679,
    "preview": "import {ComponentClient} from '@layr/component-client';\n\nimport {server} from './backend';\n\n// We create a client that i"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/README.md",
    "chars": 611,
    "preview": "# Counter with CreateReactApp (TS)\n\nA simple example to introduce the core concepts of Layr.\n\n## Install\n\nInstall the np"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/backend/package.json",
    "chars": 553,
    "preview": "{\n  \"name\": \"counter-with-create-react-app-ts-backend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vil"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/backend/src/components/counter.ts",
    "chars": 345,
    "preview": "import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';\n\nexport class Counter extends C"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/backend/src/http-server.ts",
    "chars": 186,
    "preview": "import {ComponentHTTPServer} from '@layr/component-http-server';\n\nimport {server} from './server';\n\nconst httpServer = n"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/backend/src/server.ts",
    "chars": 156,
    "preview": "import {ComponentServer} from '@layr/component-server';\n\nimport {Counter} from './components/counter';\n\nexport const ser"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/backend/tsconfig.json",
    "chars": 539,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/.gitignore",
    "chars": 310,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/package.json",
    "chars": 955,
    "preview": "{\n  \"name\": \"counter-with-create-react-app-ts-frontend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vi"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/public/index.html",
    "chars": 1721,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"%PUBLIC_URL%/favicon.i"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/public/manifest.json",
    "chars": 492,
    "preview": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n     "
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/public/robots.txt",
    "chars": 67,
    "preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/src/components/counter.tsx",
    "chars": 775,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport React from 'react';\nimport {view} from '@layr/re"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/src/index.tsx",
    "chars": 337,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport {getCounter} from './components/counter';\n\n(async ("
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/src/react-app-env.d.ts",
    "chars": 40,
    "preview": "/// <reference types=\"react-scripts\" />\n"
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/frontend/tsconfig.json",
    "chars": 527,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    "
  },
  {
    "path": "examples/v1/counter-with-create-react-app-ts/package.json",
    "chars": 560,
    "preview": "{\n  \"name\": \"counter-with-create-react-app-ts\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mv"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/README.md",
    "chars": 604,
    "preview": "# Counter with esbuild (TS)\n\nA simple example to introduce the core concepts of Layr.\n\n## Install\n\nInstall the npm depen"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/backend/package.json",
    "chars": 776,
    "preview": "{\n  \"name\": \"counter-with-esbuild-ts-backend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvi"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/backend/src/components/counter.ts",
    "chars": 345,
    "preview": "import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';\n\nexport class Counter extends C"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/backend/src/http-server.ts",
    "chars": 186,
    "preview": "import {ComponentHTTPServer} from '@layr/component-http-server';\n\nimport {server} from './server';\n\nconst httpServer = n"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/backend/src/server.ts",
    "chars": 156,
    "preview": "import {ComponentServer} from '@layr/component-server';\n\nimport {Counter} from './components/counter';\n\nexport const ser"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/backend/tsconfig.json",
    "chars": 568,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/frontend/package.json",
    "chars": 943,
    "preview": "{\n  \"name\": \"counter-with-esbuild-ts-frontend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mv"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/frontend/src/components/counter.tsx",
    "chars": 775,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport React from 'react';\nimport {view} from '@layr/re"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/frontend/src/index.html",
    "chars": 200,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>My Rollup Project</title>\n  </head>\n\n  <body>\n  "
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/frontend/src/index.tsx",
    "chars": 337,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport {getCounter} from './components/counter';\n\n(async ("
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/frontend/tsconfig.json",
    "chars": 568,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-esbuild-ts/package.json",
    "chars": 550,
    "preview": "{\n  \"name\": \"counter-with-rollup-ts\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvila.me>\",\n"
  },
  {
    "path": "examples/v1/counter-with-http/README.md",
    "chars": 308,
    "preview": "# Counter with HTTP\n\nA simple example to introduce the core concepts of Layr.\n\n## Usage\n\nInstall the npm dependencies wi"
  },
  {
    "path": "examples/v1/counter-with-http/babel.config.json",
    "chars": 199,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}]],\n  \"plugins\": [\n    [\"@babel/plugin-proposal-decorat"
  },
  {
    "path": "examples/v1/counter-with-http/jsconfig.json",
    "chars": 138,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecora"
  },
  {
    "path": "examples/v1/counter-with-http/package.json",
    "chars": 531,
    "preview": "{\n  \"name\": \"counter-with-http\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple example to introduce the core concepts"
  },
  {
    "path": "examples/v1/counter-with-http/src/backend.js",
    "chars": 773,
    "preview": "import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';\nimport {ComponentHTTPServer} fr"
  },
  {
    "path": "examples/v1/counter-with-http/src/frontend.js",
    "chars": 747,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\n\n(async () => {\n  // We create a client that is connect"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/README.md",
    "chars": 603,
    "preview": "# Counter with Parcel (TS)\n\nA simple example to introduce the core concepts of Layr.\n\n## Install\n\nInstall the npm depend"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/backend/package.json",
    "chars": 544,
    "preview": "{\n  \"name\": \"counter-with-parcel-ts-backend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvil"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/backend/src/components/counter.ts",
    "chars": 345,
    "preview": "import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';\n\nexport class Counter extends C"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/backend/src/http-server.ts",
    "chars": 186,
    "preview": "import {ComponentHTTPServer} from '@layr/component-http-server';\n\nimport {server} from './server';\n\nconst httpServer = n"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/backend/src/server.ts",
    "chars": 156,
    "preview": "import {ComponentServer} from '@layr/component-server';\n\nimport {Counter} from './components/counter';\n\nexport const ser"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/backend/tsconfig.json",
    "chars": 539,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/.gitignore",
    "chars": 15,
    "preview": "/.parcel-cache\n"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/babel.config.js",
    "chars": 478,
    "preview": "module.exports = (api) => {\n  api.cache(true);\n\n  const presets = [\n    ['@babel/preset-typescript'],\n    [\n      '@babe"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/package.json",
    "chars": 792,
    "preview": "{\n  \"name\": \"counter-with-parcel-ts-frontend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvi"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/src/components/counter.tsx",
    "chars": 775,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport React from 'react';\nimport {view} from '@layr/re"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/src/index.html",
    "chars": 202,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>My Parcel Project</title>\n  </head>\n\n  <body>\n  "
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/src/index.tsx",
    "chars": 337,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport {getCounter} from './components/counter';\n\n(async ("
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/frontend/tsconfig.json",
    "chars": 539,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-parcel-ts/package.json",
    "chars": 550,
    "preview": "{\n  \"name\": \"counter-with-parcel-ts\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvila.me>\",\n"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/README.md",
    "chars": 603,
    "preview": "# Counter with Rollup (TS)\n\nA simple example to introduce the core concepts of Layr.\n\n## Install\n\nInstall the npm depend"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/backend/package.json",
    "chars": 544,
    "preview": "{\n  \"name\": \"counter-with-rollup-ts-backend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvil"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/backend/src/components/counter.ts",
    "chars": 345,
    "preview": "import {Component, primaryIdentifier, attribute, method, expose} from '@layr/component';\n\nexport class Counter extends C"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/backend/src/http-server.ts",
    "chars": 186,
    "preview": "import {ComponentHTTPServer} from '@layr/component-http-server';\n\nimport {server} from './server';\n\nconst httpServer = n"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/backend/src/server.ts",
    "chars": 156,
    "preview": "import {ComponentServer} from '@layr/component-server';\n\nimport {Counter} from './components/counter';\n\nexport const ser"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/backend/tsconfig.json",
    "chars": 539,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/babel.config.js",
    "chars": 478,
    "preview": "module.exports = (api) => {\n  api.cache(true);\n\n  const presets = [\n    ['@babel/preset-typescript'],\n    [\n      '@babe"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/package.json",
    "chars": 1275,
    "preview": "{\n  \"name\": \"counter-with-rollup-ts-frontend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvi"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/rollup.config.js",
    "chars": 528,
    "preview": "import resolve from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport babel from '@r"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/src/components/counter.tsx",
    "chars": 775,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport React from 'react';\nimport {view} from '@layr/re"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/src/index.html",
    "chars": 200,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>My Rollup Project</title>\n  </head>\n\n  <body>\n  "
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/src/index.tsx",
    "chars": 337,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport {getCounter} from './components/counter';\n\n(async ("
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/frontend/tsconfig.json",
    "chars": 539,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/counter-with-rollup-ts/package.json",
    "chars": 550,
    "preview": "{\n  \"name\": \"counter-with-rollup-ts\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"author\": \"Manuel Vila <hi@mvila.me>\",\n"
  },
  {
    "path": "examples/v1/guestbook-cli-js/README.md",
    "chars": 174,
    "preview": "# Guestbook CLI (JS)\n\nA simple CLI app to introduce data storage with Layr.\n\nSee the [corresponding guide](https://layrj"
  },
  {
    "path": "examples/v1/guestbook-cli-js/babel.config.json",
    "chars": 199,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}]],\n  \"plugins\": [\n    [\"@babel/plugin-proposal-decorat"
  },
  {
    "path": "examples/v1/guestbook-cli-js/jsconfig.json",
    "chars": 138,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecora"
  },
  {
    "path": "examples/v1/guestbook-cli-js/package.json",
    "chars": 592,
    "preview": "{\n  \"name\": \"guestbook-cli\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple CLI app to introduce data storage with Lay"
  },
  {
    "path": "examples/v1/guestbook-cli-js/src/backend.js",
    "chars": 835,
    "preview": "import {Component, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} from '@la"
  },
  {
    "path": "examples/v1/guestbook-cli-js/src/frontend.js",
    "chars": 832,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport {Storable} from '@layr/storable';\n\n(async () => "
  },
  {
    "path": "examples/v1/guestbook-cli-ts/README.md",
    "chars": 174,
    "preview": "# Guestbook CLI (TS)\n\nA simple CLI app to introduce data storage with Layr.\n\nSee the [corresponding guide](https://layrj"
  },
  {
    "path": "examples/v1/guestbook-cli-ts/package.json",
    "chars": 440,
    "preview": "{\n  \"name\": \"guestbook-cli\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple CLI app to introduce data storage with Lay"
  },
  {
    "path": "examples/v1/guestbook-cli-ts/src/backend.ts",
    "chars": 844,
    "preview": "import {Component, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} from '@la"
  },
  {
    "path": "examples/v1/guestbook-cli-ts/src/frontend.ts",
    "chars": 920,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport {Storable} from '@layr/storable';\n\nimport type {"
  },
  {
    "path": "examples/v1/guestbook-cli-ts/tsconfig.json",
    "chars": 434,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/guestbook-web-js/README.md",
    "chars": 179,
    "preview": "# Guestbook Web (JS)\n\nA simple web app showing how to build a web frontend with Layr.\n\nSee the [corresponding guide](htt"
  },
  {
    "path": "examples/v1/guestbook-web-js/babel.config.json",
    "chars": 222,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}], \"@babel/preset-react\"],\n  \"plugins\": [\n    [\"@babel/"
  },
  {
    "path": "examples/v1/guestbook-web-js/jsconfig.json",
    "chars": 138,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecora"
  },
  {
    "path": "examples/v1/guestbook-web-js/package.json",
    "chars": 895,
    "preview": "{\n  \"name\": \"guestbook-web\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple web app showing how to build a web fronten"
  },
  {
    "path": "examples/v1/guestbook-web-js/src/backend.js",
    "chars": 835,
    "preview": "import {Component, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} from '@la"
  },
  {
    "path": "examples/v1/guestbook-web-js/src/frontend.js",
    "chars": 3581,
    "preview": "import React, {useCallback} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Component, attribute, provide} from "
  },
  {
    "path": "examples/v1/guestbook-web-js/src/index.html",
    "chars": 468,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Guestbook</title>\n    <meta name=\"view"
  },
  {
    "path": "examples/v1/guestbook-web-js/webpack.config.js",
    "chars": 1152,
    "preview": "const webpack = require('webpack');\nconst HtmlWebPackPlugin = require('html-webpack-plugin');\nconst path = require('path"
  },
  {
    "path": "examples/v1/guestbook-web-ts/README.md",
    "chars": 179,
    "preview": "# Guestbook Web (TS)\n\nA simple web app showing how to build a web frontend with Layr.\n\nSee the [corresponding guide](htt"
  },
  {
    "path": "examples/v1/guestbook-web-ts/package.json",
    "chars": 769,
    "preview": "{\n  \"name\": \"guestbook-web\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple web app showing how to build a web fronten"
  },
  {
    "path": "examples/v1/guestbook-web-ts/src/backend.ts",
    "chars": 844,
    "preview": "import {Component, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} from '@la"
  },
  {
    "path": "examples/v1/guestbook-web-ts/src/frontend.tsx",
    "chars": 3715,
    "preview": "import React, {useCallback} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Component, attribute, provide} from "
  },
  {
    "path": "examples/v1/guestbook-web-ts/src/index.html",
    "chars": 468,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Guestbook</title>\n    <meta name=\"view"
  },
  {
    "path": "examples/v1/guestbook-web-ts/tsconfig.json",
    "chars": 454,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/guestbook-web-ts/webpack.config.js",
    "chars": 1150,
    "preview": "const webpack = require('webpack');\nconst HtmlWebPackPlugin = require('html-webpack-plugin');\nconst path = require('path"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/README.md",
    "chars": 223,
    "preview": "# Guestbook Web With Authorization (JS)\n\nA simple web app showing how to build a web frontend with authorization with La"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/babel.config.json",
    "chars": 222,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}], \"@babel/preset-react\"],\n  \"plugins\": [\n    [\"@babel/"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/jsconfig.json",
    "chars": 138,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecora"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/package.json",
    "chars": 999,
    "preview": "{\n  \"name\": \"guestbook-web-with-authorization\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple web app showing how to "
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/src/backend.js",
    "chars": 1316,
    "preview": "import {Component, provide, consume, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, at"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/src/frontend.js",
    "chars": 5512,
    "preview": "import React, {useCallback} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Component, attribute, provide} from "
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/src/index.html",
    "chars": 468,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Guestbook</title>\n    <meta name=\"view"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-js/webpack.config.js",
    "chars": 1152,
    "preview": "const webpack = require('webpack');\nconst HtmlWebPackPlugin = require('html-webpack-plugin');\nconst path = require('path"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/README.md",
    "chars": 223,
    "preview": "# Guestbook Web With Authorization (TS)\n\nA simple web app showing how to build a web frontend with authorization with La"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/package.json",
    "chars": 873,
    "preview": "{\n  \"name\": \"guestbook-web-with-authorization\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple web app showing how to "
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/src/backend.ts",
    "chars": 1325,
    "preview": "import {Component, provide, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} "
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/src/frontend.tsx",
    "chars": 5640,
    "preview": "import React, {useCallback} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Component, provide, attribute} from "
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/src/index.html",
    "chars": 468,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Guestbook</title>\n    <meta name=\"view"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/tsconfig.json",
    "chars": 454,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/guestbook-web-with-authorization-ts/webpack.config.js",
    "chars": 1150,
    "preview": "const webpack = require('webpack');\nconst HtmlWebPackPlugin = require('html-webpack-plugin');\nconst path = require('path"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/README.md",
    "chars": 204,
    "preview": "# Guestbook Web With Routes (JS)\n\nA simple web app showing how to build a web frontend using routes with Layr.\n\nSee the "
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/babel.config.json",
    "chars": 222,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}], \"@babel/preset-react\"],\n  \"plugins\": [\n    [\"@babel/"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/jsconfig.json",
    "chars": 138,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecora"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/package.json",
    "chars": 952,
    "preview": "{\n  \"name\": \"guestbook-web-with-routes\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple web app showing how to build a"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/src/backend.js",
    "chars": 835,
    "preview": "import {Component, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} from '@la"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/src/frontend.js",
    "chars": 5200,
    "preview": "import React, {useCallback} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Component, attribute, provide} from "
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/src/index.html",
    "chars": 468,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Guestbook</title>\n    <meta name=\"view"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-js/webpack.config.js",
    "chars": 1152,
    "preview": "const webpack = require('webpack');\nconst HtmlWebPackPlugin = require('html-webpack-plugin');\nconst path = require('path"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/README.md",
    "chars": 204,
    "preview": "# Guestbook Web With Routes (TS)\n\nA simple web app showing how to build a web frontend using routes with Layr.\n\nSee the "
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/package.json",
    "chars": 826,
    "preview": "{\n  \"name\": \"guestbook-web-with-routes\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A simple web app showing how to build a"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/src/backend.ts",
    "chars": 844,
    "preview": "import {Component, expose, validators} from '@layr/component';\nimport {Storable, primaryIdentifier, attribute} from '@la"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/src/frontend.tsx",
    "chars": 5319,
    "preview": "import React, {useCallback} from 'react';\nimport ReactDOM from 'react-dom';\nimport {Component, attribute, provide} from "
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/src/index.html",
    "chars": 468,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Guestbook</title>\n    <meta name=\"view"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/tsconfig.json",
    "chars": 454,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v1/guestbook-web-with-routes-ts/webpack.config.js",
    "chars": 1150,
    "preview": "const webpack = require('webpack');\nconst HtmlWebPackPlugin = require('html-webpack-plugin');\nconst path = require('path"
  },
  {
    "path": "examples/v1/hello-world-js/README.md",
    "chars": 186,
    "preview": "# Hello, World! (JS)\n\nAn \"Hello, World!\" program to introduce the core concepts of Layr.\n\nSee the [corresponding guide]("
  },
  {
    "path": "examples/v1/hello-world-js/babel.config.json",
    "chars": 199,
    "preview": "{\n  \"presets\": [[\"@babel/preset-env\", {\"targets\": {\"node\": \"10\"}}]],\n  \"plugins\": [\n    [\"@babel/plugin-proposal-decorat"
  },
  {
    "path": "examples/v1/hello-world-js/jsconfig.json",
    "chars": 138,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"checkJs\": false,\n    \"experimentalDecora"
  },
  {
    "path": "examples/v1/hello-world-js/package.json",
    "chars": 541,
    "preview": "{\n  \"name\": \"hello-world-js\",\n  \"version\": \"1.0.0\",\n  \"description\": \"An \\\"Hello, World!\\\" program to introduce the core"
  },
  {
    "path": "examples/v1/hello-world-js/src/backend.js",
    "chars": 410,
    "preview": "import {Component, attribute, method, expose} from '@layr/component';\nimport {ComponentHTTPServer} from '@layr/component"
  },
  {
    "path": "examples/v1/hello-world-js/src/frontend.js",
    "chars": 419,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\n\n(async () => {\n  const client = new ComponentHTTPClien"
  },
  {
    "path": "examples/v1/hello-world-ts/README.md",
    "chars": 186,
    "preview": "# Hello, World! (TS)\n\nAn \"Hello, World!\" program to introduce the core concepts of Layr.\n\nSee the [corresponding guide]("
  },
  {
    "path": "examples/v1/hello-world-ts/package.json",
    "chars": 386,
    "preview": "{\n  \"name\": \"hello-world\",\n  \"version\": \"1.0.0\",\n  \"description\": \"An \\\"Hello, World!\\\" program to introduce the core co"
  },
  {
    "path": "examples/v1/hello-world-ts/src/backend.ts",
    "chars": 410,
    "preview": "import {Component, attribute, method, expose} from '@layr/component';\nimport {ComponentHTTPServer} from '@layr/component"
  },
  {
    "path": "examples/v1/hello-world-ts/src/frontend.ts",
    "chars": 499,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\n\nimport type {Greeter as GreeterType} from './backend';"
  },
  {
    "path": "examples/v1/hello-world-ts/tsconfig.json",
    "chars": 427,
    "preview": "{\n  \"include\": [\"src/**/*\"],\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ESNex"
  },
  {
    "path": "examples/v2/hello-world-js/.editorconfig",
    "chars": 207,
    "preview": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_"
  },
  {
    "path": "examples/v2/hello-world-js/.gitignore",
    "chars": 61,
    "preview": ".DS_Store\n*.log\nnode_modules\ndist\nbuild\n_private\n*.private.*\n"
  },
  {
    "path": "examples/v2/hello-world-js/.prettierignore",
    "chars": 24,
    "preview": "node_modules\ndist\nbuild\n"
  },
  {
    "path": "examples/v2/hello-world-js/.vscode/extensions.json",
    "chars": 93,
    "preview": "{\n  \"recommendations\": [\n    \"esbenp.prettier-vscode\",\n    \"editorconfig.editorconfig\"\n  ]\n}\n"
  },
  {
    "path": "examples/v2/hello-world-js/.vscode/settings.json",
    "chars": 626,
    "preview": "{\n  \"editor.formatOnSave\": true,\n  \"editor.tabSize\": 2,\n  \"editor.wordWrap\": \"bounded\",\n  \"editor.wordWrapColumn\": 100,\n"
  },
  {
    "path": "examples/v2/hello-world-js/README.md",
    "chars": 1838,
    "preview": "# hello-world-js\n\n## Prerequisites\n\n- Make sure you have [Node.js](https://nodejs.org/) v16 or newer installed.\n- Make s"
  },
  {
    "path": "examples/v2/hello-world-js/backend/boostr.config.mjs",
    "chars": 763,
    "preview": "export default ({services}) => ({\n  type: 'backend',\n\n  dependsOn: 'database',\n\n  environment: {\n    FRONTEND_URL: servi"
  },
  {
    "path": "examples/v2/hello-world-js/backend/boostr.config.private-example.mjs",
    "chars": 563,
    "preview": "/**\n * This is an example of a private Boostr configuration file allowing you to\n * override the `boostr.config.mjs` pub"
  },
  {
    "path": "examples/v2/hello-world-js/backend/jsconfig.json",
    "chars": 66,
    "preview": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true\n  }\n}\n"
  },
  {
    "path": "examples/v2/hello-world-js/backend/package.json",
    "chars": 206,
    "preview": "{\n  \"name\": \"hello-world-js-backend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@layr/component\""
  },
  {
    "path": "examples/v2/hello-world-js/backend/src/components/application.js",
    "chars": 373,
    "preview": "import {Component, method, expose} from '@layr/component';\n\nexport class Application extends Component {\n  @expose({call"
  },
  {
    "path": "examples/v2/hello-world-js/backend/src/index.js",
    "chars": 260,
    "preview": "import {MongoDBStore} from '@layr/mongodb-store';\n\nimport {Application} from './components/application';\n\nexport default"
  },
  {
    "path": "examples/v2/hello-world-js/boostr.config.mjs",
    "chars": 452,
    "preview": "export default () => ({\n  type: 'application',\n\n  services: {\n    frontend: './frontend',\n    backend: './backend',\n    "
  },
  {
    "path": "examples/v2/hello-world-js/database/.gitignore",
    "chars": 6,
    "preview": "/data\n"
  },
  {
    "path": "examples/v2/hello-world-js/database/boostr.config.mjs",
    "chars": 158,
    "preview": "export default () => ({\n  type: 'database',\n\n  stages: {\n    development: {\n      url: 'mongodb://localhost:16191/dev',\n"
  },
  {
    "path": "examples/v2/hello-world-js/database/boostr.config.private-example.mjs",
    "chars": 568,
    "preview": "/**\n * This is an example of a private Boostr configuration file allowing you to\n * override the `boostr.config.mjs` pub"
  },
  {
    "path": "examples/v2/hello-world-js/frontend/boostr.config.mjs",
    "chars": 1235,
    "preview": "export default ({services}) => ({\n  type: 'web-frontend',\n\n  dependsOn: 'backend',\n\n  environment: {\n    FRONTEND_URL: s"
  },
  {
    "path": "examples/v2/hello-world-js/frontend/jsconfig.json",
    "chars": 66,
    "preview": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true\n  }\n}\n"
  },
  {
    "path": "examples/v2/hello-world-js/frontend/package.json",
    "chars": 340,
    "preview": "{\n  \"name\": \"hello-world-js-frontend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@layr/component"
  },
  {
    "path": "examples/v2/hello-world-js/frontend/src/components/application.jsx",
    "chars": 1039,
    "preview": "import {Routable} from '@layr/routable';\nimport React from 'react';\nimport {layout, page, useData} from '@layr/react-int"
  },
  {
    "path": "examples/v2/hello-world-js/frontend/src/index.js",
    "chars": 575,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport {Storable} from '@layr/storable';\n\nimport {exten"
  },
  {
    "path": "examples/v2/hello-world-js/package.json",
    "chars": 221,
    "preview": "{\n  \"name\": \"hello-world-js\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"prettier\": \"@boostr/prettierrc\",\n  \"devDepende"
  },
  {
    "path": "examples/v2/hello-world-ts/.editorconfig",
    "chars": 207,
    "preview": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_"
  },
  {
    "path": "examples/v2/hello-world-ts/.gitignore",
    "chars": 61,
    "preview": ".DS_Store\n*.log\nnode_modules\ndist\nbuild\n_private\n*.private.*\n"
  },
  {
    "path": "examples/v2/hello-world-ts/.prettierignore",
    "chars": 24,
    "preview": "node_modules\ndist\nbuild\n"
  },
  {
    "path": "examples/v2/hello-world-ts/.vscode/extensions.json",
    "chars": 93,
    "preview": "{\n  \"recommendations\": [\n    \"esbenp.prettier-vscode\",\n    \"editorconfig.editorconfig\"\n  ]\n}\n"
  },
  {
    "path": "examples/v2/hello-world-ts/.vscode/settings.json",
    "chars": 626,
    "preview": "{\n  \"editor.formatOnSave\": true,\n  \"editor.tabSize\": 2,\n  \"editor.wordWrap\": \"bounded\",\n  \"editor.wordWrapColumn\": 100,\n"
  },
  {
    "path": "examples/v2/hello-world-ts/README.md",
    "chars": 1838,
    "preview": "# hello-world-ts\n\n## Prerequisites\n\n- Make sure you have [Node.js](https://nodejs.org/) v16 or newer installed.\n- Make s"
  },
  {
    "path": "examples/v2/hello-world-ts/backend/boostr.config.mjs",
    "chars": 763,
    "preview": "export default ({services}) => ({\n  type: 'backend',\n\n  dependsOn: 'database',\n\n  environment: {\n    FRONTEND_URL: servi"
  },
  {
    "path": "examples/v2/hello-world-ts/backend/boostr.config.private-example.mjs",
    "chars": 563,
    "preview": "/**\n * This is an example of a private Boostr configuration file allowing you to\n * override the `boostr.config.mjs` pub"
  },
  {
    "path": "examples/v2/hello-world-ts/backend/package.json",
    "chars": 297,
    "preview": "{\n  \"name\": \"hello-world-ts-backend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@layr/component\""
  },
  {
    "path": "examples/v2/hello-world-ts/backend/src/components/application.ts",
    "chars": 373,
    "preview": "import {Component, method, expose} from '@layr/component';\n\nexport class Application extends Component {\n  @expose({call"
  },
  {
    "path": "examples/v2/hello-world-ts/backend/src/index.ts",
    "chars": 261,
    "preview": "import {MongoDBStore} from '@layr/mongodb-store';\n\nimport {Application} from './components/application';\n\nexport default"
  },
  {
    "path": "examples/v2/hello-world-ts/backend/tsconfig.json",
    "chars": 63,
    "preview": "{\n  \"extends\": \"@boostr/tsconfig\",\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "examples/v2/hello-world-ts/boostr.config.mjs",
    "chars": 452,
    "preview": "export default () => ({\n  type: 'application',\n\n  services: {\n    frontend: './frontend',\n    backend: './backend',\n    "
  },
  {
    "path": "examples/v2/hello-world-ts/database/.gitignore",
    "chars": 6,
    "preview": "/data\n"
  },
  {
    "path": "examples/v2/hello-world-ts/database/boostr.config.mjs",
    "chars": 158,
    "preview": "export default () => ({\n  type: 'database',\n\n  stages: {\n    development: {\n      url: 'mongodb://localhost:14953/dev',\n"
  },
  {
    "path": "examples/v2/hello-world-ts/database/boostr.config.private-example.mjs",
    "chars": 568,
    "preview": "/**\n * This is an example of a private Boostr configuration file allowing you to\n * override the `boostr.config.mjs` pub"
  },
  {
    "path": "examples/v2/hello-world-ts/frontend/boostr.config.mjs",
    "chars": 1235,
    "preview": "export default ({services}) => ({\n  type: 'web-frontend',\n\n  dependsOn: 'backend',\n\n  environment: {\n    FRONTEND_URL: s"
  },
  {
    "path": "examples/v2/hello-world-ts/frontend/package.json",
    "chars": 497,
    "preview": "{\n  \"name\": \"hello-world-ts-frontend\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@layr/component"
  },
  {
    "path": "examples/v2/hello-world-ts/frontend/src/components/application.tsx",
    "chars": 1386,
    "preview": "import {Routable} from '@layr/routable';\nimport React, {Fragment} from 'react';\nimport {layout, page, useData} from '@la"
  },
  {
    "path": "examples/v2/hello-world-ts/frontend/src/index.ts",
    "chars": 704,
    "preview": "import {ComponentHTTPClient} from '@layr/component-http-client';\nimport {Storable} from '@layr/storable';\n\nimport type {"
  },
  {
    "path": "examples/v2/hello-world-ts/frontend/tsconfig.json",
    "chars": 63,
    "preview": "{\n  \"extends\": \"@boostr/tsconfig\",\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "examples/v2/hello-world-ts/package.json",
    "chars": 221,
    "preview": "{\n  \"name\": \"hello-world-ts\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"prettier\": \"@boostr/prettierrc\",\n  \"devDepende"
  }
]

// ... and 376 more files (download for full content)

About this extraction

This page contains the full source code of the liaisonjs/liaison GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 576 files (2.3 MB), approximately 644.0k tokens, and a symbol index with 1694 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!