create-nexwire 4.2.2 → 4.2.4
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/express/package.json +48 -23
- package/express/src/database/migrations/sqlite/0000_init.sql +47 -60
- package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -89
- package/express/src/database/migrations/sqlite/meta/_journal.json +1 -1
- package/express/src/database/schema.ts +2 -3
- package/express/src/framework/database/app-schema.ts +37 -0
- package/express/src/framework/database/connection.ts +198 -196
- package/express/src/framework/database/seed.ts +35 -22
- package/express/src/framework/facade.ts +35 -5
- package/express/src/framework/kernel.ts +54 -52
- package/express/src/framework/maker-cli/db/core.mjs +291 -288
- package/express/src/framework/maker-cli/index.mjs +2 -0
- package/express/src/framework/maker-cli/module/core.mjs +155 -87
- package/express/src/framework/maker-cli/module/index.mjs +13 -4
- package/express/src/framework/maker-cli/provider/core.mjs +49 -0
- package/express/src/framework/maker-cli/provider/index.mjs +12 -0
- package/express/src/framework/maker-cli/stubs/notification/controller.ts.stub +76 -77
- package/express/src/framework/maker-cli/stubs/notification/job.ts.stub +11 -13
- package/express/src/framework/maker-cli/stubs/notification/model.ts.stub +29 -0
- package/express/src/framework/maker-cli/stubs/notification/provider.ts.stub +174 -0
- package/express/src/framework/maker-cli/stubs/notification/route.api.ts.stub +11 -10
- package/express/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +1 -1
- package/express/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +25 -25
- package/express/src/framework/maker-cli/stubs/notification/schema.ts.stub +25 -25
- package/express/src/framework/maker-cli/stubs/provider/module-barrel.ts.stub +19 -0
- package/express/src/framework/maker-cli/stubs/provider/module.ts.stub +21 -0
- package/express/src/framework/maker-cli/stubs/provider/name.ts.stub +21 -0
- package/express/src/framework/maker-cli/utils/help.mjs +6 -1
- package/express/src/framework/notification/index.ts +65 -47
- package/express/src/framework/providers/adapter.ts +139 -0
- package/express/src/framework/providers/contracts.ts +126 -0
- package/express/src/framework/providers/loader.ts +105 -0
- package/express/src/framework/providers/registry.ts +88 -0
- package/express/src/middlewares/auth-middleware.ts +65 -38
- package/express/src/providers/README.md +107 -0
- package/express/src/resources/src/main.ts +1 -1
- package/express/src/resources/src/pages/auth/forgetPassword.vue +1 -1
- package/express/src/resources/src/pages/auth/login.vue +1 -1
- package/express/src/resources/src/pages/auth/register.vue +1 -1
- package/express/src/resources/src/pages/auth/resetPassword.vue +1 -1
- package/express/src/resources/src/pages/auth/verifyEmail.vue +1 -1
- package/express/src/resources/src/pages/dashboard/index.vue +66 -66
- package/express/src/storage/database/nexwire.sqlite +0 -0
- package/hono/package.json +44 -19
- package/hono/src/database/migrations/sqlite/0000_init.sql +47 -60
- package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -89
- package/hono/src/database/migrations/sqlite/meta/_journal.json +1 -1
- package/hono/src/database/schema.ts +2 -3
- package/hono/src/framework/database/app-schema.ts +37 -0
- package/hono/src/framework/database/connection.ts +198 -196
- package/hono/src/framework/database/seed.ts +35 -22
- package/hono/src/framework/facade.ts +59 -29
- package/hono/src/framework/kernel.ts +50 -48
- package/hono/src/framework/maker-cli/db/core.mjs +291 -288
- package/hono/src/framework/maker-cli/index.mjs +2 -0
- package/hono/src/framework/maker-cli/module/core.mjs +123 -52
- package/hono/src/framework/maker-cli/module/index.mjs +13 -4
- package/hono/src/framework/maker-cli/provider/core.mjs +49 -0
- package/hono/src/framework/maker-cli/provider/index.mjs +12 -0
- package/hono/src/framework/maker-cli/stubs/notification/controller.ts.stub +90 -85
- package/hono/src/framework/maker-cli/stubs/notification/job.ts.stub +10 -12
- package/hono/src/framework/maker-cli/stubs/notification/model.ts.stub +29 -0
- package/hono/src/framework/maker-cli/stubs/notification/provider.ts.stub +174 -0
- package/hono/src/framework/maker-cli/stubs/notification/route.api.ts.stub +11 -10
- package/hono/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +1 -1
- package/hono/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +25 -25
- package/hono/src/framework/maker-cli/stubs/notification/schema.ts.stub +25 -25
- package/hono/src/framework/maker-cli/stubs/provider/module-barrel.ts.stub +19 -0
- package/hono/src/framework/maker-cli/stubs/provider/module.ts.stub +21 -0
- package/hono/src/framework/maker-cli/stubs/provider/name.ts.stub +21 -0
- package/hono/src/framework/maker-cli/utils/help.mjs +6 -1
- package/hono/src/framework/notification/index.ts +65 -47
- package/hono/src/framework/providers/adapter.ts +139 -0
- package/hono/src/framework/providers/contracts.ts +126 -0
- package/hono/src/framework/providers/loader.ts +105 -0
- package/hono/src/framework/providers/registry.ts +88 -0
- package/hono/src/middlewares/auth-middleware.ts +65 -38
- package/hono/src/providers/README.md +107 -0
- package/hono/src/resources/src/main.ts +1 -1
- package/hono/src/resources/src/pages/auth/forgetPassword.vue +1 -1
- package/hono/src/resources/src/pages/auth/login.vue +1 -1
- package/hono/src/resources/src/pages/auth/register.vue +1 -1
- package/hono/src/resources/src/pages/auth/resetPassword.vue +1 -1
- package/hono/src/resources/src/pages/auth/verifyEmail.vue +1 -1
- package/hono/src/resources/src/pages/dashboard/index.vue +66 -66
- package/hono/src/storage/database/nexwire.sqlite +0 -0
- package/package.json +10 -10
- package/src/index.js +14 -6
- package/express/src/modules/auth/database/models/notification.ts +0 -24
- package/hono/src/modules/auth/database/models/notification.ts +0 -24
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Providers
|
|
2
|
+
|
|
3
|
+
Provider files in this folder are imported automatically when the application
|
|
4
|
+
boots. Use them for anything the **whole app** needs — a replacement auth
|
|
5
|
+
implementation, a payment gateway, an SMS driver, a storage backend.
|
|
6
|
+
|
|
7
|
+
There is no wiring step: drop a file in here and it runs.
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
1. Every `src/providers/**/*.{ts,js,mjs}` file is imported at boot.
|
|
12
|
+
2. Every `src/modules/<module>/providers.ts` file is imported at boot too, so a
|
|
13
|
+
module can plug itself into the app without the app knowing about it.
|
|
14
|
+
3. Every `src/modules/<module>/providers/*.ts` file is imported at boot as well,
|
|
15
|
+
for a module that offers more than one implementation.
|
|
16
|
+
4. A provider file claims a contract by registering an implementation.
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
// src/providers/payment.ts
|
|
20
|
+
import { registerProvider } from "@/framework/facade.js";
|
|
21
|
+
|
|
22
|
+
registerProvider("payment", {
|
|
23
|
+
async charge(order) {
|
|
24
|
+
return { id: "ch_123", status: "paid" };
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Read it back the same way:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { getProvider } from "@/framework/facade.js";
|
|
33
|
+
|
|
34
|
+
const payment = getProvider<any>("payment");
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Generating one
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm run maker provider:make payment
|
|
41
|
+
npm run maker module:make-provider billing stripe
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`provider:make` writes `src/providers/<name>.ts` for the whole app.
|
|
45
|
+
`module:make-provider` writes `src/modules/<module>/providers/<name>.ts` for a
|
|
46
|
+
single module. Both files register themselves when they are imported.
|
|
47
|
+
|
|
48
|
+
## Replacing the built-in auth
|
|
49
|
+
|
|
50
|
+
The framework ships with an auth module under `src/modules/auth`. To replace
|
|
51
|
+
it, delete that folder and register your own auth provider:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
// src/providers/auth.ts
|
|
55
|
+
import { registerAuthProvider } from "@/framework/facade.js";
|
|
56
|
+
import type { AuthProvider } from "@/framework/facade.js";
|
|
57
|
+
|
|
58
|
+
const authProvider: AuthProvider = {
|
|
59
|
+
async getUserById(id) {
|
|
60
|
+
// Return any user shape you like. Extra fields (tenantId, plan, status, ...)
|
|
61
|
+
// are passed straight through to `c.get("auth")` / `res.locals.auth`.
|
|
62
|
+
return { id, email: "user@example.com", tenantId: 42, plan: "pro" };
|
|
63
|
+
},
|
|
64
|
+
async findRefreshToken(jti) {
|
|
65
|
+
// Return the stored refresh token, or null when it is unknown.
|
|
66
|
+
return { id: 1, jti, revoked: false, expiresAt: new Date() };
|
|
67
|
+
},
|
|
68
|
+
async revokeRefreshToken(tokenId) {
|
|
69
|
+
// Optional. Called when a refresh token is expired or revoked.
|
|
70
|
+
},
|
|
71
|
+
async getAuthContext(user, payload) {
|
|
72
|
+
// Optional. Shapes what handlers receive as the auth context.
|
|
73
|
+
return { id: user.id, email: user.email, tenantId: user.tenantId };
|
|
74
|
+
},
|
|
75
|
+
async getUserContact(userId) {
|
|
76
|
+
// Optional. Used by `notify()` to find the email address of a user.
|
|
77
|
+
return { email: "user@example.com", name: "User" };
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
registerAuthProvider(authProvider);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Import `registerAuthProvider` and the `AuthProvider` type from
|
|
85
|
+
`@/framework/facade.js` — never from `@/framework/...` internals. The facade is
|
|
86
|
+
the public API of the framework.
|
|
87
|
+
|
|
88
|
+
## Module-to-module
|
|
89
|
+
|
|
90
|
+
Modules do not import each other. They talk through:
|
|
91
|
+
|
|
92
|
+
- `src/modules/<module>/facade.ts` — the public API of a module.
|
|
93
|
+
- `dispatchEvent` / `dispatchCommand` — for cross-module notifications.
|
|
94
|
+
- `src/providers/` — for app-wide implementations.
|
|
95
|
+
|
|
96
|
+
## Contract reference
|
|
97
|
+
|
|
98
|
+
| Method | Required | Purpose |
|
|
99
|
+
| ----------------------------------- | -------- | -------------------------------------------------------------- |
|
|
100
|
+
| `getUserById(id)` | Yes | Loads a user. Any extra fields are passed through to the auth context. |
|
|
101
|
+
| `findRefreshToken(jti)` | Yes | Loads a stored refresh token by its JWT id. |
|
|
102
|
+
| `revokeRefreshToken(id)` | No | Revokes a refresh token. `deleteRefreshToken(id)` also works. |
|
|
103
|
+
| `getAuthContext(user, payload)` | No | Shapes the object handlers receive as `auth`. |
|
|
104
|
+
| `getUserContact(userId)` | No | Finds the email/name of a user, used by notifications. |
|
|
105
|
+
|
|
106
|
+
When no provider is registered and `src/modules/auth` was deleted, the auth
|
|
107
|
+
middleware logs a warning and lets the request through instead of crashing.
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
</template>
|
|
54
54
|
|
|
55
55
|
<script setup lang="ts">
|
|
56
|
-
import { useHead } from "@
|
|
56
|
+
import { useHead } from "@unhead/vue";
|
|
57
57
|
import { ref } from "vue";
|
|
58
58
|
import { useRoute, useRouter } from "vue-router";
|
|
59
59
|
import Button from "@/components/Button.vue";
|
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Pagebar title="Dashboard" />
|
|
3
|
-
|
|
4
|
-
<div class="dashboard-placeholder">
|
|
5
|
-
<div class="row g-2 mb-2">
|
|
6
|
-
<div class="col-12 col-md-4">
|
|
7
|
-
<div class="placeholder-card"></div>
|
|
8
|
-
</div>
|
|
9
|
-
<div class="col-12 col-md-4">
|
|
10
|
-
<div class="placeholder-card"></div>
|
|
11
|
-
</div>
|
|
12
|
-
<div class="col-12 col-md-4">
|
|
13
|
-
<div class="placeholder-card"></div>
|
|
14
|
-
</div>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
<div class="placeholder-panel"></div>
|
|
18
|
-
</div>
|
|
19
|
-
</template>
|
|
20
|
-
|
|
21
|
-
<script setup lang="ts">
|
|
22
|
-
import { useHead } from "@
|
|
23
|
-
import { onMounted, onUnmounted } from "vue";
|
|
24
|
-
import Pagebar from "@/components/Pagebar.vue";
|
|
25
|
-
import { useAuth } from "@/composables/useAuth";
|
|
26
|
-
import { pulse } from "@/plugins/pulse";
|
|
27
|
-
|
|
28
|
-
useHead({ title: "Dashboard" });
|
|
29
|
-
|
|
30
|
-
const { user } = useAuth();
|
|
31
|
-
|
|
32
|
-
onMounted(() => {
|
|
33
|
-
const ch = pulse.channel("user");
|
|
34
|
-
ch.listen("user.changed", () => alert("me"));
|
|
35
|
-
onUnmounted(() => ch.stopListening("user.changed"));
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// const hardRefresh = () => window.location.reload();
|
|
39
|
-
</script>
|
|
40
|
-
|
|
41
|
-
<style scoped>
|
|
42
|
-
.placeholder-card,
|
|
43
|
-
.placeholder-panel {
|
|
44
|
-
border: 1px solid var(--app-border);
|
|
45
|
-
border-radius: 0.3rem;
|
|
46
|
-
background: var(--app-surface);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.placeholder-card {
|
|
50
|
-
min-height: 220px;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.placeholder-panel {
|
|
54
|
-
min-height: 520px;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
@media (max-width: 768px) {
|
|
58
|
-
.placeholder-card {
|
|
59
|
-
min-height: 160px;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.placeholder-panel {
|
|
63
|
-
min-height: 360px;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<Pagebar title="Dashboard" />
|
|
3
|
+
|
|
4
|
+
<div class="dashboard-placeholder">
|
|
5
|
+
<div class="row g-2 mb-2">
|
|
6
|
+
<div class="col-12 col-md-4">
|
|
7
|
+
<div class="placeholder-card"></div>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="col-12 col-md-4">
|
|
10
|
+
<div class="placeholder-card"></div>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="col-12 col-md-4">
|
|
13
|
+
<div class="placeholder-card"></div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div class="placeholder-panel"></div>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
import { useHead } from "@unhead/vue";
|
|
23
|
+
import { onMounted, onUnmounted } from "vue";
|
|
24
|
+
import Pagebar from "@/components/Pagebar.vue";
|
|
25
|
+
import { useAuth } from "@/composables/useAuth";
|
|
26
|
+
import { pulse } from "@/plugins/pulse";
|
|
27
|
+
|
|
28
|
+
useHead({ title: "Dashboard" });
|
|
29
|
+
|
|
30
|
+
const { user } = useAuth();
|
|
31
|
+
|
|
32
|
+
onMounted(() => {
|
|
33
|
+
const ch = pulse.channel("user");
|
|
34
|
+
ch.listen("user.changed", () => alert("me"));
|
|
35
|
+
onUnmounted(() => ch.stopListening("user.changed"));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// const hardRefresh = () => window.location.reload();
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<style scoped>
|
|
42
|
+
.placeholder-card,
|
|
43
|
+
.placeholder-panel {
|
|
44
|
+
border: 1px solid var(--app-border);
|
|
45
|
+
border-radius: 0.3rem;
|
|
46
|
+
background: var(--app-surface);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.placeholder-card {
|
|
50
|
+
min-height: 220px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.placeholder-panel {
|
|
54
|
+
min-height: 520px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@media (max-width: 768px) {
|
|
58
|
+
.placeholder-card {
|
|
59
|
+
min-height: 160px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.placeholder-panel {
|
|
63
|
+
min-height: 360px;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nexwire",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Scaffold a new nexwire project",
|
|
6
6
|
"bin": {
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"@socket.io/admin-ui": "^0.5",
|
|
52
52
|
"@socket.io/bun-engine": "^0.1",
|
|
53
53
|
"@socket.io/redis-adapter": "^8",
|
|
54
|
+
"@unhead/vue": "^3",
|
|
54
55
|
"@vitejs/plugin-vue": "^6",
|
|
55
56
|
"@vueuse/core": "^14",
|
|
56
|
-
"@vueuse/head": "^2",
|
|
57
57
|
"axios": "^1",
|
|
58
58
|
"bcryptjs": "^3",
|
|
59
59
|
"bootstrap": "^5",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"bullmq": "^5",
|
|
62
62
|
"bullmq-durable": "^0.2",
|
|
63
63
|
"chalk": "^5",
|
|
64
|
-
"commander": "^
|
|
64
|
+
"commander": "^15",
|
|
65
65
|
"croner": "^10",
|
|
66
66
|
"dotenv": "^17",
|
|
67
67
|
"dotenv-expand": "^13",
|
|
@@ -72,14 +72,14 @@
|
|
|
72
72
|
"ioredis": "^5",
|
|
73
73
|
"lodash-es": "^4",
|
|
74
74
|
"luxon": "^3",
|
|
75
|
-
"maildev": "^
|
|
75
|
+
"maildev": "^3",
|
|
76
76
|
"mysql2": "^3",
|
|
77
|
-
"nodemailer": "^
|
|
77
|
+
"nodemailer": "^10",
|
|
78
78
|
"pinia": "^3",
|
|
79
79
|
"pino": "^10",
|
|
80
80
|
"postgres": "^3",
|
|
81
81
|
"redis-commander": "^0.9.0",
|
|
82
|
-
"sass
|
|
82
|
+
"sass": "^1",
|
|
83
83
|
"socket.io": "^4",
|
|
84
84
|
"socket.io-client": "^4",
|
|
85
85
|
"stoker": "^2",
|
|
@@ -123,13 +123,13 @@
|
|
|
123
123
|
"@socket.io/redis-adapter": {
|
|
124
124
|
"optional": true
|
|
125
125
|
},
|
|
126
|
-
"@
|
|
126
|
+
"@unhead/vue": {
|
|
127
127
|
"optional": true
|
|
128
128
|
},
|
|
129
|
-
"@
|
|
129
|
+
"@vitejs/plugin-vue": {
|
|
130
130
|
"optional": true
|
|
131
131
|
},
|
|
132
|
-
"@vueuse/
|
|
132
|
+
"@vueuse/core": {
|
|
133
133
|
"optional": true
|
|
134
134
|
},
|
|
135
135
|
"axios": {
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
"redis-commander": {
|
|
208
208
|
"optional": true
|
|
209
209
|
},
|
|
210
|
-
"sass
|
|
210
|
+
"sass": {
|
|
211
211
|
"optional": true
|
|
212
212
|
},
|
|
213
213
|
"socket.io": {
|
package/src/index.js
CHANGED
|
@@ -130,22 +130,30 @@ async function main() {
|
|
|
130
130
|
console.log(`create-nexwire v${version}`);
|
|
131
131
|
console.log();
|
|
132
132
|
console.log("Usage:");
|
|
133
|
-
console.log(" npm create nexwire@latest <project-name
|
|
134
|
-
console.log(" pnpm create nexwire@latest <project-name
|
|
135
|
-
console.log(" bun create nexwire@latest <project-name
|
|
136
|
-
console.log(" npx create-nexwire@latest <project-name
|
|
133
|
+
console.log(" npm create nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
134
|
+
console.log(" pnpm create nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
135
|
+
console.log(" bun create nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
136
|
+
console.log(" npx create-nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
137
137
|
console.log();
|
|
138
138
|
console.log("Engines:");
|
|
139
139
|
console.log(" hono (default) Hono-based HTTP layer and OpenAPI");
|
|
140
140
|
console.log(" express Express-based HTTP layer and OpenAPI");
|
|
141
|
+
console.log();
|
|
142
|
+
console.log("Tip:");
|
|
143
|
+
console.log(" Use '.' to scaffold into the current directory (must be empty).");
|
|
141
144
|
process.exit(0);
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
if (!projectName) {
|
|
145
|
-
projectName = await ask("Project name: ");
|
|
148
|
+
projectName = await ask("Project name or '.' for the current directory: ");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!projectName) {
|
|
152
|
+
console.error("Error: Please provide a project name or '.' to scaffold into the current directory.");
|
|
153
|
+
process.exit(1);
|
|
146
154
|
}
|
|
147
155
|
|
|
148
|
-
if (
|
|
156
|
+
if (projectName !== "." && !isValidProjectName(projectName)) {
|
|
149
157
|
console.error("Error: Invalid project name. Use alphanumeric, dashes, or underscores, or '.' for the current directory.");
|
|
150
158
|
process.exit(1);
|
|
151
159
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { relations } from "drizzle-orm";
|
|
2
|
-
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
3
|
-
import { users } from "@/modules/auth/database/models/user.js";
|
|
4
|
-
|
|
5
|
-
export const notifications = sqliteTable("notifications", {
|
|
6
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
7
|
-
userId: integer("user_id")
|
|
8
|
-
.notNull()
|
|
9
|
-
.references(() => users.id, { onUpdate: "cascade", onDelete: "cascade" }),
|
|
10
|
-
type: text("type").notNull(),
|
|
11
|
-
title: text("title").notNull(),
|
|
12
|
-
body: text("body"),
|
|
13
|
-
data: text("data"),
|
|
14
|
-
link: text("link"),
|
|
15
|
-
readAt: integer("read_at", { mode: "timestamp" }),
|
|
16
|
-
createdAt: integer("created_at", { mode: "timestamp" }).defaultNow().notNull()
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
|
20
|
-
user: one(users, {
|
|
21
|
-
fields: [notifications.userId],
|
|
22
|
-
references: [users.id]
|
|
23
|
-
})
|
|
24
|
-
}));
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { relations } from "drizzle-orm";
|
|
2
|
-
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
3
|
-
import { users } from "@/modules/auth/database/models/user.js";
|
|
4
|
-
|
|
5
|
-
export const notifications = sqliteTable("notifications", {
|
|
6
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
7
|
-
userId: integer("user_id")
|
|
8
|
-
.notNull()
|
|
9
|
-
.references(() => users.id, { onUpdate: "cascade", onDelete: "cascade" }),
|
|
10
|
-
type: text("type").notNull(),
|
|
11
|
-
title: text("title").notNull(),
|
|
12
|
-
body: text("body"),
|
|
13
|
-
data: text("data"),
|
|
14
|
-
link: text("link"),
|
|
15
|
-
readAt: integer("read_at", { mode: "timestamp" }),
|
|
16
|
-
createdAt: integer("created_at", { mode: "timestamp" }).defaultNow().notNull()
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
export const notificationsRelations = relations(notifications, ({ one }) => ({
|
|
20
|
-
user: one(users, {
|
|
21
|
-
fields: [notifications.userId],
|
|
22
|
-
references: [users.id]
|
|
23
|
-
})
|
|
24
|
-
}));
|