@deployport/api-services-corelib 0.1.4 → 0.3.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.
@@ -1,61 +1,60 @@
1
1
  import { Sha256 } from '@aws-crypto/sha256-js';
2
2
  import { Runtime } from "@deployport/specular-runtime";
3
3
  import { SourceData } from "@aws-sdk/types";
4
- import { ServiceSignatureV1 } from '../specular.js';
4
+ import { ServiceSignatureV1, SignedOperationV1 } from '../specular.js';
5
+ import type { Config } from "./config.js";
5
6
 
6
7
  type Credentials = {
7
8
  keyID: string;
8
9
  secret: string;
9
10
  }
10
11
 
11
- export type Config = {
12
- deployport?: {
13
- region?: string;
14
- accessKeyID?: string;
15
- secretAccessKey?: string;
12
+ const VendorCode = 'dpp';
13
+
14
+ /**
15
+ * Replaces the `<region>` placeholder in the request URL and Host header with
16
+ * the given region. Mirrors Go's `ReplaceRegionInRequest`. Runs for every
17
+ * request that has a resolved region, whether or not the request is signed.
18
+ */
19
+ export function replaceRegionInRequest(request: Runtime.HTTPRequest, region: string): void {
20
+ if (request.url) {
21
+ request.url = request.url.replaceAll("<region>", region);
22
+ }
23
+ const host = request.headers["Host"];
24
+ if (typeof host === "string") {
25
+ request.headers["Host"] = host.replaceAll("<region>", region);
16
26
  }
17
27
  }
18
28
 
19
- const VendorCode = 'dpp';
20
-
21
29
  export async function ConfigureSignatureV1(submission: Runtime.Submission, config: Config): Promise<void> {
22
-
23
- // const { request } = submission;
24
- // const { headers } = request;
25
- // if (!headers["x-specular-signature"]) {
26
- // headers["x-specular-signature"] = "v1";
27
- // }
28
- console.log("Hello from ConfigureSignatureV1 in runtime/signer.ts!", submission)
30
+ // sign only operations that opted in via SignedOperationV1
31
+ const signedOperationV1 = submission.operation.annotations.find((a) => a instanceof SignedOperationV1);
32
+ if (!signedOperationV1) {
33
+ return;
34
+ }
29
35
  const annotations = submission.operation.resource.package.annotations;
30
- console.log("service annotations", annotations);
31
36
  const serviceSignatureV1 = annotations.find((a) => a instanceof ServiceSignatureV1);
32
37
  if (!serviceSignatureV1) {
33
38
  return;
34
39
  }
35
- console.log("signing using config", config)
36
40
  const { deployport } = config;
37
41
  if (!deployport) {
38
- console.warn("missing required deployport configuration for signing", config);
39
42
  return;
40
43
  }
41
44
  const { region, accessKeyID: keyID, secretAccessKey: secret } = deployport;
42
45
  if (!region || !keyID || !secret) {
43
- console.warn("missing required configuration for signing", deployport);
46
+ // Incomplete credentials/region: leave the request unsigned.
44
47
  return;
45
48
  }
46
49
  const { ServiceName: signingService } = serviceSignatureV1;
47
- console.log("annotations", annotations, VendorCode, signingService);
48
50
  const { longDate, shortDate } = formatDate(new Date());
49
51
  const signingScope = buildSigningScope(VendorCode, region, signingService, shortDate);
50
- console.log("signingScope", signingScope);
51
52
 
52
53
  const credentialPart = buildCredentialPart(keyID, signingScope);
53
- console.log("credentialPart", credentialPart);
54
54
 
55
55
  const authHeaderPrefix = vendorAlgorithm(VendorCode) + " " + credentialPart
56
56
 
57
57
  const bodyDigest = toHex(await hashSHA256(submission.request.body));
58
- console.log("bodyDigest", bodyDigest);
59
58
  const headers = submission.request.headers;
60
59
  headers[vendorDateHeaderKey(VendorCode)] = longDate;
61
60
  headers[vendorHeaderCanonicalNameKey(VendorCode, "Service")] = signingService;
@@ -63,7 +62,6 @@ export async function ConfigureSignatureV1(submission: Runtime.Submission, confi
63
62
  headers[vendorHeaderCanonicalNameKey(VendorCode, "Operation")] = submission.operation.name;
64
63
  headers[vendorRegionHeaderKey(VendorCode)] = region;
65
64
  headers[vendorHeaderCanonicalNameKey(VendorCode, "Content-Sha256")] = bodyDigest;
66
- console.log("headers", headers);
67
65
  const canonicalHeaders = getCanonicalHeaders(VendorCode, headers);
68
66
 
69
67
  const credentials: Credentials = {
@@ -85,7 +83,6 @@ export async function ConfigureSignatureV1(submission: Runtime.Submission, confi
85
83
  );
86
84
 
87
85
  headers["Authorization"] = [authHeaderPrefix, `SignedHeaders=${canonicalHeaders.signedHeaders}`, `Signature=${signature}`] as any;
88
- console.log("signed headers", headers);
89
86
  }
90
87
 
91
88
  function createCanonicalRequest(request: Runtime.HTTPRequest, canonicalHeaders: CanonicalHeaders, payloadHash: string): string {
@@ -104,7 +101,6 @@ function getCanonicalQuery({ path }: Runtime.HTTPRequest): string {
104
101
  }
105
102
 
106
103
  function getCanonicalPath({ path }: Runtime.HTTPRequest): string {
107
- console.log("getCanonicalPath path", path);
108
104
  return path;
109
105
  // if (this.uriEscapePath) {
110
106
  // Non-S3 services, we normalize the path and then double URI encode it.
@@ -131,7 +127,6 @@ function getCanonicalPath({ path }: Runtime.HTTPRequest): string {
131
127
  // my-object//example//photo.user should not be normalized to
132
128
  // my-object/example/photo.user
133
129
 
134
- console.log("getCanonicalPath path (curated)", path);
135
130
  return path;
136
131
  }
137
132
 
@@ -156,7 +151,6 @@ async function getSignature(
156
151
  canonicalRequest: string
157
152
  ): Promise<string> {
158
153
  const stringToSign = await createStringToSign(vendor, longDate, credentialScope, canonicalRequest);
159
- console.log("stringToSign", stringToSign);
160
154
 
161
155
  const hash = new Sha256(await keyPromise);
162
156
  hash.update(stringToSign);
@@ -169,7 +163,6 @@ async function createStringToSign(
169
163
  credentialScope: string,
170
164
  canonicalRequest: string
171
165
  ): Promise<string> {
172
- console.log('canonicalRequest', canonicalRequest);
173
166
  const hash = new Sha256();
174
167
  hash.update(canonicalRequest);
175
168
  const hashedRequest = await hash.digest();
package/package.json CHANGED
@@ -1,15 +1,41 @@
1
1
  {
2
2
  "name": "@deployport/api-services-corelib",
3
- "version": "0.1.4",
3
+ "version": "0.3.0",
4
4
  "description": "",
5
5
  "main": "./specular.js",
6
6
  "types": "./specular.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./specular.d.ts",
10
+ "default": "./specular.js"
11
+ },
12
+ "./configurator": {
13
+ "types": "./configurator/index.d.ts",
14
+ "default": "./configurator/index.js"
15
+ },
16
+ "./configurator/node": {
17
+ "types": "./configurator/loader.node.d.ts",
18
+ "default": "./configurator/loader.node.js"
19
+ }
20
+ },
21
+ "imports": {
22
+ "#config-loader": {
23
+ "browser": "./configurator/loader.browser.js",
24
+ "node": "./configurator/loader.node.js",
25
+ "default": "./configurator/loader.browser.js"
26
+ }
27
+ },
7
28
  "author": "bithavoc",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/deployport/api-services-corelib-js.git"
32
+ },
8
33
  "scripts": {
9
34
  "prepublishOnly": "npm run build-configurator",
10
35
  "generate": "specular-standalone-compiler generate",
11
- "build-configurator": "tsc configurator/index.ts --declaration --module nodenext",
36
+ "build-configurator": "tsc",
12
37
  "build": "npm run build-configurator",
38
+ "test": "vitest run",
13
39
  "clean": "rm -rf node_modules && rm -f **/*.js **/*.d.ts"
14
40
  },
15
41
  "type": "module",
@@ -17,10 +43,13 @@
17
43
  "dependencies": {
18
44
  "@aws-crypto/sha256-js": "^5.2.0",
19
45
  "@aws-sdk/types": "^3.515.0",
20
- "@deployport/specular-runtime": "^0.1.11"
46
+ "@deployport/specular-runtime": "^0.2.1",
47
+ "yaml": "^2.6.1"
21
48
  },
22
49
  "devDependencies": {
23
- "@tsconfig/node18": "^18.2.2",
24
- "@types/node": "^20.8.3"
50
+ "@tsconfig/node24": "^24.0.4",
51
+ "@types/node": "^24.13.2",
52
+ "typescript": "^6.0.3",
53
+ "vitest": "^3.0.0"
25
54
  }
26
- }
55
+ }
package/specular.d.ts CHANGED
@@ -1,23 +1,114 @@
1
1
  import { Runtime, Metadata } from '@deployport/specular-runtime';
2
+ /** Marks an operation with digital signature authentication for id4ntity verification
3
+ */
2
4
  export declare class SignedOperationV1 {
3
5
  }
6
+ /** entity ServiceSignatureV1
7
+ */
4
8
  export declare class ServiceSignatureV1 {
9
+ /** serviceName parameter
10
+ */
5
11
  ServiceName: string;
6
12
  }
13
+ /** Struct metadata
14
+ */
7
15
  export declare const AccessDeniedProblemMeta: Metadata.Struct;
16
+ /** struct AccessDeniedProblem
17
+ */
8
18
  export interface AccessDeniedProblemProperties {
19
+ /** message property
20
+ */
9
21
  message: string;
10
22
  }
11
- export declare class AccessDeniedProblem extends Error implements AccessDeniedProblemProperties, Runtime.StructInterface {
12
- message: string;
23
+ /** struct AccessDeniedProblem
24
+ */
25
+ export declare class AccessDeniedProblem extends Runtime.RpcError implements AccessDeniedProblemProperties, Runtime.StructInterface {
13
26
  get __structPath(): Metadata.StructPath;
14
27
  }
28
+ /** Struct metadata
29
+ */
15
30
  export declare const ForbiddenProblemMeta: Metadata.Struct;
31
+ /** struct ForbiddenProblem
32
+ */
16
33
  export interface ForbiddenProblemProperties {
34
+ /** message property
35
+ */
36
+ message: string;
37
+ }
38
+ /** struct ForbiddenProblem
39
+ */
40
+ export declare class ForbiddenProblem extends Runtime.RpcError implements ForbiddenProblemProperties, Runtime.StructInterface {
41
+ get __structPath(): Metadata.StructPath;
42
+ }
43
+ /** Struct metadata
44
+ */
45
+ export declare const ProblemActionMeta: Metadata.Struct;
46
+ /** A localized call-to-action surfaced alongside a problem. Title and URL
47
+ * are already resolved to a specific locale; clients render them as-is.
48
+ */
49
+ export interface ProblemActionProperties {
50
+ /** Optional stable identifier. Clients can key on it to apply custom
51
+ * presentation (icon, ordering) per well-known action.
52
+ */
53
+ id: string;
54
+ /** BCP 47 tag of the locale the title and url were resolved to. May
55
+ * differ from the caller's requested locale when a fallback was used.
56
+ */
57
+ locale: string | null;
58
+ /** title property
59
+ */
60
+ title: string;
61
+ /** url property
62
+ */
63
+ url: string | null;
64
+ }
65
+ /** A localized call-to-action surfaced alongside a problem. Title and URL
66
+ * are already resolved to a specific locale; clients render them as-is.
67
+ */
68
+ export interface ProblemAction extends ProblemActionProperties, Runtime.StructInterface {
69
+ }
70
+ /** Struct metadata
71
+ */
72
+ export declare const ThrottledProblemMeta: Metadata.Struct;
73
+ /** Raised when the caller is being throttled and should retry later.
74
+ */
75
+ export interface ThrottledProblemProperties {
76
+ /** Optional calls-to-action to help the caller (e.g. support, upgrade,
77
+ * docs links), ordered most-specific first. Empty when none apply.
78
+ */
79
+ actions: (ProblemActionProperties)[];
80
+ /** message property
81
+ */
17
82
  message: string;
83
+ /** Milliseconds the caller should wait before retrying.
84
+ */
85
+ retryAfterMs: number | null;
18
86
  }
19
- export declare class ForbiddenProblem extends Error implements ForbiddenProblemProperties, Runtime.StructInterface {
87
+ /** Raised when the caller is being throttled and should retry later.
88
+ */
89
+ export declare class ThrottledProblem extends Runtime.RpcError implements ThrottledProblemProperties, Runtime.StructInterface {
90
+ actions: (ProblemActionProperties)[];
91
+ retryAfterMs: number | null;
92
+ get __structPath(): Metadata.StructPath;
93
+ }
94
+ /** Struct metadata
95
+ */
96
+ export declare const QuotaExceededProblemMeta: Metadata.Struct;
97
+ /** Raised when a resource quota has been exceeded.
98
+ */
99
+ export interface QuotaExceededProblemProperties {
100
+ /** Optional calls-to-action to help the caller (e.g. request an increase,
101
+ * upgrade, docs links), ordered most-specific first. Empty when none apply.
102
+ */
103
+ actions: (ProblemActionProperties)[];
104
+ /** message property
105
+ */
20
106
  message: string;
107
+ }
108
+ /** Raised when a resource quota has been exceeded.
109
+ */
110
+ export declare class QuotaExceededProblem extends Runtime.RpcError implements QuotaExceededProblemProperties, Runtime.StructInterface {
111
+ actions: (ProblemActionProperties)[];
21
112
  get __structPath(): Metadata.StructPath;
22
113
  }
23
114
  export declare function SpecularPackage(): Metadata.Package;
package/specular.js CHANGED
@@ -1,40 +1,129 @@
1
- // JS gen package
2
- import { Metadata, } from '@deployport/specular-runtime';
3
- // SignedOperationV1 entity
4
- // Marks an operation with digital signature authentication for id4ntity verification
1
+ import { Runtime, Metadata, } from '@deployport/specular-runtime';
2
+ /** Marks an operation with digital signature authentication for id4ntity verification
3
+ */
5
4
  export class SignedOperationV1 {
6
5
  }
7
- // ServiceSignatureV1 entity
6
+ /** entity ServiceSignatureV1
7
+ */
8
8
  export class ServiceSignatureV1 {
9
+ /** serviceName parameter
10
+ */
9
11
  ServiceName = '';
10
12
  }
11
13
  const _pkg = new Metadata.Package("deployport", "corelib");
14
+ /** Struct metadata
15
+ */
12
16
  export const AccessDeniedProblemMeta = new Metadata.Struct(_pkg, "AccessDeniedProblem");
13
17
  new Metadata.Property(AccessDeniedProblemMeta, "message", {
14
18
  NonNullable: true,
15
19
  SubType: "builtin",
16
20
  Builtin: "string"
17
21
  });
18
- export class AccessDeniedProblem extends Error {
19
- message = '';
22
+ /** struct AccessDeniedProblem
23
+ */
24
+ export class AccessDeniedProblem extends Runtime.RpcError {
20
25
  get __structPath() {
21
26
  return AccessDeniedProblemMeta.path;
22
27
  }
23
28
  }
24
29
  AccessDeniedProblemMeta.problemInstantiate = (msg) => new AccessDeniedProblem(msg);
30
+ /** Struct metadata
31
+ */
25
32
  export const ForbiddenProblemMeta = new Metadata.Struct(_pkg, "ForbiddenProblem");
26
33
  new Metadata.Property(ForbiddenProblemMeta, "message", {
27
34
  NonNullable: true,
28
35
  SubType: "builtin",
29
36
  Builtin: "string"
30
37
  });
31
- export class ForbiddenProblem extends Error {
32
- message = '';
38
+ /** struct ForbiddenProblem
39
+ */
40
+ export class ForbiddenProblem extends Runtime.RpcError {
33
41
  get __structPath() {
34
42
  return ForbiddenProblemMeta.path;
35
43
  }
36
44
  }
37
45
  ForbiddenProblemMeta.problemInstantiate = (msg) => new ForbiddenProblem(msg);
46
+ /** Struct metadata
47
+ */
48
+ export const ProblemActionMeta = new Metadata.Struct(_pkg, "ProblemAction");
49
+ new Metadata.Property(ProblemActionMeta, "id", {
50
+ NonNullable: true,
51
+ SubType: "builtin",
52
+ Builtin: "string"
53
+ });
54
+ new Metadata.Property(ProblemActionMeta, "locale", {
55
+ NonNullable: false,
56
+ SubType: "builtin",
57
+ Builtin: "string"
58
+ });
59
+ new Metadata.Property(ProblemActionMeta, "title", {
60
+ NonNullable: true,
61
+ SubType: "builtin",
62
+ Builtin: "string"
63
+ });
64
+ new Metadata.Property(ProblemActionMeta, "url", {
65
+ NonNullable: false,
66
+ SubType: "builtin",
67
+ Builtin: "string"
68
+ });
69
+ /** Struct metadata
70
+ */
71
+ export const ThrottledProblemMeta = new Metadata.Struct(_pkg, "ThrottledProblem");
72
+ new Metadata.Property(ThrottledProblemMeta, "actions", {
73
+ NonNullable: true,
74
+ SubType: "array",
75
+ Item: {
76
+ NonNullable: true,
77
+ SubType: "userDefined",
78
+ Type: SpecularPackage().requireTypeByName("ProblemAction")
79
+ }
80
+ });
81
+ new Metadata.Property(ThrottledProblemMeta, "message", {
82
+ NonNullable: true,
83
+ SubType: "builtin",
84
+ Builtin: "string"
85
+ });
86
+ new Metadata.Property(ThrottledProblemMeta, "retryAfterMs", {
87
+ NonNullable: false,
88
+ SubType: "builtin",
89
+ Builtin: "int64"
90
+ });
91
+ /** Raised when the caller is being throttled and should retry later.
92
+ */
93
+ export class ThrottledProblem extends Runtime.RpcError {
94
+ actions = [];
95
+ retryAfterMs = null;
96
+ get __structPath() {
97
+ return ThrottledProblemMeta.path;
98
+ }
99
+ }
100
+ ThrottledProblemMeta.problemInstantiate = (msg) => new ThrottledProblem(msg);
101
+ /** Struct metadata
102
+ */
103
+ export const QuotaExceededProblemMeta = new Metadata.Struct(_pkg, "QuotaExceededProblem");
104
+ new Metadata.Property(QuotaExceededProblemMeta, "actions", {
105
+ NonNullable: true,
106
+ SubType: "array",
107
+ Item: {
108
+ NonNullable: true,
109
+ SubType: "userDefined",
110
+ Type: SpecularPackage().requireTypeByName("ProblemAction")
111
+ }
112
+ });
113
+ new Metadata.Property(QuotaExceededProblemMeta, "message", {
114
+ NonNullable: true,
115
+ SubType: "builtin",
116
+ Builtin: "string"
117
+ });
118
+ /** Raised when a resource quota has been exceeded.
119
+ */
120
+ export class QuotaExceededProblem extends Runtime.RpcError {
121
+ actions = [];
122
+ get __structPath() {
123
+ return QuotaExceededProblemMeta.path;
124
+ }
125
+ }
126
+ QuotaExceededProblemMeta.problemInstantiate = (msg) => new QuotaExceededProblem(msg);
38
127
  export function SpecularPackage() {
39
128
  return _pkg;
40
129
  }