@huluwz/pg-ethiopian-calendar 1.1.0 → 1.1.1
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 +83 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/docs/prisma.md +83 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,9 @@ SELECT to_ethiopian_timestamp(); -- '2018-04-23 14:30:00'
|
|
|
45
45
|
SELECT ethiopian_calendar_version(); -- '1.1.0'
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
## Generated Columns
|
|
48
|
+
## Generated Columns (Timestamp)
|
|
49
|
+
|
|
50
|
+
Use `to_ethiopian_timestamp()` for DateTime/Timestamp columns:
|
|
49
51
|
|
|
50
52
|
```sql
|
|
51
53
|
CREATE TABLE orders (
|
|
@@ -56,17 +58,73 @@ CREATE TABLE orders (
|
|
|
56
58
|
);
|
|
57
59
|
```
|
|
58
60
|
|
|
61
|
+
For text format, use `to_ethiopian_date()`:
|
|
62
|
+
|
|
63
|
+
```sql
|
|
64
|
+
CREATE TABLE events (
|
|
65
|
+
id SERIAL PRIMARY KEY,
|
|
66
|
+
event_date TIMESTAMP NOT NULL,
|
|
67
|
+
event_date_ethiopian VARCHAR(10) GENERATED ALWAYS AS
|
|
68
|
+
(to_ethiopian_date(event_date)) STORED
|
|
69
|
+
);
|
|
70
|
+
```
|
|
71
|
+
|
|
59
72
|
## With Prisma
|
|
60
73
|
|
|
74
|
+
### Schema
|
|
75
|
+
|
|
76
|
+
```prisma
|
|
77
|
+
model Order {
|
|
78
|
+
id Int @id @default(autoincrement())
|
|
79
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
80
|
+
createdAtEthiopian DateTime? @map("created_at_ethiopian") // Generated column
|
|
81
|
+
|
|
82
|
+
@@map("orders")
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### ⚠️ Important: Migration Workflow
|
|
87
|
+
|
|
88
|
+
Prisma doesn't natively support `GENERATED ALWAYS AS` columns. You must create migrations manually:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# ❌ DON'T do this - Prisma will generate wrong SQL
|
|
92
|
+
npx prisma migrate dev
|
|
93
|
+
|
|
94
|
+
# ✅ DO this instead - create empty migration, then edit
|
|
95
|
+
npx prisma migrate dev --create-only --name add_orders_table
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then manually edit `migration.sql`:
|
|
99
|
+
|
|
100
|
+
```sql
|
|
101
|
+
CREATE TABLE "orders" (
|
|
102
|
+
"id" SERIAL PRIMARY KEY,
|
|
103
|
+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
104
|
+
"created_at_ethiopian" TIMESTAMP(3) GENERATED ALWAYS AS
|
|
105
|
+
(to_ethiopian_timestamp(created_at)) STORED
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Finally apply:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npx prisma migrate deploy
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Usage
|
|
116
|
+
|
|
61
117
|
```typescript
|
|
62
118
|
const order = await prisma.order.create({
|
|
63
119
|
data: { name: 'Test' }
|
|
64
120
|
});
|
|
65
|
-
console.log(order.createdAtEthiopian); // auto-populated
|
|
121
|
+
console.log(order.createdAtEthiopian); // auto-populated DateTime!
|
|
66
122
|
```
|
|
67
123
|
|
|
68
124
|
## With Drizzle
|
|
69
125
|
|
|
126
|
+
Drizzle has native support for generated columns:
|
|
127
|
+
|
|
70
128
|
```typescript
|
|
71
129
|
import { sql } from 'drizzle-orm';
|
|
72
130
|
|
|
@@ -78,6 +136,29 @@ export const orders = pgTable('orders', {
|
|
|
78
136
|
});
|
|
79
137
|
```
|
|
80
138
|
|
|
139
|
+
## With TypeORM
|
|
140
|
+
|
|
141
|
+
Use raw SQL in migrations:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
export class AddEthiopianCalendar1234567890 implements MigrationInterface {
|
|
145
|
+
async up(queryRunner: QueryRunner): Promise<void> {
|
|
146
|
+
// First, run the ethiopian calendar SQL from the package
|
|
147
|
+
await queryRunner.query(`/* ethiopian calendar functions */`);
|
|
148
|
+
|
|
149
|
+
// Then create table with generated column
|
|
150
|
+
await queryRunner.query(`
|
|
151
|
+
CREATE TABLE "orders" (
|
|
152
|
+
"id" SERIAL PRIMARY KEY,
|
|
153
|
+
"created_at" TIMESTAMP DEFAULT NOW(),
|
|
154
|
+
"created_at_ethiopian" TIMESTAMP GENERATED ALWAYS AS
|
|
155
|
+
(to_ethiopian_timestamp(created_at)) STORED
|
|
156
|
+
)
|
|
157
|
+
`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
81
162
|
## API
|
|
82
163
|
|
|
83
164
|
```typescript
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.listMigrations = listMigrations;
|
|
|
13
13
|
exports.getVersionCheckSql = getVersionCheckSql;
|
|
14
14
|
const fs_1 = require("fs");
|
|
15
15
|
const path_1 = require("path");
|
|
16
|
-
exports.VERSION = "1.1.
|
|
16
|
+
exports.VERSION = "1.1.1";
|
|
17
17
|
const ORM_PACKAGES = {
|
|
18
18
|
prisma: "@prisma/client",
|
|
19
19
|
drizzle: "drizzle-orm",
|
package/docs/prisma.md
CHANGED
|
@@ -6,88 +6,126 @@
|
|
|
6
6
|
# Install the package
|
|
7
7
|
npm install @huluwz/pg-ethiopian-calendar
|
|
8
8
|
|
|
9
|
-
# Generate migration
|
|
9
|
+
# Generate migration for ethiopian calendar functions
|
|
10
10
|
npx ethiopian-calendar init prisma
|
|
11
11
|
|
|
12
12
|
# Apply migration
|
|
13
|
-
npx prisma migrate
|
|
13
|
+
npx prisma migrate deploy
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
If you prefer to set up manually:
|
|
16
|
+
## Prisma Schema
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
```prisma
|
|
19
|
+
model Order {
|
|
20
|
+
id Int @id @default(autoincrement())
|
|
21
|
+
customerName String @map("customer_name")
|
|
22
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
23
|
+
createdAtEthiopian DateTime? @map("created_at_ethiopian") // Generated column
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
@@map("orders")
|
|
26
|
+
}
|
|
24
27
|
```
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
**Note:** `createdAtEthiopian` must be optional (`DateTime?`) since Prisma only reads it—PostgreSQL generates it.
|
|
30
|
+
|
|
31
|
+
## ⚠️ Important: Migration Workflow for Generated Columns
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
Prisma doesn't natively support PostgreSQL `GENERATED ALWAYS AS` columns. When adding tables with Ethiopian date columns, **do not run `prisma migrate dev` directly**.
|
|
29
34
|
|
|
30
|
-
###
|
|
35
|
+
### The Problem
|
|
31
36
|
|
|
32
37
|
```bash
|
|
38
|
+
# ❌ DON'T do this - Prisma will generate wrong SQL
|
|
33
39
|
npx prisma migrate dev
|
|
34
40
|
```
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
Prisma sees `createdAtEthiopian DateTime?` and creates a regular nullable column, not a generated one.
|
|
37
43
|
|
|
38
|
-
###
|
|
44
|
+
### The Solution
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
```bash
|
|
47
|
+
# ✅ Step 1: Create empty migration
|
|
48
|
+
npx prisma migrate dev --create-only --name add_orders_table
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# ✅ Step 2: Edit the generated migration.sql manually
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Replace Prisma's generated SQL with:
|
|
41
56
|
|
|
42
57
|
```sql
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
created_at_ethiopian TIMESTAMP GENERATED ALWAYS AS
|
|
58
|
+
CREATE TABLE "orders" (
|
|
59
|
+
"id" SERIAL PRIMARY KEY,
|
|
60
|
+
"customer_name" TEXT NOT NULL,
|
|
61
|
+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
62
|
+
"created_at_ethiopian" TIMESTAMP(3) GENERATED ALWAYS AS
|
|
49
63
|
(to_ethiopian_timestamp(created_at)) STORED
|
|
50
64
|
);
|
|
51
65
|
```
|
|
52
66
|
|
|
53
|
-
|
|
67
|
+
```bash
|
|
68
|
+
# ✅ Step 3: Apply the migration
|
|
69
|
+
npx prisma migrate deploy
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Generated Column Types
|
|
73
|
+
|
|
74
|
+
### Timestamp (Recommended)
|
|
75
|
+
|
|
76
|
+
Preserves full date and time:
|
|
77
|
+
|
|
78
|
+
```sql
|
|
79
|
+
"created_at_ethiopian" TIMESTAMP(3) GENERATED ALWAYS AS
|
|
80
|
+
(to_ethiopian_timestamp(created_at)) STORED
|
|
81
|
+
```
|
|
54
82
|
|
|
55
83
|
```prisma
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
customerName String @map("customer_name")
|
|
59
|
-
createdAt DateTime @default(now()) @map("created_at")
|
|
60
|
-
createdAtEthiopian DateTime @map("created_at_ethiopian")
|
|
84
|
+
createdAtEthiopian DateTime? @map("created_at_ethiopian")
|
|
85
|
+
```
|
|
61
86
|
|
|
62
|
-
|
|
63
|
-
|
|
87
|
+
Result: `2018-04-26T12:30:00.000Z`
|
|
88
|
+
|
|
89
|
+
### Text/String
|
|
90
|
+
|
|
91
|
+
Date-only format:
|
|
92
|
+
|
|
93
|
+
```sql
|
|
94
|
+
"created_at_ethiopian" VARCHAR(10) GENERATED ALWAYS AS
|
|
95
|
+
(to_ethiopian_date(created_at)) STORED
|
|
64
96
|
```
|
|
65
97
|
|
|
66
|
-
|
|
98
|
+
```prisma
|
|
99
|
+
createdAtEthiopian String? @map("created_at_ethiopian") @db.VarChar(10)
|
|
100
|
+
```
|
|
67
101
|
|
|
68
|
-
|
|
102
|
+
Result: `"2018-04-26"`
|
|
103
|
+
|
|
104
|
+
## Usage in Code
|
|
69
105
|
|
|
70
106
|
```typescript
|
|
71
107
|
import { PrismaClient } from '@prisma/client'
|
|
72
108
|
|
|
73
109
|
const prisma = new PrismaClient()
|
|
74
110
|
|
|
75
|
-
// Create - Ethiopian date is auto-generated
|
|
111
|
+
// Create - Ethiopian date is auto-generated by PostgreSQL
|
|
76
112
|
const order = await prisma.order.create({
|
|
77
113
|
data: {
|
|
78
114
|
customerName: 'Abebe Kebede',
|
|
79
115
|
}
|
|
80
116
|
})
|
|
81
117
|
|
|
82
|
-
console.log(order.
|
|
118
|
+
console.log(order.createdAt) // 2026-01-04T12:30:00.000Z (Gregorian)
|
|
119
|
+
console.log(order.createdAtEthiopian) // 2018-04-26T12:30:00.000Z (Ethiopian)
|
|
83
120
|
|
|
84
|
-
// Raw
|
|
85
|
-
const today = await prisma.$queryRaw`
|
|
86
|
-
|
|
87
|
-
`
|
|
121
|
+
// Raw queries for calendar utilities
|
|
122
|
+
const today = await prisma.$queryRaw`SELECT to_ethiopian_date()`
|
|
123
|
+
const converted = await prisma.$queryRaw`SELECT from_ethiopian_date('2018-04-26')`
|
|
88
124
|
```
|
|
89
125
|
|
|
90
|
-
|
|
126
|
+
## Functional Index
|
|
127
|
+
|
|
128
|
+
For fast queries by Ethiopian date:
|
|
91
129
|
|
|
92
130
|
```sql
|
|
93
131
|
CREATE INDEX idx_orders_ethiopian
|
|
@@ -98,31 +136,34 @@ ON orders (to_ethiopian_date(created_at));
|
|
|
98
136
|
|
|
99
137
|
| Function | Description |
|
|
100
138
|
|----------|-------------|
|
|
139
|
+
| `to_ethiopian_date()` | Current Ethiopian date as text |
|
|
101
140
|
| `to_ethiopian_date(timestamp)` | Convert to Ethiopian date string (YYYY-MM-DD) |
|
|
102
141
|
| `from_ethiopian_date(text)` | Convert Ethiopian date to Gregorian timestamp |
|
|
142
|
+
| `to_ethiopian_timestamp()` | Current Ethiopian timestamp |
|
|
103
143
|
| `to_ethiopian_timestamp(timestamp)` | Convert preserving time (for generated columns) |
|
|
104
|
-
| `
|
|
144
|
+
| `ethiopian_calendar_version()` | Package version |
|
|
105
145
|
|
|
106
146
|
## Troubleshooting
|
|
107
147
|
|
|
108
148
|
### Migration Already Exists
|
|
109
149
|
|
|
110
|
-
If you get an error about the migration already existing:
|
|
111
|
-
|
|
112
150
|
```bash
|
|
113
151
|
npx prisma migrate resolve --applied 20240101000000_ethiopian_calendar
|
|
114
152
|
```
|
|
115
153
|
|
|
116
154
|
### Functions Not Found
|
|
117
155
|
|
|
118
|
-
|
|
156
|
+
Check migration status:
|
|
119
157
|
|
|
120
158
|
```bash
|
|
121
159
|
npx prisma migrate status
|
|
122
160
|
```
|
|
123
161
|
|
|
162
|
+
### Prisma Tries to "Fix" Generated Columns
|
|
163
|
+
|
|
164
|
+
If Prisma shows a migration to alter your generated columns, cancel it. The schema is correct—Prisma just doesn't understand generated columns.
|
|
165
|
+
|
|
124
166
|
## Links
|
|
125
167
|
|
|
126
168
|
- [GitHub Repository](https://github.com/HuluWZ/pg-ethiopian-calendar)
|
|
127
169
|
- [NPM Package](https://www.npmjs.com/package/@huluwz/pg-ethiopian-calendar)
|
|
128
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huluwz/pg-ethiopian-calendar",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Ethiopian calendar functions for PostgreSQL - works with Prisma, Drizzle, TypeORM",
|
|
5
5
|
"author": "Hulunlante Worku <hulunlante.w@gmail.com>",
|
|
6
6
|
"license": "PostgreSQL",
|