Skip to content

Commit 5c1fa4b

Browse files
authored
Merge pull request #16 from owenr88/release/1.2.0
v1.2.0
2 parents 486d7cd + 89c10ee commit 5c1fa4b

File tree

9 files changed

+173
-109
lines changed

9 files changed

+173
-109
lines changed

.github/workflows/on-close-pr.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
with:
5050
github_token: ${{ secrets.GITHUB_TOKEN }}
5151
custom_tag: ${{ steps.split.outputs.VERSION }}
52+
tag_prefix: ""
5253
- name: Create a GitHub release
5354
uses: ncipollo/release-action@v1
5455
with:

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Run `npm run start` to watch all packages for local development.
2020

2121
Please open an issue and create a pull request with any contributions.
2222

23+
We generate the changelog using [Angular's git message conventions](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).
24+
2325
## Release
2426

25-
Create a new release in Github to automatically bump the package.json version and release to NPM. Too easy!
27+
Close a new release/x.x.x PR to release to NPM. Too easy!

package-lock.json

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cognito-export/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cognito-export",
33
"description": "A simple CLI tool and JavaScript package for exporting users from an AWS Cognito user pool.",
4-
"version": "1.1.10",
4+
"version": "1.2.0",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
77
"bin": "dist/cli.js",
@@ -27,6 +27,7 @@
2727
"chalk": "^4.1.2",
2828
"commander": "^12.0.0",
2929
"papaparse": "^5.4.1",
30+
"zod": "^3.23.8",
3031
"zod-cognito": "^1.0.13"
3132
},
3233
"devDependencies": {

packages/cognito-export/src/exporter.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { ListUsersRequest } from "@aws-sdk/client-cognito-identity-provider";
22
import * as fs from "fs";
33
import Papa from "papaparse";
4+
import { z } from "zod";
45
import {
56
ImportRecordSchema,
67
ImportRecordSchemaType,
8+
extractCustomAttributeKeys,
79
parseUserAttributes,
810
} from "zod-cognito";
911
import CognitoBase from "./CognitoBase";
@@ -30,8 +32,22 @@ export class CognitoExport extends CognitoBase {
3032
res?.Users?.forEach((user) => {
3133
if (users.length >= limit) return false;
3234

35+
// Convert the customAttributeKeys to an object
36+
const customAttributeKeys = extractCustomAttributeKeys(
37+
user.Attributes ?? []
38+
);
39+
const customAttr: Record<string, z.ZodType<string | number>> = {};
40+
customAttributeKeys?.forEach((key) => {
41+
customAttr[key] = z.union([z.string(), z.number()]);
42+
});
43+
customAttr.sub = z.string(); // Add this to exported data
44+
const customAttributes = z.object(customAttr);
45+
3346
// Map the attributes to a key-value object
34-
const attrbs = parseUserAttributes(user.Attributes);
47+
const attrbs = parseUserAttributes<typeof customAttr>(
48+
user.Attributes,
49+
customAttributes
50+
);
3551

3652
// Return if some core data isn't there
3753
if (!user.Username) {
@@ -54,12 +70,15 @@ export class CognitoExport extends CognitoBase {
5470
return false;
5571
}
5672

73+
// Delete the sub field from the export list
74+
const { sub, ...attributesToExport } = attrbs;
75+
5776
// Add the user to the list
5877
const newUser = ImportRecordSchema.safeParse({
5978
"cognito:username": user.Username,
6079
"cognito:mfa_enabled": false,
6180
updated_at: (user.UserLastModifiedDate ?? new Date()).toISOString(),
62-
...attrbs,
81+
...attributesToExport,
6382
});
6483
if (!newUser.success) {
6584
this.log(

packages/cognito-import/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cognito-import",
33
"description": "A simple CLI tool and JavaScript package for importing users into an AWS Cognito user pool.",
4-
"version": "1.1.10",
4+
"version": "1.2.0",
55
"main": "dist/index.js",
66
"bin": "dist/cli.js",
77
"repository": {

packages/zod-cognito/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "zod-cognito",
33
"description": "Zod schemas for AWS Cognito User Pools",
4-
"version": "1.1.10",
4+
"version": "1.2.0",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
77
"repository": {

packages/zod-cognito/src/index.test.ts

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ import {
44
ImportRecordSchema,
55
ImportRecordSchemaType,
66
RawImportRecordSchema,
7-
UserAttributesSchema,
8-
UserAttributesSchemaType,
7+
RawUserAttributesSchema,
8+
RawUserAttributesSchemaType,
9+
extractCustomAttributeKeys,
910
parseUserAttributes,
11+
refineExtendedUserAttributesSchema,
1012
} from ".";
1113

1214
describe("UserAttributesSchema", () => {
15+
const RefinedUserAttributesSchema = refineExtendedUserAttributesSchema(
16+
RawUserAttributesSchema
17+
);
1318
it("should parse with email fields", () => {
1419
expect(
15-
UserAttributesSchema.safeParse({
20+
RefinedUserAttributesSchema.safeParse({
1621
sub: "test",
1722
email: "hello@test.com",
1823
email_verified: "true",
@@ -21,7 +26,7 @@ describe("UserAttributesSchema", () => {
2126
});
2227
it("should not parse email_verified without email", () => {
2328
expect(
24-
UserAttributesSchema.safeParse({
29+
RefinedUserAttributesSchema.safeParse({
2530
sub: "test",
2631
email: "",
2732
email_verified: "true",
@@ -30,7 +35,7 @@ describe("UserAttributesSchema", () => {
3035
});
3136
it("should not parse phone_number_verified without phone_number", () => {
3237
expect(
33-
UserAttributesSchema.safeParse({
38+
RefinedUserAttributesSchema.safeParse({
3439
sub: "test",
3540
phone_number: "",
3641
phone_number_verified: "true",
@@ -39,22 +44,13 @@ describe("UserAttributesSchema", () => {
3944
});
4045
it("should parse with phone_number fields", () => {
4146
expect(
42-
UserAttributesSchema.safeParse({
47+
RefinedUserAttributesSchema.safeParse({
4348
sub: "test",
4449
phone_number: "+1234567890",
4550
phone_number_verified: "true",
4651
}).success
4752
).toBe(true);
4853
});
49-
it("should not parse without email or phone_number fields", () => {
50-
expect(
51-
UserAttributesSchema.safeParse({
52-
sub: "test",
53-
email_verified: "false",
54-
phone_number_verified: "false",
55-
}).success
56-
).toBe(false);
57-
});
5854
});
5955

6056
describe("parseUserAttributes", () => {
@@ -84,18 +80,39 @@ describe("parseUserAttributes", () => {
8480
expect(result.sub).toBe("test");
8581
expect(result.email).toBe("test@test.com");
8682
expect(result.email_verified).toBe(true);
87-
// expect(result["custom:thing"]).toBe("test2");
83+
// @ts-expect-error need to fix this
84+
expect(result["custom:thing"]).toBe("test2");
85+
});
86+
});
87+
88+
describe("extractCustomAttributeKeys", () => {
89+
it("should extract custom attributes", () => {
90+
const keys = extractCustomAttributeKeys([
91+
{ Name: "sub", Value: "test" },
92+
{ Name: "email", Value: "test@test.com" },
93+
{ Name: "email_verified", Value: "true" },
94+
{ Name: "custom:thing_one", Value: "exampl" },
95+
]);
96+
expect(keys).toHaveLength(1);
97+
expect(keys[0]).toBe("custom:thing_one");
98+
});
99+
it("should not extract when there are no custom attributes", () => {
100+
const keys = extractCustomAttributeKeys([
101+
{ Name: "sub", Value: "test" },
102+
{ Name: "email", Value: "test@test.com" },
103+
{ Name: "email_verified", Value: "true" },
104+
]);
105+
expect(keys).toHaveLength(0);
88106
});
89107
});
90108

91109
describe("ImportRecordSchema", () => {
92110
const birthdate = new Date(2024, 2, 20);
93-
const baseUser: UserAttributesSchemaType &
111+
const baseUser: Omit<RawUserAttributesSchemaType, "sub"> &
94112
Pick<
95113
ImportRecordSchemaType,
96114
"cognito:username" | "cognito:mfa_enabled" | "updated_at"
97115
> = {
98-
sub: "test",
99116
"cognito:username": "test",
100117
name: "test",
101118
given_name: "test",
@@ -155,13 +172,6 @@ describe("ImportRecordSchema", () => {
155172
).toBe(false);
156173
});
157174
it("should parse with email fields", () => {
158-
console.log(
159-
ImportRecordSchema.parse({
160-
...baseUser,
161-
email: "hello@test.com",
162-
email_verified: true,
163-
})
164-
);
165175
expect(
166176
ImportRecordSchema.safeParse({
167177
...baseUser,
@@ -192,23 +202,14 @@ describe("ImportRecordSchema", () => {
192202
expect(
193203
ImportRecordSchema.safeParse({
194204
...baseUser,
195-
sub: "test",
196205
phone_number: "+1234567890",
197206
phone_number_verified: true,
198207
}).success
199208
).toBe(true);
200209
});
201-
it("should not parse without email or phone_number fields", () => {
202-
expect(
203-
ImportRecordSchema.safeParse({
204-
...baseUser,
205-
email_verified: false,
206-
phone_number_verified: false,
207-
}).success
208-
).toBe(false);
209-
});
210210
it("should have a valid birth date", () => {
211211
const result = ImportRecordSchema.parse(baseUser);
212+
console.log("result", result);
212213
expect(result.birthdate).toBe("03/20/2024");
213214
});
214215
});

0 commit comments

Comments
 (0)