laravel-request 1.2.26 → 1.2.28

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/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "laravel-request",
3
3
  "productName": "laravel-request",
4
- "version": "1.2.26",
4
+ "version": "1.2.28",
5
5
  "description": "laravel-request",
6
+ "type": "module",
6
7
  "main": "src/index.js",
7
8
  "module": "src/index.js",
8
9
  "types": "@types/laravel-request.d.ts",
9
- "scripts": {},
10
+ "scripts": {
11
+ "test": "env-cmd mocha \"tests/**/*.js\"",
12
+ "test:watch": "env-cmd mocha \"tests/**/*.js\" --watch"
13
+ },
10
14
  "keywords": [],
11
15
  "author": {
12
16
  "name": "Abramov Oleg",
@@ -19,8 +23,13 @@
19
23
  "axios-mock-adapter": "^2.1.0",
20
24
  "query-string": "^8.1.0"
21
25
  },
26
+ "devDependencies": {
27
+ "chai": "^4.5.0",
28
+ "env-cmd": "^10.1.0",
29
+ "mocha": "^10.0.0"
30
+ },
22
31
  "files": [
23
32
  "src",
24
33
  "@types"
25
34
  ]
26
- }
35
+ }
package/readme.md CHANGED
@@ -1,111 +1,266 @@
1
- Install
2
-
3
- npm install laravel-request
4
-
5
- Connected package
6
-
7
- https://github.com/olegstan/laravel-rest
8
-
9
- set domain resolver before any request
10
-
11
- ```
12
- Api.domainResolver = () => {
13
- try {
14
- return Environment.get('REACT_APP_API_URL');
15
- } catch (e) {
16
- console.log(e)
17
- return null;
18
- }
19
- }
20
- ```
21
-
22
- set auth token resolver before any request
23
-
24
- default token resolver, you can redefine it to any other
25
- ```
26
- Api.tokenResolver = async () => {
27
- try {
28
- return await localStorage.getItem('api_token');
29
- } catch (e) {
30
- console.log(e)
31
- return null;
32
- }
33
- }
34
- ```
35
-
36
- Usage get data
37
-
38
- ```
39
- Api.get('active-trade', 'index')
40
- .where('active_id', 115)
41
- .with('currency')
42
- .with('to_account', 'to_account.currency')
43
- .with('from_account', 'from_account.currency')
44
- .orderBy('trade_at', 'DESC')
45
- .all((response) => {
46
- //success
47
- }, () => {
48
- //error
49
- })
50
- }}
51
- ```
52
-
53
- or
54
-
55
- ```
56
- Api.get('active-trade', 'index')
57
- .where('id', 115)
58
- .with('currency')
59
- .with('to_account', 'to_account.currency')
60
- .with('from_account', 'from_account.currency')
61
- .orderBy('trade_at', 'DESC')
62
- .first((response) => {
63
- //success
64
-
65
- }, () => {
66
- //error
67
- })
68
- }}
69
- ```
70
-
71
-
72
- You can use
73
-
74
- all or first or paginate
75
-
76
- usage POST data
77
-
78
- ```
79
- Api.post('active', 'store', {
80
- user_id: this.props.client.id,
81
- type: 2,
82
- type_id: item.type_id
83
- })
84
- .call((response) => {
85
- //success
86
- }, (response) => {
87
- //error
88
- });
89
- ```
90
-
91
- response must be like below, for 200 status should contains key "result" with text "success"
92
-
93
- {
94
- "meta": [],
95
- "result": "success",
96
- "data": [],
97
- }
98
-
99
- you can cancel request by
100
-
101
- ```
102
-
103
- let cancelTokenSource = Api.get('active', SearchAllTypesHelper.ALL_TYPES, {
104
- item_search: searchQuery,
105
- user_id: clientId,
106
- search_stock: 1
107
- }).call(({data}) => {}, () => {}).getSource()
108
-
109
- cancelTokenSource.cancel();
110
-
111
- ```
1
+ # laravel-request
2
+
3
+ Клиентская библиотека для работы с Laravel API. Поддерживает JSON и MessagePack, fluent-интерфейс в стиле Eloquent Query Builder.
4
+
5
+ ## Содержание
6
+
7
+ - [Установка](#установка)
8
+ - [Переменные окружения](#переменные-окружения)
9
+ - [Api](#api)
10
+ - [ApiRequest](#apirequest)
11
+ - [Два типа запросов](#два-типа-запросов)
12
+ - [Выборки: примеры и payload](#выборки-примеры-и-payload)
13
+ - [Действия: call()](#действия-call)
14
+ - [Отключение уведомлений](#отключение-уведомлений)
15
+ - [Прямой вызов по URL](#прямой-вызов-по-url)
16
+ - [Отмена запроса](#отмена-запроса)
17
+ - [Лицензия](#лицензия)
18
+
19
+ ---
20
+
21
+ ## Установка
22
+
23
+ ```bash
24
+ npm install laravel-request
25
+ ```
26
+
27
+ ## Переменные окружения
28
+
29
+ | Переменная | Описание |
30
+ |------------|----------|
31
+ | `REACT_APP_API_URL` | Базовый URL API |
32
+ | `REACT_APP_DEBUG` | `true`/`false` — логирование запросов и ответов |
33
+
34
+ ---
35
+
36
+ ## Api
37
+
38
+ ```javascript
39
+ import { Api } from 'laravel-request';
40
+ ```
41
+
42
+ | Метод | Описание |
43
+ |-------|----------|
44
+ | `Api.get(controller, action, data)` | GET |
45
+ | `Api.post(controller, action, data)` | POST |
46
+ | `Api.put(controller, action, data)` | PUT |
47
+ | `Api.patch(controller, action, data)` | PATCH |
48
+ | `Api.delete(controller, action, id, data)` | DELETE |
49
+ | `Api.getArg(controller, action, arg, data)` | GET с аргументом в URL (например, index/123) |
50
+ | `Api.getUrl(url, data)` | Прямой GET по URL |
51
+
52
+ URL формируется как: `{domain}/api/v1/call/{controller}/{action}`
53
+
54
+ ---
55
+
56
+ ## ApiRequest
57
+
58
+ ### Два типа запросов
59
+
60
+ **Выборка (список)** — `Api.get(controller, 'index')` или `'list'`
61
+ Цепочка `where()`, `select()`, `orderBy()` и т.д. + метод выполнения:
62
+
63
+ | Метод | Результат |
64
+ |-------|-----------|
65
+ | `first()` | Первая страница |
66
+ | `all()` | Все записи |
67
+ | `paginate(page, perPage)` | Страница с пагинацией |
68
+ | `pluck(fields)` | Только указанные поля |
69
+ | `call()` | Без указания способа |
70
+
71
+ **Действие** — POST/PUT/PATCH/DELETE или GET одной записи (index)
72
+ Всегда завершается `call()`.
73
+
74
+ ### Выборки: примеры и payload
75
+
76
+ Данные уходят в query-параметрах URL (или в теле POST, если длина >5000 символов).
77
+
78
+ При `REACT_APP_API_URL=https://api.example.com` URL формируется как `https://api.example.com/api/v1/call/{controller}/{action}`.
79
+
80
+ **first():**
81
+
82
+ URL: `https://api.example.com/api/v1/call/product/index` (GET)
83
+
84
+ ```javascript
85
+ Api.get('product', 'index')
86
+ .select(['id', 'name', 'price'])
87
+ .where('status', '=', 'active')
88
+ .orderBy('created_at', 'desc')
89
+ .first(success, error, final);
90
+ ```
91
+ ```json
92
+ {
93
+ "arguments": [],
94
+ "query": [
95
+ { "select": [["id", "name", "price"]] },
96
+ { "where": ["status", "=", "active"] },
97
+ { "orderBy": ["created_at", "desc"] }
98
+ ],
99
+ "data": { "paginateType": "first" },
100
+ "unique_hash": "xK9...",
101
+ "timestamp": 1708123456789
102
+ }
103
+ ```
104
+
105
+ **all():**
106
+
107
+ URL: `https://api.example.com/api/v1/call/product/index` (GET)
108
+
109
+ ```javascript
110
+ Api.get('product', 'index')
111
+ .where('category_id', '=', 1)
112
+ .all(success, error, final);
113
+ ```
114
+ ```json
115
+ {
116
+ "arguments": [],
117
+ "query": [{ "where": ["category_id", "=", 1] }],
118
+ "data": { "paginateType": "all" },
119
+ "unique_hash": "xK9...",
120
+ "timestamp": 1708123456789
121
+ }
122
+ ```
123
+
124
+ **paginate():**
125
+
126
+ URL: `https://api.example.com/api/v1/call/product/index` (GET)
127
+
128
+ ```javascript
129
+ Api.get('product', 'index')
130
+ .whereIn('category_id', [1, 2, 3])
131
+ .orderBy('name')
132
+ .paginate(2, 15, success, error, final);
133
+ ```
134
+ ```json
135
+ {
136
+ "arguments": [],
137
+ "query": [
138
+ { "whereIn": ["category_id", [1, 2, 3]] },
139
+ { "orderBy": ["name"] }
140
+ ],
141
+ "data": {
142
+ "paginateType": "paginate",
143
+ "page": 2,
144
+ "perPage": 15
145
+ },
146
+ "unique_hash": "xK9...",
147
+ "timestamp": 1708123456789
148
+ }
149
+ ```
150
+
151
+ **pluck():**
152
+
153
+ URL: `https://api.example.com/api/v1/call/product/index` (GET)
154
+
155
+ ```javascript
156
+ Api.get('product', 'index')
157
+ .pluck(['id', 'name'], success, error, final);
158
+ ```
159
+ ```json
160
+ {
161
+ "arguments": [],
162
+ "query": [],
163
+ "data": {
164
+ "paginateType": "pluck",
165
+ "fields": ["id", "name"]
166
+ },
167
+ "unique_hash": "xK9...",
168
+ "timestamp": 1708123456789
169
+ }
170
+ ```
171
+
172
+ **first() — сложный (whereHas, with):**
173
+
174
+ URL: `https://api.example.com/api/v1/call/product/index` (GET)
175
+
176
+ ```javascript
177
+ Api.get('product', 'index')
178
+ .select(['id', 'name', 'price'])
179
+ .where('status', '=', 'active')
180
+ .whereHas('category', (q) => q.where('visible', true))
181
+ .with(['images', 'category'])
182
+ .orderBy('created_at', 'desc')
183
+ .first(success, error, final);
184
+ ```
185
+ ```json
186
+ {
187
+ "arguments": [],
188
+ "query": [
189
+ { "select": [["id", "name", "price"]] },
190
+ { "where": ["status", "=", "active"] },
191
+ { "whereHas": ["category", { "query": [{ "where": ["visible", true] }] }] },
192
+ { "with": [["images", "category"]] },
193
+ { "orderBy": ["created_at", "desc"] }
194
+ ],
195
+ "data": { "paginateType": "first" },
196
+ "unique_hash": "xK9...",
197
+ "timestamp": 1708123456789
198
+ }
199
+ ```
200
+
201
+ **getArg()** (например, index/123):
202
+
203
+ URL: `https://api.example.com/api/v1/call/user/index` (GET, id=123 в payload)
204
+
205
+ ```javascript
206
+ Api.getArg('user', 'index', 123).call(success, error, final);
207
+ ```
208
+ ```json
209
+ {
210
+ "arguments": [123],
211
+ "query": [],
212
+ "data": {},
213
+ "unique_hash": "xK9...",
214
+ "timestamp": 1708123456789
215
+ }
216
+ ```
217
+
218
+ ### Действия: call()
219
+
220
+ ```javascript
221
+ // URL: https://api.example.com/api/v1/call/user/store (POST)
222
+ Api.post('user', 'store', { name: 'John', email: 'john@example.com' })
223
+ .call(success, error, final);
224
+
225
+ // URL: https://api.example.com/api/v1/call/user/update (PUT)
226
+ Api.put('user', 'update', { id: 1, name: 'John' })
227
+ .call(success, error, final);
228
+
229
+ // URL: https://api.example.com/api/v1/call/user/destroy (DELETE, id=123 в payload)
230
+ Api.delete('user', 'destroy', 123)
231
+ .call(success, error, final);
232
+
233
+ // URL: https://api.example.com/api/v1/call/user/index (GET, id=123 в payload)
234
+ Api.getArg('user', 'index', 123)
235
+ .call(success, error, final);
236
+ ```
237
+
238
+ ### Отключение уведомлений
239
+
240
+ ```javascript
241
+ Api.get('product', 'index').withoutNotify().first(success, error, final);
242
+
243
+ Api.post('user', 'store', data)
244
+ .withoutNotify((status) => status !== 422)
245
+ .call(success, error, final);
246
+ ```
247
+
248
+ ### Прямой вызов по URL
249
+
250
+ ```javascript
251
+ Api.getUrl('https://api.example.com/custom/endpoint')
252
+ .callUrl(success, error, final);
253
+ ```
254
+
255
+ ### Отмена запроса
256
+
257
+ ```javascript
258
+ const request = Api.get('product', 'index').first(success, error, final);
259
+ request.getSource().cancel();
260
+ ```
261
+
262
+ ---
263
+
264
+ ## Лицензия
265
+
266
+ MIT © Abramov Oleg
package/src/Api.js CHANGED
@@ -1,4 +1,4 @@
1
- import ApiRequest from "./ApiRequest";
1
+ import ApiRequest from "./ApiRequest.js";
2
2
  import axios from "axios";
3
3
  import { decode } from "@msgpack/msgpack";
4
4
 
package/src/ApiProxy.js CHANGED
@@ -1,4 +1,4 @@
1
- import Api from "./Api";
1
+ import Api from "./Api.js";
2
2
 
3
3
  export default class ApiProxy extends Api
4
4
  {
package/src/ApiRequest.js CHANGED
@@ -1,6 +1,6 @@
1
- import Api from "./Api";
2
- import Builder from "./Builder";
3
- import Binding from "./Binding";
1
+ import Api from "./Api.js";
2
+ import Builder from "./Builder.js";
3
+ import Binding from "./Binding.js";
4
4
  import axios from "axios";
5
5
 
6
6
  /**
@@ -221,6 +221,19 @@ export default class ApiRequest {
221
221
  return this.executeRequest(successCallback, errorCallback, finalCallback, params, byUrl)
222
222
  }
223
223
 
224
+ /**
225
+ * Returns built query array and arguments without executing the request.
226
+ * Useful for testing and debugging.
227
+ * @return {{ query: Array, data: object, arguments: Array }}
228
+ */
229
+ getBuiltPayload() {
230
+ return {
231
+ query: this.builder.toArray(),
232
+ data: this.data,
233
+ arguments: this.arguments,
234
+ };
235
+ }
236
+
224
237
  /**
225
238
  * Constructs request data object based on provided keys
226
239
  * @param dataKey
package/src/Builder.js CHANGED
@@ -60,7 +60,17 @@ export default class Builder {
60
60
  if (typeof val == 'function') {
61
61
  var func = val;
62
62
  args[key] = {query: new Builder()};
63
- args[key].query = func(args[key].query).toArray();
63
+
64
+ var result = func(args[key].query);
65
+
66
+ if (!(result instanceof Builder)) {
67
+ throw new Error(
68
+ 'Callback for "' + method + '" must return instance of Builder. ' +
69
+ 'Did you forget "return query" in the callback?'
70
+ );
71
+ }
72
+
73
+ args[key].query = result.toArray();
64
74
  }
65
75
 
66
76
  return;
package/src/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import Api from "./Api";
2
- import ApiProxy from "./ApiProxy";
3
- import ApiRequest from "./ApiRequest";
4
- import Binding from "./Binding";
5
- import Builder from "./Builder";
6
- import UrlBind from "./UrlBind";
1
+ import Api from "./Api.js";
2
+ import ApiProxy from "./ApiProxy.js";
3
+ import ApiRequest from "./ApiRequest.js";
4
+ import Binding from "./Binding.js";
5
+ import Builder from "./Builder.js";
6
+ import UrlBind from "./UrlBind.js";
7
7
 
8
8
 
9
9