Skip to content

Commit f42caa3

Browse files
✨ add example to docs
1 parent 841131c commit f42caa3

208 files changed

Lines changed: 1766 additions & 4659 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CODE_OF_CONDUCT.md

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
We as members, contributors, and leaders pledge to make participation in our
66
community a harassment-free experience for everyone, regardless of age, body
77
size, visible or invisible disability, ethnicity, sex characteristics, gender
8-
identity and expression, level of experience, education, socio-economic status,
9-
nationality, personal appearance, race, religion, or sexual identity
8+
identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity
109
and orientation.
1110

12-
We pledge to act and interact in ways that contribute to an open, welcoming,
13-
diverse, inclusive, and healthy community.
11+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
1412

1513
## Our Standards
1614

@@ -20,8 +18,7 @@ community include:
2018
* Demonstrating empathy and kindness toward other people
2119
* Being respectful of differing opinions, viewpoints, and experiences
2220
* Giving and gracefully accepting constructive feedback
23-
* Accepting responsibility and apologizing to those affected by our mistakes,
24-
and learning from the experience
21+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
2522
* Focusing on what is best not just for us as individuals, but for the
2623
overall community
2724

@@ -40,8 +37,7 @@ Examples of unacceptable behavior include:
4037

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

4642
Community leaders have the right and responsibility to remove, edit, or reject
4743
comments, commits, code, wiki edits, issues, and other contributions that are
@@ -52,8 +48,7 @@ decisions when appropriate.
5248

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

5954
## Enforcement
@@ -106,16 +101,15 @@ Violating these terms may lead to a permanent ban.
106101
### 4. Permanent Ban
107102

108103
**Community Impact**: Demonstrating a pattern of violation of community
109-
standards, including sustained inappropriate behavior, harassment of an
104+
standards, including sustained inappropriate behavior, harassment of an
110105
individual, or aggression toward or disparagement of classes of individuals.
111106

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

115110
## Attribution
116111

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

