fable 3.1.72 → 3.1.73

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.
Files changed (37) hide show
  1. package/docs/README.md +30 -6
  2. package/docs/_brand.json +18 -0
  3. package/docs/_playground.json +10 -0
  4. package/docs/_sidebar.md +2 -0
  5. package/docs/_version.json +3 -3
  6. package/docs/architecture.md +201 -39
  7. package/docs/index.html +6 -7
  8. package/docs/pict-docuserve.min.js +91 -0
  9. package/docs/pict-docuserve.min.js.map +1 -0
  10. package/docs/playground.md +38 -0
  11. package/docs/retold-catalog.json +1 -1
  12. package/docs/retold-keyword-index.json +8721 -8105
  13. package/docs/services/README.md +26 -9
  14. package/docs/services/anticipate.md +104 -40
  15. package/docs/services/csv-parser.md +63 -35
  16. package/docs/services/data-format.md +154 -49
  17. package/docs/services/data-generation.md +77 -16
  18. package/docs/services/dates.md +103 -36
  19. package/docs/services/environment-data.md +13 -2
  20. package/docs/services/expression-parser.md +280 -68
  21. package/docs/services/file-persistence.md +142 -150
  22. package/docs/services/logging.md +93 -37
  23. package/docs/services/logic.md +70 -22
  24. package/docs/services/manifest.md +114 -26
  25. package/docs/services/math.md +168 -63
  26. package/docs/services/meta-template.md +312 -158
  27. package/docs/services/object-cache.md +94 -11
  28. package/docs/services/operation.md +68 -6
  29. package/docs/services/progress-time.md +74 -13
  30. package/docs/services/progress-tracker-set.md +101 -3
  31. package/docs/services/rest-client.md +136 -104
  32. package/docs/services/settings-manager.md +133 -40
  33. package/docs/services/template.md +71 -22
  34. package/docs/services/utility.md +121 -29
  35. package/docs/services/uuid.md +58 -10
  36. package/package.json +2 -2
  37. package/.claude/settings.local.json +0 -8
@@ -5,8 +5,12 @@ The ProgressTrackerSet service manages named progress trackers for tracking the
5
5
  ## Access
6
6
 
7
7
  ```javascript
8
+ const libFable = require('fable');
9
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
10
+
8
11
  // On-demand service - instantiate when needed
9
12
  const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
13
+ console.log('trackerSet:', typeof trackerSet);
10
14
  ```
11
15
 
12
16
  ## Basic Usage
@@ -14,6 +18,8 @@ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
14
18
  ### Create and Start a Tracker
15
19
 
16
20
  ```javascript
21
+ const libFable = require('fable');
22
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
17
23
  const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
18
24
 
19
25
  // Create a tracker with 100 total operations
@@ -21,38 +27,62 @@ trackerSet.createProgressTracker('download', 100);
21
27
 
22
28
  // Start the tracker (begins timing)
23
29
  trackerSet.startProgressTracker('download');
30
+ console.log('Started:', trackerSet.getProgressTrackerStatusString('download'));
24
31
  ```
25
32
 
26
33
  ### Increment Progress
27
34
 
28
35
  ```javascript
36
+ const libFable = require('fable');
37
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
38
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
39
+ trackerSet.createProgressTracker('download', 100);
40
+ trackerSet.startProgressTracker('download');
41
+
29
42
  // Increment by 1
30
43
  trackerSet.incrementProgressTracker('download');
31
44
 
32
45
  // Increment by a specific amount
33
46
  trackerSet.incrementProgressTracker('download', 10);
47
+
48
+ console.log('Completed:', trackerSet.getProgressTrackerCompletedOperationCountString('download'));
34
49
  ```
35
50
 
36
51
  ### End the Tracker
37
52
 
38
53
  ```javascript
54
+ const libFable = require('fable');
55
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
56
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
57
+ trackerSet.createProgressTracker('download', 100);
58
+ trackerSet.startProgressTracker('download');
59
+ trackerSet.incrementProgressTracker('download', 100);
60
+
39
61
  trackerSet.endProgressTracker('download');
62
+ console.log('End status:', trackerSet.getProgressTrackerStatusString('download'));
40
63
  ```
41
64
 
42
65
  ### Get Status
43
66
 
