chore: dox++
This commit is contained in:
parent
935e0a0054
commit
fc83c21bb6
4
TODO.md
4
TODO.md
|
@ -21,7 +21,7 @@
|
||||||
- [x] Rename all hooks to dot-first notation; rewrite `lookupFlecks()`.
|
- [x] Rename all hooks to dot-first notation; rewrite `lookupFlecks()`.
|
||||||
- [x] ensureUniqueReduction moved into invokeMerge
|
- [x] ensureUniqueReduction moved into invokeMerge
|
||||||
- [x] `bootstrap({without: ['badplatform']})` should be handled by passing `{platforms: ['!badplatform']}`
|
- [x] `bootstrap({without: ['badplatform']})` should be handled by passing `{platforms: ['!badplatform']}`
|
||||||
- [ ] static documentation site generator
|
- [x] documentation site generator
|
||||||
- [ ] config validation
|
- [ ] config validation
|
||||||
- [ ] hints for hook types
|
- [ ] hints for hook types
|
||||||
- [ ] user redux server hydrate fails if no user in req
|
- [ ] user redux server hydrate fails if no user in req
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
- [ ] @babel/register@7.18.x has a bug
|
- [ ] @babel/register@7.18.x has a bug
|
||||||
- [ ] `$flecks/db/sequelize` should be `$flecks/db.sequelize`
|
- [ ] `$flecks/db/sequelize` should be `$flecks/db.sequelize`
|
||||||
- [x] `url()` in styles breaks HMR
|
- [x] `url()` in styles breaks HMR
|
||||||
- [ ] 2 underscores for `FLECKS_ENV` variables
|
- [x] 2 underscores for `FLECKS_ENV` variables
|
||||||
- [x] flecks add
|
- [x] flecks add
|
||||||
|
|
||||||
# Next
|
# Next
|
||||||
|
|
|
@ -39,9 +39,7 @@ const {
|
||||||
throw new Error(`@flecks/create-app: invalid app name: ${errors.join(', ')}`);
|
throw new Error(`@flecks/create-app: invalid app name: ${errors.join(', ')}`);
|
||||||
}
|
}
|
||||||
const destination = join(FLECKS_CORE_ROOT, app);
|
const destination = join(FLECKS_CORE_ROOT, app);
|
||||||
if (!app.startsWith('@')) {
|
const name = app.startsWith('@') ? app : `@${app}/monorepo`;
|
||||||
app = `@${app}/monorepo`;
|
|
||||||
}
|
|
||||||
if (!await testDestination(destination)) {
|
if (!await testDestination(destination)) {
|
||||||
const error = new Error(
|
const error = new Error(
|
||||||
`@flecks/create-app: destination '${destination} already exists: aborting`,
|
`@flecks/create-app: destination '${destination} already exists: aborting`,
|
||||||
|
@ -49,13 +47,16 @@ const {
|
||||||
error.code = 129;
|
error.code = 129;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const fileTree = await move(app, join(__dirname, 'template'), 'app', flecks);
|
const fileTree = await move(name, join(__dirname, 'template'), 'app', flecks);
|
||||||
fileTree.pipe(
|
fileTree.pipe(
|
||||||
'build/flecks.yml',
|
'build/flecks.yml',
|
||||||
transform((chunk, encoding, done, stream) => {
|
transform((chunk, encoding, done, stream) => {
|
||||||
const yml = loadYml(chunk);
|
const yml = loadYml(chunk);
|
||||||
yml['@flecks/core/server'] = {packageManager};
|
if ('npm' !== packageManager) {
|
||||||
stream.push(dumpYml(yml, {sortKeys: true}));
|
yml['@flecks/core/server'] = {packageManager};
|
||||||
|
}
|
||||||
|
yml['@flecks/core'] = {id: app};
|
||||||
|
stream.push(dumpYml(yml, {forceQuotes: true, sortKeys: true}));
|
||||||
done();
|
done();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -67,6 +68,6 @@ const {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await program.parseAsync(process.argv);
|
await program.parseAsync(process.argv);
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
"@babel/types": "^7.17.0",
|
"@babel/types": "^7.17.0",
|
||||||
"@flecks/core": "^2.0.3",
|
"@flecks/core": "^2.0.3",
|
||||||
"@webpack-cli/serve": "^2.0.5",
|
"@webpack-cli/serve": "^2.0.5",
|
||||||
"add-asset-html-webpack-plugin": "^6.0.0",
|
"add-asset-html-webpack-plugin": "^3.2.2",
|
||||||
"assert": "^2.1.0",
|
"assert": "^2.1.0",
|
||||||
"autoprefixer": "^9.8.6",
|
"autoprefixer": "^9.8.6",
|
||||||
"before-build-webpack": "^0.2.13",
|
"before-build-webpack": "^0.2.13",
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: Adding a fleck
|
|
||||||
description: Add a fleck to your application to extend its functionality.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Adding a fleck
|
|
||||||
|
|
||||||
`@flecks/web` is a fleck that builds and serves a webpage. You can add it to your application
|
|
||||||
using flecks:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx flecks add @flecks/web
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, if you run `npm start`, you'll see a line in the output:
|
|
||||||
|
|
||||||
```
|
|
||||||
@flecks/web/server/http HTTP server up @ 0.0.0.0:32340!
|
|
||||||
```
|
|
||||||
|
|
||||||
## Finally... a white page?
|
|
||||||
|
|
||||||
If you visit `localhost:32340` in your browser, you should now see... a blank white page! Don't fret
|
|
||||||
though; if you open the devtools in your browser, you will see a little messaging from your
|
|
||||||
application that will look something like:
|
|
||||||
|
|
||||||
```
|
|
||||||
[webpack-dev-server] Server started: Hot Module Replacement enabled, Live Reloading enabled, Progress disabled, Overlay enabled.
|
|
||||||
[HMR] Waiting for update signal from WDS...
|
|
||||||
flecks client v2.0.3 loading runtime...
|
|
||||||
```
|
|
||||||
|
|
||||||
This is a good sign! This means we successfully added a web server with HMR enabled by default.
|
|
||||||
Oh, the possibilities...
|
|
||||||
|
|
||||||
## Proceed with the hooking
|
|
||||||
|
|
||||||
How does flecks know to start the web server when the application starts? Great question! This is
|
|
||||||
accomplished through the use of hooks. You'll see how to configure that hook in the next section.
|
|
||||||
|
|
||||||
For now, we'll learn how to create our own fleck and do a little hooking of our own. Take that, dad!
|
|
115
website/docs/adding-flecks.mdx
Normal file
115
website/docs/adding-flecks.mdx
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
---
|
||||||
|
title: Adding flecks
|
||||||
|
description: Add flecks to your application to extend its functionality.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Adding flecks
|
||||||
|
|
||||||
|
`@flecks/web` is a fleck that builds and serves a webpage. You can add it to your application
|
||||||
|
using the CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx flecks add @flecks/web
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, if you run `npm start`, you'll see a line in the output:
|
||||||
|
|
||||||
|
```
|
||||||
|
@flecks/web/server/http HTTP server up @ 0.0.0.0:32340!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Finally... a white page?
|
||||||
|
|
||||||
|
If you visit `localhost:32340` in your browser, you should now see... a blank white page! Don't fret
|
||||||
|
though; if you open the devtools in your browser, you will see a little messaging from your
|
||||||
|
application that will look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
[webpack-dev-server] Server started: Hot Module Replacement enabled, Live Reloading enabled, Progress disabled, Overlay enabled.
|
||||||
|
[HMR] Waiting for update signal from WDS...
|
||||||
|
flecks client v2.0.3 loading runtime...
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a good sign! This means we successfully added a web server with HMR enabled by default.
|
||||||
|
Oh, the possibilities...
|
||||||
|
|
||||||
|
## Proceed with the hooking
|
||||||
|
|
||||||
|
Let's make our fleck `say-hello` hook into `@flecks/web` client to do something when the client
|
||||||
|
comes up (e.g. the browser loads the page).
|
||||||
|
|
||||||
|
```javascript title="packages/say-hello/src/index.js"
|
||||||
|
export const hooks = {
|
||||||
|
// highlight-start
|
||||||
|
'@flecks/web/client.up': async () => {
|
||||||
|
window.document.body.append('hello world');
|
||||||
|
},
|
||||||
|
// highlight-end
|
||||||
|
'@flecks/server.up': async (flecks) => {
|
||||||
|
const {id} = flecks.get('@flecks/core');
|
||||||
|
process.stdout.write(` hello server: ID ${id}\n`);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, restart your application and refresh your website. Glorious, isn't it?
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Everything so far... plus Electron!
|
||||||
|
|
||||||
|
Let's add another core fleck. flecks ships with a core fleck `@flecks/electron`. This runs your
|
||||||
|
application inside of an instance of [Electron](https://www.electronjs.org/). You'll add the fleck:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx flecks add @flecks/electron
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you'll update your `build/flecks.yml` like so:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
'@flecks/core':
|
||||||
|
id: 'hello-world'
|
||||||
|
'@flecks/electron': {}
|
||||||
|
// highlight-start
|
||||||
|
'@flecks/server':
|
||||||
|
up:
|
||||||
|
- '...'
|
||||||
|
- '@flecks/web'
|
||||||
|
- '@flecks/electron'
|
||||||
|
// highlight-end
|
||||||
|
'@flecks/web': {}
|
||||||
|
'@hello-world/say-hello:./packages/say-hello/src': {}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ~~flecking~~ pecking order
|
||||||
|
|
||||||
|
We added some configuration to `@flecks/server`. The `up` key configures the order in which flecks
|
||||||
|
are initialized when the server comes up. We make sure `@flecks/web` serves a webpage before
|
||||||
|
`@flecks/electron` tries to visit it.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
|
||||||
|
`'...'` just means "everything else": if any other flecks implement that hook then they will run
|
||||||
|
here in an **undefined** order. It is valid to provide entries both before and after `'...'`, but
|
||||||
|
`'...'` must only appear one time per list.
|
||||||
|
|
||||||
|
The default configuration of
|
||||||
|
`@flecks/server.up` is simply:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
'@flecks/server':
|
||||||
|
up:
|
||||||
|
- '...'
|
||||||
|
```
|
||||||
|
|
||||||
|
However in this case the order of hook execution is undefined. That's why we configure it
|
||||||
|
explicitly.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Finally `npm start` and you will see something like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Isn't it beautiful? :relieved:
|
|
@ -5,8 +5,8 @@ description: Configure `build/flecks.yml` and your application.
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
You have a flecks application! ...but it doesn't do much. This is because a flecks application is
|
You have a flecks application! ...but it doesn't do much. By default, your application will have
|
||||||
composed of individual flecks and by default, your application will have only two flecks:
|
only two flecks:
|
||||||
`@flecks/core` and `@flecks/server`. Your `build/flecks.yml` file will look like this:
|
`@flecks/core` and `@flecks/server`. Your `build/flecks.yml` file will look like this:
|
||||||
|
|
||||||
```yml title="build/flecks.yml"
|
```yml title="build/flecks.yml"
|
||||||
|
@ -20,24 +20,22 @@ For a deep dive of configurable core flecks, see
|
||||||
|
|
||||||
## `build/flecks.yml`
|
## `build/flecks.yml`
|
||||||
|
|
||||||
A good first configuration step is to set the ID of your application.
|
Your flecks application stores its build configuration in a directory located at `build`. By
|
||||||
|
default, there is a single file located there: `flecks.yml`. This is where all the individual
|
||||||
|
flecks are configured.
|
||||||
|
|
||||||
Your application's ID is configured at the `id` key of `@flecks/core`'s configuration. To set your
|
Your application's ID is configured at the `id` key of `@flecks/core`'s configuration:
|
||||||
application's ID to `hello_world`, update your `build/flecks.yml` to look like this:
|
|
||||||
|
|
||||||
```yml title="build/flecks.yml"
|
```yml title="build/flecks.yml"
|
||||||
// highlight-start
|
// highlight-start
|
||||||
'@flecks/core':
|
'@flecks/core':
|
||||||
id: 'hello_world'
|
id: 'hello-world'
|
||||||
// highlight-end
|
// highlight-end
|
||||||
'@flecks/server': {}
|
'@flecks/server': {}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Adding more
|
Notice that the ID was set automatically by the app creation utility.
|
||||||
|
|
||||||
If you were studious enough to take a peek at [the generated configuration page](/docs/flecks/@flecks/dox/config)
|
## Moving forward
|
||||||
above, you may have noticed that there were a lot more flecks there than just the two in our
|
|
||||||
application.
|
|
||||||
|
|
||||||
For instance, there is a `@flecks/web` fleck that turns your little old server application into one
|
In the next section, we'll look at how to create a fleck.
|
||||||
that can build and serve a webpage. We'll see how to add it in the next section.
|
|
||||||
|
|
|
@ -4,30 +4,27 @@ description: A fleck is a module but also so much more.
|
||||||
---
|
---
|
||||||
|
|
||||||
If you are following along from the previous getting started
|
If you are following along from the previous getting started
|
||||||
[configuration page](./configuration), you have an application with 3 flecks:
|
[configuration page](./configuration), you have an application with 2 flecks:
|
||||||
|
|
||||||
- `@flecks/core`
|
- `@flecks/core`
|
||||||
- `@flecks/server`
|
- `@flecks/server`
|
||||||
- `@flecks/web`
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>About that "3 flecks" thing...</summary>
|
<summary>About that "2 flecks" thing...</summary>
|
||||||
|
|
||||||
Actually, your server application has 6 flecks at this point:
|
Actually, your server application has **4 flecks** at this point:
|
||||||
|
|
||||||
- `@flecks/core`
|
- `@flecks/core`
|
||||||
- `@flecks/core/server`
|
- `@flecks/core/server`
|
||||||
- `@flecks/server`
|
- `@flecks/server`
|
||||||
- `@flecks/server/server`
|
- `@flecks/server/server`
|
||||||
- `@flecks/web`
|
|
||||||
- `@flecks/web/server`
|
|
||||||
|
|
||||||
flecks will load the `[...]/server` fleck under any fleck that is loaded on the server. This is
|
flecks will load the `[...]/server` fleck under any fleck that is loaded on the server. This is
|
||||||
also the case when using `@flecks/web` which will automatically load `[...]/client` flecks
|
also the case when using `@flecks/web` which will automatically load `[...]/client` flecks
|
||||||
which are only loaded in the browser. We'll be exploring this specifically in the next section.
|
which are only loaded in the browser. We'll be exploring this specifically in the next section.
|
||||||
If you're intersted in diving deeper, see [the platforms concept page](#todo).
|
If you're intersted in diving deeper, see [the platforms concept page](#todo).
|
||||||
|
|
||||||
Some frameworks make it a little cheesier to work with isomorphic code, but the flecks
|
Some frameworks make it a little more opaque to work with isomorphic code, but the flecks
|
||||||
philosophy is that visibility is believability: you'll have to be explicit about which code
|
philosophy is that visibility is believability: you'll have to be explicit about which code
|
||||||
runs where.
|
runs where.
|
||||||
</details>
|
</details>
|
||||||
|
@ -63,7 +60,6 @@ After some output, you'll find your new fleck at `packages/say-hello`. Let's ins
|
||||||
'@flecks/core':
|
'@flecks/core':
|
||||||
id: 'hello_world'
|
id: 'hello_world'
|
||||||
'@flecks/server': {}
|
'@flecks/server': {}
|
||||||
'@flecks/web': {}
|
|
||||||
// highlight-next-line
|
// highlight-next-line
|
||||||
'@hello-world/say-hello:./packages/say-hello/src': {}
|
'@hello-world/say-hello:./packages/say-hello/src': {}
|
||||||
```
|
```
|
||||||
|
@ -107,68 +103,53 @@ There is a source file at `packages/say-hello/src/index.js` but for now it's emp
|
||||||
out a bit:
|
out a bit:
|
||||||
|
|
||||||
```javascript title="packages/say-hello/src/index.js"
|
```javascript title="packages/say-hello/src/index.js"
|
||||||
exports.hooks = {
|
export const hooks = {
|
||||||
'@flecks/web/client.up': async () => {
|
'@flecks/server.up': async () => {
|
||||||
window.document.body.append('hello world');
|
process.stdout.write(' hello server\n');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, restart your application and visit your website. Glorious, isn't it?
|
Now, restart your application:
|
||||||
|
|
||||||
## Everything so far... plus Electron!
|
|
||||||
|
|
||||||
Let's add another core fleck. flecks ships with a core fleck `@flecks/electron`. This runs your
|
|
||||||
application inside of an instance of [Electron](https://www.electronjs.org/). You'll add the fleck:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx flecks add @flecks/electron
|
npm run start
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you'll update your `build/flecks.yml` like so:
|
You will be greeted by a line in the output:
|
||||||
|
|
||||||
```yml
|
```terminal
|
||||||
'@flecks/core':
|
hello server
|
||||||
id: 'hello_world'
|
|
||||||
'@flecks/electron': {}
|
|
||||||
// highlight-start
|
|
||||||
'@flecks/server':
|
|
||||||
up:
|
|
||||||
- '...'
|
|
||||||
- '@flecks/web'
|
|
||||||
- '@flecks/electron'
|
|
||||||
// highlight-end
|
|
||||||
'@flecks/web': {}
|
|
||||||
'@hello-world/say-hello:./packages/say-hello/src': {}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### ~~flecking~~ pecking order
|
### flecks injection
|
||||||
|
|
||||||
We added some configuration to `@flecks/server`. The `up` key configures the order in which flecks
|
Hook implementations may receive arguments. After any arguments, the `flecks` instance is always
|
||||||
are initialized when the server comes up. We make sure `@flecks/web` serves a webpage before
|
passed.
|
||||||
`@flecks/electron` tries to visit it.
|
|
||||||
|
|
||||||
:::tip
|
`@flecks/server.up` doesn't pass any arguments, so the `flecks` instance is the first argument.
|
||||||
|
Let's see how to use the instance to read some configuration:
|
||||||
|
|
||||||
`'...'` just means "everything else": if any other flecks implement that hook then they will run
|
```javascript title="packages/say-hello/src/index.js"
|
||||||
here. It is valid to provide entries both before and after `'...'`.
|
export const hooks = {
|
||||||
|
'@flecks/server.up': async (flecks) => {
|
||||||
The default configuration of
|
const {id} = flecks.get('@flecks/core');
|
||||||
`@flecks/server.up` is simply:
|
process.stdout.write(` hello server: ID ${id}\n`);
|
||||||
|
},
|
||||||
```yml
|
};
|
||||||
'@flecks/server':
|
|
||||||
up:
|
|
||||||
- '...'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
However in this case the order of hook execution is undefined. That's why we configure it
|
This time, you will see:
|
||||||
explicitly.
|
|
||||||
|
```terminal
|
||||||
|
hello server: ID hello-world
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
...or whatever your application's ID is. We're assuming you're following along from
|
||||||
|
[the configuration page](./configuration).
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Finally `npm start` and you will see something like this:
|
Next, we'll add and interact with some of the flecks shipped by default.
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Isn't it beautiful? :relieved:
|
|
||||||
|
|
|
@ -18,37 +18,35 @@ so:
|
||||||
```
|
```
|
||||||
|
|
||||||
When running your application in different execution environments (say, production) you may want to
|
When running your application in different execution environments (say, production) you may want to
|
||||||
override configuration such as this. This is done by using the a prefix followed by the
|
override configuration such as this. This is done by like so:
|
||||||
fleck name and the key. The template literal for such a transformation would look like:
|
|
||||||
|
|
||||||
### Syntax
|
### Syntax
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
`FLECKS_ENV__${Flecks.environmentalize(path)}__${key}`
|
`FLECKS_ENV__${Flecks.environmentalize(fleck)}__${key}`
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note
|
:::tip
|
||||||
|
|
||||||
Notice the `environmentalize` transformation: `@flecks/core`'s `id` key is set using the
|
As an example, `@flecks/core`'s `id` key is set using the following variable:
|
||||||
following variable:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
FLECKS_ENV__flecks_core__id=foobar
|
FLECKS_ENV__flecks_core__id=foobar
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>`Flecks.environmentalize`</summary>
|
<summary>`Flecks.environmentalize` implementation</summary>
|
||||||
```javascript
|
```javascript
|
||||||
static environmentalize(path) {
|
static environmentalize(path) {
|
||||||
return path
|
return path
|
||||||
// - `@flecks/core` -> `FLECKS_CORE`
|
// - `@flecks/core` -> `flecks_core`
|
||||||
.replace(/[^a-zA-Z0-9]/g, '_')
|
.replace(/[^a-zA-Z0-9]/g, '_')
|
||||||
.replace(/_*(.*)_*/, '$1');
|
.replace(/_*(.*)_*/, '$1');
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Also note that the fleck path and key are still case-sensitive. This is because they are
|
Note that the fleck path and key are still case-sensitive. This is because they are
|
||||||
user-defined.
|
user-defined.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
BIN
website/docs/flecks-web.png
Normal file
BIN
website/docs/flecks-web.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -11,8 +11,8 @@ export default {
|
||||||
items: [
|
items: [
|
||||||
'installation',
|
'installation',
|
||||||
'configuration',
|
'configuration',
|
||||||
'adding-a-fleck',
|
|
||||||
'creating-a-fleck',
|
'creating-a-fleck',
|
||||||
|
'adding-flecks',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user