@deallony/shared 1.2.69 → 1.2.72

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 CHANGED
@@ -1,43 +1,64 @@
1
- # @deallony/shared
2
-
3
- Shared TypeScript types, DTOs, Zod schemas, and utilities for Deallony projects.
4
-
5
- ## One-command releases
6
-
7
- Run from a clean, synchronized `main` branch with push access to `origin/main`.
8
-
9
- | Command | Action |
10
- | --- | --- |
11
- | `npm run deploy` | Bump patch, build, publish to npm, commit/tag/push GitLab |
12
- | `npm run deploy:minor` | npm + GitLab minor release |
13
- | `npm run deploy:major` | npm + GitLab major release |
14
- | `npm run deploy:dry-run` | Preview version and inspect current package, no mutation |
15
- | `npm run deploy:git` | Bump patch, build, commit/tag/push GitLab without npm publish |
16
- | `npm run deploy:git:minor` | GitLab-only minor release |
17
- | `npm run deploy:git:major` | GitLab-only major release |
18
- | `npm run deploy:git:dry-run` | Preview GitLab-only release |
19
-
20
- Version increments follow semantic versioning; `1.2.99` becomes `1.2.100`.
21
-
22
- ### Automatic npm login
23
-
24
- `npm run deploy` first checks `npm whoami`. If npm returns E401 or ENEEDAUTH,
25
- the script runs `npm login --registry=https://registry.npmjs.org/ --auth-type=web` and
26
- opens the browser sign-in flow. After you finish logging in, it rechecks your
27
- identity and continues the same release. Network failures and canceled logins
28
- stop the release before modifying the package version. `deploy:git` never logs
29
- into npm.
30
-
31
- ### npm authentication
32
-
33
- Run `npm login --registry=https://registry.npmjs.org/` and ensure your account has
34
- publishing permission for the public scoped package `@deallony/shared`.
35
- Complete any npm 2FA prompts when required. Never commit npm tokens.
36
-
37
- ### Failure recovery
38
-
39
- If publishing fails, inspect and restore generated local changes before retrying.
40
- If npm publication succeeds but Git push/commit fails, **do not republish that version**.
41
- Resolve the Git issue and push the existing release commit and `vX.Y.Z` tag.
42
-
43
- Merge this feature branch first; merging does not trigger publication automatically.
1
+ # @deallony/shared
2
+
3
+ Shared TypeScript types, DTOs, Zod schemas, and utilities for Deallony projects.
4
+
5
+ ## One-command releases
6
+
7
+ Run from a clean, synchronized `main` branch with push access to `origin/main`.
8
+
9
+ | Command | Action |
10
+ | --- | --- |
11
+ | `npm run deploy` | Bump patch, build, publish to npm, commit/tag/push GitLab |
12
+ | `npm run deploy:minor` | npm + GitLab minor release |
13
+ | `npm run deploy:major` | npm + GitLab major release |
14
+ | `npm run deploy:dry-run` | Preview version and inspect current package, no mutation |
15
+ | `npm run deploy:git` | Bump patch, build, commit/tag/push GitLab without npm publish |
16
+ | `npm run deploy:git:minor` | GitLab-only minor release |
17
+ | `npm run deploy:git:major` | GitLab-only major release |
18
+ | `npm run deploy:git:dry-run` | Preview GitLab-only release |
19
+
20
+ Version increments follow semantic versioning; `1.2.99` becomes `1.2.100`.
21
+
22
+ ### Automatic npm login
23
+
24
+ `npm run deploy` first checks `npm whoami`. If npm returns E401 or ENEEDAUTH,
25
+ the script runs `npm login --registry=https://registry.npmjs.org/ --auth-type=web` and
26
+ opens the browser sign-in flow. After you finish logging in, it rechecks your
27
+ identity and continues the same release. Network failures and canceled logins
28
+ stop the release before modifying the package version. `deploy:git` never logs
29
+ into npm.
30
+
31
+ ### npm authentication
32
+
33
+ Run `npm login --registry=https://registry.npmjs.org/` and ensure your account has
34
+ publishing permission for the public scoped package `@deallony/shared`.
35
+ Complete any npm 2FA prompts when required. Never commit npm tokens.
36
+
37
+ ### Publish without browser approval
38
+
39
+ A normal `npm login` session still makes `npm publish` open the browser for 2FA
40
+ on every release. A granular token with "bypass 2FA" removes that step:
41
+
42
+ 1. On npmjs.com open your avatar > **Access Tokens** > **Generate New Token** >
43
+ **Granular Access Token**.
44
+ 2. Name it `deallony-shared-publish`, pick an expiration (npm caps write tokens,
45
+ so note the date to renew), and tick **Bypass two-factor authentication (2FA)**.
46
+ 3. Under **Packages and scopes** choose **Read and write**, **Only select
47
+ packages and scopes**, and select `@deallony/shared`. Leave organizations at
48
+ no access. Generate and copy the token.
49
+ 4. Run `notepad $HOME\.npmrc` (PowerShell) and set this line, replacing any
50
+ existing `//registry.npmjs.org/:_authToken=` line:
51
+ `//registry.npmjs.org/:_authToken=<paste token>`. Save. Editing the file
52
+ keeps the token out of shell history; never paste it into a repo `.npmrc`.
53
+ 5. Check with `npm whoami`, then `npm run deploy:dry-run`.
54
+
55
+ When the token expires, `npm whoami` fails and the script falls back to browser
56
+ login; generate a new token and repeat step 4.
57
+
58
+ ### Failure recovery
59
+
60
+ If publishing fails, inspect and restore generated local changes before retrying.
61
+ If npm publication succeeds but Git push/commit fails, **do not republish that version**.
62
+ Resolve the Git issue and push the existing release commit and `vX.Y.Z` tag.
63
+
64
+ Merge this feature branch first; merging does not trigger publication automatically.
@@ -6,6 +6,30 @@ export declare const APP_ROUTES: {
6
6
  pathname: string;
7
7
  };