121115
Community Impact Guidelines were inspired by [Mozilla's code of conduct

en/cli/cli-database.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ The command accepts an optional ORM argument to skip the first selection step. W
1515

1616
## When to use
1717

18-
Use this command at the beginning of a project or when adding database access to an existing Spraxium application. It is the equivalent of manually installing packages, writing connection boilerplate, and registering the module , all collapsed into a single interactive flow. Run it once per database integration; for schema changes or migrations, use the ORM tooling directly after setup.
18+
Use this command at the beginning of a project or when adding database access to an existing Spraxium application. It is the equivalent of manually installing packages, writing connection boilerplate, and registering the module, all collapsed into a single interactive flow. Run it once per database integration; for schema changes or migrations, use the ORM tooling directly after setup.
1919

2020
## Supported ORMs
2121

2222
<DropdownGroup>
23-
<Dropdown title="Prisma , schema-first with auto-generated client">
23+
<Dropdown title="Prisma, schema-first with auto-generated client">
2424
Prisma is the best choice when you want a strongly typed query client generated from a declarative schema file. It supports PostgreSQL, MySQL, and SQLite out of the box. After the wizard runs, define your models in `prisma/schema.prisma` and run `npx prisma migrate dev` to apply changes. Prisma is ideal for teams that prefer schema-as-source-of-truth workflows, readable migration history, and full TypeScript type safety from database to application layer.
2525
</Dropdown>
26-
<Dropdown title="Drizzle , lightweight SQL-native TypeScript ORM">
26+
<Dropdown title="Drizzle, lightweight SQL-native TypeScript ORM">
2727
Drizzle is suited for projects that value small bundle size, direct SQL control, and schema defined in TypeScript rather than a separate file. It supports PostgreSQL, MySQL, and SQLite. The generated *DatabaseService* exposes a `.getDb()` method that returns the Drizzle query builder, ready to use. Choose Drizzle when you want minimal abstraction with full TypeScript inference and prefer defining tables as TypeScript objects over `.prisma` syntax.
2828
</Dropdown>
29-
<Dropdown title="TypeORM , decorator-based with Active Record or Data Mapper">
29+
<Dropdown title="TypeORM, decorator-based with Active Record or Data Mapper">
3030
TypeORM is the established choice for teams coming from NestJS or Spring backgrounds who are comfortable with class decorators such as *@Entity*, *@Column*, and *@Repository*. It supports PostgreSQL, MySQL, and SQLite. Use TypeORM when your team prefers entity classes as the source of truth and wants a familiar pattern for migrations and relation management.
3131
</Dropdown>
32-
<Dropdown title="Mongoose , document model for MongoDB">
32+
<Dropdown title="Mongoose, document model for MongoDB">
3333
Mongoose is the right pick when your data is document-oriented and MongoDB is your database. It has a single database target, so the wizard skips the engine selection step. The generated module includes a schema definition and a service that wraps the Mongoose model. Choose Mongoose for applications that need flexible schemas, embedded documents, or MongoDB-specific query operators.
3434
</Dropdown>
35-
<Dropdown title="Mikro-ORM , versatile ORM with Unit of Work pattern">
35+
<Dropdown title="Mikro-ORM, versatile ORM with Unit of Work pattern">
3636
Mikro-ORM is a strong choice for advanced use cases that benefit from the Unit of Work pattern and Identity Map. It supports PostgreSQL, MySQL, SQLite, and MongoDB. Mikro-ORM is well suited for complex domain models with deep relation graphs, where controlled change tracking across a request lifecycle matters more than simplicity of setup.
3737
</Dropdown>
3838
</DropdownGroup>

en/cli/cli-dev.mdx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,7 @@ spraxium dev
2424
```typescript filename="spraxium.config.ts"
2525
export default {
2626
dev: {
27-
entrypoint: 'src/main.ts',
28-
include: ['src/**'],
29-
exclude: ['src/**/*.spec.ts'],
30-
debounce: 300,
31-
},
32-
};
27+
entrypoint: 'src/main.ts', include: ['src/**'], exclude: ['src/**/*.spec.ts'], debounce: 300, }, };
3328
```
3429

3530
<DropdownGroup>

en/components/components-buttons.mdx

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,7 @@ A static button is the simplest interactive component. You decorate a class with
4949
import { Button } from '@spraxium/components';
5050

5151
@Button({
52-
customId: 'confirm_action',
53-
label: 'Confirm',
54-
style: 'success',
55-
emoji: '',
56-
})
52+
customId: 'confirm_action', label: 'Confirm', style: 'success', emoji: '', })
5753
export class ConfirmButton {}
5854
```
5955
</Tab>
@@ -134,10 +130,7 @@ Link buttons open a URL in the user's browser without firing any handler on the
134130
import { LinkButton } from '@spraxium/components';
135131

136132
@LinkButton({
137-
url: 'https://docs.example.com',
138-
label: 'View Documentation',
139-
emoji: '📖',
140-
})
133+
url: 'https://docs.example.com', label: 'View Documentation', emoji: '📖', })
141134
export class DocsLinkButton {}
142135
```
143136

@@ -188,19 +181,15 @@ import { ModerationCommand } from './moderation.command';
188181
@SlashCommandHandler(ModerationCommand)
189182
export class ModerationCommandHandler {
190183
constructor(
191-
private readonly buttons: ButtonService,
192-
private readonly context: ContextService,
193-
) {}
184+
private readonly buttons: ButtonService, private readonly context: ContextService, ) {}
194185

195186
async handle(@Ctx() interaction: ChatInputCommandInteraction): Promise<void> {
196187
const ctx = await this.context.create({ targetUserId: '123456' });
197188
const actionRow = this.buttons.rowWithContext(ctx, ConfirmButton, CancelButton);
198189
const linkRow = this.buttons.build(DocsLinkButton);
199190

200191
await interaction.reply({
201-
content: 'Review the moderation action below.',
202-
components: [actionRow, linkRow],
203-
});
192+
content: 'Review the moderation action below.', components: [actionRow, linkRow], });
204193
}
205194
}
206195
```
@@ -258,11 +247,7 @@ import { UserBanButtonHandler } from './components/user-ban.handler';
258247

259248
@Module({
260249
handlers: [
261-
ConfirmButtonHandler,
262-
CancelButtonHandler,
263-
UserBanButtonHandler,
264-
],
265-
})
250+
ConfirmButtonHandler, CancelButtonHandler, UserBanButtonHandler, ], })
266251
export class ModerationModule {}
267252
```
268253

