api_ianmenethil_comopenapiService.ts38 matches
1/**
2* openapi.service.ts - Serves the OpenAPI specification.
3* Uses OpenAPILoader to get the fully resolved specification.
4*/
56import { stringify } from "yaml";
7import { loadOpenAPISpec } from "@/openapi/loader.ts";
8import { getCurrentDateInSydney } from "@/utils/dateUtils.ts";
9import { Context } from "hono";
30}
3132interface OpenAPIDocument {
33openapi: string;
34info: any;
35servers: any[];
37components: any;
38// Adding an index signature to make it compatible with yaml.stringify
39// and to acknowledge that OpenAPI documents can have various other top-level extension fields.
40[key: string]: any;
41}
4243export class OpenapiSpecService {
44private openapiSpecPromise: Promise<OpenAPIDocument> | null = null;
45private readonly rootPath: string;
4647constructor(rootPath: string) {
48this.rootPath = rootPath;
49this.openapiSpecPromise = loadOpenAPISpec(this.rootPath) as Promise<OpenAPIDocument>;
50}
5152private async getSpec(): Promise<OpenAPIDocument> {
53if (!this.openapiSpecPromise) {
54console.warn(
55"OpenapiSpecService: Spec promise not initialized or failed, attempting to load now.",
56);
57this.openapiSpecPromise = loadOpenAPISpec(this.rootPath) as Promise<OpenAPIDocument>;
58}
59try {
60const spec = await this.openapiSpecPromise;
61if (!spec) { // Check if the loaded spec is null or undefined
62throw new Error("Loaded OpenAPI specification is null or undefined.");
63}
64return spec;
65} catch (error: unknown) {
66const message = getErrorMessage(error);
67console.error("OpenapiSpecService: Failed to load/get OpenAPI spec:", error); // Log the original error too
68this.openapiSpecPromise = null; // Clear the promise so it can be retried
69throw new Error(`Failed to load OpenAPI specification: ${message}`);
70}
71}
7273async getOpenAPIJSONObject(): Promise<OpenAPIDocument> {
74return await this.getSpec();
75}
7677async getOpenAPIYAMLString(): Promise<string> {
78try {
79const jsonSpec = await this.getSpec();
80// The OpenAPIDocument with an index signature [key: string]: any;
81// should now be compatible with stringify.
82return stringify(jsonSpec);
83} catch (error: unknown) {
84const message = getErrorMessage(error);
85console.error("OpenapiSpecService: Failed to generate OpenAPI YAML:", error);
86throw new Error(`Failed to generate OpenAPI YAML specification: ${message}`);
87}
88}
93error: errorMessage,
94format,
95service: "openapi-spec-service",
96timestamp: getCurrentDateInSydney(),
97};
106return {
107valid: false,
108error: `OpenAPI spec validation failed: ${message}`,
109};
110}
112}
113114export const openapiSpecService = new OpenapiSpecService("src/openapi/spec");
115116/**
117* OpenAPI JSON handler function for use in service router
118* @param c - Hono context with Variables
119* @returns Response with OpenAPI JSON specification
120*/
121export async function getOpenAPIJSON(c: Context<{ Variables: Variables }>): Promise<Response> {
122try {
123const spec = await openapiSpecService.getOpenAPIJSONObject();
124return c.json(spec);
125} catch (error) {
126const msg = getErrorMessage(error);
127console.error(`Error in getOpenAPIJSON: ${msg}`, error);
128return c.json(openapiSpecService.createErrorResponse(msg, "json"), 500);
129}
130}
131132/**
133* OpenAPI YAML handler function for use in service router
134* @param c - Hono context with Variables
135* @returns Response with OpenAPI YAML specification
136*/
137export async function getOpenAPIYAML(c: Context<{ Variables: Variables }>): Promise<Response> {
138try {
139const yamlString = await openapiSpecService.getOpenAPIYAMLString();
140c.res.headers.set("Content-Type", "application/yaml; charset=utf-8");
141return c.text(yamlString);
142} catch (error) {
143const msg = getErrorMessage(error);
144console.error(`Error in getOpenAPIYAML: ${msg}`, error);
145return c.json(openapiSpecService.createErrorResponse(msg, "yaml"), 500);
146}
147}
1/**
2* spotify.auth.service.ts — Spotify OAuth authentication service handlers.
3* Implements OpenAPI operations using existing middleware and services.
4*/
5292async function fetchSpotifyUserInfo(accessToken: string) {
293try {
294const userRequest = await fetch("https://api.spotify.com/v1/me", {
295headers: {
296"Authorization": `Bearer ${accessToken}`,
api_ianmenethil_comindex.ts1 match
1// F:\zApps\valtown.servers\APIServer\src\handlers\oauth\index.ts
23export { getGoogleOAuthURL, handleGoogleCallback } from "./googleAuthService.ts";
1// F:\zApps\valtown.servers\APIServer\src\handlers\oauth\google.auth.service.ts
2/**
3* auth.service.ts — OAuth authentication service handlers.
4* Implements OpenAPI operations using existing middleware and services.
5*/
6
1// F:\zApps\valtown.servers\APIServer\src\handlers\oauth\github.auth.service.ts
2/**
3* github.auth.service.ts — GitHub OAuth authentication service handlers.
4* Implements OpenAPI operations using existing middleware and services.
5*/
6296"Authorization": `Bearer ${accessToken}`,
297"Accept": "application/vnd.github.v3+json",
298"User-Agent": "Val.town-API-Server/2.0",
299},
300});
348async function fetchGitHubUserEmail(accessToken: string) {
349try {
350const emailRequest = await fetch("https://api.github.com/user/emails", {
351headers: {
352"Authorization": `Bearer ${accessToken}`,
353"Accept": "application/vnd.github.v3+json",
354"User-Agent": "Val.town-API-Server/2.0",
355},
356});
api_ianmenethil_cominfoService.ts19 matches
45// You can store these in environment variables or a config file
6const API_VERSION = Deno.env.get("API_VERSION") || "1.0.0";
7const API_BUILD = Deno.env.get("API_BUILD") || "unknown";
8const API_ENV = Deno.env.get("API_ENV") || "development";
910/**
11* Service for providing API information and version details
12*/
13export class InfoService {
14/**
15* Get basic API information
16* @returns API info object with status and basic metadata
17*/
18getApiInfo() {
19return {
20success: true,
21name: "ValTown API Server",
22version: API_VERSION,
23status: "operational",
24environment: API_ENV,
25timestamp: getCurrentDateInSydney(),
26uptime: null, // Note: Deno doesn't have process.uptime()
29swagger: "/v1/docs",
30redoc: "/v1/redoc",
31openapi: "/v1/openapi.json",
32},
33external: {
47success: true,
48version: {
49api: API_VERSION,
50build: API_BUILD,
51environment: API_ENV,
52node: Deno.version.deno,
53v8: Deno.version.v8,
8586/**
87* API info handler function for use in service router
88* @param c - Hono context with Variables
89* @returns Response with API information
90*/
91export function getApiInfo(c: Context<{ Variables: Variables }>): Response {
92try {
93const info = infoService.getApiInfo();
94return c.json(info);
95} catch (error) {
96const errorResponse = infoService.createErrorResponse(
97error instanceof Error ? error.message : "Failed to retrieve API information",
98);
99return c.json(errorResponse, 500);
api_ianmenethil_comhashService.ts20 matches
31*/
32export const ZenithHashRequestSchema = z.object({
33apiKey: z.string().min(1, "API key cannot be empty"),
34username: z.string().min(1, "Username cannot be empty"),
35password: z.string().min(1, "Password cannot be empty"),
6061export const AuthenticatedZenithHashRequestSchema = z.object({
62apiKey: z.string().min(1, "API key cannot be empty"),
63username: z.string().optional(),
64password: z.string().optional(),
128*
129* This endpoint helps clients generate the required fingerprint
130* for Zenith Payments API integration without exposing credentials.
131*
132* The generated hash should be used as the 'fingerprint' field
456457// Create hash string according to Zenith format
458const { apiKey, mode, paymentAmount, merchantUniquePaymentId, timestamp } = validatedData;
459const hashString =
460`${apiKey}|${username}|${password}|${mode}|${paymentAmount}|${merchantUniquePaymentId}|${timestamp}`;
461462// Get algorithm
530531/**
532* Generate hash using Web Crypto API
533*/
534async function generateHash(data: string, algorithm: string): Promise<string> {
547break;
548case "SHA3-512":
549// SHA3-512 is not natively supported in Web Crypto API
550// Try it first, fallback to SHA-512
551try {
626suggestion =
627'Payment amount must be in cents/pence as whole numbers only. For $12.34, use "1234". For $100.00, use "10000".';
628} else if (field === "apiKey") {
629suggestion = "API key should be provided by Zenith Payments";
630}
631672673return await c.json({
674purpose: "Generate fingerprint hash for Zenith Payments API",
675endpoint: "/v1/hash",
676current_time: currentTime,
699description: "SHA-1 hash of concatenated fields",
700algorithm: "SHA-1",
701use_case: "Zenith API v3 integration",
702warning: "SHA-1 is deprecated for security reasons, use v5",
703example_request: {
704apiKey: "test_api_key",
705username: "merchant_user",
706password: "merchant_pass",
715description: "SHA-512 hash of concatenated fields",
716algorithm: "SHA-512",
717use_case: "Zenith API v4 integration (recommended by Zenith)",
718example_request: {
719apiKey: "test_api_key",
720username: "merchant_user",
721password: "merchant_pass",
732use_case: "Most secure option for future compatibility",
733example_request: {
734apiKey: "test_api_key",
735username: "merchant_user",
736password: "merchant_pass",
745v3_v4_v5_format: {
746description: "Concatenated string format for hashing",
747format: "apiKey|username|password|mode|paymentAmount|merchantUniquePaymentId|timestamp",
748example: "test_api_key|merchant_user|merchant_pass|0|10050|INV-2025-001|2025-06-15T19:42:13Z",
749},
750required_fields: {
755v3_v4_v5: {
756public_access: [
757"apiKey",
758"username",
759"password",
764],
765authenticated_access: [
766"apiKey",
767"username (optional)",
768"password (optional)",
786},
787authenticated_access: {
788description: "Requires API key or session authentication",
789benefit: "Username and password can use environment defaults if not provided in request",
790},
api_ianmenethil_comhash.service.ts20 matches
31*/
32export const ZenithHashRequestSchema = z.object({
33apiKey: z.string().min(1, "API key cannot be empty"),
34username: z.string().min(1, "Username cannot be empty"),
35password: z.string().min(1, "Password cannot be empty"),
6061export const AuthenticatedZenithHashRequestSchema = z.object({
62apiKey: z.string().min(1, "API key cannot be empty"),
63username: z.string().optional(),
64password: z.string().optional(),
128*
129* This endpoint helps clients generate the required fingerprint
130* for Zenith Payments API integration without exposing credentials.
131*
132* The generated hash should be used as the 'fingerprint' field
456457// Create hash string according to Zenith format
458const { apiKey, mode, paymentAmount, merchantUniquePaymentId, timestamp } = validatedData;
459const hashString =
460`${apiKey}|${username}|${password}|${mode}|${paymentAmount}|${merchantUniquePaymentId}|${timestamp}`;
461462// Get algorithm
530531/**
532* Generate hash using Web Crypto API
533*/
534async function generateHash(data: string, algorithm: string): Promise<string> {
547break;
548case "SHA3-512":
549// SHA3-512 is not natively supported in Web Crypto API
550// Try it first, fallback to SHA-512
551try {
626suggestion =
627'Payment amount must be in cents/pence as whole numbers only. For $12.34, use "1234". For $100.00, use "10000".';
628} else if (field === "apiKey") {
629suggestion = "API key should be provided by Zenith Payments";
630}
631672673return await c.json({
674purpose: "Generate fingerprint hash for Zenith Payments API",
675endpoint: "/v1/hash",
676current_time: currentTime,
699description: "SHA-1 hash of concatenated fields",
700algorithm: "SHA-1",
701use_case: "Zenith API v3 integration",
702warning: "SHA-1 is deprecated for security reasons, use v5",
703example_request: {
704apiKey: "test_api_key",
705username: "merchant_user",
706password: "merchant_pass",
715description: "SHA-512 hash of concatenated fields",
716algorithm: "SHA-512",
717use_case: "Zenith API v4 integration (recommended by Zenith)",
718example_request: {
719apiKey: "test_api_key",
720username: "merchant_user",
721password: "merchant_pass",
732use_case: "Most secure option for future compatibility",
733example_request: {
734apiKey: "test_api_key",
735username: "merchant_user",
736password: "merchant_pass",
745v3_v4_v5_format: {
746description: "Concatenated string format for hashing",
747format: "apiKey|username|password|mode|paymentAmount|merchantUniquePaymentId|timestamp",
748example: "test_api_key|merchant_user|merchant_pass|0|10050|INV-2025-001|2025-06-15T19:42:13Z",
749},
750required_fields: {
755v3_v4_v5: {
756public_access: [
757"apiKey",
758"username",
759"password",
764],
765authenticated_access: [
766"apiKey",
767"username (optional)",
768"password (optional)",
786},
787authenticated_access: {
788description: "Requires API key or session authentication",
789benefit: "Username and password can use environment defaults if not provided in request",
790},
2import type { HonoVariables as Variables } from "@/types/index.ts";
3import {
4fetchFromFirecrawlAPI,
5FirecrawlMapInput,
6FirecrawlMapInputSchema,
7performFirecrawlMap,
8ScraperInput,
9ScraperSchema,
10} from "../external-apis/firecrawlClient.ts";
1112// Helper function to get error messages
24* firecrawlScrape operation handler
25* POST /v1/firecrawl/scrape
26* Handles requests to the Firecrawl scrape API for a single URL.
27*/
28export async function firecrawlScrapeHandler(
50const scrapeInput: ScraperInput = validationResult.data;
5152// Call the Firecrawl API through the client function
53const firecrawlResponse = await fetchFromFirecrawlAPI(scrapeInput);
5455// Type assertion to ensure it's a valid JSON value
6162// Handle specific error cases
63if (message.includes("Configuration error: invalid or missing FIRECRAWL_API_KEY")) {
64return c.json({
65success: false,
66error: "Firecrawl API configuration error. Please contact support.",
67}, 503); // Service Unavailable
68}
71return c.json({
72success: false,
73error: "Firecrawl API returned an error during scrape.",
74details: error.message,
75}, 502); // Bad Gateway
87* firecrawlMap operation handler
88* POST /v1/firecrawl/map
89* Handles requests to the Firecrawl map API for discovering URLs on a website.
90*/
91export async function firecrawlMapHandler(c: Context<{ Variables: Variables }>): Promise<Response> {
93const requestBody = await c.req.json();
9495// Validate the request body against the FirecrawlMapInputSchema
96const validationResult = FirecrawlMapInputSchema.safeParse(requestBody);
9798if (!validationResult.success) {
106107// Use the validated data with explicit type
108const mapInput: FirecrawlMapInput = validationResult.data;
109110// Call the dedicated map function with validated input
111const firecrawlResponse = await performFirecrawlMap(mapInput);
112113// Type assertion to ensure it's a valid JSON value
119120// Handle specific error cases
121if (message.includes("Configuration error: invalid or missing FIRECRAWL_API_KEY")) {
122return c.json({
123success: false,
124error: "Firecrawl API configuration error. Please contact support.",
125}, 503); // Service Unavailable
126}
129return c.json({
130success: false,
131error: "Firecrawl API returned an error during map operation.",
132details: error.message,
133}, 502); // Bad Gateway
1// F:\zApps\valtown.servers\APIServer\src\handlers\echo.service.ts
2import { getCurrentDateInSydney } from "@/utils/dateUtils.ts";
3