44
67
  ```javascript
68
+ const libFable = require('fable');
69
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
70
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
71
+ trackerSet.createProgressTracker('download', 100);
72
+ trackerSet.startProgressTracker('download');
73
+ trackerSet.incrementProgressTracker('download', 45);
74
+
45
75
  // Get a human-readable status string
46
76
  const status = trackerSet.getProgressTrackerStatusString('download');
47
- // e.g., "ProgressTracker download is 45.000% completed - 45 / 100 operations over 2s 150ms (median 47ms per). Estimated completion: 2s 585ms"
77
+ console.log('status:', status);
48
78
 
49
79
  // Get just the percent complete
50
80
  const percent = trackerSet.getProgressTrackerPercentCompleteString('download');
51
- // e.g., "45.000%"
81
+ console.log('percent:', percent);
52
82
 
53
83
  // Get completed count
54
84
  const count = trackerSet.getProgressTrackerCompletedOperationCountString('download');
55
- // e.g., "45"
85
+ console.log('count:', count);
56
86
 
57
87
  // Log status directly
58
88
  trackerSet.logProgressTrackerStatus('download');
@@ -65,7 +95,12 @@ trackerSet.logProgressTrackerStatus('download');
65
95
  Create a new progress tracker. Default hash is `'Default'`, default total is `100`.
66
96
 
67
97
  ```javascript
98
+ const libFable = require('fable');
99
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
100
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
101
+
68
102
  const tracker = trackerSet.createProgressTracker('import-records', 500);
103
+ console.log('Tracker data:', tracker);
69
104
  ```
70
105
 
71
106
  Returns the tracker data object.
@@ -75,7 +110,12 @@ Returns the tracker data object.
75
110
  Start timing a progress tracker. Creates the tracker if it doesn't exist.
76
111
 
77
112
  ```javascript
113
+ const libFable = require('fable');
114
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
115
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
116
+
78
117
  trackerSet.startProgressTracker('import-records');
118
+ console.log('Started import-records');
79
119
  ```
80
120
 
81
121
  ### `endProgressTracker(hash)`
@@ -83,7 +123,13 @@ trackerSet.startProgressTracker('import-records');
83
123
  Mark the tracker as complete, recording the end timestamp.
84
124
 
85
125
  ```javascript
126
+ const libFable = require('fable');
127
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
128
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
129
+ trackerSet.startProgressTracker('import-records');
130
+
86
131
  trackerSet.endProgressTracker('import-records');
132
+ console.log('Ended import-records');
87
133
  ```
88
134
 
89
135
  ### `incrementProgressTracker(hash, amount)`
@@ -91,8 +137,15 @@ trackerSet.endProgressTracker('import-records');
91
137
  Increment the current operation count. Defaults to incrementing by 1. Auto-starts the tracker if not started.
92
138
 
93
139
  ```javascript
140
+ const libFable = require('fable');
141
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
142
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
143
+ trackerSet.createProgressTracker('import-records', 100);
144
+ trackerSet.startProgressTracker('import-records');
145
+
94
146
  trackerSet.incrementProgressTracker('import-records');
95
147
  trackerSet.incrementProgressTracker('import-records', 5);
148
+ console.log('Completed:', trackerSet.getProgressTrackerCompletedOperationCountString('import-records'));
96
149
  ```
97
150
 
98
151
  ### `updateProgressTracker(hash, currentOperations)`
@@ -100,7 +153,14 @@ trackerSet.incrementProgressTracker('import-records', 5);
100
153
  Set the current operation count to an absolute value.
101
154
 
102
155
  ```javascript
156
+ const libFable = require('fable');
157
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
158
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
159
+ trackerSet.createProgressTracker('import-records', 500);
160
+ trackerSet.startProgressTracker('import-records');
161
+
103
162
  trackerSet.updateProgressTracker('import-records', 250);
163
+ console.log('Status:', trackerSet.getProgressTrackerStatusString('import-records'));
104
164
  ```
105
165
 
106
166
  ### `setProgressTrackerTotalOperations(hash, total)`
@@ -108,7 +168,13 @@ trackerSet.updateProgressTracker('import-records', 250);
108
168
  Change the total number of expected operations.
109
169
 
110
170
  ```javascript
