Adding typescript example

Change-Id: Ib318ec5df15df672282e027e5673489d63d69f21
diff --git a/offers/dining/typescript/package-lock.json b/offers/dining/typescript/package-lock.json
new file mode 100644
index 0000000..91e8334
--- /dev/null
+++ b/offers/dining/typescript/package-lock.json
@@ -0,0 +1,193 @@
+{
+  "name": "google-offers",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "google-offers",
+      "version": "1.0.0",
+      "license": "ISC",
+      "dependencies": {
+        "debug": "^4.4.3",
+        "ms": "^2.1.3",
+        "ts-proto": "^2.11.2"
+      },
+      "devDependencies": {
+        "typescript": "^5.9.3"
+      }
+    },
+    "node_modules/@bufbuild/protobuf": {
+      "version": "2.11.0",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@bufbuild/protobuf/-/protobuf-2.11.0.tgz",
+      "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==",
+      "license": "(Apache-2.0 AND BSD-3-Clause)"
+    },
+    "node_modules/case-anything": {
+      "version": "2.1.13",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/case-anything/-/case-anything-2.1.13.tgz",
+      "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/debug": {
+      "version": "4.4.3",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "license": "Apache-2.0",
+      "bin": {
+        "detect-libc": "bin/detect-libc.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/dprint-node": {
+      "version": "1.0.8",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/dprint-node/-/dprint-node-1.0.8.tgz",
+      "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==",
+      "license": "MIT",
+      "dependencies": {
+        "detect-libc": "^1.0.3"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "license": "MIT"
+    },
+    "node_modules/ts-poet": {
+      "version": "6.12.0",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/ts-poet/-/ts-poet-6.12.0.tgz",
+      "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "dprint-node": "^1.0.8"
+      }
+    },
+    "node_modules/ts-proto": {
+      "version": "2.11.2",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/ts-proto/-/ts-proto-2.11.2.tgz",
+      "integrity": "sha512-+bPq2zDwNtJHtuyu2fGYgvTDxS7cBcY4u4moO1LyFA+my144Mfj9/sbNyGXKMtBK7DNXVGf76puwGa6hPzJw/g==",
+      "license": "ISC",
+      "dependencies": {
+        "@bufbuild/protobuf": "^2.10.2",
+        "case-anything": "^2.1.13",
+        "ts-poet": "^6.12.0",
+        "ts-proto-descriptors": "2.1.0"
+      },
+      "bin": {
+        "protoc-gen-ts_proto": "protoc-gen-ts_proto"
+      }
+    },
+    "node_modules/ts-proto-descriptors": {
+      "version": "2.1.0",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/ts-proto-descriptors/-/ts-proto-descriptors-2.1.0.tgz",
+      "integrity": "sha512-S5EZYEQ6L9KLFfjSRpZWDIXDV/W7tAj8uW7pLsihIxyr62EAVSiKuVPwE8iWnr849Bqa53enex1jhDUcpgquzA==",
+      "license": "ISC",
+      "dependencies": {
+        "@bufbuild/protobuf": "^2.0.0"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    }
+  },
+  "dependencies": {
+    "@bufbuild/protobuf": {
+      "version": "2.11.0",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@bufbuild/protobuf/-/protobuf-2.11.0.tgz",
+      "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ=="
+    },
+    "case-anything": {
+      "version": "2.1.13",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/case-anything/-/case-anything-2.1.13.tgz",
+      "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng=="
+    },
+    "debug": {
+      "version": "4.4.3",
+      "requires": {
+        "ms": "^2.1.3"
+      }
+    },
+    "detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="
+    },
+    "dprint-node": {
+      "version": "1.0.8",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/dprint-node/-/dprint-node-1.0.8.tgz",
+      "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==",
+      "requires": {
+        "detect-libc": "^1.0.3"
+      }
+    },
+    "ms": {
+      "version": "2.1.3"
+    },
+    "ts-poet": {
+      "version": "6.12.0",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/ts-poet/-/ts-poet-6.12.0.tgz",
+      "integrity": "sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==",
+      "requires": {
+        "dprint-node": "^1.0.8"
+      }
+    },
+    "ts-proto": {
+      "version": "2.11.2",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/ts-proto/-/ts-proto-2.11.2.tgz",
+      "integrity": "sha512-+bPq2zDwNtJHtuyu2fGYgvTDxS7cBcY4u4moO1LyFA+my144Mfj9/sbNyGXKMtBK7DNXVGf76puwGa6hPzJw/g==",
+      "requires": {
+        "@bufbuild/protobuf": "^2.10.2",
+        "case-anything": "^2.1.13",
+        "ts-poet": "^6.12.0",
+        "ts-proto-descriptors": "2.1.0"
+      }
+    },
+    "ts-proto-descriptors": {
+      "version": "2.1.0",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/ts-proto-descriptors/-/ts-proto-descriptors-2.1.0.tgz",
+      "integrity": "sha512-S5EZYEQ6L9KLFfjSRpZWDIXDV/W7tAj8uW7pLsihIxyr62EAVSiKuVPwE8iWnr849Bqa53enex1jhDUcpgquzA==",
+      "requires": {
+        "@bufbuild/protobuf": "^2.0.0"
+      }
+    },
+    "typescript": {
+      "version": "5.9.3",
+      "resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "dev": true
+    }
+  }
+}
diff --git a/offers/dining/typescript/package.json b/offers/dining/typescript/package.json
new file mode 100644
index 0000000..044c4a7
--- /dev/null
+++ b/offers/dining/typescript/package.json
@@ -0,0 +1,20 @@
+{
+  "name": "google-offers",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "dependencies": {
+    "debug": "^4.4.3",
+    "ms": "^2.1.3",
+    "ts-proto": "^2.11.2"
+  },
+  "scripts": {
+    "build": "tsc --build",
+    "clean": "tsc --build --clean"
+  },
+  "devDependencies": {
+    "typescript": "^5.9.3"
+  },
+  "author": "",
+  "license": "ISC"
+}
diff --git a/offers/dining/typescript/src/offer_feed.ts b/offers/dining/typescript/src/offer_feed.ts
new file mode 100644
index 0000000..3e1b119
--- /dev/null
+++ b/offers/dining/typescript/src/offer_feed.ts
@@ -0,0 +1,115 @@
+import { 
+  Offer, 
+  OfferFeed, 
+  OfferSource, 
+  ActionType, 
+  OfferMode, 
+  OfferCategory 
+} from "./generated/offer"; // Path to your generated types
+import { Money } from "./generated/money";
+import { DayOfWeek } from "./generated/dayofweek";
+import { TimeOfDay } from "./generated/timeofday";
+import { Timestamp } from "./generated/google/protobuf/timestamp";
+import { Duration } from "./generated/google/protobuf/duration";
+
+// 200 MB Limit
+const MAX_BYTES_DATA_FILE = 200 * 1024 * 1024;
+
+function generateOfferFeed() {
+  // Build the Offer object
+  const offer: Offer = {
+    offer_id: "offer-1",
+    entity_ids: ["dining-1"],
+    offer_source: OfferSource.OFFER_SOURCE_AGGREGATOR,
+    action_type: ActionType.ACTION_TYPE_DINING,
+    offer_modes: [
+      OfferMode.OFFER_MODE_WALK_IN,
+      OfferMode.OFFER_MODE_FREE_RESERVATION,
+    ],
+    offer_category: OfferCategory.OFFER_CATEGORY_BASE_OFFER,
+    offer_details: {
+      offer_display_text: "₹100 off on your order",
+      // Set 'oneof' field: discountValue
+      discount_value: {
+        currency_code: "INR",
+        units: 100,
+      },
+    },
+    offer_restrictions: {
+      combinable_with_other_offers: true,
+      combinable_offer_categories: [
+        OfferCategory.OFFER_CATEGORY_ADD_ON_PAYMENT_OFFER,
+        OfferCategory.OFFER_CATEGORY_ADD_ON_COUPON_OFFER,
+      ],
+    },
+    terms: {
+      restricted_to_certain_users: false,
+      terms_and_conditions: "Valid on all menu items.",
+    },
+    validity_periods: [
+      {
+        valid_period: {
+          valid_from_time: new Date(1687062000000),
+          valid_through_time: new Date(1956556800000),
+        },
+        time_of_day: [
+          // Monday - Thursday Window
+          {
+            time_windows: {
+              open_time: { hours: 13, minutes: 0, seconds: 0, nanos: 0 },
+              close_time: { hours: 23, minutes: 0, seconds: 0, nanos: 0 },
+            },
+            day_of_week: [
+              DayOfWeek.MONDAY,
+              DayOfWeek.TUESDAY,
+              DayOfWeek.WEDNESDAY,
+              DayOfWeek.THURSDAY,
+            ],
+          },
+          // Friday - Sunday Window
+          {
+            time_windows: {
+              open_time: { hours: 13, minutes: 0, seconds: 0, nanos: 0 },
+              close_time: { hours: 23, minutes: 59, seconds: 59, nanos: 0 },
+            },
+            day_of_week: [
+              DayOfWeek.FRIDAY,
+              DayOfWeek.SATURDAY,
+              DayOfWeek.SUNDAY,
+            ],
+          },
+        ],
+      },
+    ],
+    offer_url: "https://www.example-restaurant.com/offer/base_offer_1",
+    image_url: "https://www.example-restaurant.com/images/offer_base.jpg",
+  };
+
+  // 2. Initialize the Feed
+  const feed: OfferFeed = { data: [] };
+
+  // 3. Size checking
+  // encode().finish() returns a Uint8Array (the binary representation)
+  const offerSize = new Blob([JSON.stringify(offer)]).size;
+  const currentFeedSize = new Blob([JSON.stringify(feed)]).size;
+  
+  if (currentFeedSize + offerSize < MAX_BYTES_DATA_FILE) {
+    if (feed.data == undefined) {
+      feed.data = [offer]; 
+    } else {
+      feed.data.push(offer);
+    }
+  } else {
+    // Logic for file rotation goes here
+    console.log("Feed size limit reached. Rotate file.");
+  }
+
+  // 4. Serialize to JSON
+  // In JS/TS, we often just use JSON.stringify for the plain object
+  // if you used proto3 and want to ensure proper enum/timestamp formatting,
+  // use the library's toJSON method.
+  const jsonOutput = JSON.stringify(feed);
+  console.log(jsonOutput);
+}
+
+generateOfferFeed();
diff --git a/offers/dining/typescript/tsconfig.json b/offers/dining/typescript/tsconfig.json
new file mode 100644
index 0000000..7bdb266
--- /dev/null
+++ b/offers/dining/typescript/tsconfig.json
@@ -0,0 +1,15 @@
+{
+  "include": ["src/**/*"],
+  "compilerOptions": {
+    "outDir": "dist",
+    "rootDir": "src",
+    "allowJs": true,
+    "target": "ES2020",
+    "module": "commonjs",
+    "declaration": false,
+    "sourceMap": true,
+    "strict": true,
+    "esModuleInterop": true,
+    "forceConsistentCasingInFileNames": true
+  }
+}
diff --git a/offers/dining/typescript/tsconfig.tsbuildinfo b/offers/dining/typescript/tsconfig.tsbuildinfo
new file mode 100644
index 0000000..2b9927e
--- /dev/null
+++ b/offers/dining/typescript/tsconfig.tsbuildinfo
@@ -0,0 +1 @@
+{"root":["./src/offer_feed.ts","./src/generated/date.ts","./src/generated/dayofweek.ts","./src/generated/money.ts","./src/generated/offer.ts","./src/generated/timeofday.ts","./src/generated/google/protobuf/duration.ts","./src/generated/google/protobuf/timestamp.ts"],"version":"5.9.3"}
\ No newline at end of file