en/components/components-context.mdx

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,16 @@ import { SetupWizardCommand } from './setup-wizard.command';
2929
@SlashCommandHandler(SetupWizardCommand)
3030
export class SetupWizardCommandHandler {
3131
constructor(
32-
private readonly context: ContextService,
33-
private readonly buttons: ButtonService,
34-
) {}
32+
private readonly context: ContextService, private readonly buttons: ButtonService, ) {}
3533

3634
async handle(@Ctx() interaction: ChatInputCommandInteraction): Promise<void> {
3735
const ctx = await this.context.create(
38-
{ step: 1, guildId: interaction.guildId, settings: {} },
39-
{ ttl: 600, restrictedTo: interaction.user.id },
40-
);
36+
{ step: 1, guildId: interaction.guildId, settings: {} }, { ttl: 600, restrictedTo: interaction.user.id }, );
4137

4238
const row = this.buttons.rowWithContext(ctx, NextStepButton);
4339

4440
await interaction.reply({
45-
content: 'Welcome to the setup wizard. Click Next to begin.',
46-
components: [row],
47-
});
41+
content: 'Welcome to the setup wizard. Click Next to begin.', components: [row], });
4842
}
4943
}
5044
```
@@ -114,14 +108,10 @@ interface WizardData {
114108
@ButtonHandler(NextStepButton)
115109
export class NextStepButtonHandler {
116110
async handle(
117-
@Ctx() interaction: ButtonInteraction,
118-
@FlowContext() ctx: SpraxiumContext<WizardData>,
119-
): Promise<void> {
111+
@Ctx() interaction: ButtonInteraction, @FlowContext() ctx: SpraxiumContext<WizardData>, ): Promise<void> {
120112
const { step, settings } = ctx.data;
121113
await interaction.reply({
122-
content: `You are on step ${step}. Current settings: ${JSON.stringify(settings)}`,
123-
ephemeral: true,
124-
});
114+
content: `You are on step ${step}. Current settings: ${JSON.stringify(settings)}`, ephemeral: true, });
125115
}
126116
}
127117
```
@@ -148,18 +138,12 @@ export class StepTwoButtonHandler {
148138
constructor(private readonly context: ContextService) {}
149139

150140
async handle(
151-
@Ctx() interaction: ButtonInteraction,
152-
@FlowContext() ctx: SpraxiumContext<WizardData>,
153-
): Promise<void> {
141+
@Ctx() interaction: ButtonInteraction, @FlowContext() ctx: SpraxiumContext<WizardData>, ): Promise<void> {
154142
await this.context.update<WizardData>(ctx.id, {
155-
step: 2,
156-
settings: { ...ctx.data.settings, language: 'en' },
157-
});
143+
step: 2, settings: { ...ctx.data.settings, language: 'en' }, });
158144

159145
await interaction.reply({
160-
content: 'Step 2 complete. Proceeding to step 3.',
161-
ephemeral: true,
162-
});
146+
content: 'Step 2 complete. Proceeding to step 3.', ephemeral: true, });
163147
}
164148
}
165149
```
@@ -180,9 +164,7 @@ export class FinishWizardHandler {
180164
constructor(private readonly context: ContextService) {}
181165

182166
async handle(
183-
@Ctx() interaction: ButtonInteraction,
184-
@FlowContext() ctx: SpraxiumContext<unknown>,
185-
): Promise<void> {
167+
@Ctx() interaction: ButtonInteraction, @FlowContext() ctx: SpraxiumContext<unknown>, ): Promise<void> {
186168
await this.context.delete(ctx.id);
187169
await interaction.reply({ content: 'Setup complete!', ephemeral: true });
188170
}
@@ -235,10 +217,7 @@ import { defineComponents } from '@spraxium/components';
235217

236218
export const componentsPlugin = defineComponents({
237219
context: {
238-
storage: 'redis',
239-
defaultTtl: 600,
240-
},
241-
});
220+
storage: 'redis', defaultTtl: 600, }, });
242221
```
243222

