From dfbe63bd2a4e3a8e2d4b401aff53772341c29dcf Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 12:38:03 +0200 Subject: [PATCH 01/10] build: add job for building server code Signed-off-by: Mark Sagi-Kazar --- .dagger/generate.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.dagger/generate.go b/.dagger/generate.go index a2d3991d0..3938fcba4 100644 --- a/.dagger/generate.go +++ b/.dagger/generate.go @@ -96,6 +96,18 @@ func (m *Generate) WebSdk() *dagger.Directory { WithoutDirectory("node_modules") } +func (m *Generate) Server() *dagger.Directory { + openapi := m.Openapi() + + source := m.Source. + WithFile("api/openapi.yaml", openapi) + + return goModule(). + WithSource(source). + Exec([]string{"go", "generate", "-x", "./api"}). + Directory("/work/src/api") +} + func (m *Generate) Check(ctx context.Context) error { result := goModuleCross(""). WithSource(m.Source). From 1d4bad0ef91f7b49048d0fcf2294e1a8de85f284 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 12:46:21 +0200 Subject: [PATCH 02/10] fix(api): move subjects back to OpenMeter Signed-off-by: Mark Sagi-Kazar --- api/spec/src/cloud/subjects.tsp | 56 ++------------------------- api/spec/src/main.tsp | 1 + api/spec/src/notification/event.tsp | 8 +--- api/spec/src/subjects.tsp | 59 +++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 api/spec/src/subjects.tsp diff --git a/api/spec/src/cloud/subjects.tsp b/api/spec/src/cloud/subjects.tsp index 74989bc02..2833bb478 100644 --- a/api/spec/src/cloud/subjects.tsp +++ b/api/spec/src/cloud/subjects.tsp @@ -16,14 +16,14 @@ interface Subjects { */ @get @operationId("listSubjects") - list(): Subject[] | OpenMeter.CommonErrors; + list(): OpenMeter.Subject[] | OpenMeter.CommonErrors; /** * Get subject by ID or key. */ @get @operationId("getSubject") - get(@path subjectIdOrKey: string): Subject | OpenMeter.NotFoundError | OpenMeter.CommonErrors; + get(@path subjectIdOrKey: string): OpenMeter.Subject | OpenMeter.NotFoundError | OpenMeter.CommonErrors; /** * Upserts a subject. Creates or updates subject. @@ -33,7 +33,7 @@ interface Subjects { */ @post @operationId("upsertSubject") - upsert(@body subject: Subject[]): Subject[] | OpenMeter.CommonErrors; + upsert(@body subject: OpenMeter.Subject[]): OpenMeter.Subject[] | OpenMeter.CommonErrors; /** * Delete subject by ID or key. @@ -42,53 +42,3 @@ interface Subjects { @operationId("deleteSubject") delete(@path subjectIdOrKey: string): void | OpenMeter.CommonErrors; } - -/** - * A subject is a unique identifier for a user or entity. - */ -@friendlyName("Subject") -@example(#{ - id: "01G65Z755AFWAKHE12NY0CQ9FH", - key: "customer-id", - displayName: "Customer Name", - metadata: #{ hubspotId: "123456" }, - currentPeriodStart: DateTime.fromISO("2023-01-01T00:00:00Z"), - currentPeriodEnd: DateTime.fromISO("2023-02-01T00:00:00Z"), - stripeCustomerId: "cus_JMOlctsKV8", -}) -model Subject { - // Validator doesn't obey required for readOnly properties - // See: https://github.com/stoplightio/spectral/issues/1274 - - /** - * A unique identifier for the subject. - */ - @visibility("read") - @example("01G65Z755AFWAKHE12NY0CQ9FH") - id: ULID; - - /** - * A unique, human-readable identifier for the subject. - * Must consist only alphanumeric and underscore characters. - */ - @example("customer-id") - key: Key; - - /** - * A human-readable display name for the subject. - */ - @example("Customer Name") - displayName?: string; - - @example(#{ hubspotId: "123456" }) - metadata?: Record; - - @example(DateTime.fromISO("2023-01-01T00:00:00Z")) - currentPeriodStart?: DateTime; - - @example(DateTime.fromISO("2023-02-01T00:00:00Z")) - currentPeriodEnd?: DateTime; - - @example("cus_JMOlctsKV8") - stripeCustomerId?: string; -} diff --git a/api/spec/src/main.tsp b/api/spec/src/main.tsp index 36299389f..e5f079590 100644 --- a/api/spec/src/main.tsp +++ b/api/spec/src/main.tsp @@ -13,6 +13,7 @@ import "./customer.tsp"; import "./events.tsp"; import "./meters.tsp"; import "./portal.tsp"; +import "./subjects.tsp"; import "./debug.tsp"; import "./notification"; import "./entitlements"; diff --git a/api/spec/src/notification/event.tsp b/api/spec/src/notification/event.tsp index 3a1d14684..ca5e95712 100644 --- a/api/spec/src/notification/event.tsp +++ b/api/spec/src/notification/event.tsp @@ -108,7 +108,7 @@ model EventBalanceThresholdPayloadData { @visibility("read") @summary("Subject") - subject: Subject; + subject: OpenMeter.Subject; @visibility("read") @summary("Entitlement Value") @@ -119,12 +119,6 @@ model EventBalanceThresholdPayloadData { threshold: RuleBalanceThresholdValue; } -/** - * FIXME: move subject api to OpenMeter so Subject model is avaiable here. - */ -@friendlyName("DummySubject") -model Subject {} - /** * Type of the notification event. */ diff --git a/api/spec/src/subjects.tsp b/api/spec/src/subjects.tsp new file mode 100644 index 000000000..f13083f83 --- /dev/null +++ b/api/spec/src/subjects.tsp @@ -0,0 +1,59 @@ +import "@typespec/http"; +import "@typespec/rest"; +import "@typespec/openapi3"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.OpenAPI; + +namespace OpenMeter; + +/** + * A subject is a unique identifier for a user or entity. + */ +@friendlyName("Subject") +@example(#{ + id: "01G65Z755AFWAKHE12NY0CQ9FH", + key: "customer-id", + displayName: "Customer Name", + metadata: #{ hubspotId: "123456" }, + currentPeriodStart: DateTime.fromISO("2023-01-01T00:00:00Z"), + currentPeriodEnd: DateTime.fromISO("2023-02-01T00:00:00Z"), + stripeCustomerId: "cus_JMOlctsKV8", +}) +model Subject { + // Validator doesn't obey required for readOnly properties + // See: https://github.com/stoplightio/spectral/issues/1274 + + /** + * A unique identifier for the subject. + */ + @visibility("read") + @example("01G65Z755AFWAKHE12NY0CQ9FH") + id: ULID; + + /** + * A unique, human-readable identifier for the subject. + * Must consist only alphanumeric and underscore characters. + */ + @example("customer-id") + key: Key; + + /** + * A human-readable display name for the subject. + */ + @example("Customer Name") + displayName?: string; + + @example(#{ hubspotId: "123456" }) + metadata?: Record; + + @example(DateTime.fromISO("2023-01-01T00:00:00Z")) + currentPeriodStart?: DateTime; + + @example(DateTime.fromISO("2023-02-01T00:00:00Z")) + currentPeriodEnd?: DateTime; + + @example("cus_JMOlctsKV8") + stripeCustomerId?: string; +} From 95eee29ca52076b227daaf1226cecdd8e7520f6f Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 13:08:52 +0200 Subject: [PATCH 03/10] fix(api): generate string ID parameters for meters Signed-off-by: Mark Sagi-Kazar --- api/spec/src/meters.tsp | 2 +- api/spec/src/types.tsp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/api/spec/src/meters.tsp b/api/spec/src/meters.tsp index f3e73c423..3175498bf 100644 --- a/api/spec/src/meters.tsp +++ b/api/spec/src/meters.tsp @@ -194,7 +194,7 @@ enum WindowSize { /** * A unique meter identifier. */ -alias MeterIdentifier = ULID | Key; +alias MeterIdentifier = ULIDOrKey; /** * Meter query parameters. diff --git a/api/spec/src/types.tsp b/api/spec/src/types.tsp index b02731250..a286d8d0b 100644 --- a/api/spec/src/types.tsp +++ b/api/spec/src/types.tsp @@ -17,6 +17,17 @@ scalar ULID extends string; @maxLength(64) scalar Key extends string; +/** + * ULID (Universally Unique Lexicographically Sortable Identifier). + * A key is a unique string that is used to identify a resource. + * + * TODO: this is a temporary solution to support both ULID and Key in the same spec for codegen. + */ +@pattern("^[a-z0-9]+(?:_[a-z0-9]+)*$|^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$") +@minLength(1) +@maxLength(64) +scalar ULIDOrKey extends string; + // NOTE (andras): key format enforcement isn't supported by TypeSpec (patternProperties). See: https://github.com/microsoft/typespec/discussions/1626 /** * Set of key-value pairs. From 2e1681b8ef30f17064bf58190ed42730d5b716da Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 15:40:09 +0200 Subject: [PATCH 04/10] fix: make subject metadata match current API (null, unknown) Signed-off-by: Mark Sagi-Kazar --- api/spec/src/subjects.tsp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/spec/src/subjects.tsp b/api/spec/src/subjects.tsp index f13083f83..61f0acc91 100644 --- a/api/spec/src/subjects.tsp +++ b/api/spec/src/subjects.tsp @@ -45,8 +45,10 @@ model Subject { @example("Customer Name") displayName?: string; + // TODO: figure out if we want to support arbitrary values or string only + @example(#{ hubspotId: "123456" }) - metadata?: Record; + metadata?: Record | null; @example(DateTime.fromISO("2023-01-01T00:00:00Z")) currentPeriodStart?: DateTime; From 11281c645661324cfa089f8afd63389de402510c Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 15:41:10 +0200 Subject: [PATCH 05/10] fix: make metadata non-required as per the current implementation Signed-off-by: Mark Sagi-Kazar --- api/spec/src/entitlements/feature.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/spec/src/entitlements/feature.tsp b/api/spec/src/entitlements/feature.tsp index e30242e35..5e473bb26 100644 --- a/api/spec/src/entitlements/feature.tsp +++ b/api/spec/src/entitlements/feature.tsp @@ -91,7 +91,7 @@ model FeatureCreateInputs { @summary("Optional metadata") @example(#{ key: "value" }) - metadata: Metadata; + metadata?: Metadata; // /** // * The meter that the feature is associated with and and based on which usage is calculated. From 71fbb2bcc8c7eef74152150a2d92503642b74a41 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 15:41:50 +0200 Subject: [PATCH 06/10] fix: make generated metadata a type alias for easier transition Signed-off-by: Mark Sagi-Kazar --- api/spec/src/types.tsp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/spec/src/types.tsp b/api/spec/src/types.tsp index a286d8d0b..b457558a9 100644 --- a/api/spec/src/types.tsp +++ b/api/spec/src/types.tsp @@ -1,3 +1,7 @@ +import "@typespec/openapi3"; + +using TypeSpec.OpenAPI; + /** * ULID (Universally Unique Lexicographically Sortable Identifier). */ @@ -29,10 +33,12 @@ scalar Key extends string; scalar ULIDOrKey extends string; // NOTE (andras): key format enforcement isn't supported by TypeSpec (patternProperties). See: https://github.com/microsoft/typespec/discussions/1626 +// TODO: decide if we want to use the generated Metadata type instead and update code to use it /** * Set of key-value pairs. * Metadata can be used to store additional information about a resource. */ +@extension("x-go-type", "map[string]string") @example(#{ externalId: "019142cc-a016-796a-8113-1a942fecd26d" }) model Metadata { ...Record; From 00dfe76e6ccf182910ce5971bc8136a3f7e685b0 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 15:47:00 +0200 Subject: [PATCH 07/10] fix: meter slug should be a list Signed-off-by: Mark Sagi-Kazar --- api/spec/src/entitlements/feature.tsp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/spec/src/entitlements/feature.tsp b/api/spec/src/entitlements/feature.tsp index 5e473bb26..2ddbd97d6 100644 --- a/api/spec/src/entitlements/feature.tsp +++ b/api/spec/src/entitlements/feature.tsp @@ -32,12 +32,14 @@ interface Features { /** * Filter by meterSlug */ - @query meterSlug?: string, + @query + meterSlug?: string[], /** * Filter by meterGroupByFilters */ - @query includeArchived?: boolean = false, + @query + includeArchived?: boolean = false, ...OpenMeter.QueryPagination, ...OpenMeter.QueryLimitOffset, From ed8eac6168eb11460999f88c450d9975aaf05227 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 17:13:33 +0200 Subject: [PATCH 08/10] fix: make generated entitlement type a type alias for easier transition Signed-off-by: Mark Sagi-Kazar --- api/spec/src/entitlements/entitlements.tsp | 1 + 1 file changed, 1 insertion(+) diff --git a/api/spec/src/entitlements/entitlements.tsp b/api/spec/src/entitlements/entitlements.tsp index 8a1e11153..b2babbc13 100644 --- a/api/spec/src/entitlements/entitlements.tsp +++ b/api/spec/src/entitlements/entitlements.tsp @@ -76,6 +76,7 @@ interface Entitlements { * Type of the entitlement. */ @friendlyName("EntitlementType") +@extension("x-go-type", "string") enum EntitlementType { metered: "metered", boolean: "boolean", From 8a545fad7774390674f674fdd3f515b5d1966f73 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 17:17:39 +0200 Subject: [PATCH 09/10] fix: add missing id to feature Signed-off-by: Mark Sagi-Kazar --- api/spec/src/entitlements/feature.tsp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/spec/src/entitlements/feature.tsp b/api/spec/src/entitlements/feature.tsp index 2ddbd97d6..4e4fac061 100644 --- a/api/spec/src/entitlements/feature.tsp +++ b/api/spec/src/entitlements/feature.tsp @@ -127,4 +127,11 @@ model Feature { ...ResourceTimestamps; ...Archiveable; ...FeatureCreateInputs; + + /** + * Readonly unique ULID identifier. + */ + @example("01ARZ3NDEKTSV4RRFFQ69G5FAV") + @visibility("read") + id: ULID; } From 6d7282545818628ccbd5e7388e30e995f4bd159c Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Wed, 2 Oct 2024 17:33:21 +0200 Subject: [PATCH 10/10] fix: add missing id to entitlement Signed-off-by: Mark Sagi-Kazar --- api/spec/src/entitlements/entitlements.tsp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/spec/src/entitlements/entitlements.tsp b/api/spec/src/entitlements/entitlements.tsp index b2babbc13..03d7bfabd 100644 --- a/api/spec/src/entitlements/entitlements.tsp +++ b/api/spec/src/entitlements/entitlements.tsp @@ -226,6 +226,13 @@ model EntitlementSharedFields { ...ResourceTimestamps; ...OmitProperties; + /** + * Readonly unique ULID identifier. + */ + @example("01ARZ3NDEKTSV4RRFFQ69G5FAV") + @visibility("read") + id: ULID; + /** * The type of the entitlement. */