Skip to content

Commit

Permalink
docs(types): add JSDoc documentation for network and global types
Browse files Browse the repository at this point in the history
- Add comprehensive JSDoc for network type definitions (MainnetNetworkId, TestnetNetworkId, SandboxNetworkId)
- Document Window interface extension for Keplr wallet integration
- Include usage examples and parameter descriptions for getOfflineSignerAuto
- Improve type definitions readability with detailed descriptions

Signed-off-by: Greg Osuri <[email protected]>
  • Loading branch information
gosuri committed Dec 10, 2024
1 parent d0a9162 commit e8cac9f
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 24 deletions.
111 changes: 109 additions & 2 deletions src/sdl/SDL/SDL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,54 @@ function isString(str: any): str is string {

type NetworkVersion = "beta2" | "beta3";

/**
* SDL (Stack Definition Language) parser and validator
* Handles parsing and validation of Akash deployment manifests
*
* @example
* ```ts
* import { SDL } from './SDL';
*
* const yaml = `
* version: "2.0"
* services:
* web:
* image: nginx
* expose:
* - port: 80
* as: 80
* to:
* - global: true
* `;
*
* // Parse SDL from YAML string
* const sdl = SDL.fromString(yaml);
*
* // Get deployment manifest
* const manifest = sdl.manifest();
*
* // Get deployment groups
* const groups = sdl.groups();
* ```
*/
export class SDL {
/**
* Creates an SDL instance from a YAML string
* @param yaml - The YAML string containing the SDL definition
* @param version - The SDL version (beta2 or beta3)
* @param networkId - The network ID to validate against
*/
static fromString(yaml: string, version: NetworkVersion = "beta2", networkId: NetworkId = MAINNET_ID) {
const data = YAML.load(yaml) as v3Sdl;
return new SDL(data, version, networkId);
}

/**
* Validates SDL YAML string (deprecated)
* @deprecated Use SDL.constructor directly
*/
static validate(yaml: string) {
console.warn("SDL.validate is deprecated. Use SDL.constructor directly.");
// TODO: this should really be cast to unknown, then assigned
// to v2 or v3 SDL only after being validated
const data = YAML.load(yaml) as v3Sdl;

for (const [name, profile] of Object.entries(data.profiles.compute || {})) {
Expand All @@ -77,6 +115,23 @@ export class SDL {
return data;
}

/**
* Validates the GPU configuration for a given service profile.
*
* @param name - The name of the service profile.
* @param gpu - The GPU resource configuration.
* @throws Will throw an error if the GPU configuration is invalid.
*
* @example
* ```ts
* SDL.validateGPU("web", {
* units: "1",
* attributes: {
* vendor: { nvidia: [{ model: "RTX 3080", ram: "10GB", interface: "pcie" }] }
* }
* });
* ```
*/
static validateGPU(name: string, gpu: v3ResourceGPU | undefined) {
if (gpu) {
if (typeof gpu.units === "undefined") {
Expand Down Expand Up @@ -118,6 +173,21 @@ export class SDL {
}
}

/**
* Validates the storage configuration for a given service.
*
* @param name - The name of the service.
* @param storage - The storage resource configuration.
* @throws Will throw an error if the storage configuration is invalid.
*
* @example
* ```ts
* SDL.validateStorage("web", {
* size: "10Gi",
* attributes: { class: "ssd" }
* });
* ```
*/
static validateStorage(name: string, storage?: v2ResourceStorage | v2ResourceStorageArray) {
if (!storage) {
throw new Error("Storage is required for service " + name);
Expand Down Expand Up @@ -579,6 +649,19 @@ export class SDL {
};
}

/**
* Parses the service protocol.
*
* @param proto - The protocol string (e.g., "TCP", "UDP").
* @returns The parsed protocol.
* @throws Will throw an error if the protocol is unsupported.
*
* @example
* ```ts
* const protocol = SDL.parseServiceProto("TCP");
* // protocol is "TCP"
* ```
*/
parseServiceProto(proto?: string) {
const raw = proto?.toUpperCase();
let result = "TCP";
Expand Down Expand Up @@ -814,6 +897,18 @@ export class SDL {
return this.version === "beta2" ? this.v2Manifest(asString) : this.v3Manifest(asString);
}

/**
* Computes the endpoint sequence numbers for the given SDL.
*
* @param sdl - The SDL data.
* @returns An object mapping IPs to their sequence numbers.
*
* @example
* ```ts
* const sequenceNumbers = sdl.computeEndpointSequenceNumbers(sdlData);
* // sequenceNumbers might be { "192.168.1.1": 1, "192.168.1.2": 2 }
* ```
*/
computeEndpointSequenceNumbers(sdl: v2Sdl) {
return Object.fromEntries(
Object.values(sdl.services).flatMap(service =>
Expand Down Expand Up @@ -1131,6 +1226,18 @@ export class SDL {
.map(name => groups[name]);
}

/**
* Escapes HTML characters in a string.
*
* @param raw - The raw string to escape.
* @returns The escaped string.
*
* @example
* ```ts
* const escaped = sdl.escapeHtml("<div>Hello</div>");
* // escaped is "\\u003cdiv\\u003eHello\\u003c/div\\u003e"
* ```
*/
escapeHtml(raw: string) {
return raw.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
}
Expand Down
24 changes: 24 additions & 0 deletions src/sdl/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,25 @@
/**
* SDL (Stack Definition Language) module exports
* Provides functionality for parsing and validating Akash deployment manifests
*
* @example
* ```ts
* import { SDL } from './sdl';
*
* const yaml = `
* version: "2.0"
* services:
* web:
* image: nginx
* expose:
* - port: 80
* as: 80
* to:
* - global: true
* `;
*
* const sdl = SDL.fromString(yaml);
* const manifest = sdl.manifest();
* ```
*/
export * from "./SDL/SDL";
64 changes: 43 additions & 21 deletions src/sdl/sizes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
const prefixes = "kmgtpe".split("");

/**
* Converts resource strings like "1k", "5gi", "10m" to their numeric values
* @example
* ```ts
* convertResourceString("1k") // Returns 1000
* convertResourceString("5gi") // Returns 5368709120
* convertResourceString("10m") // Returns 10000000
* ```
*/
export function convertResourceString(resourceStr: string): number {
const [value, prefix, unit] = parseSizeString(resourceStr.toLowerCase());
const power = prefixes.indexOf(prefix);
const base = unit === "i" ? 1024 : 1000;

return power !== -1 ? value * Math.pow(base, power + 1) : value;
}

/**
* Converts CPU resource strings to their millicpu values
* @example
* ```ts
* convertCpuResourceString("1") // Returns 1000
* convertCpuResourceString("500m") // Returns 500
* ```
*/
export function convertCpuResourceString(resourceStr: string): number {
const [value, unit] = parseCpuResourceString(resourceStr.toLowerCase());

if (unit === "m") {
return value;
}

return value * 1000;
}

/**
* Parses a size string into value and unit components
* @internal
*/
function parseSizeString(size: string): [number, string, string] {
const regex = /^([\d.]+)([a-zA-Z])([a-zA-Z]*)$/;
const match = size.match(regex);
Expand All @@ -12,17 +51,10 @@ function parseSizeString(size: string): [number, string, string] {
throw new Error(`Invalid size string: ${size}`);
}

export function convertResourceString(resourceStr: string): number {
const [value, prefix, unit] = parseSizeString(resourceStr.toLowerCase());
const power = prefixes.indexOf(prefix);
const base = unit === "i" ? 1024 : 1000;

return power !== -1 ? value * Math.pow(base, power + 1) : value;
}

// checks to see if the resource string has an suffix, and extracts the
// value and suffix if it does, otherwise return the numerical value and
// an empty string
/**
* Parses a CPU resource string into value and unit components
* @internal
*/
function parseCpuResourceString(size: string): [number, string] {
const regex = /^([\d.]+)([a-zA-Z]*)$/;
const match = size.match(regex);
Expand All @@ -34,13 +66,3 @@ function parseCpuResourceString(size: string): [number, string] {

throw new Error(`Invalid size string: ${size}`);
}

export function convertCpuResourceString(resourceStr: string): number {
const [value, unit] = parseCpuResourceString(resourceStr.toLowerCase());

if (unit === "m") {
return value;
}

return value * 1000;
}
24 changes: 23 additions & 1 deletion src/stargate/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
import { MessageType, messageTypeRegistry, UnknownMessage } from "@akashnetwork/akash-api/typeRegistry";

/**
* Retrieves the Akash type registry.
* @returns An array of tuples containing the type URL and the corresponding message type.
*/
export const getAkashTypeRegistry: () => [string, MessageType<UnknownMessage>][] = () =>
Array.from(messageTypeRegistry).map(([path, type]) => [`/${path}`, type]);

/**
* Gets the type URL for a given message type.
* @param type - The message type for which to get the URL.
* @returns The URL string for the specified message type.
*/
export const getTypeUrl: (type: MessageType) => string = type => `/${type.$type}`;

/* TODO: this should be generated from the proto files */
/**
* Enum for Akash message types.
* @enum {string}
*/
export enum Message {
/** Message type for creating a certificate. */
MsgCreateCertificate = "/akash.cert.v1beta3.MsgCreateCertificate",
/** Message type for revoking a certificate. */
MsgRevokeCertificate = "/akash.cert.v1beta3.MsgRevokeCertificate",
/** Message type for creating a deployment. */
MsgCreateDeployment = "/akash.deployment.v1beta3.MsgCreateDeployment",
/** Message type for closing a deployment. */
MsgCloseDeployment = "/akash.deployment.v1beta3.MsgCloseDeployment",
/** Message type for depositing into a deployment. */
MsgDepositDeployment = "/akash.deployment.v1beta3.MsgDepositDeployment",
/** Message type for updating a deployment. */
MsgUpdateDeployment = "/akash.deployment.v1beta3.MsgUpdateDeployment",
/** Message type for closing a group. */
MsgCloseGroup = "/akash.deployment.v1beta3.MsgCloseGroup",
/** Message type for pausing a group. */
MsgPauseGroup = "/akash.deployment.v1beta3.MsgPauseGroup",
/** Message type for starting a group. */
MsgStartGroup = "/akash.deployment.v1beta3.MsgStartGroup",
/** Message type for creating a lease. */
MsgCreateLease = "/akash.market.v1beta4.MsgCreateLease"
}
15 changes: 15 additions & 0 deletions src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,22 @@ import { OfflineDirectSigner, OfflineSigner } from "@cosmjs/proto-signing";
export {};

declare global {
/**
* Extends the Window interface to include Keplr wallet integration methods.
* @interface Window
*/
interface Window {
/**
* Gets an offline signer for automatic signing of transactions.
* This method is injected by the Keplr wallet extension.
*
* @param {string} chainId - The chain ID of the network to connect to
* @returns {Promise<OfflineSigner | OfflineDirectSigner>} A promise that resolves to either an OfflineSigner or OfflineDirectSigner
* @throws {Error} If Keplr wallet is not installed or user rejects the connection
*
* @example
* const signer = await window.getOfflineSignerAuto("cosmoshub-4");
*/
getOfflineSignerAuto: (chainId: string) => Promise<OfflineSigner | OfflineDirectSigner>;
}
}
20 changes: 20 additions & 0 deletions src/types/network.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
/**
* Type representing the mainnet network identifier.
* Used for production environment connections.
*/
export type MainnetNetworkId = "mainnet";

/**
* Type representing the testnet network identifier.
* Used for testing and development purposes.
*/
export type TestnetNetworkId = "testnet";

/**
* Type representing the sandbox network identifier.
* Used for local development and testing.
*/
export type SandboxNetworkId = "sandbox";

/**
* Union type combining all possible network identifiers.
* Can be either "mainnet", "testnet", or "sandbox".
* @typedef {MainnetNetworkId | TestnetNetworkId | SandboxNetworkId} NetworkId
*/
export type NetworkId = MainnetNetworkId | TestnetNetworkId | SandboxNetworkId;

0 comments on commit e8cac9f

Please sign in to comment.