restix 0.0.1 → 0.0.2

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/api.js CHANGED
@@ -1,11 +1,11 @@
1
1
  export class NexAPI {
2
2
  #base = 'http://localhost:5000';
3
3
  #api_maps;
4
- #defaults;
4
+ #defaults = { headers: { 'X-Client-Signature': 'restix/0.0.2 (by SignorP)' } };
5
5
  constructor(base, api_maps, defaults) {
6
6
  this.#base = base;
7
7
  this.#api_maps = api_maps;
8
- this.#defaults = defaults ?? {};
8
+ this.#defaults = { ...defaults, headers: { ...defaults?.headers ?? {}, ...this.#defaults.headers } };
9
9
  }
10
10
  async request(prefix, data) {
11
11
  const api = this.#api_maps[prefix];
@@ -36,12 +36,11 @@ export class NexAPI {
36
36
  fetchOptoin.body = JSON.stringify(this.#injectData(api.map.body, data));
37
37
  if (api.map.headers.length > 0)
38
38
  fetchOptoin.headers = this.#injectData(api.map.headers, data);
39
- console.log(url, method, { ...fetchOptoin });
40
39
  const res = await fetch(url, fetchOptoin);
41
40
  if (res.status === api.status.safe)
42
41
  return await res[api.res]();
43
42
  else if (api.status && api.status[res.status])
44
- return api.status[res.status]?.();
43
+ return await api.status[res.status]?.(res);
45
44
  return undefined;
46
45
  }
47
46
  #injectUrlData(url, params, data) {
package/api.ts CHANGED
@@ -2,14 +2,13 @@ import type { API_MAPS, Exact } from './types'
2
2
 
3
3
  export class NexAPI<API_INTERFACE extends { [k: string]: any }> {
4
4
  #base = 'http://localhost:5000'
5
-
6
5
  #api_maps: API_MAPS<API_INTERFACE>
7
6
  #defaults: {
8
7
  body?: Record<string, string>
9
8
  params?: Record<string, string>
10
9
  query?: Record<string, string>
11
10
  headers?: Record<string, string>
12
- }
11
+ } = { headers: { 'X-Client-Signature': 'restix/0.0.2 (by SignorP)' } }
13
12
 
14
13
  constructor(base: string, api_maps: API_MAPS<API_INTERFACE>, defaults?: {
15
14
  body?: Record<string, string>
@@ -19,7 +18,7 @@ export class NexAPI<API_INTERFACE extends { [k: string]: any }> {
19
18
  }) {
20
19
  this.#base = base
21
20
  this.#api_maps = api_maps
22
- this.#defaults = defaults ?? {}
21
+ this.#defaults = { ...defaults, headers: { ...defaults?.headers ?? {}, ...this.#defaults.headers } }
23
22
  }
24
23
 
25
24
  async request<URL extends (keyof API_INTERFACE) & string>(prefix: URL, data: Exact<API_INTERFACE[URL], API_INTERFACE[URL]>) {
@@ -46,10 +45,9 @@ export class NexAPI<API_INTERFACE extends { [k: string]: any }> {
46
45
  if (api.map.query.length > 0) url = this.#injectQuery(url, api.map.query, data)
47
46
  if (api.map.body.length > 0) fetchOptoin.body = JSON.stringify(this.#injectData(api.map.body, data))
48
47
  if (api.map.headers.length > 0) fetchOptoin.headers = this.#injectData(api.map.headers, data)
49
- console.log(url, method, { ...fetchOptoin })
50
48
  const res = await fetch(url, fetchOptoin)
51
49
  if (res.status === api.status.safe) return await res[api.res]()
52
- else if (api.status && api.status[res.status]) return api.status[res.status]?.()
50
+ else if (api.status && api.status[res.status]) return await api.status[res.status]?.(res)
53
51
  return undefined
54
52
  }
55
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "restix",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Type-safe HTTP client builder for CLI tools and backend applications",
5
5
  "main": "index.js",
6
6
  "types": "./index.d.ts",
package/test.test.js CHANGED
@@ -1,13 +1,113 @@
1
1
  import { NexAPI } from './api';
2
2
  import { apiMap } from './utils';
3
+ /* -------------------------------------------------------
4
+ API MAPS
5
+ ------------------------------------------------------- */
3
6
  const api_maps = {
4
- 'GET /users': {
5
- map: apiMap(),
7
+ // PARAM INJECTION
8
+ 'GET /packages/cli/name/{name}': {
9
+ map: apiMap({
10
+ params: ['name']
11
+ }),
12
+ res: 'json',
13
+ status: {
14
+ safe: 200,
15
+ 404: () => 'PACKAGE NOT FOUND'
16
+ }
17
+ },
18
+ // MULTIPLE PARAMS
19
+ 'GET /packages/cli/name/{name}/{version}': {
20
+ map: apiMap({
21
+ params: ['*']
22
+ }),
23
+ res: 'json',
24
+ status: {
25
+ safe: 200,
26
+ 404: () => 'VERSION NOT FOUND'
27
+ }
28
+ },
29
+ // BODY INJECTION
30
+ 'POST /packages/cli/create': {
31
+ map: apiMap({
32
+ body: ['*']
33
+ }),
34
+ res: 'json',
35
+ status: {
36
+ safe: 201,
37
+ 400: () => 'BAD REQUEST'
38
+ }
39
+ },
40
+ // QUERY + HEADER INJECTION
41
+ 'GET /packages/cli/search': {
42
+ map: apiMap({
43
+ query: ['q'],
44
+ headers: ['Authorization']
45
+ }),
6
46
  res: 'json',
7
47
  status: {
8
48
  safe: 200
9
49
  }
10
50
  }
11
51
  };
12
- const api = new NexAPI('http://localhost:5000', api_maps);
13
- console.log(JSON.stringify(await api.request('GET /users', { selam: 'selam' }), null, 4));
52
+ /* -------------------------------------------------------
53
+ API INSTANCE
54
+ ------------------------------------------------------- */
55
+ const api = new NexAPI('http://localhost:5000', api_maps, {
56
+ headers: {
57
+ 'User-Agent': 'restix-cli'
58
+ }
59
+ });
60
+ /* -------------------------------------------------------
61
+ FEATURE SHOWCASE
62
+ ------------------------------------------------------- */
63
+ // -----------------------------------------
64
+ // SIMPLE PARAM REQUEST
65
+ // GET /packages/cli/name/xnex
66
+ // -----------------------------------------
67
+ await api.request('GET /packages/cli/name/{name}', {
68
+ name: 'xnex'
69
+ });
70
+ // -----------------------------------------
71
+ // MULTI PARAM REQUEST
72
+ // GET /packages/cli/name/xnex/0.0.1
73
+ // -----------------------------------------
74
+ await api.request('GET /packages/cli/name/{name}/{version}', {
75
+ name: 'xnex',
76
+ version: '0.0.1'
77
+ });
78
+ // -----------------------------------------
79
+ // BODY PAYLOAD
80
+ // POST /packages/cli/create
81
+ // -----------------------------------------
82
+ await api.request('POST /packages/cli/create', {
83
+ name: 'xnex',
84
+ version: '0.0.1',
85
+ developer: 'Signor P'
86
+ });
87
+ // -----------------------------------------
88
+ // QUERY + HEADER
89
+ // GET /packages/cli/search?query=nex
90
+ // Header: token
91
+ // -----------------------------------------
92
+ await api.request('GET /packages/cli/search', {
93
+ q: 'nex',
94
+ Authorization: 'Bearer AUTH_TOKEN'
95
+ });
96
+ // -----------------------------------------
97
+ // TYPE SAFETY DEMO (INTENTIONAL ERRORS)
98
+ // -----------------------------------------
99
+ // ❌ extra field not allowed
100
+ // await api.request(
101
+ // 'GET /packages/cli/name/{name}',
102
+ // {
103
+ // name: 'xnex',
104
+ // extra: 'nope'
105
+ // }
106
+ // )
107
+ // ❌ missing field
108
+ // await api.request(
109
+ // 'POST /packages/cli/create',
110
+ // {
111
+ // name: 'xnex'
112
+ // }
113
+ // )
package/test.test.ts CHANGED
@@ -1,13 +1,81 @@
1
1
  import { NexAPI } from './api'
2
- import type { API_MAPS } from './types'
2
+ import type { API_MAPS, GET_API } from './types'
3
3
  import { apiMap } from './utils'
4
4
 
5
+ /* -------------------------------------------------------
6
+ API CONTRACT
7
+ ------------------------------------------------------- */
8
+
5
9
  interface API_INTERFACE {
6
- 'GET /users': {}
10
+ 'GET /packages/cli/name/{name}': {
11
+ name: string
12
+ }
13
+
14
+ 'GET /packages/cli/name/{name}/{version}': {
15
+ name: string
16
+ version: string
17
+ }
18
+
19
+ 'POST /packages/cli/create': {
20
+ name: string
21
+ version: string
22
+ developer: string
23
+ }
24
+
25
+ 'GET /packages/cli/search': {
26
+ q: string
27
+ Authorization: string
28
+ }
7
29
  }
30
+
31
+ /* -------------------------------------------------------
32
+ API MAPS
33
+ ------------------------------------------------------- */
34
+
8
35
  const api_maps: API_MAPS<API_INTERFACE> = {
9
- 'GET /users': {
10
- map: apiMap(),
36
+
37
+ // PARAM INJECTION
38
+ 'GET /packages/cli/name/{name}': {
39
+ map: apiMap<GET_API<API_INTERFACE, 'GET /packages/cli/name/{name}'>>({
40
+ params: ['name']
41
+ }),
42
+ res: 'json',
43
+ status: {
44
+ safe: 200,
45
+ 404: () => 'PACKAGE NOT FOUND'
46
+ }
47
+ },
48
+
49
+ // MULTIPLE PARAMS
50
+ 'GET /packages/cli/name/{name}/{version}': {
51
+ map: apiMap<GET_API<API_INTERFACE, 'GET /packages/cli/name/{name}/{version}'>>({
52
+ params: ['*']
53
+ }),
54
+ res: 'json',
55
+ status: {
56
+ safe: 200,
57
+ 404: () => 'VERSION NOT FOUND'
58
+ }
59
+ },
60
+
61
+ // BODY INJECTION
62
+ 'POST /packages/cli/create': {
63
+ map: apiMap<GET_API<API_INTERFACE, 'POST /packages/cli/create'>>({
64
+ body: ['*']
65
+ }),
66
+ res: 'json',
67
+ status: {
68
+ safe: 201,
69
+ 400: () => 'BAD REQUEST'
70
+ }
71
+ },
72
+
73
+ // QUERY + HEADER INJECTION
74
+ 'GET /packages/cli/search': {
75
+ map: apiMap<GET_API<API_INTERFACE, 'GET /packages/cli/search'>>({
76
+ query: ['q'],
77
+ headers: ['Authorization']
78
+ }),
11
79
  res: 'json',
12
80
  status: {
13
81
  safe: 200
@@ -15,5 +83,95 @@ const api_maps: API_MAPS<API_INTERFACE> = {
15
83
  }
16
84
  }
17
85
 
18
- const api = new NexAPI<API_INTERFACE>('http://localhost:5000', api_maps)
19
- console.log(JSON.stringify(await api.request('GET /users', { selam: 'selam' }), null, 4))
86
+ /* -------------------------------------------------------
87
+ API INSTANCE
88
+ ------------------------------------------------------- */
89
+
90
+ const api = new NexAPI<API_INTERFACE>(
91
+ 'http://localhost:5000',
92
+ api_maps,
93
+ {
94
+ headers: {
95
+ 'User-Agent': 'restix-cli'
96
+ }
97
+ }
98
+ )
99
+
100
+ /* -------------------------------------------------------
101
+ FEATURE SHOWCASE
102
+ ------------------------------------------------------- */
103
+
104
+
105
+ // -----------------------------------------
106
+ // SIMPLE PARAM REQUEST
107
+ // GET /packages/cli/name/xnex
108
+ // -----------------------------------------
109
+ await api.request(
110
+ 'GET /packages/cli/name/{name}',
111
+ {
112
+ name: 'xnex'
113
+ }
114
+ )
115
+
116
+
117
+ // -----------------------------------------
118
+ // MULTI PARAM REQUEST
119
+ // GET /packages/cli/name/xnex/0.0.1
120
+ // -----------------------------------------
121
+ await api.request(
122
+ 'GET /packages/cli/name/{name}/{version}',
123
+ {
124
+ name: 'xnex',
125
+ version: '0.0.1'
126
+ }
127
+ )
128
+
129
+
130
+ // -----------------------------------------
131
+ // BODY PAYLOAD
132
+ // POST /packages/cli/create
133
+ // -----------------------------------------
134
+ await api.request(
135
+ 'POST /packages/cli/create',
136
+ {
137
+ name: 'xnex',
138
+ version: '0.0.1',
139
+ developer: 'Signor P'
140
+ }
141
+ )
142
+
143
+
144
+ // -----------------------------------------
145
+ // QUERY + HEADER
146
+ // GET /packages/cli/search?query=nex
147
+ // Header: token
148
+ // -----------------------------------------
149
+ await api.request(
150
+ 'GET /packages/cli/search',
151
+ {
152
+ q: 'nex',
153
+ Authorization: 'Bearer AUTH_TOKEN'
154
+ }
155
+ )
156
+
157
+
158
+ // -----------------------------------------
159
+ // TYPE SAFETY DEMO (INTENTIONAL ERRORS)
160
+ // -----------------------------------------
161
+
162
+ // ❌ extra field not allowed
163
+ // await api.request(
164
+ // 'GET /packages/cli/name/{name}',
165
+ // {
166
+ // name: 'xnex',
167
+ // extra: 'nope'
168
+ // }
169
+ // )
170
+
171
+ // ❌ missing field
172
+ // await api.request(
173
+ // 'POST /packages/cli/create',
174
+ // {
175
+ // name: 'xnex'
176
+ // }
177
+ // )
package/types.d.ts CHANGED
@@ -10,7 +10,7 @@ export interface API_MAP_TYPE<K extends string> {
10
10
  res: keyof Pick<Response, 'json' | 'text' | 'blob'>;
11
11
  status: {
12
12
  safe: number;
13
- [k: number]: () => any;
13
+ [k: number]: (res: Response) => any;
14
14
  };
15
15
  }
16
16
  export type API_MAPS<T extends Record<string, any>> = {
package/types.ts CHANGED
@@ -13,7 +13,7 @@ export interface API_MAP_TYPE<K extends string> {
13
13
  res: keyof Pick<Response, 'json' | 'text' | 'blob'>
14
14
  status: {
15
15
  safe: number
16
- [k: number]: () => any
16
+ [k: number]: (res: Response) => any
17
17
  }
18
18
  }
19
19