stonyx 0.2.3-alpha.8 → 0.2.3-alpha.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -7
- package/config/{environment.js → environment copy.ts } +16 -12
- package/dist/cli/help.d.ts +8 -0
- package/dist/cli/help.js +43 -0
- package/dist/cli/load-commands.d.ts +10 -0
- package/dist/cli/load-commands.js +49 -0
- package/dist/cli/new.d.ts +72 -0
- package/dist/cli/new.js +422 -0
- package/dist/cli/serve.d.ts +6 -0
- package/dist/cli/serve.js +49 -0
- package/dist/cli/test-setup.d.ts +1 -0
- package/dist/cli/test-setup.js +30 -0
- package/dist/cli/test.d.ts +4 -0
- package/dist/cli/test.js +23 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +53 -0
- package/dist/exports/config.d.ts +2 -0
- package/dist/exports/config.js +2 -0
- package/dist/exports/log.d.ts +2 -0
- package/{src → dist}/exports/log.js +1 -2
- package/dist/exports/test-helpers.d.ts +5 -0
- package/dist/exports/test-helpers.js +7 -0
- package/dist/lifecycle.d.ts +7 -0
- package/dist/lifecycle.js +18 -0
- package/dist/main.d.ts +22 -0
- package/dist/main.js +102 -0
- package/dist/modules.d.ts +5 -0
- package/dist/modules.js +186 -0
- package/dist/util/duplicate-core.d.ts +186 -0
- package/dist/util/duplicate-core.js +377 -0
- package/dist/util/import-config.d.ts +52 -0
- package/dist/util/import-config.js +256 -0
- package/dist/util/resolve-entry-point.d.ts +1 -0
- package/dist/util/resolve-entry-point.js +14 -0
- package/dist/util/resolve-module-name.d.ts +14 -0
- package/dist/util/resolve-module-name.js +33 -0
- package/package.json +41 -12
- package/scripts/postinstall-manifest.js +16 -0
- package/scripts/postinstall.js +17 -2
- package/.claude/index.md +0 -96
- package/.github/workflows/ci.yml +0 -16
- package/.github/workflows/publish.yml +0 -51
- package/docs/api.md +0 -89
- package/docs/cli.md +0 -78
- package/docs/configuration.md +0 -72
- package/docs/conventions/cron-conventions.md +0 -195
- package/docs/conventions/discord-conventions.md +0 -62
- package/docs/conventions/framework-modules.md +0 -140
- package/docs/conventions/index.md +0 -25
- package/docs/conventions/orm-conventions.md +0 -190
- package/docs/conventions/project-structure.md +0 -105
- package/docs/conventions/rest-conventions.md +0 -96
- package/docs/conventions/testing-conventions.md +0 -56
- package/docs/developing-modules.md +0 -108
- package/docs/index.md +0 -15
- package/docs/lifecycle.md +0 -47
- package/docs/logging.md +0 -52
- package/docs/modules.md +0 -78
- package/docs/testing.md +0 -64
- package/src/cli/help.js +0 -48
- package/src/cli/load-commands.js +0 -56
- package/src/cli/new.js +0 -237
- package/src/cli/serve.js +0 -38
- package/src/cli/test-setup.js +0 -8
- package/src/cli/test.js +0 -27
- package/src/cli.js +0 -63
- package/src/exports/config.js +0 -3
- package/src/exports/test-helpers.js +0 -8
- package/src/lifecycle.js +0 -17
- package/src/main.js +0 -101
- package/src/modules.js +0 -112
package/docs/api.md
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# API Reference
|
|
2
|
-
|
|
3
|
-
Public exports available from the `stonyx` package.
|
|
4
|
-
|
|
5
|
-
## Exports Map
|
|
6
|
-
|
|
7
|
-
| Import Path | Export | Description |
|
|
8
|
-
|-------------|--------|-------------|
|
|
9
|
-
| `stonyx` | `default` (Stonyx class) | Main framework class (singleton) |
|
|
10
|
-
| `stonyx` | `waitForModule(name)` | Wait for an async module to be ready |
|
|
11
|
-
| `stonyx/config` | `default` (config object) | Live reference to Stonyx configuration |
|
|
12
|
-
| `stonyx/log` | `default` (Chronicle instance) | Live reference to Chronicle logger |
|
|
13
|
-
| `stonyx/lifecycle` | `runStartupHooks(modules)` | Run startup hooks on a module array |
|
|
14
|
-
| `stonyx/lifecycle` | `runShutdownHooks(modules)` | Run shutdown hooks in reverse order |
|
|
15
|
-
| `stonyx/test-helpers` | `setupIntegrationTests(hooks)` | QUnit hook for integration test setup |
|
|
16
|
-
|
|
17
|
-
## Stonyx Class
|
|
18
|
-
|
|
19
|
-
```js
|
|
20
|
-
import Stonyx from 'stonyx';
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Constructor
|
|
24
|
-
|
|
25
|
-
```js
|
|
26
|
-
new Stonyx(config, rootPath)
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
- **config** — Full environment configuration object
|
|
30
|
-
- **rootPath** — Absolute path to the project root
|
|
31
|
-
|
|
32
|
-
Returns the existing instance if one already exists (singleton pattern).
|
|
33
|
-
|
|
34
|
-
### Static Properties
|
|
35
|
-
|
|
36
|
-
| Property | Type | Description |
|
|
37
|
-
|----------|------|-------------|
|
|
38
|
-
| `Stonyx.instance` | `Stonyx` | The singleton instance |
|
|
39
|
-
| `Stonyx.ready` | `Promise` | Resolves when all modules are initialized |
|
|
40
|
-
| `Stonyx.initialized` | `boolean` | Whether Stonyx has started initialization |
|
|
41
|
-
|
|
42
|
-
### Static Getters
|
|
43
|
-
|
|
44
|
-
| Getter | Returns | Throws |
|
|
45
|
-
|--------|---------|--------|
|
|
46
|
-
| `Stonyx.config` | Config object | If not initialized |
|
|
47
|
-
| `Stonyx.log` | Chronicle instance | If not initialized |
|
|
48
|
-
|
|
49
|
-
### Instance Properties
|
|
50
|
-
|
|
51
|
-
| Property | Type | Description |
|
|
52
|
-
|----------|------|-------------|
|
|
53
|
-
| `instance.config` | `object` | Merged environment configuration |
|
|
54
|
-
| `instance.chronicle` | `Chronicle` | Logger instance |
|
|
55
|
-
| `instance.modules` | `Array` | Loaded module instances |
|
|
56
|
-
|
|
57
|
-
## waitForModule
|
|
58
|
-
|
|
59
|
-
```js
|
|
60
|
-
import { waitForModule } from 'stonyx';
|
|
61
|
-
|
|
62
|
-
await waitForModule('rest-server');
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Waits for a specific `@stonyx/*` module to complete initialization. Pass the module name **without** the `@stonyx/` prefix.
|
|
66
|
-
|
|
67
|
-
Throws if the module is not registered in project dependencies.
|
|
68
|
-
|
|
69
|
-
## Lifecycle Functions
|
|
70
|
-
|
|
71
|
-
```js
|
|
72
|
-
import { runStartupHooks, runShutdownHooks } from 'stonyx/lifecycle';
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### runStartupHooks(modules)
|
|
76
|
-
|
|
77
|
-
Calls `startup()` on each module in array order. Skips modules without a `startup` method.
|
|
78
|
-
|
|
79
|
-
### runShutdownHooks(modules)
|
|
80
|
-
|
|
81
|
-
Calls `shutdown()` on each module in **reverse** array order. Errors are caught and logged — one failing hook does not prevent others from running.
|
|
82
|
-
|
|
83
|
-
## setupIntegrationTests
|
|
84
|
-
|
|
85
|
-
```js
|
|
86
|
-
import { setupIntegrationTests } from 'stonyx/test-helpers';
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Registers a QUnit `before` hook that waits for `Stonyx.ready`. Use within a `module()` block to ensure Stonyx is fully initialized before tests run.
|
package/docs/cli.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# CLI
|
|
2
|
-
|
|
3
|
-
Stonyx includes a CLI that handles bootstrapping, module initialization, and application execution.
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
stonyx <command> [...args]
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Built-in Commands
|
|
12
|
-
|
|
13
|
-
| Command | Alias | Description |
|
|
14
|
-
|---------|-------|-------------|
|
|
15
|
-
| `serve` | `s` | Bootstrap Stonyx and run the app |
|
|
16
|
-
| `test` | `t` | Bootstrap Stonyx in test mode and run tests |
|
|
17
|
-
| `help` | `h` | Show available commands |
|
|
18
|
-
|
|
19
|
-
### serve
|
|
20
|
-
|
|
21
|
-
Bootstraps Stonyx (loads config, initializes modules, runs lifecycle hooks), then imports your application entry point.
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
stonyx serve # Runs app.js by default
|
|
25
|
-
stonyx serve --entry custom.js # Runs a custom entry file
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
The serve command also registers `SIGTERM` and `SIGINT` handlers that run [shutdown hooks](lifecycle.md) before exiting.
|
|
29
|
-
|
|
30
|
-
### test
|
|
31
|
-
|
|
32
|
-
Runs your test suite using [QUnit](https://qunitjs.com/) with automatic Stonyx bootstrapping. Sets `NODE_ENV=test` and applies any [test config overrides](configuration.md#test-environment-overrides).
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
stonyx test # Runs test/**/*-test.js by default
|
|
36
|
-
stonyx test "test/unit/**/*.js" # Custom test glob
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### help
|
|
40
|
-
|
|
41
|
-
Displays all available commands, including any [module commands](#module-commands).
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
stonyx help
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Module Commands
|
|
48
|
-
|
|
49
|
-
Stonyx modules can register custom CLI commands by exporting a `./commands` entry in their `package.json`. These are automatically discovered and available through the CLI.
|
|
50
|
-
|
|
51
|
-
```json
|
|
52
|
-
{
|
|
53
|
-
"exports": {
|
|
54
|
-
"./commands": "./src/commands.js"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
The commands file should export an object mapping command names to definitions:
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
export default {
|
|
63
|
-
'db:migrate': {
|
|
64
|
-
description: 'Run database migrations',
|
|
65
|
-
bootstrap: true,
|
|
66
|
-
run: async ({ args, cwd }) => { /* ... */ }
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
- **`bootstrap: true`** — Stonyx will be fully initialized before the command runs
|
|
72
|
-
- **`bootstrap: false`** — The command runs without Stonyx initialization
|
|
73
|
-
|
|
74
|
-
Module commands appear under "Module commands" in `stonyx help` output. If two modules register the same command name, the first one loaded wins and a warning is printed.
|
|
75
|
-
|
|
76
|
-
## Environment Variables
|
|
77
|
-
|
|
78
|
-
The CLI automatically loads `.env` files via `process.loadEnvFile()` before executing any command.
|
package/docs/configuration.md
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# Configuration
|
|
2
|
-
|
|
3
|
-
Stonyx uses a centralized configuration file that all modules read from at startup.
|
|
4
|
-
|
|
5
|
-
## Environment Config
|
|
6
|
-
|
|
7
|
-
Your project's configuration lives at `config/environment.js`:
|
|
8
|
-
|
|
9
|
-
```js
|
|
10
|
-
const { DEBUG, NODE_ENV } = process.env;
|
|
11
|
-
|
|
12
|
-
const environment = NODE_ENV ?? 'development';
|
|
13
|
-
|
|
14
|
-
export default {
|
|
15
|
-
environment,
|
|
16
|
-
debug: DEBUG ?? environment === 'development',
|
|
17
|
-
|
|
18
|
-
// Module-specific configuration
|
|
19
|
-
restServer: { logColor: 'yellow', port: 3000 },
|
|
20
|
-
cron: { log: true },
|
|
21
|
-
};
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
This file is auto-generated on `npm install` via the postinstall script if it doesn't already exist.
|
|
25
|
-
|
|
26
|
-
> **Note:** `config/environment.js` is gitignored by default so each environment can have its own settings.
|
|
27
|
-
|
|
28
|
-
## Module Configuration
|
|
29
|
-
|
|
30
|
-
Each Stonyx module reads its configuration from a top-level key matching its camelCase name. For example, `@stonyx/rest-server` reads from `config.restServer`.
|
|
31
|
-
|
|
32
|
-
Async modules ship with their own default config at `config/environment.js` inside the module package. Your project config is merged on top of these defaults — you only need to specify overrides.
|
|
33
|
-
|
|
34
|
-
## Logging Configuration
|
|
35
|
-
|
|
36
|
-
Any config key with a `logColor` property automatically creates a [Chronicle](logging.md) log type:
|
|
37
|
-
|
|
38
|
-
```js
|
|
39
|
-
export default {
|
|
40
|
-
myService: {
|
|
41
|
-
logColor: 'purple', // Required — enables log creation
|
|
42
|
-
logMethod: 'highlight', // Optional — custom method name (defaults to key name)
|
|
43
|
-
logTimestamp: true, // Optional — include timestamps
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
This works for both module configs and custom service configs. See [Logging](logging.md) for details.
|
|
49
|
-
|
|
50
|
-
## Test Environment Overrides
|
|
51
|
-
|
|
52
|
-
When `NODE_ENV=test`, Stonyx automatically looks for `test/config/environment.js` in your project root:
|
|
53
|
-
|
|
54
|
-
```js
|
|
55
|
-
// test/config/environment.js
|
|
56
|
-
export default {
|
|
57
|
-
debug: false,
|
|
58
|
-
restServer: { port: 0 },
|
|
59
|
-
};
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
These overrides are deep-merged into the main config using in-place mutation, so any existing references (like `stonyx/config` exports) stay valid.
|
|
63
|
-
|
|
64
|
-
## Accessing Config at Runtime
|
|
65
|
-
|
|
66
|
-
```js
|
|
67
|
-
import config from 'stonyx/config';
|
|
68
|
-
|
|
69
|
-
console.log(config.environment); // 'development', 'test', etc.
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
The `stonyx/config` export is a live reference to the Stonyx instance config. It will throw if accessed before Stonyx is initialized.
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
# Cron Conventions
|
|
2
|
-
|
|
3
|
-
Scheduling conventions for `@stonyx/cron`. Covers the legacy interval API and the advanced scheduling system.
|
|
4
|
-
|
|
5
|
-
## Legacy API (Simple Intervals)
|
|
6
|
-
|
|
7
|
-
For basic recurring callbacks, use the `Cron` class directly:
|
|
8
|
-
|
|
9
|
-
```js
|
|
10
|
-
import Cron from '@stonyx/cron';
|
|
11
|
-
|
|
12
|
-
const cron = new Cron();
|
|
13
|
-
|
|
14
|
-
// register(key, callback, intervalSeconds, runOnInit?)
|
|
15
|
-
cron.register('health-check', async () => {
|
|
16
|
-
await checkHealth();
|
|
17
|
-
}, 300, true);
|
|
18
|
-
|
|
19
|
-
// Unregister when done
|
|
20
|
-
cron.unregister('health-check');
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
`Cron` is a singleton — only one instance per process.
|
|
24
|
-
|
|
25
|
-
## Advanced Scheduling (CronService)
|
|
26
|
-
|
|
27
|
-
For jobs with cron expressions, one-shot scheduling, AI input normalization, and run history:
|
|
28
|
-
|
|
29
|
-
```js
|
|
30
|
-
import CronService from '@stonyx/cron/service';
|
|
31
|
-
|
|
32
|
-
const service = new CronService();
|
|
33
|
-
|
|
34
|
-
service.onJobDue = async (job) => {
|
|
35
|
-
// Execute the job's work
|
|
36
|
-
return { status: 'ok', summary: 'completed' };
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
await service.start();
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Schedule Kinds
|
|
43
|
-
|
|
44
|
-
Three schedule types, specified in `schedule.kind`:
|
|
45
|
-
|
|
46
|
-
| Kind | Purpose | Required fields |
|
|
47
|
-
|------|---------|----------------|
|
|
48
|
-
| `every` | Recurring interval | `everyMs` (milliseconds) |
|
|
49
|
-
| `cron` | Cron expression | `expr` (5-field), optional `tz` |
|
|
50
|
-
| `at` | One-shot | `at` (ISO-8601 string) |
|
|
51
|
-
|
|
52
|
-
```js
|
|
53
|
-
// Recurring every 60 seconds
|
|
54
|
-
await service.add({
|
|
55
|
-
name: 'Diagnostics',
|
|
56
|
-
schedule: { kind: 'every', everyMs: 60_000 },
|
|
57
|
-
payload: { kind: 'agentTurn', message: 'run diagnostics' },
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// Daily at 9am Eastern
|
|
61
|
-
await service.add({
|
|
62
|
-
name: 'Morning Report',
|
|
63
|
-
schedule: { kind: 'cron', expr: '0 9 * * *', tz: 'America/New_York' },
|
|
64
|
-
payload: { kind: 'agentTurn', message: 'generate morning report' },
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// One-shot reminder (auto-deletes after run)
|
|
68
|
-
await service.add({
|
|
69
|
-
name: 'Reminder',
|
|
70
|
-
schedule: { kind: 'at', at: '2026-07-01T12:00:00Z' },
|
|
71
|
-
payload: { kind: 'agentTurn', message: 'follow up on PR' },
|
|
72
|
-
});
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Payload Kinds
|
|
76
|
-
|
|
77
|
-
| Kind | Target | Key field |
|
|
78
|
-
|------|--------|-----------|
|
|
79
|
-
| `agentTurn` | Isolated agent session | `message` |
|
|
80
|
-
| `systemEvent` | Main session | `text` |
|
|
81
|
-
|
|
82
|
-
`sessionTarget` is inferred automatically: `agentTurn` → `isolated`, `systemEvent` → `main`.
|
|
83
|
-
|
|
84
|
-
### CRUD
|
|
85
|
-
|
|
86
|
-
```js
|
|
87
|
-
const job = await service.add({ ... }); // Create
|
|
88
|
-
const found = service.get(job.id); // Read
|
|
89
|
-
const updated = await service.update(job.id, { name: 'Renamed' }); // Update
|
|
90
|
-
await service.remove(job.id); // Delete
|
|
91
|
-
|
|
92
|
-
// List (excludes disabled by default)
|
|
93
|
-
const jobs = service.list();
|
|
94
|
-
const all = service.list({ includeDisabled: true });
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Manual Execution
|
|
98
|
-
|
|
99
|
-
```js
|
|
100
|
-
// Force-run regardless of schedule
|
|
101
|
-
await service.run(job.id, 'force');
|
|
102
|
-
|
|
103
|
-
// Only run if due
|
|
104
|
-
await service.run(job.id, 'due');
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Run History
|
|
108
|
-
|
|
109
|
-
```js
|
|
110
|
-
const history = service.runs(job.id);
|
|
111
|
-
// [{ status, error?, summary?, runAtMs, durationMs, nextRunAtMs, ts }]
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### AI Input Normalization
|
|
115
|
-
|
|
116
|
-
CronService accepts loose input from AI tool calls and normalizes it:
|
|
117
|
-
|
|
118
|
-
- Missing `schedule.kind` is inferred from fields (`everyMs` → `every`, `expr` → `cron`, `at` → `at`)
|
|
119
|
-
- Bare `message` or `text` at the top level is wrapped into a `payload`
|
|
120
|
-
- `deleteAfterRun` is auto-set for one-shot (`at`) jobs
|
|
121
|
-
- `delivery: { mode: 'announce' }` is auto-set for isolated `agentTurn` jobs
|
|
122
|
-
|
|
123
|
-
```js
|
|
124
|
-
// AI might send this flat structure
|
|
125
|
-
await service.add({
|
|
126
|
-
name: 'Weather Check',
|
|
127
|
-
schedule: { everyMs: 120000 },
|
|
128
|
-
message: 'check the weather',
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Normalized to:
|
|
132
|
-
// {
|
|
133
|
-
// schedule: { kind: 'every', everyMs: 120000 },
|
|
134
|
-
// payload: { kind: 'agentTurn', message: 'check the weather' },
|
|
135
|
-
// sessionTarget: 'isolated',
|
|
136
|
-
// delivery: { mode: 'announce' },
|
|
137
|
-
// }
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## ORM Data Model
|
|
141
|
-
|
|
142
|
-
When persisting cron data with `@stonyx/orm`, use the following model structure. Reference implementations are in `@stonyx/cron`'s `test/sample/`.
|
|
143
|
-
|
|
144
|
-
### Models
|
|
145
|
-
|
|
146
|
-
```
|
|
147
|
-
models/
|
|
148
|
-
cron-job.js # name, enabled, deleteAfterRun, sessionTarget, wakeMode, timestamps
|
|
149
|
-
cron-job/
|
|
150
|
-
schedule.js # kind, at, everyMs, anchorMs, expr, tz
|
|
151
|
-
payload.js # kind, message, text
|
|
152
|
-
state.js # nextRunAtMs, lastRunAtMs, lastStatus, consecutiveErrors, etc.
|
|
153
|
-
delivery.js # mode
|
|
154
|
-
cron-run.js # jobId, status, error, summary, runAtMs, durationMs, ts
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
**Property ordering:** `attr()` → `belongsTo()` (on parent model)
|
|
158
|
-
|
|
159
|
-
The parent `cron-job` model uses `belongsTo` for schedule, payload, state, and delivery sub-models. This follows the property flattening rule — no passthrough objects.
|
|
160
|
-
|
|
161
|
-
### DB Schema
|
|
162
|
-
|
|
163
|
-
```js
|
|
164
|
-
import { Model, hasMany } from '@stonyx/orm';
|
|
165
|
-
|
|
166
|
-
export default class DBModel extends Model {
|
|
167
|
-
cronJobs = hasMany('cron-job');
|
|
168
|
-
cronJobSchedules = hasMany('cron-job/schedule');
|
|
169
|
-
cronJobPayloads = hasMany('cron-job/payload');
|
|
170
|
-
cronJobStates = hasMany('cron-job/state');
|
|
171
|
-
cronJobDeliveries = hasMany('cron-job/delivery');
|
|
172
|
-
cronRuns = hasMany('cron-run');
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Serializers
|
|
177
|
-
|
|
178
|
-
Identity maps for all cron models — field names match the model attributes directly.
|
|
179
|
-
|
|
180
|
-
## Configuration
|
|
181
|
-
|
|
182
|
-
```js
|
|
183
|
-
// config/environment.js
|
|
184
|
-
export default {
|
|
185
|
-
cron: {
|
|
186
|
-
log: true, // enable cron logging (uses stonyx/log)
|
|
187
|
-
},
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## When to Use Which
|
|
192
|
-
|
|
193
|
-
- **Simple recurring callback** → `Cron.register(key, callback, interval)`
|
|
194
|
-
- **Scheduled jobs with history, CRUD, AI input** → `CronService`
|
|
195
|
-
- **Never use raw `setInterval` or `setTimeout`** for recurring work
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# Discord Conventions
|
|
2
|
-
|
|
3
|
-
Conventions for projects using `@stonyx/discord`.
|
|
4
|
-
|
|
5
|
-
## Command Files
|
|
6
|
-
|
|
7
|
-
- One class per file in the configured command directory (default: `discord-commands/`)
|
|
8
|
-
- Each file default-exports a class extending `Command` from `@stonyx/discord`
|
|
9
|
-
- Class must define a `data` property (a `SlashCommandBuilder` instance) and an `async execute(interaction)` method
|
|
10
|
-
- Class ordering: static properties → `data` → `execute()`
|
|
11
|
-
- Filenames use kebab-case; `forEachFileImport` converts to camelCase for internal registration
|
|
12
|
-
- Permission checks belong in the consuming application, not in the module
|
|
13
|
-
|
|
14
|
-
```js
|
|
15
|
-
import { Command } from '@stonyx/discord';
|
|
16
|
-
import { SlashCommandBuilder } from 'discord.js';
|
|
17
|
-
|
|
18
|
-
export default class PingCommand extends Command {
|
|
19
|
-
data = new SlashCommandBuilder()
|
|
20
|
-
.setName('ping')
|
|
21
|
-
.setDescription('Replies with Pong!');
|
|
22
|
-
|
|
23
|
-
async execute(interaction) {
|
|
24
|
-
await interaction.reply('Pong!');
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Event Handler Files
|
|
30
|
-
|
|
31
|
-
- One class per file in the configured event directory (default: `discord-events/`)
|
|
32
|
-
- Each file default-exports a class extending `EventHandler` from `@stonyx/discord`
|
|
33
|
-
- Class must set `static event` to a valid Discord.js event name (e.g., `'messageCreate'`, `'voiceStateUpdate'`)
|
|
34
|
-
- Class must implement a `handle(...args)` method matching the Discord.js event signature
|
|
35
|
-
- Class ordering: static properties → `handle()`
|
|
36
|
-
|
|
37
|
-
```js
|
|
38
|
-
import { EventHandler } from '@stonyx/discord';
|
|
39
|
-
|
|
40
|
-
export default class WelcomeHandler extends EventHandler {
|
|
41
|
-
static event = 'guildMemberAdd';
|
|
42
|
-
|
|
43
|
-
handle(member) {
|
|
44
|
-
// Welcome new member
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Configuration
|
|
50
|
-
|
|
51
|
-
- Config namespace: `config.discord`
|
|
52
|
-
- Environment variables prefixed with `DISCORD_`
|
|
53
|
-
- Logging: `log.discord()` — configured via `logColor: '#7289da'` and `logMethod: 'discord'`
|
|
54
|
-
- Intent auto-derivation: the module computes required gateway intents from discovered event handlers; use `additionalIntents` in config for edge cases
|
|
55
|
-
|
|
56
|
-
## Module Keywords
|
|
57
|
-
|
|
58
|
-
```json
|
|
59
|
-
"keywords": ["stonyx-async", "stonyx-module"]
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
`stonyx-async` indicates the module's `init()` is async and must be awaited by the framework.
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
# Framework Modules
|
|
2
|
-
|
|
3
|
-
When to use which `@stonyx/*` module. Always check these before reaching for Node built-ins or npm packages.
|
|
4
|
-
|
|
5
|
-
## `stonyx/log`
|
|
6
|
-
|
|
7
|
-
All logging goes through `stonyx/log`. Never use `console.log`, `console.warn`, or `console.error`.
|
|
8
|
-
|
|
9
|
-
```js
|
|
10
|
-
import log from 'stonyx/log';
|
|
11
|
-
|
|
12
|
-
log.info('Server started');
|
|
13
|
-
log.error('Connection failed', error);
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Custom log types can be configured in `config/environment.js`:
|
|
17
|
-
|
|
18
|
-
```js
|
|
19
|
-
export default {
|
|
20
|
-
socket: { logColor: 'magenta' }
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## `@stonyx/utils`
|
|
25
|
-
|
|
26
|
-
Utility library organized by domain. Always check here before using Node built-ins or adding npm dependencies.
|
|
27
|
-
|
|
28
|
-
### File I/O (`@stonyx/utils/file`)
|
|
29
|
-
|
|
30
|
-
**`fs` is explicitly prohibited.** Use these instead:
|
|
31
|
-
|
|
32
|
-
- `createFile(filePath, data, options?)` — write a new file (creates parent dirs)
|
|
33
|
-
- `updateFile(filePath, data, options?)` — atomic update via swap file
|
|
34
|
-
- `copyFile(sourcePath, targetPath, options?)` — copy with optional overwrite
|
|
35
|
-
- `readFile(filePath, options?)` — read file, supports `{ json: true }` and `{ missingFileCallback }`
|
|
36
|
-
- `deleteFile(filePath, options?)` — delete file, supports `{ ignoreAccessFailure: true }`
|
|
37
|
-
- `createDirectory(dir)` — recursive mkdir
|
|
38
|
-
- `deleteDirectory(dir)` — recursive rm
|
|
39
|
-
- `forEachFileImport(dir, callback, options?)` — iterate and dynamically import all `.js` files in a directory
|
|
40
|
-
- `fileExists(filePath)` — check existence
|
|
41
|
-
|
|
42
|
-
### Object Manipulation (`@stonyx/utils/object`)
|
|
43
|
-
|
|
44
|
-
- `deepCopy(obj)` — deep clone via JSON
|
|
45
|
-
- `objToJson(obj, format?)` — stringify with formatting
|
|
46
|
-
- `makeArray(obj)` — wrap in array if not already
|
|
47
|
-
- `mergeObject(obj1, obj2, options?)` — deep merge objects, supports `{ ignoreNewKeys: true }`
|
|
48
|
-
- `get(obj, path)` — dot-path property access (e.g., `get(obj, 'a.b.c')`)
|
|
49
|
-
- `getOrSet(map, key, defaultValue)` — get from Map or set default (supports factory functions)
|
|
50
|
-
|
|
51
|
-
### String Transforms (`@stonyx/utils/string`)
|
|
52
|
-
|
|
53
|
-
- `kebabCaseToCamelCase(str)` — `'my-thing'` → `'myThing'`
|
|
54
|
-
- `kebabCaseToPascalCase(str)` — `'my-thing'` → `'MyThing'`
|
|
55
|
-
- `camelCaseToKebabCase(str)` — `'myThing'` → `'my-thing'`
|
|
56
|
-
- `generateRandomString(length?)` — alphanumeric random string (default 8 chars)
|
|
57
|
-
- `pluralize(str)` — basic pluralization
|
|
58
|
-
|
|
59
|
-
### Date / Timestamp (`@stonyx/utils/date`)
|
|
60
|
-
|
|
61
|
-
- `getTimestamp(dateObject?)` — Unix timestamp in seconds (current time if no arg)
|
|
62
|
-
|
|
63
|
-
### Promises (`@stonyx/utils/promise`)
|
|
64
|
-
|
|
65
|
-
- `sleep(seconds)` — async delay
|
|
66
|
-
|
|
67
|
-
### Interactive Prompts (`@stonyx/utils/prompt`)
|
|
68
|
-
|
|
69
|
-
- `confirm(question)` — yes/no prompt, returns boolean
|
|
70
|
-
- `prompt(question)` — free-text input, returns string
|
|
71
|
-
|
|
72
|
-
File issues on `stonyx-utils` for any gaps rather than adding workarounds or npm dependencies.
|
|
73
|
-
|
|
74
|
-
## `@stonyx/events`
|
|
75
|
-
|
|
76
|
-
All pub/sub event handling. Never create custom event emitters.
|
|
77
|
-
|
|
78
|
-
- `setup(eventNames)` — register valid event names
|
|
79
|
-
- `subscribe(event, callback)` — listen for events
|
|
80
|
-
- `once(event, callback)` — single-fire listener
|
|
81
|
-
- `unsubscribe(event, callback)` — remove listener
|
|
82
|
-
- `emit(event, ...args)` — fire event
|
|
83
|
-
- `clear(event)` / `reset()` — cleanup
|
|
84
|
-
|
|
85
|
-
## `@stonyx/cron`
|
|
86
|
-
|
|
87
|
-
All scheduled and interval tasks. Never use raw `setInterval` or `setTimeout` for recurring work.
|
|
88
|
-
|
|
89
|
-
**Legacy API** — simple recurring callbacks:
|
|
90
|
-
|
|
91
|
-
- `register(key, callback, interval, runOnInit?)` — schedule a recurring job
|
|
92
|
-
- `unregister(key)` — cancel a job
|
|
93
|
-
|
|
94
|
-
**Advanced API** (`@stonyx/cron/service`) — full scheduling with CRUD, run history, and AI normalization:
|
|
95
|
-
|
|
96
|
-
- `add(input)` / `get(id)` / `update(id, patch)` / `remove(id)` / `list(opts?)` — CRUD
|
|
97
|
-
- `run(id, mode?)` — manual execution (`'force'` or `'due'`)
|
|
98
|
-
- `runs(id, limit?)` — run history
|
|
99
|
-
- `onJobDue` — callback for job execution
|
|
100
|
-
|
|
101
|
-
Three schedule kinds: `every` (interval), `cron` (expression), `at` (one-shot).
|
|
102
|
-
|
|
103
|
-
See [Cron Conventions](./cron-conventions.md) for full details.
|
|
104
|
-
|
|
105
|
-
Configurable via `config/environment.js`:
|
|
106
|
-
|
|
107
|
-
```js
|
|
108
|
-
export default {
|
|
109
|
-
cron: { log: true }
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## `@stonyx/sockets`
|
|
114
|
-
|
|
115
|
-
WebSocket handlers. Class ordering: static properties → `server()` method → `client()` method.
|
|
116
|
-
|
|
117
|
-
Exports: `SocketServer`, `SocketClient`, `Handler`, `Sockets`
|
|
118
|
-
|
|
119
|
-
## `@stonyx/discord`
|
|
120
|
-
|
|
121
|
-
Discord bot with command and event handler auto-discovery. Class ordering: static properties → `data` / `static event` → `execute()` / `handle()`.
|
|
122
|
-
|
|
123
|
-
Exports: `DiscordBot`, `Command`, `EventHandler`, `Discord`, `chunkMessage`
|
|
124
|
-
|
|
125
|
-
## `@stonyx/oauth`
|
|
126
|
-
|
|
127
|
-
OAuth providers. Class ordering: constructor with `super()` → async methods → transform methods.
|
|
128
|
-
|
|
129
|
-
Key methods: `getAuthorizationUrl()`, `handleCallback()`, `getSession()`, `logout()`
|
|
130
|
-
|
|
131
|
-
## `@abofs/code-conventions`
|
|
132
|
-
|
|
133
|
-
Shared lint and formatting config. Import and spread; never define local rules.
|
|
134
|
-
|
|
135
|
-
Exports:
|
|
136
|
-
- `@abofs/code-conventions/eslint` — ESLint config
|
|
137
|
-
- `@abofs/code-conventions/prettier` — Prettier config
|
|
138
|
-
- `@abofs/code-conventions/eslint-ember` — Ember-specific ESLint
|
|
139
|
-
- `@abofs/code-conventions/template-lint` — Template linting
|
|
140
|
-
- `@abofs/code-conventions/lint-staged` — Lint-staged config
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Stonyx Framework Conventions
|
|
2
|
-
|
|
3
|
-
Universal rules that apply to every Stonyx project. Section-specific conventions are linked below.
|
|
4
|
-
|
|
5
|
-
## Universal Rules
|
|
6
|
-
|
|
7
|
-
- **One class per file** — each file exports a single default class (or function for transforms)
|
|
8
|
-
- **Constants**: shared across files → dedicated constants file; single-use → top of the consuming file
|
|
9
|
-
- **No `console.log` / `.warn` / `.error`** — use `log` from `stonyx/log` for all logging
|
|
10
|
-
- **Check `@stonyx/utils` first** — before reaching for Node built-ins or npm packages, check if `@stonyx/utils` already provides what you need (file I/O, object manipulation, string transforms, date/timestamp, promises, prompts). File issues on stonyx-utils for gaps rather than working around them
|
|
11
|
-
- **`fs` is prohibited** — use file utilities from `@stonyx/utils/file` instead
|
|
12
|
-
- **Always LTS Node or higher** — version specified in `.nvmrc`
|
|
13
|
-
- **Always pnpm** — never npm or yarn
|
|
14
|
-
- **Lint config**: import from `@abofs/code-conventions`; never define local lint rules
|
|
15
|
-
- **ES Modules** — all projects use `"type": "module"` and ESM imports
|
|
16
|
-
|
|
17
|
-
## Section Conventions
|
|
18
|
-
|
|
19
|
-
- [Project Structure](./project-structure.md) — directory layout, file organization, config conventions
|
|
20
|
-
- [Framework Modules](./framework-modules.md) — when to use which `@stonyx/*` module
|
|
21
|
-
- [Cron Conventions](./cron-conventions.md) — scheduling, job model, CronService API, ORM data model
|
|
22
|
-
- [ORM Conventions](./orm-conventions.md) — models, serializers, access control, transforms, hooks
|
|
23
|
-
- [REST Conventions](./rest-conventions.md) — REST server request classes and handlers
|
|
24
|
-
- [Discord Conventions](./discord-conventions.md) — Discord bot commands and event handlers
|
|
25
|
-
- [Testing Conventions](./testing-conventions.md) — test organization, patterns, and tooling
|