171
+ const libFable = require('fable');
172
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
173
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
174
+ trackerSet.createProgressTracker('import-records', 500);
175
+
111
176
  trackerSet.setProgressTrackerTotalOperations('import-records', 1000);
177
+ console.log('Total updated; data:', trackerSet.getProgressTrackerData('import-records').TotalCount);
112
178
  ```
113
179
 
114
180
  ### `getProgressTracker(hash)`
@@ -116,9 +182,16 @@ trackerSet.setProgressTrackerTotalOperations('import-records', 1000);
116
182
  Get a ProgressTracker wrapper object for a given hash. This provides convenience methods for working with the tracker:
117
183
 
118
184
  ```javascript
185
+ const libFable = require('fable');
186
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
187
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
188
+ trackerSet.createProgressTracker('import-records', 100);
189
+ trackerSet.startProgressTracker('import-records');
190
+
119
191
  const tracker = trackerSet.getProgressTracker('import-records');
120
192
  tracker.incrementProgressTracker(1);
121
193
  tracker.setProgressTrackerTotalOperations(500);
194
+ console.log('Tracker after wrapper ops:', trackerSet.getProgressTrackerData('import-records'));
122
195
  ```
123
196
 
124
197
  ### `getProgressTrackerData(hash)`
@@ -126,7 +199,15 @@ tracker.setProgressTrackerTotalOperations(500);
126
199
  Get the raw tracker data object:
127
200
 
128
201
  ```javascript
202
+ const libFable = require('fable');
203
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
204
+ const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
205
+ trackerSet.createProgressTracker('import-records', 100);
206
+ trackerSet.startProgressTracker('import-records');
207
+ trackerSet.incrementProgressTracker('import-records', 45);
208
+
129
209
  const data = trackerSet.getProgressTrackerData('import-records');
210
+ console.log(data);
130
211
  // {
131
212
  // Hash: 'import-records',
132
213
  // StartTimeStamp: 1700000000000,
@@ -162,6 +243,12 @@ Each tracker data object contains:
162
243
  ### Batch Processing with Progress
163
244
 
164
245
  ```javascript
246
+ const libFable = require('fable');
247
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
248
+
249
+ // Stubbed processItem for the playground demo
250
+ function processItem(item, cb) { console.log('processed:', item); cb(); }
251
+
165
252
  function processBatch(fable, items, fCallback) {
166
253
  const trackerSet = fable.instantiateServiceProvider('ProgressTrackerSet');
167
254
 
@@ -190,6 +277,8 @@ function processBatch(fable, items, fCallback) {
190
277
  fCallback();
191
278
  });
192
279
  }
280
+
281
+ processBatch(fable, ['a', 'b', 'c', 'd'], () => console.log('Batch done.'));
193
282
  ```
194
283
 
195
284
  ### Integration with Operation Service