244223
## ContextService API reference
@@ -300,22 +279,16 @@ import { VerificationCommand } from './verification.command';
300279
@SlashCommandHandler(VerificationCommand)
301280
export class VerificationCommandHandler {
302281
constructor(
303-
private readonly context: ContextService,
304-
private readonly buttons: ButtonService,
305-
) {}
282+
private readonly context: ContextService, private readonly buttons: ButtonService, ) {}
306283

307284
async handle(@Ctx() interaction: ChatInputCommandInteraction): Promise<void> {
308285
const ctx = await this.context.create(
309-
{ userId: interaction.user.id },
310-
{ ttl: 300, restrictedTo: interaction.user.id },
311-
);
286+
{ userId: interaction.user.id }, { ttl: 300, restrictedTo: interaction.user.id }, );
312287

313288
const row = this.buttons.rowWithContext(ctx, VerifyButton);
314289

315290
await interaction.reply({
316-
content: 'Click the button to verify your identity.',
317-
components: [row],
318-
});
291+
content: 'Click the button to verify your identity.', components: [row], });
319292
}
320293
}
321294
```

en/components/components-embeds.mdx

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@ The simplest embed uses the *@Embed* class decorator with a static schema. This
2323
import { Embed } from '@spraxium/components';
2424

2525
@Embed({
26-
title: 'Welcome',
27-
description: 'Welcome to the server! Please read the rules.',
28-
color: 0x5865F2,
29-
footer: { text: 'Spraxium Bot' },
30-
timestamp: true,
31-
})
26+
title: 'Welcome', description: 'Welcome to the server! Please read the rules.', color: 0x5865F2, footer: { text: 'Spraxium Bot' }, timestamp: true, })
3227
export class WelcomeEmbed {}
3328
```
3429

@@ -63,10 +58,7 @@ export class UserProfileEmbed {
6358
level!: never;
6459

6560
@EmbedField<ProfileData>({
66-
name: 'Status',
67-
value: (data) => (data.isPremium ? '⭐ Premium' : 'Free'),
68-
inline: true,
69-
})
61+
name: 'Status', value: (data) => (data.isPremium ? '⭐ Premium' : 'Free'), inline: true, })
7062
status!: never;
7163

7264
@EmbedFooter<ProfileData>((data) => ({ text: `ID: ${data.username}` }))
@@ -216,15 +208,13 @@ export class PremiumProfileEmbed {
216208

217209
@EmbedWhen<ProfileData>((d) => d.isPremium)
218210
@EmbedField<ProfileData>({
219-
name: 'Premium Since',
220-
value: (d) => d.premiumSince ?? 'Unknown',
221-
})
211+
name: 'Premium Since', value: (d) => d.premiumSince ?? 'Unknown', })
222212
premiumField!: never;
223213
}
224214
```
225215

226216
<Callout type="warning">
227-
Always apply *@EmbedWhen* before *@EmbedField* on the same property. The decorator stacking order matters if the predicate returns false, the field metadata is skipped entirely during rendering.
217+
Always apply *@EmbedWhen* before *@EmbedField* on the same property. The decorator stacking order matters, if the predicate returns false, the field metadata is skipped entirely during rendering.
228218
</Callout>
229219

230220
## DescriptionBuilder
@@ -287,11 +277,7 @@ export class ProfileCommandHandler {
287277

288278
async handle(@Ctx() interaction: ChatInputCommandInteraction): Promise<void> {
289279
const profileData = {
290-
username: interaction.user.username,
291-
level: 42,
292-
isPremium: true,
293-
avatarUrl: interaction.user.displayAvatarURL(),
294-
};
280+
username: interaction.user.username, level: 42, isPremium: true, avatarUrl: interaction.user.displayAvatarURL(), };
295281

296282
const embed = this.embeds.build(UserProfileEmbed, profileData);
297283
await interaction.reply({ embeds: [embed] });
@@ -308,8 +294,7 @@ import { Module } from '@spraxium/common';
308294
import { ProfileCommand } from './commands/profile.command';
309295

310296
@Module({
311-
commands: [ProfileCommand],
312-
})
297+
commands: [ProfileCommand], })
313298
export class ProfileModule {}
314299
```
315300

0 commit comments

Comments
 (0)