@diphyx/harlemify 0.0.1

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amir Reza Dalir
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Harlemify
2
+
3
+ API state management for Nuxt powered by [Harlem](https://harlemjs.com/)
4
+
5
+ ![Harlemify](https://raw.githubusercontent.com/diphyx/harlemify/main/docs/_media/icon.svg)
6
+
7
+ ## Features
8
+
9
+ - Zod schema validation with field metadata
10
+ - Automatic API client with runtime config
11
+ - CRUD operations with endpoint status tracking
12
+ - SSR support via Harlem SSR plugin
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @diphyx/harlemify
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ // nuxt.config.ts
24
+ export default defineNuxtConfig({
25
+ modules: ["@diphyx/harlemify"],
26
+ harlemify: {
27
+ api: {
28
+ url: "https://api.example.com",
29
+ },
30
+ },
31
+ });
32
+ ```
33
+
34
+ ```typescript
35
+ // stores/user.ts
36
+ import { z, createStore, Endpoint, ApiAction } from "@diphyx/harlemify";
37
+
38
+ const UserSchema = z.object({
39
+ id: z.number().meta({
40
+ indicator: true,
41
+ }),
42
+ name: z.string().meta({
43
+ actions: [ApiAction.POST, ApiAction.PUT],
44
+ }),
45
+ });
46
+
47
+ export const userStore = createStore("user", UserSchema, {
48
+ [Endpoint.GET_UNITS]: {
49
+ action: ApiAction.GET,
50
+ url: "/users",
51
+ },
52
+ [Endpoint.POST_UNIT]: {
53
+ action: ApiAction.POST,
54
+ url: "/users",
55
+ },
56
+ });
57
+ ```
58
+
59
+ ## Documentation
60
+
61
+ Full documentation available at [https://diphyx.github.io/harlemify/](https://diphyx.github.io/harlemify/)
62
+
63
+ ## License
64
+
65
+ MIT
@@ -0,0 +1,5 @@
1
+ module.exports = function(...args) {
2
+ return import('./module.mjs').then(m => m.default.call(this, ...args))
3
+ }
4
+ const _meta = module.exports.meta = require('./module.json')
5
+ module.exports.getMeta = () => Promise.resolve(_meta)
@@ -0,0 +1,19 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+ import { MaybeRefOrGetter } from 'vue';
3
+
4
+ type ApiRequestHeader = MaybeRefOrGetter<Record<string, unknown>>;
5
+ type ApiRequestQuery = MaybeRefOrGetter<Record<string, unknown>>;
6
+ interface ApiOptions {
7
+ url?: string;
8
+ headers?: ApiRequestHeader;
9
+ query?: ApiRequestQuery;
10
+ timeout?: number;
11
+ }
12
+
13
+ interface ModuleOptions {
14
+ api?: Pick<ApiOptions, "url" | "timeout">;
15
+ }
16
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
17
+
18
+ export { _default as default };
19
+ export type { ModuleOptions };
@@ -0,0 +1,19 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+ import { MaybeRefOrGetter } from 'vue';
3
+
4
+ type ApiRequestHeader = MaybeRefOrGetter<Record<string, unknown>>;
5
+ type ApiRequestQuery = MaybeRefOrGetter<Record<string, unknown>>;
6
+ interface ApiOptions {
7
+ url?: string;
8
+ headers?: ApiRequestHeader;
9
+ query?: ApiRequestQuery;
10
+ timeout?: number;
11
+ }
12
+
13
+ interface ModuleOptions {
14
+ api?: Pick<ApiOptions, "url" | "timeout">;
15
+ }
16
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
17
+
18
+ export { _default as default };
19
+ export type { ModuleOptions };
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "harlemify",
3
+ "configKey": "harlemify",
4
+ "compatibility": {
5
+ "nuxt": ">=3.0.0 || >=4.0.0"
6
+ },
7
+ "version": "0.0.1",
8
+ "builder": {
9
+ "@nuxt/module-builder": "0.8.4",
10
+ "unbuild": "unknown"
11
+ }
12
+ }
@@ -0,0 +1,31 @@
1
+ import { defineNuxtModule, createResolver, addPlugin, addImportsDir, updateRuntimeConfig } from '@nuxt/kit';
2
+
3
+ const module = defineNuxtModule({
4
+ meta: {
5
+ name: "harlemify",
6
+ configKey: "harlemify",
7
+ compatibility: {
8
+ nuxt: ">=3.0.0 || >=4.0.0"
9
+ }
10
+ },
11
+ defaults: {
12
+ api: {}
13
+ },
14
+ setup(options, _) {
15
+ const { resolve } = createResolver(import.meta.url);
16
+ addPlugin(resolve("./runtime", "plugin"));
17
+ addImportsDir(resolve("./runtime", "core"));
18
+ updateRuntimeConfig({
19
+ public: {
20
+ harlemify: options
21
+ },
22
+ options: {
23
+ build: {
24
+ transpile: [/@harlem\//]
25
+ }
26
+ }
27
+ });
28
+ }
29
+ });
30
+
31
+ export { module as default };
@@ -0,0 +1,63 @@
1
+ import { type MaybeRefOrGetter } from "vue";
2
+ export declare enum ApiAction {
3
+ GET = "get",
4
+ POST = "post",
5
+ PUT = "put",
6
+ PATCH = "patch",
7
+ DELETE = "delete"
8
+ }
9
+ export declare enum ApiResponseType {
10
+ JSON = "json",
11
+ TEXT = "text",
12
+ BLOB = "blob",
13
+ ARRAY_BUFFER = "arrayBuffer"
14
+ }
15
+ export declare enum ApiErrorSource {
16
+ REQUEST = "request",
17
+ RESPONSE = "response"
18
+ }
19
+ export type ApiRequestHeader = MaybeRefOrGetter<Record<string, unknown>>;
20
+ export type ApiRequestQuery = MaybeRefOrGetter<Record<string, unknown>>;
21
+ export type ApiRequestBody = MaybeRefOrGetter<string | number | ArrayBuffer | FormData | Blob | Record<string, any>>;
22
+ export interface ApiRequestOptions<A extends ApiAction = ApiAction, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery, B extends ApiRequestBody = ApiRequestBody> {
23
+ action?: A;
24
+ headers?: H;
25
+ query?: Q;
26
+ body?: B;
27
+ responseType?: ApiResponseType;
28
+ retry?: number | false;
29
+ retryDelay?: number;
30
+ retryStatusCodes?: number[];
31
+ }
32
+ export interface ApiOptions {
33
+ url?: string;
34
+ headers?: ApiRequestHeader;
35
+ query?: ApiRequestQuery;
36
+ timeout?: number;
37
+ }
38
+ export type ApiActionOptions<A extends ApiAction, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery, B extends ApiRequestBody = ApiRequestBody> = Omit<ApiRequestOptions<A, H, Q, B>, "action">;
39
+ export interface ApiErrorOptions {
40
+ source: ApiErrorSource;
41
+ method: string;
42
+ url: string;
43
+ message?: string;
44
+ }
45
+ export declare class ApiError extends Error {
46
+ source: ApiErrorSource;
47
+ method: string;
48
+ url: string;
49
+ constructor(options: ApiErrorOptions);
50
+ }
51
+ export declare class ApiRequestError extends ApiError {
52
+ constructor(options: Omit<ApiErrorOptions, "source">);
53
+ }
54
+ export declare class ApiResponseError extends ApiError {
55
+ constructor(options: Omit<ApiErrorOptions, "source">);
56
+ }
57
+ export declare function createApi(options?: ApiOptions): {
58
+ get: <T, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery>(url: string, options?: ApiActionOptions<ApiAction.GET, H, Q, never>) => Promise<T>;
59
+ post: <T, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery, B extends ApiRequestBody = ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.POST, H, Q, B>) => Promise<T>;
60
+ put: <T, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery, B extends ApiRequestBody = ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.PUT, H, Q, B>) => Promise<T>;
61
+ patch: <T, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery, B extends ApiRequestBody = ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.PATCH, H, Q, B>) => Promise<T>;
62
+ del: <T, H extends ApiRequestHeader = ApiRequestHeader, Q extends ApiRequestQuery = ApiRequestQuery>(url: string, options?: ApiActionOptions<ApiAction.DELETE, H, Q, never>) => Promise<T>;
63
+ };
@@ -0,0 +1,122 @@
1
+ import { toValue } from "vue";
2
+ export var ApiAction = /* @__PURE__ */ ((ApiAction2) => {
3
+ ApiAction2["GET"] = "get";
4
+ ApiAction2["POST"] = "post";
5
+ ApiAction2["PUT"] = "put";
6
+ ApiAction2["PATCH"] = "patch";
7
+ ApiAction2["DELETE"] = "delete";
8
+ return ApiAction2;
9
+ })(ApiAction || {});
10
+ export var ApiResponseType = /* @__PURE__ */ ((ApiResponseType2) => {
11
+ ApiResponseType2["JSON"] = "json";
12
+ ApiResponseType2["TEXT"] = "text";
13
+ ApiResponseType2["BLOB"] = "blob";
14
+ ApiResponseType2["ARRAY_BUFFER"] = "arrayBuffer";
15
+ return ApiResponseType2;
16
+ })(ApiResponseType || {});
17
+ export var ApiErrorSource = /* @__PURE__ */ ((ApiErrorSource2) => {
18
+ ApiErrorSource2["REQUEST"] = "request";
19
+ ApiErrorSource2["RESPONSE"] = "response";
20
+ return ApiErrorSource2;
21
+ })(ApiErrorSource || {});
22
+ export class ApiError extends Error {
23
+ source;
24
+ method;
25
+ url;
26
+ constructor(options) {
27
+ super(options.message || "Unknown error");
28
+ this.name = "ApiError";
29
+ this.source = options.source;
30
+ this.method = options.method;
31
+ this.url = options.url;
32
+ }
33
+ }
34
+ export class ApiRequestError extends ApiError {
35
+ constructor(options) {
36
+ super({
37
+ ...options,
38
+ source: "request" /* REQUEST */
39
+ });
40
+ }
41
+ }
42
+ export class ApiResponseError extends ApiError {
43
+ constructor(options) {
44
+ super({
45
+ ...options,
46
+ source: "response" /* RESPONSE */
47
+ });
48
+ }
49
+ }
50
+ export function createApi(options) {
51
+ async function request(url, requestOptions) {
52
+ return $fetch(url, {
53
+ baseURL: options?.url,
54
+ method: requestOptions?.action ?? "get" /* GET */,
55
+ headers: {
56
+ ...toValue(options?.headers),
57
+ ...toValue(requestOptions?.headers)
58
+ },
59
+ query: {
60
+ ...toValue(requestOptions?.query),
61
+ ...toValue(options?.query)
62
+ },
63
+ body: toValue(requestOptions?.body),
64
+ timeout: requestOptions?.timeout ?? options?.timeout,
65
+ responseType: requestOptions?.responseType,
66
+ retry: requestOptions?.retry,
67
+ retryDelay: requestOptions?.retryDelay,
68
+ retryStatusCodes: requestOptions?.retryStatusCodes,
69
+ onRequestError({ request: request2, options: options2, error }) {
70
+ throw new ApiRequestError({
71
+ method: options2.method,
72
+ url: request2.toString(),
73
+ message: error?.message
74
+ });
75
+ },
76
+ onResponseError({ request: request2, options: options2, error }) {
77
+ throw new ApiResponseError({
78
+ method: options2.method,
79
+ url: request2.toString(),
80
+ message: error?.message
81
+ });
82
+ }
83
+ });
84
+ }
85
+ async function get(url, options2) {
86
+ return request(url, {
87
+ ...options2,
88
+ action: "get" /* GET */
89
+ });
90
+ }
91
+ async function post(url, options2) {
92
+ return request(url, {
93
+ ...options2,
94
+ action: "post" /* POST */
95
+ });
96
+ }
97
+ async function put(url, options2) {
98
+ return request(url, {
99
+ ...options2,
100
+ action: "put" /* PUT */
101
+ });
102
+ }
103
+ async function patch(url, options2) {
104
+ return request(url, {
105
+ ...options2,
106
+ action: "patch" /* PATCH */
107
+ });
108
+ }
109
+ async function del(url, options2) {
110
+ return request(url, {
111
+ ...options2,
112
+ action: "delete" /* DELETE */
113
+ });
114
+ }
115
+ return {
116
+ get,
117
+ post,
118
+ put,
119
+ patch,
120
+ del
121
+ };
122
+ }
@@ -0,0 +1,125 @@
1
+ import { z } from "zod";
2
+ import { type Extension, type BaseState } from "@harlem/core";
3
+ import { Endpoint, type EndpointDefinition, type EndpointMemory } from "../utils/endpoint.js";
4
+ import { ApiAction, type ApiActionOptions, type ApiOptions } from "./api.js";
5
+ export declare function createStore<T extends z.ZodRawShape>(name: string, schema: z.ZodObject<T>, endpoints?: Partial<Record<Endpoint, EndpointDefinition>>, options?: {
6
+ api?: ApiOptions;
7
+ extensions?: Extension<BaseState>[];
8
+ }): {
9
+ api: {
10
+ get: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery>(url: string, options?: ApiActionOptions<ApiAction.GET, H, Q, never>) => Promise<T_1>;
11
+ post: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery, B extends import("./api").ApiRequestBody = import("./api").ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.POST, H, Q, B>) => Promise<T_1>;
12
+ put: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery, B extends import("./api").ApiRequestBody = import("./api").ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.PUT, H, Q, B>) => Promise<T_1>;
13
+ patch: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery, B extends import("./api").ApiRequestBody = import("./api").ApiRequestBody>(url: string, options?: ApiActionOptions<ApiAction.PATCH, H, Q, B>) => Promise<T_1>;
14
+ del: <T_1, H extends import("./api").ApiRequestHeader = import("./api").ApiRequestHeader, Q extends import("./api").ApiRequestQuery = import("./api").ApiRequestQuery>(url: string, options?: ApiActionOptions<ApiAction.DELETE, H, Q, never>) => Promise<T_1>;
15
+ };
16
+ store: Omit<import("@harlem/core").Store<{
17
+ memory: {
18
+ unit: z.core.$InferObjectOutput<T, {}> | null;
19
+ units: z.core.$InferObjectOutput<T, {}>[];
20
+ };
21
+ endpoints: Record<Endpoint, EndpointMemory>;
22
+ }>, never>;
23
+ memorizedUnit: import("@vue/reactivity").ComputedRef<import("@vue/reactivity").DeepReadonly<z.core.$InferObjectOutput<T, {}>> | null>;
24
+ memorizedUnits: import("@vue/reactivity").ComputedRef<readonly import("@vue/reactivity").DeepReadonly<z.core.$InferObjectOutput<T, {}>>[]>;
25
+ hasMemorizedUnits: (...units: ({
26
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
27
+ } & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => Record<keyof z.core.$InferObjectOutput<T, {}>, boolean>;
28
+ endpointsStatus: {
29
+ getUnitIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
30
+ getUnitIsPending: import("@vue/reactivity").ComputedRef<boolean>;
31
+ getUnitIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
32
+ getUnitIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
33
+ getUnitsIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
34
+ getUnitsIsPending: import("@vue/reactivity").ComputedRef<boolean>;
35
+ getUnitsIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
36
+ getUnitsIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
37
+ postUnitIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
38
+ postUnitIsPending: import("@vue/reactivity").ComputedRef<boolean>;
39
+ postUnitIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
40
+ postUnitIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
41
+ postUnitsIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
42
+ postUnitsIsPending: import("@vue/reactivity").ComputedRef<boolean>;
43
+ postUnitsIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
44
+ postUnitsIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
45
+ putUnitIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
46
+ putUnitIsPending: import("@vue/reactivity").ComputedRef<boolean>;
47
+ putUnitIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
48
+ putUnitIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
49
+ putUnitsIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
50
+ putUnitsIsPending: import("@vue/reactivity").ComputedRef<boolean>;
51
+ putUnitsIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
52
+ putUnitsIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
53
+ patchUnitIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
54
+ patchUnitIsPending: import("@vue/reactivity").ComputedRef<boolean>;
55
+ patchUnitIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
56
+ patchUnitIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
57
+ patchUnitsIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
58
+ patchUnitsIsPending: import("@vue/reactivity").ComputedRef<boolean>;
59
+ patchUnitsIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
60
+ patchUnitsIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
61
+ deleteUnitIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
62
+ deleteUnitIsPending: import("@vue/reactivity").ComputedRef<boolean>;
63
+ deleteUnitIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
64
+ deleteUnitIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
65
+ deleteUnitsIsIdle: import("@vue/reactivity").ComputedRef<boolean>;
66
+ deleteUnitsIsPending: import("@vue/reactivity").ComputedRef<boolean>;
67
+ deleteUnitsIsSuccess: import("@vue/reactivity").ComputedRef<boolean>;
68
+ deleteUnitsIsFailed: import("@vue/reactivity").ComputedRef<boolean>;
69
+ };
70
+ setMemorizedUnit: import("@harlem/core").Mutation<z.core.$InferObjectOutput<T, {}> | null, void>;
71
+ setMemorizedUnits: (payload: z.core.$InferObjectOutput<T, {}>[]) => void;
72
+ editMemorizedUnit: import("@harlem/core").Mutation<{
73
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
74
+ } & Partial<z.core.$InferObjectOutput<T, {}>>, void>;
75
+ editMemorizedUnits: (payload: ({
76
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
77
+ } & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => void;
78
+ dropMemorizedUnit: import("@harlem/core").Mutation<{
79
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
80
+ } & Partial<z.core.$InferObjectOutput<T, {}>>, void>;
81
+ dropMemorizedUnits: (payload: ({
82
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
83
+ } & Partial<z.core.$InferObjectOutput<T, {}>>)[]) => void;
84
+ patchEndpointMemory: (payload: {
85
+ key: Endpoint;
86
+ memory: EndpointMemory;
87
+ }) => void;
88
+ purgeEndpointMemory: (payload?: unknown) => void;
89
+ getUnit: (unit: {
90
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
91
+ } & Partial<z.core.$InferObjectOutput<T, {}>>, options?: Omit<ApiActionOptions<ApiAction.GET>, "body">) => Promise<z.core.$InferObjectOutput<T, {}>>;
92
+ getUnits: (options?: Omit<ApiActionOptions<ApiAction.GET>, "body">) => Promise<z.core.$InferObjectOutput<T, {}>[]>;
93
+ postUnit: (unit: z.core.$InferObjectOutput<T, {}>, options?: ApiActionOptions<ApiAction.POST> & {
94
+ validate?: boolean;
95
+ }) => Promise<z.core.$InferObjectOutput<T, {}>>;
96
+ postUnits: (units: z.core.$InferObjectOutput<T, {}>[], options?: ApiActionOptions<ApiAction.POST> & {
97
+ validate?: boolean;
98
+ }) => Promise<z.core.$InferObjectOutput<T, {}>[]>;
99
+ putUnit: (unit: z.core.$InferObjectOutput<T, {}>, options?: ApiActionOptions<ApiAction.PUT> & {
100
+ validate?: boolean;
101
+ }) => Promise<z.core.$InferObjectOutput<T, {}>>;
102
+ putUnits: (units: z.core.$InferObjectOutput<T, {}>[], options?: ApiActionOptions<ApiAction.PUT> & {
103
+ validate?: boolean;
104
+ }) => Promise<z.core.$InferObjectOutput<T, {}>[]>;
105
+ patchUnit: (unit: {
106
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
107
+ } & Partial<z.core.$InferObjectOutput<T, {}>>, options?: ApiActionOptions<ApiAction.PATCH> & {
108
+ validate?: boolean;
109
+ }) => Promise<{
110
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
111
+ } & Partial<z.core.$InferObjectOutput<T, {}>>>;
112
+ patchUnits: (units: ({
113
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
114
+ } & Partial<z.core.$InferObjectOutput<T, {}>>)[], options?: ApiActionOptions<ApiAction.PATCH> & {
115
+ validate?: boolean;
116
+ }) => Promise<({
117
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
118
+ } & Partial<z.core.$InferObjectOutput<T, {}>>)[]>;
119
+ deleteUnit: (unit: {
120
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
121
+ } & Partial<z.core.$InferObjectOutput<T, {}>>, options?: Omit<ApiActionOptions<ApiAction.DELETE>, "body">) => Promise<boolean>;
122
+ deleteUnits: (units: ({
123
+ [x: string]: keyof z.core.$InferObjectOutput<T, {}>;
124
+ } & Partial<z.core.$InferObjectOutput<T, {}>>)[], options?: Omit<ApiActionOptions<ApiAction.DELETE>, "body">) => Promise<boolean>;
125
+ };
@@ -0,0 +1,440 @@
1
+ import { defu } from "defu";
2
+ import {
3
+ createStore as createHarlemStore
4
+ } from "@harlem/core";
5
+ import { resolveSchema } from "../utils/schema.js";
6
+ import {
7
+ makeEndpointStatusKey,
8
+ getEndpoint,
9
+ resolveEndpointUrl,
10
+ makeEndpointsStatus,
11
+ Endpoint,
12
+ EndpointStatus
13
+ } from "../utils/endpoint.js";
14
+ import {
15
+ createApi
16
+ } from "./api.js";
17
+ export function createStore(name, schema, endpoints, options) {
18
+ const config = useRuntimeConfig();
19
+ const api = createApi({
20
+ ...config.public.harlemify.api,
21
+ ...options?.api
22
+ });
23
+ const { indicator } = resolveSchema(schema);
24
+ const store = createHarlemStore(
25
+ name,
26
+ {
27
+ memory: {
28
+ unit: null,
29
+ units: []
30
+ },
31
+ endpoints: {}
32
+ },
33
+ {
34
+ extensions: options?.extensions ?? []
35
+ }
36
+ );
37
+ const memorizedUnit = store.getter("memorizedUnit", (state) => {
38
+ return state.memory.unit;
39
+ });
40
+ const memorizedUnits = store.getter("memorizedUnits", (state) => {
41
+ return state.memory.units;
42
+ });
43
+ function hasMemorizedUnits(...units) {
44
+ const output = {};
45
+ for (const unit of units) {
46
+ const exists = memorizedUnits.value.some((memorizedUnit2) => {
47
+ return memorizedUnit2[indicator] === unit[indicator];
48
+ });
49
+ output[unit[indicator]] = exists;
50
+ }
51
+ return output;
52
+ }
53
+ const setMemorizedUnit = store.mutation(
54
+ "setMemorizedUnit",
55
+ (state, unit = null) => {
56
+ state.memory.unit = unit;
57
+ }
58
+ );
59
+ const setMemorizedUnits = store.mutation(
60
+ "setMemorizedUnits",
61
+ (state, units = []) => {
62
+ state.memory.units = units;
63
+ }
64
+ );
65
+ const editMemorizedUnit = store.mutation(
66
+ "editMemorizedUnit",
67
+ (state, unit) => {
68
+ if (state.memory.unit?.[indicator] === unit[indicator]) {
69
+ state.memory.unit = defu(unit, state.memory.unit);
70
+ }
71
+ }
72
+ );
73
+ const editMemorizedUnits = store.mutation(
74
+ "editMemorizedUnits",
75
+ (state, units) => {
76
+ for (const unit of units) {
77
+ const index = state.memory.units.findIndex((memorizedUnit2) => {
78
+ return memorizedUnit2[indicator] === unit[indicator];
79
+ });
80
+ if (index !== -1) {
81
+ state.memory.units[index] = defu(
82
+ unit,
83
+ state.memory.units[index]
84
+ );
85
+ }
86
+ }
87
+ }
88
+ );
89
+ const dropMemorizedUnit = store.mutation(
90
+ "dropMemorizedUnit",
91
+ (state, unit) => {
92
+ if (state.memory.unit?.[indicator] === unit[indicator]) {
93
+ state.memory.unit = null;
94
+ }
95
+ }
96
+ );
97
+ const dropMemorizedUnits = store.mutation(
98
+ "dropMemorizedUnits",
99
+ (state, units) => {
100
+ state.memory.units = state.memory.units.filter((memorizedUnit2) => {
101
+ for (const unit of units) {
102
+ if (memorizedUnit2[indicator] === unit[indicator]) {
103
+ return false;
104
+ }
105
+ }
106
+ return true;
107
+ });
108
+ }
109
+ );
110
+ const endpointsStatus = makeEndpointsStatus(store.getter);
111
+ const patchEndpointMemory = store.mutation(
112
+ "patchEndpointMemory",
113
+ (state, {
114
+ key,
115
+ memory
116
+ }) => {
117
+ state.endpoints[key] = memory;
118
+ }
119
+ );
120
+ const purgeEndpointMemory = store.mutation(
121
+ "purgeEndpointMemory",
122
+ (state) => {
123
+ state.endpoints = {};
124
+ }
125
+ );
126
+ function patchEndpointMemoryTo(key, memory) {
127
+ if (memory.status === EndpointStatus.PENDING) {
128
+ const statusKey = makeEndpointStatusKey(
129
+ key,
130
+ EndpointStatus.PENDING
131
+ );
132
+ if (endpointsStatus[statusKey].value) {
133
+ throw new Error(`Endpoint "${key}" is already pending`);
134
+ }
135
+ }
136
+ patchEndpointMemory({
137
+ key,
138
+ memory
139
+ });
140
+ }
141
+ async function getUnit(unit, options2) {
142
+ const endpoint = getEndpoint(endpoints, Endpoint.GET_UNIT);
143
+ patchEndpointMemoryTo(Endpoint.GET_UNIT, {
144
+ status: EndpointStatus.PENDING
145
+ });
146
+ try {
147
+ const resolvedUrl = resolveEndpointUrl(endpoint.url, {
148
+ [indicator]: unit[indicator]
149
+ });
150
+ const response = await api.get(resolvedUrl, options2);
151
+ setMemorizedUnit(response);
152
+ patchEndpointMemoryTo(Endpoint.GET_UNIT, {
153
+ status: EndpointStatus.SUCCESS
154
+ });
155
+ return response;
156
+ } catch (error) {
157
+ patchEndpointMemoryTo(Endpoint.GET_UNIT, {
158
+ status: EndpointStatus.FAILED
159
+ });
160
+ throw error;
161
+ }
162
+ }
163
+ async function getUnits(options2) {
164
+ const endpoint = getEndpoint(endpoints, Endpoint.GET_UNITS);
165
+ patchEndpointMemoryTo(Endpoint.GET_UNITS, {
166
+ status: EndpointStatus.PENDING
167
+ });
168
+ try {
169
+ const resolvedUrl = resolveEndpointUrl(endpoint.url);
170
+ const response = await api.get(resolvedUrl, options2);
171
+ setMemorizedUnits(response);
172
+ patchEndpointMemoryTo(Endpoint.GET_UNITS, {
173
+ status: EndpointStatus.SUCCESS
174
+ });
175
+ return response;
176
+ } catch (error) {
177
+ patchEndpointMemoryTo(Endpoint.GET_UNITS, {
178
+ status: EndpointStatus.FAILED
179
+ });
180
+ throw error;
181
+ }
182
+ }
183
+ async function postUnit(unit, options2) {
184
+ const endpoint = getEndpoint(endpoints, Endpoint.POST_UNIT);
185
+ const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
186
+ if (options2?.validate) {
187
+ schema.pick(resolvedSchema.keys).parse(unit);
188
+ }
189
+ patchEndpointMemoryTo(Endpoint.POST_UNIT, {
190
+ status: EndpointStatus.PENDING
191
+ });
192
+ try {
193
+ const resolvedUrl = resolveEndpointUrl(endpoint.url, {
194
+ [indicator]: unit[indicator]
195
+ });
196
+ const response = await api.post(resolvedUrl, {
197
+ ...options2,
198
+ body: options2?.body ?? resolvedSchema.values
199
+ });
200
+ setMemorizedUnit(response);
201
+ patchEndpointMemoryTo(Endpoint.POST_UNIT, {
202
+ status: EndpointStatus.SUCCESS
203
+ });
204
+ return response;
205
+ } catch (error) {
206
+ patchEndpointMemoryTo(Endpoint.POST_UNIT, {
207
+ status: EndpointStatus.FAILED
208
+ });
209
+ throw error;
210
+ }
211
+ }
212
+ async function postUnits(units, options2) {
213
+ const endpoint = getEndpoint(endpoints, Endpoint.POST_UNITS);
214
+ const body = units.map((unit) => {
215
+ const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
216
+ if (options2?.validate) {
217
+ schema.pick(resolvedSchema.keys).parse(unit);
218
+ }
219
+ return resolvedSchema.values;
220
+ });
221
+ patchEndpointMemoryTo(Endpoint.POST_UNITS, {
222
+ status: EndpointStatus.PENDING
223
+ });
224
+ try {
225
+ const resolvedUrl = resolveEndpointUrl(endpoint.url);
226
+ const response = await api.post(resolvedUrl, {
227
+ ...options2,
228
+ body: options2?.body ?? body
229
+ });
230
+ setMemorizedUnits([
231
+ ...memorizedUnits.value,
232
+ ...response
233
+ ]);
234
+ patchEndpointMemoryTo(Endpoint.POST_UNITS, {
235
+ status: EndpointStatus.SUCCESS
236
+ });
237
+ return response;
238
+ } catch (error) {
239
+ patchEndpointMemoryTo(Endpoint.POST_UNITS, {
240
+ status: EndpointStatus.FAILED
241
+ });
242
+ throw error;
243
+ }
244
+ }
245
+ async function putUnit(unit, options2) {
246
+ const endpoint = getEndpoint(endpoints, Endpoint.PUT_UNIT);
247
+ const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
248
+ if (options2?.validate) {
249
+ schema.pick(resolvedSchema.keys).parse(unit);
250
+ }
251
+ patchEndpointMemoryTo(Endpoint.PUT_UNIT, {
252
+ status: EndpointStatus.PENDING
253
+ });
254
+ try {
255
+ const resolvedUrl = resolveEndpointUrl(endpoint.url, {
256
+ [indicator]: unit[indicator]
257
+ });
258
+ const response = await api.put(resolvedUrl, {
259
+ ...options2,
260
+ body: options2?.body ?? resolvedSchema.values
261
+ });
262
+ setMemorizedUnit(response);
263
+ patchEndpointMemoryTo(Endpoint.PUT_UNIT, {
264
+ status: EndpointStatus.SUCCESS
265
+ });
266
+ return response;
267
+ } catch (error) {
268
+ patchEndpointMemoryTo(Endpoint.PUT_UNIT, {
269
+ status: EndpointStatus.FAILED
270
+ });
271
+ throw error;
272
+ }
273
+ }
274
+ async function putUnits(units, options2) {
275
+ const endpoint = getEndpoint(endpoints, Endpoint.PUT_UNITS);
276
+ const body = units.map((unit) => {
277
+ const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
278
+ if (options2?.validate) {
279
+ schema.pick(resolvedSchema.keys).parse(unit);
280
+ }
281
+ return resolvedSchema.values;
282
+ });
283
+ patchEndpointMemoryTo(Endpoint.PUT_UNITS, {
284
+ status: EndpointStatus.PENDING
285
+ });
286
+ try {
287
+ const resolvedUrl = resolveEndpointUrl(endpoint.url);
288
+ const response = await api.put(resolvedUrl, {
289
+ ...options2,
290
+ body: options2?.body ?? body
291
+ });
292
+ setMemorizedUnits(response);
293
+ patchEndpointMemoryTo(Endpoint.PUT_UNITS, {
294
+ status: EndpointStatus.SUCCESS
295
+ });
296
+ return response;
297
+ } catch (error) {
298
+ patchEndpointMemoryTo(Endpoint.PUT_UNITS, {
299
+ status: EndpointStatus.FAILED
300
+ });
301
+ throw error;
302
+ }
303
+ }
304
+ async function patchUnit(unit, options2) {
305
+ const endpoint = getEndpoint(endpoints, Endpoint.PATCH_UNIT);
306
+ const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
307
+ if (options2?.validate) {
308
+ schema.pick(resolvedSchema.keys).partial().parse(unit);
309
+ }
310
+ patchEndpointMemoryTo(Endpoint.PATCH_UNIT, {
311
+ status: EndpointStatus.PENDING
312
+ });
313
+ try {
314
+ const resolvedUrl = resolveEndpointUrl(endpoint.url, {
315
+ [indicator]: unit[indicator]
316
+ });
317
+ const response = await api.patch(
318
+ resolvedUrl,
319
+ {
320
+ ...options2,
321
+ body: options2?.body ?? resolvedSchema.values
322
+ }
323
+ );
324
+ editMemorizedUnit(response);
325
+ patchEndpointMemoryTo(Endpoint.PATCH_UNIT, {
326
+ status: EndpointStatus.SUCCESS
327
+ });
328
+ return response;
329
+ } catch (error) {
330
+ patchEndpointMemoryTo(Endpoint.PATCH_UNIT, {
331
+ status: EndpointStatus.FAILED
332
+ });
333
+ throw error;
334
+ }
335
+ }
336
+ async function patchUnits(units, options2) {
337
+ const endpoint = getEndpoint(endpoints, Endpoint.PATCH_UNITS);
338
+ const body = units.map((unit) => {
339
+ const resolvedSchema = resolveSchema(schema, endpoint.action, unit);
340
+ if (options2?.validate) {
341
+ schema.pick(resolvedSchema.keys).partial().parse(unit);
342
+ }
343
+ return resolvedSchema.values;
344
+ });
345
+ patchEndpointMemoryTo(Endpoint.PATCH_UNITS, {
346
+ status: EndpointStatus.PENDING
347
+ });
348
+ try {
349
+ const resolvedUrl = resolveEndpointUrl(endpoint.url);
350
+ const response = await api.patch(resolvedUrl, {
351
+ ...options2,
352
+ body: options2?.body ?? body
353
+ });
354
+ editMemorizedUnits(response);
355
+ patchEndpointMemoryTo(Endpoint.PATCH_UNITS, {
356
+ status: EndpointStatus.SUCCESS
357
+ });
358
+ return response;
359
+ } catch (error) {
360
+ patchEndpointMemoryTo(Endpoint.PATCH_UNITS, {
361
+ status: EndpointStatus.FAILED
362
+ });
363
+ throw error;
364
+ }
365
+ }
366
+ async function deleteUnit(unit, options2) {
367
+ const endpoint = getEndpoint(endpoints, Endpoint.DELETE_UNIT);
368
+ patchEndpointMemoryTo(Endpoint.DELETE_UNIT, {
369
+ status: EndpointStatus.PENDING
370
+ });
371
+ try {
372
+ const resolvedUrl = resolveEndpointUrl(endpoint.url, {
373
+ [indicator]: unit[indicator]
374
+ });
375
+ await api.del(
376
+ resolvedUrl,
377
+ options2
378
+ );
379
+ dropMemorizedUnit(unit);
380
+ patchEndpointMemoryTo(Endpoint.DELETE_UNIT, {
381
+ status: EndpointStatus.SUCCESS
382
+ });
383
+ return true;
384
+ } catch (error) {
385
+ patchEndpointMemoryTo(Endpoint.DELETE_UNIT, {
386
+ status: EndpointStatus.FAILED
387
+ });
388
+ throw error;
389
+ }
390
+ }
391
+ async function deleteUnits(units, options2) {
392
+ const endpoint = getEndpoint(endpoints, Endpoint.DELETE_UNITS);
393
+ patchEndpointMemoryTo(Endpoint.DELETE_UNITS, {
394
+ status: EndpointStatus.PENDING
395
+ });
396
+ try {
397
+ const resolvedUrl = resolveEndpointUrl(endpoint.url);
398
+ await api.del(
399
+ resolvedUrl,
400
+ options2
401
+ );
402
+ dropMemorizedUnits(units);
403
+ patchEndpointMemoryTo(Endpoint.DELETE_UNITS, {
404
+ status: EndpointStatus.SUCCESS
405
+ });
406
+ return true;
407
+ } catch (error) {
408
+ patchEndpointMemoryTo(Endpoint.DELETE_UNITS, {
409
+ status: EndpointStatus.FAILED
410
+ });
411
+ throw error;
412
+ }
413
+ }
414
+ return {
415
+ api,
416
+ store,
417
+ memorizedUnit,
418
+ memorizedUnits,
419
+ hasMemorizedUnits,
420
+ endpointsStatus,
421
+ setMemorizedUnit,
422
+ setMemorizedUnits,
423
+ editMemorizedUnit,
424
+ editMemorizedUnits,
425
+ dropMemorizedUnit,
426
+ dropMemorizedUnits,
427
+ patchEndpointMemory,
428
+ purgeEndpointMemory,
429
+ getUnit,
430
+ getUnits,
431
+ postUnit,
432
+ postUnits,
433
+ putUnit,
434
+ putUnits,
435
+ patchUnit,
436
+ patchUnits,
437
+ deleteUnit,
438
+ deleteUnits
439
+ };
440
+ }
@@ -0,0 +1,5 @@
1
+ export { z } from "zod";
2
+ export { ApiAction, ApiResponseType, ApiErrorSource, type ApiRequestHeader, type ApiRequestQuery, type ApiRequestBody, type ApiRequestOptions, type ApiOptions, type ApiActionOptions, type ApiErrorOptions, createApi, ApiError, ApiRequestError, ApiResponseError, } from "./core/api.js";
3
+ export { Endpoint, EndpointStatus, type EndpointDefinition, type EndpointMemory, } from "./utils/endpoint.js";
4
+ export { type SchemaMeta, getMeta, resolveSchema } from "./utils/schema.js";
5
+ export { createStore } from "./core/store.js";
@@ -0,0 +1,16 @@
1
+ export { z } from "zod";
2
+ export {
3
+ ApiAction,
4
+ ApiResponseType,
5
+ ApiErrorSource,
6
+ createApi,
7
+ ApiError,
8
+ ApiRequestError,
9
+ ApiResponseError
10
+ } from "./core/api.js";
11
+ export {
12
+ Endpoint,
13
+ EndpointStatus
14
+ } from "./utils/endpoint.js";
15
+ export { getMeta, resolveSchema } from "./utils/schema.js";
16
+ export { createStore } from "./core/store.js";
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import { createVuePlugin } from "@harlem/core";
2
+ import {
3
+ createClientSSRPlugin,
4
+ createServerSSRPlugin
5
+ } from "@harlem/plugin-ssr";
6
+ export default defineNuxtPlugin((nuxtApp) => {
7
+ const plugins = [];
8
+ if (nuxtApp.payload.serverRendered) {
9
+ if (import.meta.server) {
10
+ plugins.push(createServerSSRPlugin());
11
+ }
12
+ if (import.meta.client) {
13
+ plugins.push(createClientSSRPlugin());
14
+ }
15
+ }
16
+ const harlem = createVuePlugin({
17
+ plugins
18
+ });
19
+ nuxtApp.vueApp.use(harlem);
20
+ });
@@ -0,0 +1,72 @@
1
+ import type { BaseState } from "@harlem/core";
2
+ import type { ApiAction } from "../core/api.js";
3
+ export declare enum Endpoint {
4
+ GET_UNIT = "getUnit",
5
+ GET_UNITS = "getUnits",
6
+ POST_UNIT = "postUnit",
7
+ POST_UNITS = "postUnits",
8
+ PUT_UNIT = "putUnit",
9
+ PUT_UNITS = "putUnits",
10
+ PATCH_UNIT = "patchUnit",
11
+ PATCH_UNITS = "patchUnits",
12
+ DELETE_UNIT = "deleteUnit",
13
+ DELETE_UNITS = "deleteUnits"
14
+ }
15
+ export declare enum EndpointStatus {
16
+ IDLE = "idle",
17
+ PENDING = "pending",
18
+ SUCCESS = "success",
19
+ FAILED = "failed"
20
+ }
21
+ export interface EndpointDefinition {
22
+ action: ApiAction;
23
+ url: string | ((keys: Record<PropertyKey, unknown>) => string);
24
+ }
25
+ export interface EndpointMemory {
26
+ status: EndpointStatus;
27
+ }
28
+ export declare function makeEndpointStatusKey<K extends Endpoint, S extends EndpointStatus>(key: K, status: S): `${K}Is${Capitalize<S>}`;
29
+ export declare function getEndpoint(endpoints: Partial<Record<Endpoint, EndpointDefinition>> | undefined, key: Endpoint): EndpointDefinition;
30
+ export declare function resolveEndpointUrl<T extends Record<PropertyKey, unknown>>(url: string | ((parameters: T) => string), parameters?: T): string;
31
+ export declare function makeEndpointsStatus<T>(getter: (name: string, fn: (state: BaseState) => boolean) => T): {
32
+ getUnitIsIdle: T;
33
+ getUnitIsPending: T;
34
+ getUnitIsSuccess: T;
35
+ getUnitIsFailed: T;
36
+ getUnitsIsIdle: T;
37
+ getUnitsIsPending: T;
38
+ getUnitsIsSuccess: T;
39
+ getUnitsIsFailed: T;
40
+ postUnitIsIdle: T;
41
+ postUnitIsPending: T;
42
+ postUnitIsSuccess: T;
43
+ postUnitIsFailed: T;
44
+ postUnitsIsIdle: T;
45
+ postUnitsIsPending: T;
46
+ postUnitsIsSuccess: T;
47
+ postUnitsIsFailed: T;
48
+ putUnitIsIdle: T;
49
+ putUnitIsPending: T;
50
+ putUnitIsSuccess: T;
51
+ putUnitIsFailed: T;
52
+ putUnitsIsIdle: T;
53
+ putUnitsIsPending: T;
54
+ putUnitsIsSuccess: T;
55
+ putUnitsIsFailed: T;
56
+ patchUnitIsIdle: T;
57
+ patchUnitIsPending: T;
58
+ patchUnitIsSuccess: T;
59
+ patchUnitIsFailed: T;
60
+ patchUnitsIsIdle: T;
61
+ patchUnitsIsPending: T;
62
+ patchUnitsIsSuccess: T;
63
+ patchUnitsIsFailed: T;
64
+ deleteUnitIsIdle: T;
65
+ deleteUnitIsPending: T;
66
+ deleteUnitIsSuccess: T;
67
+ deleteUnitIsFailed: T;
68
+ deleteUnitsIsIdle: T;
69
+ deleteUnitsIsPending: T;
70
+ deleteUnitsIsSuccess: T;
71
+ deleteUnitsIsFailed: T;
72
+ };
@@ -0,0 +1,48 @@
1
+ export var Endpoint = /* @__PURE__ */ ((Endpoint2) => {
2
+ Endpoint2["GET_UNIT"] = "getUnit";
3
+ Endpoint2["GET_UNITS"] = "getUnits";
4
+ Endpoint2["POST_UNIT"] = "postUnit";
5
+ Endpoint2["POST_UNITS"] = "postUnits";
6
+ Endpoint2["PUT_UNIT"] = "putUnit";
7
+ Endpoint2["PUT_UNITS"] = "putUnits";
8
+ Endpoint2["PATCH_UNIT"] = "patchUnit";
9
+ Endpoint2["PATCH_UNITS"] = "patchUnits";
10
+ Endpoint2["DELETE_UNIT"] = "deleteUnit";
11
+ Endpoint2["DELETE_UNITS"] = "deleteUnits";
12
+ return Endpoint2;
13
+ })(Endpoint || {});
14
+ export var EndpointStatus = /* @__PURE__ */ ((EndpointStatus2) => {
15
+ EndpointStatus2["IDLE"] = "idle";
16
+ EndpointStatus2["PENDING"] = "pending";
17
+ EndpointStatus2["SUCCESS"] = "success";
18
+ EndpointStatus2["FAILED"] = "failed";
19
+ return EndpointStatus2;
20
+ })(EndpointStatus || {});
21
+ export function makeEndpointStatusKey(key, status) {
22
+ return `${key}Is${status.charAt(0).toUpperCase() + status.slice(1)}`;
23
+ }
24
+ export function getEndpoint(endpoints, key) {
25
+ const endpoint = endpoints?.[key];
26
+ if (!endpoint) {
27
+ throw new Error(`Endpoint "${key}" is not configured`);
28
+ }
29
+ return endpoint;
30
+ }
31
+ export function resolveEndpointUrl(url, parameters = {}) {
32
+ if (typeof url === "function") {
33
+ return url(parameters);
34
+ }
35
+ return url;
36
+ }
37
+ export function makeEndpointsStatus(getter) {
38
+ const output = {};
39
+ for (const key of Object.values(Endpoint)) {
40
+ for (const status of Object.values(EndpointStatus)) {
41
+ const statusKey = makeEndpointStatusKey(key, status);
42
+ output[statusKey] = getter(statusKey, (state) => {
43
+ return state.endpoints[key]?.status === status;
44
+ });
45
+ }
46
+ }
47
+ return output;
48
+ }
@@ -0,0 +1,12 @@
1
+ import { z } from "zod";
2
+ import type { ApiAction } from "../core/api.js";
3
+ export interface SchemaMeta {
4
+ indicator?: boolean;
5
+ actions?: ApiAction[];
6
+ }
7
+ export declare function getMeta(field: any): SchemaMeta | undefined;
8
+ export declare function resolveSchema<T extends z.ZodRawShape, S extends z.infer<z.ZodObject<T>>>(schema: z.ZodObject<T>, action?: ApiAction, input?: Partial<S>): {
9
+ indicator: keyof S;
10
+ keys: Record<keyof S, true>;
11
+ values: Partial<S>;
12
+ };
@@ -0,0 +1,26 @@
1
+ export function getMeta(field) {
2
+ return field.meta();
3
+ }
4
+ export function resolveSchema(schema, action, input) {
5
+ const output = {
6
+ indicator: "id",
7
+ keys: {},
8
+ values: {}
9
+ };
10
+ for (const key of Object.keys(schema.shape)) {
11
+ const meta = getMeta(schema.shape[key]);
12
+ if (meta?.indicator) {
13
+ output.indicator = key;
14
+ }
15
+ if (!action || !meta?.actions) {
16
+ continue;
17
+ }
18
+ if (meta?.actions.includes(action)) {
19
+ output.keys[key] = true;
20
+ if (input && key in input) {
21
+ output.values[key] = input[key];
22
+ }
23
+ }
24
+ }
25
+ return output;
26
+ }
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module.js'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module.js'
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module'
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@diphyx/harlemify",
3
+ "version": "0.0.1",
4
+ "description": "API state management for Nuxt powered by Harlem",
5
+ "keywords": [
6
+ "nuxt",
7
+ "nuxt-module",
8
+ "harlem",
9
+ "state-management",
10
+ "api",
11
+ "zod",
12
+ "vue",
13
+ "typescript"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/diphyx/harlemify.git"
18
+ },
19
+ "homepage": "https://diphyx.github.io/harlemify/",
20
+ "bugs": {
21
+ "url": "https://github.com/diphyx/harlemify/issues"
22
+ },
23
+ "license": "MIT",
24
+ "author": "Amir Reza Dalir",
25
+ "type": "module",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/types.d.ts",
29
+ "import": "./dist/module.mjs",
30
+ "require": "./dist/module.cjs"
31
+ }
32
+ },
33
+ "main": "./dist/module.cjs",
34
+ "module": "./dist/module.mjs",
35
+ "types": "./dist/types.d.ts",
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "dependencies": {
40
+ "@nuxt/kit": "^3.14.0",
41
+ "@harlem/core": "^3.0.0",
42
+ "@harlem/plugin-ssr": "^3.0.0",
43
+ "defu": "^6.0.0",
44
+ "zod": "^4.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@nuxt/devtools": "^1.6.0",
48
+ "@nuxt/eslint-config": "^0.6.0",
49
+ "@nuxt/module-builder": "^0.8.0",
50
+ "@nuxt/schema": "^3.14.0",
51
+ "@nuxt/test-utils": "^3.14.0",
52
+ "@types/node": "^22.0.0",
53
+ "eslint": "^9.0.0",
54
+ "nuxt": "^3.14.0",
55
+ "typescript": "^5.6.0",
56
+ "vitest": "^2.0.0"
57
+ },
58
+ "scripts": {
59
+ "postinstall": "nuxi prepare playground",
60
+ "build": "nuxt-module-build build",
61
+ "dev": "nuxi dev playground",
62
+ "lint": "eslint . --fix",
63
+ "test": "vitest run"
64
+ }
65
+ }