@@ -197,6 +286,13 @@ function processBatch(fable, items, fCallback) {
197
286
  The Operation service uses ProgressTrackerSet internally. Each step gets its own progress tracker, and the overall operation has one too. Inside a step, use `this.ProgressTracker`:
198
287
 
199
288
  ```javascript
289
+ const libFable = require('fable');
290
+ const fable = new libFable({ Product: 'TrackerDemo', ProductVersion: '1.0.0' });
291
+
292
+ const operation = fable.instantiateServiceProvider('Operation', { Name: 'Items' }, 'ITEMS-OP');
293
+ const items = ['a', 'b', 'c'];
294
+ function processItem(item) { console.log('processed:', item); }
295
+
200
296
  operation.addStep(
201
297
  function (fStepComplete) {
202
298
  this.ProgressTracker.setProgressTrackerTotalOperations(items.length);
@@ -211,6 +307,8 @@ operation.addStep(
211
307
  },
212
308
  {}, 'Process', 'Process all items', 'PROCESS'
213
309
  );
310
+
311
+ operation.execute((pError) => console.log('Op done — pError:', pError));
214
312
  ```
215
313
 
216
314
  ## Notes
@@ -5,12 +5,17 @@ The RestClient service provides HTTP/REST client functionality with support for
5
5
  ## Access
6
6
 
7
7
  ```javascript
8
+ const libFable = require('fable');
9
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
10
+
8
11
  // On-demand service - must be instantiated
9
12
  const restClient = fable.instantiateServiceProvider('RestClient');
13
+ console.log('restClient:', typeof restClient);
10
14
 
11
15
  // Or create named instances for different purposes
12
- const apiClient = fable.instantiateServiceProvider('RestClient', {}, 'api');
16
+ const apiClient = fable.instantiateServiceProvider('RestClient', {}, 'api');
13
17
  const authClient = fable.instantiateServiceProvider('RestClient', { TraceLog: true }, 'auth');
18
+ console.log('Named instances ready:', typeof apiClient, typeof authClient);
14
19
  ```
15
20
 
16
21
  ## Configuration
@@ -18,9 +23,13 @@ const authClient = fable.instantiateServiceProvider('RestClient', { TraceLog: tr
18
23
  ### Options
19
24
 
20
25
  ```javascript
26
+ const libFable = require('fable');
27
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
28
+
21
29
  const restClient = fable.instantiateServiceProvider('RestClient', {
22
30
  TraceLog: true // Enable request/response logging
23
31
  });
32
+ console.log('TraceLog enabled:', restClient.options.TraceLog);
24
33
  ```
25
34
 
26
35
  ### URL Prefix
@@ -28,12 +37,15 @@ const restClient = fable.instantiateServiceProvider('RestClient', {
28
37
  Set a global URL prefix in Fable settings:
29
38
 
30
39
  ```javascript
31
- const fable = new Fable({
40
+ const libFable = require('fable');
41
+ const fable = new libFable({
32
42
  RestClientURLPrefix: 'https://api.example.com'
33
43
  });
44
+ console.log('URL prefix:', fable.settings.RestClientURLPrefix);
34
45
 
35
- // All requests will be prefixed
36
- restClient.getJSON('/users', callback); // Requests https://api.example.com/users
46
+ // In Node.js (network calls are skipped in the browser playground):
47
+ // restClient.getJSON('/users', callback); // -> Requests https://api.example.com/users
48
+ console.info(" restClient.getJSON('/users', callback); // -> https://api.example.com/users");
37
49
  ```
38
50
 
39
51
  ## JSON Requests
@@ -41,86 +53,73 @@ restClient.getJSON('/users', callback); // Requests https://api.example.com/use
41
53
  ### GET JSON
42
54
 
43
55
  ```javascript
44
- // Simple URL
45
- restClient.getJSON('https://api.example.com/users', (error, response, data) => {
46
- if (error) {
47
- console.error('Request failed:', error);
48
- return;
49
- }
50
- console.log('Status:', response.statusCode);
51
- console.log('Data:', data); // Parsed JSON
52
- });
53
-
54
- // With options
55
- restClient.getJSON({
56
- url: 'https://api.example.com/users',
57
- headers: {
58
- 'Authorization': 'Bearer token123'
59
- }
60
- }, (error, response, data) => {
61
- console.log(data);
62
- });
56
+ // Node.js reference — real HTTP requests don't run in the browser playground (CORS).
57
+ console.info("In Node.js:");
58
+ console.info(" // Simple URL");
59
+ console.info(" restClient.getJSON('https://api.example.com/users', (error, response, data) => {");
60
+ console.info(" if (error) { console.error('Request failed:', error); return; }");
61
+ console.info(" console.log('Status:', response.statusCode);");
62
+ console.info(" console.log('Data:', data); // Parsed JSON");
63
+ console.info(" });");
64
+ console.info(" // With options");
65
+ console.info(" restClient.getJSON({");
66
+ console.info(" url: 'https://api.example.com/users',");
67
+ console.info(" headers: { Authorization: 'Bearer token123' }");
68
+ console.info(" }, (error, response, data) => { console.log(data); });");
63
69
  ```
64
70
 
65
71
  ### POST JSON
66
72
 
67
73
  ```javascript
68
- restClient.postJSON({
69
- url: 'https://api.example.com/users',
70
- body: {
71
- name: 'John Doe',
72
- email: 'john@example.com'
73
- }
74
- }, (error, response, data) => {
75
- console.log('Created user:', data);
76
- });
74
+ // Node.js reference — real HTTP requests don't run in the browser playground.
75
+ console.info("In Node.js:");
76
+ console.info(" restClient.postJSON({");
77
+ console.info(" url: 'https://api.example.com/users',");
78
+ console.info(" body: { name: 'John Doe', email: 'john@example.com' }");
79
+ console.info(" }, (error, response, data) => { console.log('Created user:', data); });");
77
80
  ```
78
81
 
79
82
  ### PUT JSON
80
83
 
81
84
  ```javascript
82
- restClient.putJSON({
83
- url: 'https://api.example.com/users/123',
84
- body: {
85
- name: 'John Smith'
86
- }
87
- }, (error, response, data) => {
88
- console.log('Updated user:', data);
89
- });
85
+ // Node.js reference — real HTTP requests don't run in the browser playground.
86
+ console.info("In Node.js:");
87
+ console.info(" restClient.putJSON({");
88
+ console.info(" url: 'https://api.example.com/users/123',");
89
+ console.info(" body: { name: 'John Smith' }");
90
+ console.info(" }, (error, response, data) => { console.log('Updated user:', data); });");
90
91
  ```
91
92
 
92
93
  ### PATCH JSON
93
94
 
94
95
  ```javascript
95
- restClient.patchJSON({
96
- url: 'https://api.example.com/users/123',
97
- body: {
98
- email: 'john.smith@example.com'
99
- }
100
- }, (error, response, data) => {
101
- console.log('Patched user:', data);
102
- });
96
+ // Node.js reference — real HTTP requests don't run in the browser playground.
97
+ console.info("In Node.js:");
98
+ console.info(" restClient.patchJSON({");
99
+ console.info(" url: 'https://api.example.com/users/123',");
100
+ console.info(" body: { email: 'john.smith@example.com' }");
101
+ console.info(" }, (error, response, data) => { console.log('Patched user:', data); });");
103
102
  ```
104
103
 
105
104
  ### DELETE JSON
106
105
 
107
106
  ```javascript
108
- restClient.delJSON({
109
- url: 'https://api.example.com/users/123'
110
- }, (error, response, data) => {
111
- console.log('Deleted user');
112
- });
107
+ // Node.js reference — real HTTP requests don't run in the browser playground.
108
+ console.info("In Node.js:");
109
+ console.info(" restClient.delJSON({");
110
+ console.info(" url: 'https://api.example.com/users/123'");
111
+ console.info(" }, (error, response, data) => { console.log('Deleted user'); });");
113
112
  ```
114
113
 
115
114
  ### HEAD JSON
116
115
 
117
116
  ```javascript
118
- restClient.headJSON({
119
- url: 'https://api.example.com/users/123',
120
- body: {} // Required but not sent
121
- }, (error, response, data) => {
122
- console.log('Headers:', response.headers);
123
- });
117
+ // Node.js reference — real HTTP requests don't run in the browser playground.
118
+ console.info("In Node.js:");
119
+ console.info(" restClient.headJSON({");
120
+ console.info(" url: 'https://api.example.com/users/123',");
121
+ console.info(" body: {} // Required but not sent");
122
+ console.info(" }, (error, response, data) => { console.log('Headers:', response.headers); });");
124
123
  ```
125
124
 
126
125
  ## Raw Text Requests
@@ -128,9 +127,11 @@ restClient.headJSON({
128
127
  ### GET Raw Text
129
128
 
130
129
  ```javascript
131
- restClient.getRawText('https://example.com/page.html', (error, response, text) => {
132
- console.log('HTML:', text);
133
- });
130
+ // Node.js reference — real HTTP requests don't run in the browser playground.
131
+ console.info("In Node.js:");
132
+ console.info(" restClient.getRawText('https://example.com/page.html', (error, response, text) => {");
133
+ console.info(" console.log('HTML:', text);");
134
+ console.info(" });");
134
135
  ```
135
136
 
136
137
  ## Chunked Requests
@@ -140,24 +141,26 @@ For streaming or large responses:
140
141
  ### Text Chunks
141
142
 
142
143
  ```javascript
143
- restClient.executeChunkedRequest({
144
- method: 'GET',
145
- url: 'https://example.com/large-file.txt'
146
- }, (error, response, data) => {
147
- console.log('Complete data:', data);
148
- });
144
+ // Node.js reference — real HTTP requests don't run in the browser playground.
145
+ console.info("In Node.js:");
146
+ console.info(" restClient.executeChunkedRequest({");
147
+ console.info(" method: 'GET',");
148
+ console.info(" url: 'https://example.com/large-file.txt'");
149
+ console.info(" }, (error, response, data) => { console.log('Complete data:', data); });");
149
150
  ```
150
151
 
151
152
  ### Binary Chunks
152
153
 
153
154
  ```javascript
154
- restClient.executeChunkedRequestBinary({
155
- method: 'GET',
156
- url: 'https://example.com/image.png'
157
- }, (error, response, buffer) => {
158
- // buffer is a Node.js Buffer
159
- require('fs').writeFileSync('image.png', buffer);
160
- });
155
+ // Node.js reference — real HTTP + fs don't run in the browser playground.
156
+ console.info("In Node.js:");
157
+ console.info(" restClient.executeChunkedRequestBinary({");
158
+ console.info(" method: 'GET',");
159
+ console.info(" url: 'https://example.com/image.png'");
160
+ console.info(" }, (error, response, buffer) => {");
161
+ console.info(" // buffer is a Node.js Buffer");
162
+ console.info(" require('fs').writeFileSync('image.png', buffer);");
163
+ console.info(" });");
161
164
  ```
162
165
 
163
166
  ## Cookie Management
@@ -165,10 +168,15 @@ restClient.executeChunkedRequestBinary({
165
168
  ### Set Cookies
166
169
 
167
170
  ```javascript
171
+ const libFable = require('fable');
172
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
173
+ const restClient = fable.instantiateServiceProvider('RestClient');
174
+
168
175
  restClient.cookie = {
169
176
  'session_id': 'abc123',
170
177
  'user_token': 'xyz789'
171
178
  };
179
+ console.log('Cookies set:', restClient.cookie);
172
180
  ```
173
181
 
174
182
  ### Automatic Cookie Handling
@@ -176,10 +184,16 @@ restClient.cookie = {
176
184
  Cookies are automatically included in subsequent requests:
177
185
 
178
186
  ```javascript
187
+ const libFable = require('fable');
188
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
189
+ const restClient = fable.instantiateServiceProvider('RestClient');
190
+
179
191
  restClient.cookie = { session: 'abc123' };
192
+ console.log('Cookie set:', restClient.cookie);
180
193
 
181
- // This request will include the session cookie
182
- restClient.getJSON('/protected-resource', callback);
194
+ // In Node.js (browser playground skips real network):
195
+ // restClient.getJSON('/protected-resource', callback);
196
+ console.info(" // restClient.getJSON('/protected-resource', callback); // sends session cookie");
183
197
  ```
184
198
 
185
199
  ## Request Options
@@ -187,17 +201,18 @@ restClient.getJSON('/protected-resource', callback);
187
201
  All request methods accept an options object:
188
202
 
189
203
  ```javascript
190
- {
204
+ const requestOptionsShape = {
191
205
  url: 'https://api.example.com/endpoint',
192
206
  method: 'GET', // Usually set by the convenience method
193
207
  headers: {
194
208
  'Authorization': 'Bearer token',
195
- 'Content-Type': 'application/json',
196
- 'Accept': 'application/json'
209
+ 'Content-Type': 'application/json',
210
+ 'Accept': 'application/json'
197
211
  },
198
212
  body: { /* request body for POST/PUT/PATCH */ },
199
213
  timeout: 30000 // Request timeout in milliseconds
200
- }
214
+ };
215
+ console.log('requestOptionsShape:', requestOptionsShape);
201
216
  ```
202
217
 
203
218
  ## Custom Request Preparation
@@ -205,12 +220,21 @@ All request methods accept an options object:
205
220
  Override the `prepareRequestOptions` function to modify all outgoing requests:
206
221
 
207
222
  ```javascript
223
+ const libFable = require('fable');
224
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
225
+ const restClient = fable.instantiateServiceProvider('RestClient');
226
+
227
+ function getAccessToken() { return 'demo-token-abc123'; }
228
+
208
229
  restClient.prepareRequestOptions = (options) => {
209
230
  // Add authentication to all requests
210
231
  if (!options.headers) options.headers = {};
211
232
  options.headers['Authorization'] = 'Bearer ' + getAccessToken();
212
233
  return options;
213
234
  };
235
+
236
+ const sample = restClient.prepareRequestOptions({ url: '/users' });
237
+ console.log('Prepared options:', sample);
214
238
  ```
215
239
 
216
240
  ## Trace Logging
@@ -218,12 +242,17 @@ restClient.prepareRequestOptions = (options) => {
218
242
  Enable detailed request logging:
219
243
 
220
244
  ```javascript
245
+ const libFable = require('fable');
246
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
247
+
221
248
  const restClient = fable.instantiateServiceProvider('RestClient', {
222
249
  TraceLog: true
223
250
  });
224
251
 
225
252
  // Or enable globally
226
253
  fable.TraceLog = true;
254
+ console.log('Per-instance TraceLog:', restClient.options.TraceLog);
255
+ console.log('Global fable.TraceLog:', fable.TraceLog);
227
256
 
228
257
  // Logs include:
229
258
  // - Request start time
@@ -246,33 +275,29 @@ Beginning GET request to https://api.example.com/users at 1704067200000
246
275
  Access the underlying `simple-get` library directly:
247
276
 
248
277
  ```javascript
249
- restClient.simpleGet({
250
- method: 'GET',
251
- url: 'https://example.com',
252
- // ... other simple-get options
253
- }, callback);
278
+ // Node.js reference — real HTTP requests don't run in the browser playground.
279
+ console.info("In Node.js:");
280
+ console.info(" restClient.simpleGet({");
281
+ console.info(" method: 'GET',");
282
+ console.info(" url: 'https://example.com',");
283
+ console.info(" // ... other simple-get options");
284
+ console.info(" }, callback);");
254
285
  ```
255
286
 
256
287
  ## Error Handling
257
288
 
258
289
  ```javascript
259
- restClient.getJSON('https://api.example.com/users', (error, response, data) => {
260
- if (error) {
261
- // Network error, timeout, etc.
262
- console.error('Network error:', error.message);
263
- return;
264
- }
265
-
266
- if (response.statusCode >= 400) {
267
- // HTTP error status
268
- console.error('HTTP error:', response.statusCode);
269
- console.error('Error body:', data);
270
- return;
271
- }
272
-
273
- // Success
274
- console.log('Data:', data);
275
- });
290
+ // Node.js reference — real HTTP requests don't run in the browser playground.
291
+ console.info("In Node.js:");
292
+ console.info(" restClient.getJSON('https://api.example.com/users', (error, response, data) => {");
293
+ console.info(" if (error) { console.error('Network error:', error.message); return; }");
294
+ console.info(" if (response.statusCode >= 400) {");
295
+ console.info(" console.error('HTTP error:', response.statusCode);");
296
+ console.info(" console.error('Error body:', data);");
297
+ console.info(" return;");
298
+ console.info(" }");
299
+ console.info(" console.log('Data:', data);");
300
+ console.info(" });");
276
301
  ```
277
302
 
278
303
  ## Multiple Instances
@@ -280,11 +305,14 @@ restClient.getJSON('https://api.example.com/users', (error, response, data) => {
280
305
  Create separate clients for different APIs:
281
306
 
282
307
  ```javascript
308
+ const libFable = require('fable');
309
+ const fable = new libFable({ Product: 'RestClientDemo', ProductVersion: '1.0.0' });
310
+
283
311
  const mainApi = fable.instantiateServiceProvider('RestClient', {}, 'main-api');
284
312
  const authApi = fable.instantiateServiceProvider('RestClient', {}, 'auth-api');
285
313
 
286
314
  // Set different cookies for each
287
- mainApi.cookie = { api_session: '...' };
315
+ mainApi.cookie = { api_session: '...' };
288
316
  authApi.cookie = { auth_session: '...' };
289
317
 
290
318
  // Set different request preparation
@@ -293,4 +321,8 @@ authApi.prepareRequestOptions = (options) => {
293
321
  options.headers['X-Auth-Service'] = 'true';
294
322
  return options;
295
323
  };
324
+
325
+ console.log('mainApi cookie keys:', Object.keys(mainApi.cookie));
326
+ console.log('authApi cookie keys:', Object.keys(authApi.cookie));
327
+ console.log('authApi prepared headers:', authApi.prepareRequestOptions({}).headers);
296
328
  ```