• Decorator for lifecycle-driven service requests within KOS models

    Eliminates service boilerplate by integrating HTTP requests directly into the model lifecycle. Responses are cached in ServiceResponseStore for access via utility functions, avoiding "magic last parameter" patterns.

    Type Parameters

    • Paths extends Record<string, any> = Record<string, any>
    • Path extends string | number | symbol = string
    • Method extends HttpMethod = "get"
    • Response = any
    • TransformedResponse = Response

    Parameters

    Returns ((target, propertyKey, descriptor) => PropertyDescriptor)

    Method decorator

      • (target, propertyKey, descriptor): PropertyDescriptor
      • Parameters

        • target: any
        • propertyKey: string
        • descriptor: PropertyDescriptor

        Returns PropertyDescriptor

    Example: Basic GET request during LOAD

    @kosServiceRequest({
    path: PATH_DEVICE_STATUS,
    method: 'get',
    lifecycle: DependencyLifecycle.LOAD,
    cache: { retention: ResponseRetention.SINGLE }
    })
    private onStatusLoaded(): void {
    const response = getServiceResponse(this, PATH_DEVICE_STATUS, 'get');
    this.status = response?.status;
    }

    Example: Method-driven request with execution context

    @kosServiceRequest({
    path: PATH_VM_INSTALL,
    method: 'post',
    requestOptions: {
    timeout: 10000 // Decorator-level default timeout
    }
    })
    async createRelease(
    path: string,
    keysetId?: string,
    ctx: KosExecutionContext<paths, typeof PATH_VM_INSTALL, 'post'>
    ): Promise<void> {
    const [error, response] = await ctx.$request({
    queryParams: { keySetId: keysetId },
    body: { path },
    requestOptions: {
    destinationAddress: 'device-123', // Runtime options merged with decorator options
    headers: { 'X-Custom-Header': 'value' }
    }
    });
    if (error) throw new Error(error);
    return response?.data;
    }

    Example: Container model with iteration

    @kosServiceRequest({
    path: PATH_INGREDIENTS,
    method: 'get',
    lifecycle: DependencyLifecycle.LOAD,
    iterateOver: 'data.ingredients',
    modelFactory: Ingredient.factory,
    mappings: [
    { from: 'id', to: 'id' },
    { from: 'name', to: 'name' }
    ]
    })
    private onIngredientsLoaded(): void {
    const response = getServiceResponse(this, PATH_INGREDIENTS, 'get');
    // Mappings already applied to response data
    response?.forEach(i => this.ingredients.addModel(i));
    }