8
8
  };
9
+ readonly notifications: {
10
+ /** The notification centre (favorites updates) */
11
+ readonly list: () => {
12
+ pathname: string;
13
+ };
14
+ readonly settings: () => {
15
+ pathname: string;
16
+ };
17
+ };
18
+ readonly favorites: {
19
+ readonly compare: (ad_ids: (number | string)[]) => {
20
+ pathname: string;
21
+ params: {
22
+ ids: string;
23
+ };
24
+ };
25
+ /** A favorites list someone shared */
26
+ readonly sharedList: (token: string) => {
27
+ pathname: string;
28
+ params: {
29
+ token: string;
30
+ };
31
+ };
32
+ };
9
33
  readonly categories: {
10
34
  readonly all: (params: {
11
35
  type: SubjectTypeValue;
@@ -5,6 +5,19 @@ exports.APP_ROUTES = {
5
5
  main: {
6
6
  home: () => ({ pathname: "/(tabs)" }),
7
7
  },
8
+ notifications: {
9
+ /** The notification centre (favorites updates) */
10
+ list: () => ({ pathname: "/notifications" }),
11
+ settings: () => ({ pathname: "/notifications/settings" }),
12
+ },
13
+ favorites: {
14
+ compare: (ad_ids) => ({
15
+ pathname: "/favorites/compare",
16
+ params: { ids: ad_ids.join(",") },
17
+ }),
18
+ /** A favorites list someone shared */
19
+ sharedList: (token) => ({ pathname: "/favorites/list/[token]", params: { token } }),
20
+ },
8
21
  categories: {
9
22
  all: (params) => ({
10
23
  pathname: "/category/all-category",
@@ -68,8 +68,11 @@ export type IAd = {
68
68
  created_at?: string | Date;
69
69
  updated_at?: string | Date;
70
70
  expires_at?: string | Date | null;
71
+ deleted_at?: string | Date | null;
72
+ /** My ads: how many users saved this ad */
73
+ favorites_count?: number;
71
74
  };
72
- export type SaveAdDto = Partial<Omit<IAd, "created_at" | "updated_at" | "views" | "user" | "promotions" | "company">> & {
75
+ export type SaveAdDto = Partial<Omit<IAd, "created_at" | "updated_at" | "views" | "user" | "promotions" | "company" | "deleted_at" | "favorites_count">> & {
73
76
  id?: number;
74
77
  latitude?: number;
75
78
  longitude?: number;
@@ -9,12 +9,14 @@ export type IChatRoom = {
9
9
  name: string;
10
10
  phone: string;
11
11
  email?: string;
12
+ avatar_url?: string | null;
12
13
  };
13
14
  provider: {
14
15
  id: number;
15
16
  name: string;
16
17
  phone: string;
17
18
  email?: string;
19
+ avatar_url?: string | null;
18
20
  };
19
21
  ad?: {
20
22
  id: number;
@@ -23,6 +25,8 @@ export type IChatRoom = {
23
25
  chats?: IChatMessage[];
24
26
  lastMessage?: string;
25
27
  lastMessageAt?: Date;
28
+ /** Messages in this room the current user has not seen yet. */
29
+ unread_count?: number;
26
30
  };
27
31
  export type IChatMessage = {
28
32
  id: number;
@@ -30,14 +34,27 @@ export type IChatMessage = {
30
34
  message_type: MessageTypeEnum;
31
35
  payload?: Record<string, any> | null;
32
36
  created_at: Date;
37
+ delivered_at?: Date | string | null;
38
+ seen_at?: Date | string | null;
33
39
  chat_room_id: number;
34
40
  sender_id: number;
35
41
  sender: {
36
42
  id: number;
37
43
  name: string;
38
44
  phone: string;
45
+ avatar_url?: string | null;
39
46
  };
40
47
  };
48
+ /** Live `inboxMessage` socket event sent to the receiver of a new message. */
49
+ export type IChatInboxMessage = {
50
+ chat_room_id: number;
51
+ message_id: number;
52
+ message: string;
53
+ message_type: MessageTypeEnum;
54
+ payload?: Record<string, any> | null;
55
+ sender_id: number;
56
+ created_at: Date | string;
57
+ };
41
58
  export declare enum MessageTypeEnum {
42
59
  TEXT = 1,
43
60
  PRICE_OFFER = 2,
@@ -0,0 +1,57 @@
1
+ import { IAd } from "../ad/Ad";
2
+ /** Notifications kept in the user's notification centre. Only favorites updates for now. */
3
+ export declare enum NotificationTypeEnum {
4
+ FAVORITE_PRICE_DROP = "favorite_price_drop",
5
+ FAVORITE_SOLD = "favorite_sold",
6
+ FAVORITE_BACK = "favorite_back",
7
+ FAVORITE_SIMILAR = "favorite_similar"
8
+ }
9
+ export type NotificationText = {
10
+ ar: string;
11
+ en: string;
12
+ };
13
+ export type INotificationData = {
14
+ ad_id?: number;
15
+ old_price?: number;
16
+ new_price?: number;
17
+ currency_id?: number | null;
18
+ /** FAVORITE_SIMILAR: the new ads and what they match */
19
+ ad_ids?: number[];
20
+ count?: number;
21
+ subject_type?: string;
22
+ category_id?: number | null;
23
+ };
24
+ export type INotification = {
25
+ id: number;
26
+ user_id: number;
27
+ type: NotificationTypeEnum;
28
+ title: NotificationText;
29
+ body: NotificationText;
30
+ ad_id: number | null;
31
+ ad?: IAd | null;
32
+ data: INotificationData | null;
33
+ /** Same key within 24 hours updates the existing row instead of adding one */
34
+ group_key: string | null;
35
+ read_at: Date | string | null;
36
+ push_status: "pending" | "sent" | "skipped" | "failed";
37
+ pushed_at: Date | string | null;
38
+ created_at: Date | string;
39
+ updated_at?: Date | string;
40
+ };
41
+ export type INotificationSetting = {
42
+ type: NotificationTypeEnum;
43
+ push_enabled: boolean;
44
+ inbox_enabled: boolean;
45
+ };
46
+ export type GetNotificationsDto = {
47
+ page?: number;
48
+ limit?: number;
49
+ type?: NotificationTypeEnum;
50
+ };
51
+ export type MarkNotificationsReadDto = {
52
+ ids?: number[];
53
+ all?: boolean;
54
+ };
55
+ export type UpdateNotificationSettingsDto = {
56
+ settings: INotificationSetting[];
57
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationTypeEnum = void 0;
4
+ /** Notifications kept in the user's notification centre. Only favorites updates for now. */
5
+ var NotificationTypeEnum;
6
+ (function (NotificationTypeEnum) {
7
+ NotificationTypeEnum["FAVORITE_PRICE_DROP"] = "favorite_price_drop";
8
+ NotificationTypeEnum["FAVORITE_SOLD"] = "favorite_sold";
9
+ NotificationTypeEnum["FAVORITE_BACK"] = "favorite_back";
10
+ NotificationTypeEnum["FAVORITE_SIMILAR"] = "favorite_similar";
11
+ })(NotificationTypeEnum || (exports.NotificationTypeEnum = NotificationTypeEnum = {}));
@@ -57,6 +57,7 @@ export * as Chat from "./communication/Chat";
57
57
  export * as Device from "./communication/Device";
58
58
  export * as MessageTemplate from "./communication/MessageTemplate";
59
59
  export * as NotificationToken from "./communication/NotificationToken";
60
+ export * as Notification from "./communication/Notification";
60
61
  export * as File from "./media/File";
61
62
  export * as Media from "./media/Media";
62
63
  export * as Image from "./media/Image";
@@ -37,7 +37,7 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.Favorite = exports.Wallet = exports.Permission = exports.Role = exports.User = exports.EventVenue = exports.EventWedding = exports.EventTimeline = exports.EventRsvp = exports.Event = exports.District = exports.City = exports.AdminBoundary = exports.WorkType = exports.UsedProductCondition = exports.UsedProductAge = exports.Unit = exports.Transmission = exports.RegionalSpec = exports.PublisherType = exports.PropertyStatus = exports.PriceType = exports.OfferType = exports.LicenseType = exports.FuelType = exports.Feature = exports.Facility = exports.Currency = exports.Color = exports.CategoryWorkType = exports.Category = exports.CarBody = exports.UsedProduct = exports.Service = exports.PropertySubType = exports.Property = exports.MotorTrim = exports.Motor = exports.AdPromotion = exports.Addresses = exports.AdDailyViews = exports.AdLocation = exports.Ad = exports.FilterParams = exports.ModuleFetchEndpoints = exports.Config = exports.AccessType = exports.Status = exports.Response = exports.LocalizedName = void 0;
40
- exports.Payment = exports.Analysis = exports.GeminiApiKey = exports.Google = exports.Kyc = exports.SocialMediaProfile = exports.SocialMediaPlatform = exports.Image = exports.Media = exports.File = exports.NotificationToken = exports.MessageTemplate = exports.Device = exports.Chat = exports.AppStartScreen = exports.MetaData = exports.Company = exports.PotentialUser = exports.Loyalty = void 0;
40
+ exports.Payment = exports.Analysis = exports.GeminiApiKey = exports.Google = exports.Kyc = exports.SocialMediaProfile = exports.SocialMediaPlatform = exports.Image = exports.Media = exports.File = exports.Notification = exports.NotificationToken = exports.MessageTemplate = exports.Device = exports.Chat = exports.AppStartScreen = exports.MetaData = exports.Company = exports.PotentialUser = exports.Loyalty = void 0;
41
41
  // common
42
42
  exports.LocalizedName = __importStar(require("./common/LocalizedName"));
43
43
  exports.Response = __importStar(require("./common/Response"));
@@ -104,6 +104,7 @@ exports.Chat = __importStar(require("./communication/Chat"));
104
104
  exports.Device = __importStar(require("./communication/Device"));
105
105
  exports.MessageTemplate = __importStar(require("./communication/MessageTemplate"));
106
106
  exports.NotificationToken = __importStar(require("./communication/NotificationToken"));
107
+ exports.Notification = __importStar(require("./communication/Notification"));
107
108
  // media
108
109
  exports.File = __importStar(require("./media/File"));
109
110
  exports.Media = __importStar(require("./media/Media"));
@@ -4,11 +4,49 @@ export declare enum FavoritableType {
4
4
  USED_PRODUCTS = "used_products",
5
5
  SERVICES = "services"
6
6
  }
7
+ /** A named group of the user's favorites, e.g. "Family car". Shared through share_token. */
8
+ export type IFavoriteList = {
9
+ id: number;
10
+ user_id: number;
11
+ name: string;
12
+ share_token: string;
13
+ created_at?: Date | string;
14
+ /** Number of favorites in the list, sent with the user's lists */
15
+ count?: number;
16
+ /** Up to four ads for the list's cover */
17
+ preview_ads?: IAd[];
18
+ };
7
19
  export type IFavorite = {
8
20
  id: number;
9
21
  user_id: number;
10
22
  user: IUser;
11
23
  created_at: Date | string;
12
24
  ad: IAd;
25
+ /** The ad's price and currency when it was saved, to show how much it dropped */
26
+ saved_price?: number | null;
27
+ saved_currency_id?: number | null;
28
+ /** The last price the user was notified about, so a drop is not announced twice */
29
+ last_notified_price?: number | null;
30
+ /** Price-drop, sold and back-on-sale alerts for this ad */
31
+ notify?: boolean;
32
+ /** Private note, only the user sees it */
33
+ note?: string | null;
34
+ list_id?: number | null;
13
35
  };
14
36
  export type FavoriteType = IFavorite;
37
+ /** Availability of a favorite's ad, derived from its status and deletion */
38
+ export declare enum FavoriteAvailability {
39
+ AVAILABLE = "available",
40
+ SOLD = "sold",
41
+ UNAVAILABLE = "unavailable"
42
+ }
43
+ export type UpdateFavoriteDto = {
44
+ ad_id: number;
45
+ note?: string | null;
46
+ notify?: boolean;
47
+ list_id?: number | null;
48
+ };
49
+ export type SaveFavoriteListDto = {
50
+ id?: number;
51
+ name: string;
52
+ };
@@ -1,8 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FavoritableType = void 0;
3
+ exports.FavoriteAvailability = exports.FavoritableType = void 0;
4
4
  var FavoritableType;
5
5
  (function (FavoritableType) {
6
6
  FavoritableType["USED_PRODUCTS"] = "used_products";
7
7
  FavoritableType["SERVICES"] = "services";
8
8
  })(FavoritableType || (exports.FavoritableType = FavoritableType = {}));
9
+ /** Availability of a favorite's ad, derived from its status and deletion */
10
+ var FavoriteAvailability;
11
+ (function (FavoriteAvailability) {
12
+ FavoriteAvailability["AVAILABLE"] = "available";
13
+ FavoriteAvailability["SOLD"] = "sold";
14
+ FavoriteAvailability["UNAVAILABLE"] = "unavailable";
15
+ })(FavoriteAvailability || (exports.FavoriteAvailability = FavoriteAvailability = {}));
@@ -2,6 +2,19 @@ export const APP_ROUTES = {
2
2
  main: {
3
3
  home: () => ({ pathname: "/(tabs)" }),
4
4
  },
5
+ notifications: {
6
+ /** The notification centre (favorites updates) */
7
+ list: () => ({ pathname: "/notifications" }),
8
+ settings: () => ({ pathname: "/notifications/settings" }),
9
+ },
10
+ favorites: {
11
+ compare: (ad_ids) => ({
12
+ pathname: "/favorites/compare",
13
+ params: { ids: ad_ids.join(",") },
14
+ }),
15
+ /** A favorites list someone shared */
16
+ sharedList: (token) => ({ pathname: "/favorites/list/[token]", params: { token } }),
17
+ },
5
18
  categories: {
6
19
  all: (params) => ({
7
20
  pathname: "/category/all-category",
@@ -0,0 +1,8 @@
1
+ /** Notifications kept in the user's notification centre. Only favorites updates for now. */
2
+ export var NotificationTypeEnum;
3
+ (function (NotificationTypeEnum) {
4
+ NotificationTypeEnum["FAVORITE_PRICE_DROP"] = "favorite_price_drop";
5
+ NotificationTypeEnum["FAVORITE_SOLD"] = "favorite_sold";
6
+ NotificationTypeEnum["FAVORITE_BACK"] = "favorite_back";
7
+ NotificationTypeEnum["FAVORITE_SIMILAR"] = "favorite_similar";
8
+ })(NotificationTypeEnum || (NotificationTypeEnum = {}));
@@ -67,6 +67,7 @@ export * as Chat from "./communication/Chat.js";
67
67
  export * as Device from "./communication/Device.js";
68
68
  export * as MessageTemplate from "./communication/MessageTemplate.js";
69
69
  export * as NotificationToken from "./communication/NotificationToken.js";
70
+ export * as Notification from "./communication/Notification.js";
70
71
  // media
71
72
  export * as File from "./media/File.js";
72
73
  export * as Media from "./media/Media.js";
@@ -3,3 +3,10 @@ export var FavoritableType;
3
3
  FavoritableType["USED_PRODUCTS"] = "used_products";
4
4
  FavoritableType["SERVICES"] = "services";
5
5
  })(FavoritableType || (FavoritableType = {}));
6
+ /** Availability of a favorite's ad, derived from its status and deletion */
7
+ export var FavoriteAvailability;
8
+ (function (FavoriteAvailability) {
9
+ FavoriteAvailability["AVAILABLE"] = "available";
10
+ FavoriteAvailability["SOLD"] = "sold";
11
+ FavoriteAvailability["UNAVAILABLE"] = "unavailable";
12
+ })(FavoriteAvailability || (FavoriteAvailability = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deallony/shared",
3
- "version": "1.2.69",
3
+ "version": "1.2.72",
4
4
  "private": false,
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",