@wenlarge/ostrol-communication 0.5.0

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.
Files changed (53) hide show
  1. package/dist/config/astro-engine-config.d.ts +1 -0
  2. package/dist/config/astro-engine-config.js +4 -0
  3. package/dist/config/astrology-config.d.ts +1 -0
  4. package/dist/config/astrology-config.js +4 -0
  5. package/dist/config/auth-config.d.ts +1 -0
  6. package/dist/config/auth-config.js +4 -0
  7. package/dist/config/billing-config.d.ts +1 -0
  8. package/dist/config/billing-config.js +4 -0
  9. package/dist/generated/astro_engine.d.ts +93 -0
  10. package/dist/generated/astro_engine.js +30 -0
  11. package/dist/generated/astrology.d.ts +92 -0
  12. package/dist/generated/astrology.js +50 -0
  13. package/dist/generated/auth.d.ts +131 -0
  14. package/dist/generated/auth.js +53 -0
  15. package/dist/generated/billing.d.ts +62 -0
  16. package/dist/generated/billing.js +41 -0
  17. package/dist/generated/common.d.ts +17 -0
  18. package/dist/generated/common.js +18 -0
  19. package/dist/generated/google/protobuf/empty.d.ts +13 -0
  20. package/dist/generated/google/protobuf/empty.js +11 -0
  21. package/dist/generated/google/protobuf/struct.d.ts +82 -0
  22. package/dist/generated/google/protobuf/struct.js +117 -0
  23. package/dist/grpc-client/grpc-client.module.d.ts +10 -0
  24. package/dist/grpc-client/grpc-client.module.js +68 -0
  25. package/dist/grpc-client/index.d.ts +1 -0
  26. package/dist/grpc-client/index.js +17 -0
  27. package/dist/helpers/helper.d.ts +12 -0
  28. package/dist/helpers/helper.js +31 -0
  29. package/dist/helpers/struct-to-json.d.ts +3 -0
  30. package/dist/helpers/struct-to-json.js +46 -0
  31. package/dist/index.d.ts +18 -0
  32. package/dist/index.js +69 -0
  33. package/dist/kafka/commit-kafka-offset.d.ts +16 -0
  34. package/dist/kafka/commit-kafka-offset.js +14 -0
  35. package/dist/kafka/kafka-topics.d.ts +13 -0
  36. package/dist/kafka/kafka-topics.js +19 -0
  37. package/dist/kafka/payloads.d.ts +67 -0
  38. package/dist/kafka/payloads.js +3 -0
  39. package/dist/pagination/cursor.d.ts +17 -0
  40. package/dist/pagination/cursor.js +42 -0
  41. package/package.json +49 -0
  42. package/proto/astro_engine.proto +60 -0
  43. package/proto/astrology.proto +78 -0
  44. package/proto/auth.proto +123 -0
  45. package/proto/billing.proto +56 -0
  46. package/proto/common.proto +17 -0
  47. package/src/generated/astro_engine.ts +144 -0
  48. package/src/generated/astrology.ts +135 -0
  49. package/src/generated/auth.ts +215 -0
  50. package/src/generated/billing.ts +117 -0
  51. package/src/generated/common.ts +28 -0
  52. package/src/generated/google/protobuf/empty.ts +23 -0
  53. package/src/generated/google/protobuf/struct.ts +179 -0
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ // Keyset (seek) cursor pagination shared by every list endpoint. The cursor is an
3
+ // opaque base64url of the last row's sort key { v, id } where v is the ordering
4
+ // value (createdAt / publishedAt ISO string). The (v, id) tuple keeps paging stable
5
+ // across rows that share a timestamp. See backend-structure pagination section.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.encodeCursor = encodeCursor;
8
+ exports.decodeCursor = decodeCursor;
9
+ exports.clampLimit = clampLimit;
10
+ exports.buildCursorPage = buildCursorPage;
11
+ function encodeCursor(v, id) {
12
+ return Buffer.from(JSON.stringify({ v, id }), "utf8").toString("base64url");
13
+ }
14
+ function decodeCursor(cursor) {
15
+ if (!cursor)
16
+ return null;
17
+ try {
18
+ const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
19
+ if (typeof parsed?.v === "string" && typeof parsed?.id === "string") {
20
+ return { v: parsed.v, id: parsed.id };
21
+ }
22
+ return null;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ // Clamps a requested page size into [1, max] with a default fallback.
29
+ function clampLimit(limit, max = 50, def = 20) {
30
+ if (!Number.isFinite(limit) || limit <= 0)
31
+ return def;
32
+ return Math.min(Math.floor(limit), max);
33
+ }
34
+ // Builds a CursorResponse from rows fetched with `LIMIT limit + 1`: the extra row
35
+ // signals hasMore and is dropped; nextCursor is derived from the last kept row.
36
+ function buildCursorPage(rows, limit, toKey) {
37
+ const hasMore = rows.length > limit;
38
+ const data = hasMore ? rows.slice(0, limit) : rows;
39
+ const last = data[data.length - 1];
40
+ const nextCursor = hasMore && last ? encodeCursor(toKey(last).v, toKey(last).id) : null;
41
+ return { data, nextCursor, hasMore };
42
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@wenlarge/ostrol-communication",
3
+ "version": "0.5.0",
4
+ "description": "Shared gRPC proto contracts, generated clients and Kafka helpers for Ostrol microservices.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "proto",
10
+ "src/generated"
11
+ ],
12
+ "scripts": {
13
+ "proto:build": "protoc --plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto --proto_path=proto --ts_proto_out=src/generated proto/*.proto --ts_proto_opt=nestJs=true,esModuleInterop=true,forceLong=string,useOptionals=messages,useDate=true,addGrpcMetadata=true,stringEnums=true",
14
+ "build": "npm run proto:build && tsc",
15
+ "clean": "rm -rf dist src/generated",
16
+ "prepare": "npm run build"
17
+ },
18
+ "keywords": [
19
+ "nestjs",
20
+ "grpc",
21
+ "proto",
22
+ "kafka",
23
+ "typescript",
24
+ "microservices",
25
+ "ostrol"
26
+ ],
27
+ "author": "Kerem Çakır <kerem.cakirr@gmail.com>",
28
+ "license": "UNLICENSED",
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@grpc/grpc-js": "^1.14.1",
34
+ "@grpc/proto-loader": "^0.7.15",
35
+ "rxjs": "^7.8.1"
36
+ },
37
+ "devDependencies": {
38
+ "@nestjs/common": "^10.4.20",
39
+ "@nestjs/microservices": "^10.4.20",
40
+ "@types/node": "^24.9.1",
41
+ "ts-proto": "^1.181.2",
42
+ "typescript": "^5.3.3"
43
+ },
44
+ "peerDependencies": {
45
+ "@grpc/grpc-js": "^1.14.1",
46
+ "@nestjs/common": "^10.x",
47
+ "@nestjs/microservices": "^10.x"
48
+ }
49
+ }
@@ -0,0 +1,60 @@
1
+ syntax = "proto3";
2
+
3
+ import "google/protobuf/struct.proto";
4
+
5
+ package astro_engine;
6
+
7
+ // Implemented by the PYTHON astro-engine service (Kerykeion). Pure compute:
8
+ // no DB, no Kafka, stateless. Called only by the astrology service's workers.
9
+ // astro-engine generates its stubs from THIS file via grpc_tools.protoc; it does
10
+ // not install the npm package. Complex outputs are returned as Struct (JSON) to
11
+ // avoid pinning a rigid schema onto Kerykeion's output shape.
12
+ service AstroEngineService {
13
+ rpc ComputeNatal (ComputeNatalRequest) returns (ComputeNatalResponse);
14
+ rpc ComputeTransits (ComputeTransitsRequest) returns (ComputeTransitsResponse);
15
+ rpc ForecastTransits (ForecastTransitsRequest) returns (ForecastTransitsResponse);
16
+ }
17
+
18
+ message ComputeNatalRequest {
19
+ reserved 2; // was `timezone`; now derived from lat/lng in astro-engine
20
+ reserved "timezone";
21
+ string birthAt = 1; // ISO 8601
22
+ double lat = 3;
23
+ double lng = 4;
24
+ }
25
+
26
+ message ComputeNatalResponse {
27
+ google.protobuf.Struct rawData = 1; // full chart
28
+ google.protobuf.Struct natalPoints = 2; // points cached for transit checks
29
+ string timezone = 3; // IANA zone resolved from lat/lng, e.g. "Europe/Istanbul"
30
+ }
31
+
32
+ message ComputeTransitsRequest {
33
+ google.protobuf.Struct natalPoints = 1; // cached natal points
34
+ string at = 2; // ISO 8601 moment to compute the sky for
35
+ }
36
+
37
+ message ComputeTransitsResponse {
38
+ google.protobuf.Struct transits = 1; // current positions
39
+ google.protobuf.Struct aspects = 2; // aspects-to-natal within orb
40
+ }
41
+
42
+ // Deterministic forecast: every exact transit aspect to the natal points across
43
+ // [fromAt, toAt]. Drives the precomputed transit_event schedule.
44
+ message ForecastTransitsRequest {
45
+ google.protobuf.Struct natalPoints = 1;
46
+ string fromAt = 2; // ISO 8601
47
+ string toAt = 3; // ISO 8601
48
+ }
49
+
50
+ message TransitAspect {
51
+ string transitingBody = 1; // e.g. "mars"
52
+ string natalPoint = 2; // e.g. "sun"
53
+ string aspect = 3; // e.g. "conjunction"
54
+ string exactAt = 4; // ISO 8601 — trigger time
55
+ double orb = 5;
56
+ }
57
+
58
+ message ForecastTransitsResponse {
59
+ repeated TransitAspect events = 1;
60
+ }
@@ -0,0 +1,78 @@
1
+ syntax = "proto3";
2
+
3
+ import "google/protobuf/struct.proto";
4
+ import "common.proto";
5
+
6
+ package astrology;
7
+
8
+ service AstrologyService {
9
+ rpc FindManyPost (FindManyPostRequest) returns (FindManyPostResponse);
10
+ rpc FindFirstPost (FindFirstPostRequest) returns (Post);
11
+ rpc GetNatalChart (GetNatalChartRequest) returns (NatalChart);
12
+ }
13
+
14
+ enum PostType {
15
+ POST_TYPE_UNSPECIFIED = 0;
16
+ GENERAL = 1; // userId empty; canonical English post + per-language translation rows
17
+ DAILY = 2;
18
+ WEEKLY = 3;
19
+ MONTHLY = 4;
20
+ TRANSIT_ALERT = 5;
21
+ }
22
+
23
+ enum CalculationStatus {
24
+ CALCULATION_STATUS_UNSPECIFIED = 0;
25
+ PENDING = 1;
26
+ IN_PROGRESS = 2;
27
+ DONE = 3;
28
+ FAILED = 4;
29
+ }
30
+
31
+ message Post {
32
+ string id = 1;
33
+ string userId = 2; // empty => general
34
+ PostType type = 3;
35
+ string title = 4;
36
+ string content = 5;
37
+ string language = 6; // general posts: "en"; personal posts: user's language at generation time
38
+ common.Plan plan = 7;
39
+ bool shouldNotify = 8;
40
+ string publishedAt = 9; // ISO 8601
41
+ string createdAt = 10; // ISO 8601
42
+ string sourcePostId = 11; // translations: id of the canonical (English) post; empty on canonical/personal posts
43
+ }
44
+
45
+ message NatalChart {
46
+ string id = 1;
47
+ string userId = 2;
48
+ google.protobuf.Struct rawData = 3;
49
+ google.protobuf.Struct natalPoints = 4;
50
+ CalculationStatus status = 5;
51
+ string summary = 6;
52
+ string deepSummary = 7;
53
+ google.protobuf.Struct personalityScores = 8;
54
+ string personalitySummary = 9;
55
+ }
56
+
57
+ // GENERAL feed: userId left empty. Personal types: userId set (caller).
58
+ message FindManyPostRequest {
59
+ common.CursorRequest page = 1;
60
+ PostType type = 2;
61
+ string userId = 3;
62
+ string language = 4; // GENERAL only: language variant to return; empty => "en"
63
+ }
64
+
65
+ message FindManyPostResponse {
66
+ repeated Post data = 1;
67
+ string nextCursor = 2;
68
+ bool hasMore = 3;
69
+ }
70
+
71
+ message FindFirstPostRequest {
72
+ string id = 1; // canonical post id (GENERAL translations are addressed via their canonical id)
73
+ string language = 2; // GENERAL only: preferred translation; falls back to the canonical post when absent
74
+ }
75
+
76
+ message GetNatalChartRequest {
77
+ string userId = 1;
78
+ }
@@ -0,0 +1,123 @@
1
+ syntax = "proto3";
2
+
3
+ import "google/protobuf/empty.proto";
4
+ import "common.proto";
5
+
6
+ package auth;
7
+
8
+ service AuthService {
9
+ rpc Register (RegisterRequest) returns (AuthResponse);
10
+ rpc Login (LoginRequest) returns (AuthResponse);
11
+ rpc OAuthLogin (OAuthLoginRequest) returns (AuthResponse);
12
+ rpc RefreshToken (RefreshTokenRequest) returns (AuthResponse);
13
+ rpc UpdateProfile (UpdateProfileRequest) returns (AuthResponse);
14
+ rpc OAuthLink (OAuthLinkRequest) returns (google.protobuf.Empty);
15
+ rpc OAuthUnlink (OAuthUnlinkRequest) returns (google.protobuf.Empty);
16
+ rpc GetUser (GetUserRequest) returns (User);
17
+ rpc UpdateUserPlan (UpdateUserPlanRequest) returns (google.protobuf.Empty);
18
+ rpc DeleteAccount (DeleteAccountRequest) returns (google.protobuf.Empty);
19
+ }
20
+
21
+ enum OAuthProvider {
22
+ OAUTH_PROVIDER_UNSPECIFIED = 0;
23
+ GOOGLE = 1;
24
+ MICROSOFT = 2;
25
+ }
26
+
27
+ enum UserStatus {
28
+ USER_STATUS_UNSPECIFIED = 0;
29
+ ACTIVE = 1;
30
+ SUSPENDED = 2;
31
+ DELETED = 3;
32
+ }
33
+
34
+ message User {
35
+ reserved 6; // was `birthTimezone`; timezone is derived from lat/lng in astro-engine
36
+ reserved "birthTimezone";
37
+ string id = 1;
38
+ string email = 2;
39
+ bool emailVerified = 3;
40
+ string name = 4;
41
+ string birthAt = 5; // ISO 8601, empty if unset
42
+ string language = 7; // BCP-47
43
+ double birthLat = 8;
44
+ double birthLng = 9;
45
+ string birthLocationName = 10;
46
+ common.Plan plan = 11;
47
+ UserStatus status = 12;
48
+ repeated OAuthProvider linkedProviders = 13;
49
+ // Current IANA timezone (device-reported, e.g. "Europe/Istanbul"), empty if
50
+ // unset. NOT the birth timezone — that stays server-derived from lat/lng.
51
+ string timezone = 14;
52
+ }
53
+
54
+ message AuthResponse {
55
+ string accessToken = 1; // RS256 JWT, short TTL
56
+ string refreshToken = 2; // revocable, Redis-backed
57
+ User user = 3;
58
+ }
59
+
60
+ message RegisterRequest {
61
+ string name = 1;
62
+ string email = 2;
63
+ string password = 3;
64
+ string language = 4;
65
+ string timezone = 5; // current IANA timezone (device-reported), optional
66
+ }
67
+
68
+ message LoginRequest {
69
+ string email = 1;
70
+ string password = 2;
71
+ }
72
+
73
+ message OAuthLoginRequest {
74
+ OAuthProvider provider = 1;
75
+ string providerToken = 2;
76
+ string language = 3;
77
+ string timezone = 4; // current IANA timezone (device-reported), optional
78
+ }
79
+
80
+ message RefreshTokenRequest {
81
+ string refreshToken = 1;
82
+ }
83
+
84
+ message UpdateProfileRequest {
85
+ reserved 4; // was `birthTimezone`; timezone is derived from lat/lng in astro-engine
86
+ reserved "birthTimezone";
87
+ // Partial update: every field except userId is `optional` so absence is
88
+ // distinguishable from proto3 defaults ("" / 0). Without presence tracking a
89
+ // language-only PATCH used to arrive with birthLat=0/birthLng=0 and silently
90
+ // overwrite the stored birth coordinates.
91
+ string userId = 1; // caller, from gateway
92
+ optional string name = 2;
93
+ optional string birthAt = 3;
94
+ optional double birthLat = 5;
95
+ optional double birthLng = 6;
96
+ optional string birthLocationName = 7;
97
+ optional string language = 8;
98
+ optional string timezone = 9; // current IANA timezone; never triggers a natal recalc
99
+ }
100
+
101
+ message OAuthLinkRequest {
102
+ string userId = 1;
103
+ OAuthProvider provider = 2;
104
+ string providerToken = 3;
105
+ }
106
+
107
+ message OAuthUnlinkRequest {
108
+ string userId = 1;
109
+ OAuthProvider provider = 2;
110
+ }
111
+
112
+ message GetUserRequest {
113
+ string userId = 1;
114
+ }
115
+
116
+ message UpdateUserPlanRequest {
117
+ string userId = 1;
118
+ common.Plan plan = 2;
119
+ }
120
+
121
+ message DeleteAccountRequest {
122
+ string userId = 1;
123
+ }
@@ -0,0 +1,56 @@
1
+ syntax = "proto3";
2
+
3
+ import "google/protobuf/empty.proto";
4
+ import "common.proto";
5
+
6
+ package billing;
7
+
8
+ service BillingService {
9
+ rpc GetSubscription (GetSubscriptionRequest) returns (Subscription);
10
+ rpc CreateCheckoutSession (CreateCheckoutSessionRequest) returns (CheckoutSession);
11
+ rpc CreatePortalSession (CreatePortalSessionRequest) returns (PortalSession);
12
+ rpc HandleWebhookEvent (WebhookEventRequest) returns (google.protobuf.Empty);
13
+ }
14
+
15
+ enum SubscriptionStatus {
16
+ SUBSCRIPTION_STATUS_UNSPECIFIED = 0;
17
+ ACTIVE = 1;
18
+ PAST_DUE = 2;
19
+ CANCELLED = 3;
20
+ EXPIRED = 4;
21
+ }
22
+
23
+ message Subscription {
24
+ string id = 1;
25
+ string userId = 2;
26
+ common.Plan plan = 3;
27
+ SubscriptionStatus status = 4;
28
+ bool cancelAtPeriodEnd = 5;
29
+ string currentPeriodStart = 6; // ISO 8601
30
+ string currentPeriodEnd = 7; // ISO 8601
31
+ }
32
+
33
+ message GetSubscriptionRequest {
34
+ string userId = 1;
35
+ }
36
+
37
+ message CreateCheckoutSessionRequest {
38
+ string userId = 1;
39
+ }
40
+
41
+ message CreatePortalSessionRequest {
42
+ string userId = 1;
43
+ }
44
+
45
+ message CheckoutSession {
46
+ string checkoutUrl = 1; // Stripe checkout page
47
+ }
48
+
49
+ message PortalSession {
50
+ string portalUrl = 1; // Stripe customer portal
51
+ }
52
+
53
+ message WebhookEventRequest {
54
+ bytes payload = 1; // raw Stripe webhook body
55
+ string signature = 2; // Stripe-Signature header
56
+ }
@@ -0,0 +1,17 @@
1
+ syntax = "proto3";
2
+
3
+ package common;
4
+
5
+ enum Plan {
6
+ PLAN_UNSPECIFIED = 0;
7
+ FREE = 1;
8
+ PREMIUM = 2;
9
+ }
10
+
11
+ // Keyset (seek) cursor pagination request. `cursor` is an opaque base64 of the
12
+ // last row's sort key ({ v, id }); empty on the first page. `limit` is capped
13
+ // server-side (e.g. <= 50). See cursor.ts encode/decode helpers.
14
+ message CursorRequest {
15
+ string cursor = 1;
16
+ int32 limit = 2;
17
+ }
@@ -0,0 +1,144 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v1.181.2
4
+ // protoc v3.21.5
5
+ // source: astro_engine.proto
6
+
7
+ /* eslint-disable */
8
+ import { Metadata } from "@grpc/grpc-js";
9
+ import { GrpcMethod, GrpcStreamMethod } from "@nestjs/microservices";
10
+ import { wrappers } from "protobufjs";
11
+ import { Observable } from "rxjs";
12
+ import { Struct } from "./google/protobuf/struct";
13
+
14
+ export const protobufPackage = "astro_engine";
15
+
16
+ export interface ComputeNatalRequest {
17
+ /** ISO 8601 */
18
+ birthAt: string;
19
+ lat: number;
20
+ lng: number;
21
+ }
22
+
23
+ export interface ComputeNatalResponse {
24
+ /** full chart */
25
+ rawData?:
26
+ | { [key: string]: any }
27
+ | undefined;
28
+ /** points cached for transit checks */
29
+ natalPoints?:
30
+ | { [key: string]: any }
31
+ | undefined;
32
+ /** IANA zone resolved from lat/lng, e.g. "Europe/Istanbul" */
33
+ timezone: string;
34
+ }
35
+
36
+ export interface ComputeTransitsRequest {
37
+ /** cached natal points */
38
+ natalPoints?:
39
+ | { [key: string]: any }
40
+ | undefined;
41
+ /** ISO 8601 moment to compute the sky for */
42
+ at: string;
43
+ }
44
+
45
+ export interface ComputeTransitsResponse {
46
+ /** current positions */
47
+ transits?:
48
+ | { [key: string]: any }
49
+ | undefined;
50
+ /** aspects-to-natal within orb */
51
+ aspects?: { [key: string]: any } | undefined;
52
+ }
53
+
54
+ /**
55
+ * Deterministic forecast: every exact transit aspect to the natal points across
56
+ * [fromAt, toAt]. Drives the precomputed transit_event schedule.
57
+ */
58
+ export interface ForecastTransitsRequest {
59
+ natalPoints?:
60
+ | { [key: string]: any }
61
+ | undefined;
62
+ /** ISO 8601 */
63
+ fromAt: string;
64
+ /** ISO 8601 */
65
+ toAt: string;
66
+ }
67
+
68
+ export interface TransitAspect {
69
+ /** e.g. "mars" */
70
+ transitingBody: string;
71
+ /** e.g. "sun" */
72
+ natalPoint: string;
73
+ /** e.g. "conjunction" */
74
+ aspect: string;
75
+ /** ISO 8601 — trigger time */
76
+ exactAt: string;
77
+ orb: number;
78
+ }
79
+
80
+ export interface ForecastTransitsResponse {
81
+ events: TransitAspect[];
82
+ }
83
+
84
+ export const ASTRO_ENGINE_PACKAGE_NAME = "astro_engine";
85
+
86
+ wrappers[".google.protobuf.Struct"] = { fromObject: Struct.wrap, toObject: Struct.unwrap } as any;
87
+
88
+ /**
89
+ * Implemented by the PYTHON astro-engine service (Kerykeion). Pure compute:
90
+ * no DB, no Kafka, stateless. Called only by the astrology service's workers.
91
+ * astro-engine generates its stubs from THIS file via grpc_tools.protoc; it does
92
+ * not install the npm package. Complex outputs are returned as Struct (JSON) to
93
+ * avoid pinning a rigid schema onto Kerykeion's output shape.
94
+ */
95
+
96
+ export interface AstroEngineServiceClient {
97
+ computeNatal(request: ComputeNatalRequest, metadata?: Metadata): Observable<ComputeNatalResponse>;
98
+
99
+ computeTransits(request: ComputeTransitsRequest, metadata?: Metadata): Observable<ComputeTransitsResponse>;
100
+
101
+ forecastTransits(request: ForecastTransitsRequest, metadata?: Metadata): Observable<ForecastTransitsResponse>;
102
+ }
103
+
104
+ /**
105
+ * Implemented by the PYTHON astro-engine service (Kerykeion). Pure compute:
106
+ * no DB, no Kafka, stateless. Called only by the astrology service's workers.
107
+ * astro-engine generates its stubs from THIS file via grpc_tools.protoc; it does
108
+ * not install the npm package. Complex outputs are returned as Struct (JSON) to
109
+ * avoid pinning a rigid schema onto Kerykeion's output shape.
110
+ */
111
+
112
+ export interface AstroEngineServiceController {
113
+ computeNatal(
114
+ request: ComputeNatalRequest,
115
+ metadata?: Metadata,
116
+ ): Promise<ComputeNatalResponse> | Observable<ComputeNatalResponse> | ComputeNatalResponse;
117
+
118
+ computeTransits(
119
+ request: ComputeTransitsRequest,
120
+ metadata?: Metadata,
121
+ ): Promise<ComputeTransitsResponse> | Observable<ComputeTransitsResponse> | ComputeTransitsResponse;
122
+
123
+ forecastTransits(
124
+ request: ForecastTransitsRequest,
125
+ metadata?: Metadata,
126
+ ): Promise<ForecastTransitsResponse> | Observable<ForecastTransitsResponse> | ForecastTransitsResponse;
127
+ }
128
+
129
+ export function AstroEngineServiceControllerMethods() {
130
+ return function (constructor: Function) {
131
+ const grpcMethods: string[] = ["computeNatal", "computeTransits", "forecastTransits"];
132
+ for (const method of grpcMethods) {
133
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
134
+ GrpcMethod("AstroEngineService", method)(constructor.prototype[method], method, descriptor);
135
+ }
136
+ const grpcStreamMethods: string[] = [];
137
+ for (const method of grpcStreamMethods) {
138
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
139
+ GrpcStreamMethod("AstroEngineService", method)(constructor.prototype[method], method, descriptor);
140
+ }
141
+ };
142
+ }
143
+
144
+ export const ASTRO_ENGINE_SERVICE_NAME = "AstroEngineService";