Skip to content

Commit 21e2fd1

Browse files
Merge pull request #13 from celestifyhq/dx
Dx
2 parents 8df0f80 + 26a6478 commit 21e2fd1

File tree

10 files changed

+5449
-1290
lines changed

10 files changed

+5449
-1290
lines changed

.github/workflows/npm-publish.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ jobs:
2727
- name: Build
2828
run: npm run build
2929

30+
- name: Run Tests
31+
run: npm test
32+
3033
- name: Create Release Pull Request or Publish
3134
id: changesets
3235
uses: changesets/action@v1

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
dist/*
2-
test/*
32
.vscode/
43
node_modules/
54
.dev.vars

RELEASING.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Releasing a New Version
2+
3+
This project uses [Changesets](https://github.com/changesets/changesets) to manage versioning and publishing to npm. The process is automated using GitHub Actions.
4+
5+
## Steps to Release
6+
7+
1. **Make your code changes**: Implement your features, bug fixes, etc., on a feature branch (e.g., `issue/your-issue-number` or `feat/short-description`).
8+
9+
2. **Create a Changeset**:
10+
Before committing your changes, or after your main changes are staged, run the following command:
11+
```bash
12+
npx changeset
13+
```
14+
* You will be prompted to select the package(s) to version (select `fcm-cloudflare-workers`).
15+
* Choose the type of change according to [SemVer](https://semver.org/) (patch, minor, or major).
16+
* `patch`: For bug fixes or very small changes (e.g., 2.0.0 -> 2.0.1)
17+
* `minor`: For new features that are backward-compatible (e.g., 2.0.0 -> 2.1.0)
18+
* `major`: For breaking changes (e.g., 2.0.0 -> 3.0.0)
19+
* Enter a clear and concise summary of the changes. This summary will be used in the `CHANGELOG.md`.
20+
21+
3. **Commit the Changeset and Your Code**:
22+
Add the generated changeset file (located in the `.changeset/` directory) and your code changes to git and commit them:
23+
```bash
24+
git add .
25+
git commit -m "feat: your descriptive commit message (includes changeset)"
26+
```
27+
Or, if you prefer separate commits:
28+
```bash
29+
git add .changeset/your-changeset-name.md
30+
git commit -m "chore: add changeset for upcoming release"
31+
# then commit your code changes
32+
git add src/ # or other changed files
33+
git commit -m "feat: implemented new feature X"
34+
```
35+
36+
4. **Push Your Branch**:
37+
Push your feature branch to GitHub:
38+
```bash
39+
git push origin your-branch-name
40+
```
41+
42+
5. **Create a Pull Request**:
43+
Go to the GitHub repository and create a Pull Request (PR) from your feature branch to the `main` branch.
44+
45+
6. **Merge the Pull Request**:
46+
Once the PR is reviewed and approved, merge it into the `main` branch.
47+
48+
7. **Automatic Versioning and Publishing**:
49+
* Upon merging to `main`, the `Publish to npm` GitHub Action (defined in `.github/workflows/npm-publish.yml`) will trigger.
50+
* This action uses the changeset to:
51+
* Bump the version in `package.json`.
52+
* Update `CHANGELOG.md`.
53+
* Publish the new version to npm.
54+
* Create a new PR titled "chore: version packages" (or similar) which contains the version bump and changelog updates.
55+
56+
8. **Merge the Versioning Pull Request**:
57+
Review and merge the "chore: version packages" PR created by the Changesets action. This finalizes the release process by updating the `package.json` and `CHANGELOG.md` on the `main` branch.
58+
59+
Your package is now published with the new version!

fixtures/fcm.middleware.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,50 @@
11
import type { Context, MiddlewareHandler } from "hono";
22
import { FCM, FcmOptions } from 'fcm-cloudflare-workers';
3+
import { KVNamespace } from "@cloudflare/workers-types";
34

4-
import { env } from "hono/adapter";
5-
6-
type FirebaseEnv = {
5+
export type FcmMiddlewareBindings = {
76
FIREBASE_SERVICE_ACCOUNT_JSON: string;
87
MY_WORKER_CACHE: KVNamespace;
98
};
109

10+
export type FcmMiddlewareVariables = {
11+
fcm: FCM;
12+
};
13+
1114
/**
1215
* An abstracted middleware that creates an instance of an FCM client
1316
*
1417
* @param c
1518
* @param next
1619
*/
17-
export const fcmMiddleware: MiddlewareHandler = async (
18-
c: Context,
19-
next: any,
20+
export const fcmMiddleware: MiddlewareHandler<{ Bindings: FcmMiddlewareBindings, Variables: FcmMiddlewareVariables }> = async (
21+
c: Context<{ Bindings: FcmMiddlewareBindings, Variables: FcmMiddlewareVariables }>,
22+
next: () => Promise<void>,
2023
) => {
21-
const firebaseEnv = env<FirebaseEnv>(c);
22-
23-
const fcmOptions = new FcmOptions({
24-
serviceAccount: JSON.parse(firebaseEnv.FIREBASE_SERVICE_ACCOUNT_JSON),
25-
kvStore: firebaseEnv.MY_WORKER_CACHE,
26-
kvCacheKey: "fcm-token-cache",
27-
});
24+
const serviceAccountJson = c.env.FIREBASE_SERVICE_ACCOUNT_JSON;
25+
const kvCache = c.env.MY_WORKER_CACHE;
2826

29-
const fcmClient = new FCM(fcmOptions);
27+
if (!serviceAccountJson) {
28+
console.error("FIREBASE_SERVICE_ACCOUNT_JSON not found in c.env");
29+
throw new Error("FIREBASE_SERVICE_ACCOUNT_JSON not found in environment bindings.");
30+
}
31+
if (!kvCache) {
32+
console.error("MY_WORKER_CACHE not found in c.env");
33+
throw new Error("MY_WORKER_CACHE not found in environment bindings.");
34+
}
3035

31-
c.set("fcm", fcmClient);
36+
try {
37+
const fcmOptions = new FcmOptions({
38+
serviceAccount: JSON.parse(serviceAccountJson),
39+
kvStore: kvCache,
40+
kvCacheKey: "fcm-token-cache",
41+
});
42+
const fcmClient = new FCM(fcmOptions);
43+
c.set("fcm", fcmClient);
44+
} catch (e) {
45+
console.error("Error initializing FCM client in middleware:", e);
46+
throw e;
47+
}
48+
3249
await next();
3350
};

fixtures/index.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,38 @@
11
import { Hono } from "hono";
2-
import { fcmMiddleware } from "./fcm.middleware";
2+
import { fcmMiddleware, FcmMiddlewareBindings, FcmMiddlewareVariables } from "./fcm.middleware";
33
import { z } from "zod";
44
import { zValidator } from "@hono/zod-validator";
55
import { StatusCode } from "hono/utils/http-status";
66
import { FCM, FcmMessage, EnhancedFcmMessage } from "fcm-cloudflare-workers";
7-
import { KVNamespace } from "@cloudflare/workers-types";
87

9-
type Bindings = {
10-
FIREBASE_PROJECT_ID: string; // Firebase project ID
11-
FIREBASE_SERVICE_ACCOUNT_JSON: string; // Firebase service account JSON
12-
MY_WORKER_CACHE: KVNamespace; // Worker KV namespace
8+
type AppBindings = FcmMiddlewareBindings & {
9+
// ANOTHER_KV: KVNamespace;
1310
};
1411

15-
type Variables = {
12+
type AppVariables = FcmMiddlewareVariables & {
1613
error: {
1714
response: (
18-
StatusCode: StatusCode,
15+
statusCode: number,
1916
message: string,
2017
description: string
21-
) => void;
18+
) => Response;
2219
};
23-
fcm: FCM,
2420
};
2521

26-
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>().basePath(
22+
const app = new Hono<{ Bindings: AppBindings; Variables: AppVariables }>().basePath(
2723
"/api"
2824
);
2925

26+
app.use(async (c, next) => {
27+
c.set("error", {
28+
response: (statusCode, message, description) => {
29+
console.error(`Error: ${message} - ${description}`);
30+
return c.json({ error: message, description }, statusCode as any);
31+
},
32+
});
33+
await next();
34+
});
35+
3036
app.use(fcmMiddleware);
3137

3238
// Schema for legacy single push
@@ -92,7 +98,7 @@ app.post("/push-single", zValidator("json", sendSinglePushSchema), async (c) =>
9298
}
9399
} catch (error) {
94100
console.log(error);
95-
return c.var.error.response(400, "Sending Failed", error.message);
101+
return c.var.error.response(400, "Sending Failed", (error as Error).message);
96102
}
97103

98104
return c.json({ success: true });
@@ -119,7 +125,7 @@ app.post("/push-multi", zValidator("json", sendMultiPushSchema), async (c) => {
119125
}
120126
} catch (error) {
121127
console.log(error);
122-
return c.var.error.response(400, "Sending Failed", error.message);
128+
return c.var.error.response(400, "Sending Failed", (error as Error).message);
123129
}
124130

125131
return c.json({ success: true });
@@ -136,7 +142,7 @@ app.post("/v2/push-token", zValidator("json", z.object({
136142
return c.json({ success: true });
137143
} catch (error) {
138144
console.log(error);
139-
return c.var.error.response(400, "Sending Failed", error.message);
145+
return c.var.error.response(400, "Sending Failed", (error as Error).message);
140146
}
141147
});
142148

@@ -154,7 +160,7 @@ app.post("/v2/push-tokens", zValidator("json", z.object({
154160
});
155161
} catch (error) {
156162
console.log(error);
157-
return c.var.error.response(400, "Sending Failed", error.message);
163+
return c.var.error.response(400, "Sending Failed", (error as Error).message);
158164
}
159165
});
160166

@@ -169,7 +175,7 @@ app.post("/v2/push-topic", zValidator("json", z.object({
169175
return c.json({ success: true });
170176
} catch (error) {
171177
console.log(error);
172-
return c.var.error.response(400, "Sending Failed", error.message);
178+
return c.var.error.response(400, "Sending Failed", (error as Error).message);
173179
}
174180
});
175181

@@ -184,7 +190,7 @@ app.post("/v2/push-condition", zValidator("json", z.object({
184190
return c.json({ success: true });
185191
} catch (error) {
186192
console.log(error);
187-
return c.var.error.response(400, "Sending Failed", error.message);
193+
return c.var.error.response(400, "Sending Failed", (error as Error).message);
188194
}
189195
});
190196

jest.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
testEnvironment: 'node',
4+
testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
5+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
6+
};

0 commit comments

Comments
 (0)