json-rest-api 1.0.1 → 1.0.3

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.
@@ -1,15 +0,0 @@
1
- {
2
- "name": "test-examples",
3
- "version": "1.0.0",
4
- "type": "module",
5
- "description": "Testing jsonrestapi examples",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
- },
9
- "dependencies": {
10
- "busboy": "^1.6.0",
11
- "express": "^5.1.0",
12
- "hooked-api": "^1.0.2",
13
- "jsonrestapi": "file:.."
14
- }
15
- }
@@ -1,11 +0,0 @@
1
- import { Api } from 'hooked-api';
2
-
3
- // Create a new API instance
4
- const api = new Api({
5
- name: 'my-library-api',
6
- version: '1.0.0'
7
- });
8
-
9
- console.log('✓ Basic API creation works!');
10
- console.log(' API name:', api.options.name);
11
- console.log(' API version:', api.options.version);
@@ -1,116 +0,0 @@
1
- import { Api } from 'hooked-api';
2
- import { RestApiPlugin } from 'json-rest-api';
3
-
4
- const api = new Api({
5
- name: 'my-library-api',
6
- version: '1.0.0'
7
- });
8
-
9
- // Use the REST API plugin
10
- api.use(RestApiPlugin);
11
-
12
- // Define a books resource
13
- api.addResource('books', {
14
- schema: {
15
- title: { type: 'string', required: true },
16
- author: { type: 'string', required: true },
17
- year: { type: 'number' },
18
- isbn: { type: 'string' }
19
- }
20
- });
21
-
22
- // Add simple data helpers (in real apps, these would connect to a database)
23
- api.customize({
24
- vars: {
25
- helpers: {
26
- dataQuery: async ({ scopeName, queryParams }) => {
27
- // For now, just return some fake books
28
- const fakeBooks = [
29
- { id: '1', title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', year: 1925 },
30
- { id: '2', title: '1984', author: 'George Orwell', year: 1949 },
31
- { id: '3', title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960 }
32
- ];
33
-
34
- return {
35
- data: fakeBooks.map(book => ({
36
- type: 'books',
37
- id: book.id,
38
- attributes: {
39
- title: book.title,
40
- author: book.author,
41
- year: book.year
42
- }
43
- }))
44
- };
45
- },
46
-
47
- dataGet: async ({ scopeName, id }) => {
48
- // Return a single fake book
49
- const book = { id, title: 'Example Book', author: 'Example Author', year: 2024 };
50
-
51
- return {
52
- data: {
53
- type: 'books',
54
- id: book.id,
55
- attributes: {
56
- title: book.title,
57
- author: book.author,
58
- year: book.year
59
- }
60
- }
61
- };
62
- },
63
-
64
- dataPost: async ({ scopeName, inputRecord }) => {
65
- // Pretend to create a book and return it
66
- const newBook = {
67
- id: String(Date.now()), // Simple ID generation
68
- ...inputRecord.data.attributes
69
- };
70
-
71
- return {
72
- data: {
73
- type: 'books',
74
- id: newBook.id,
75
- attributes: {
76
- title: newBook.title,
77
- author: newBook.author,
78
- year: newBook.year
79
- }
80
- }
81
- };
82
- },
83
-
84
- dataPut: async ({ scopeName, id, inputRecord }) => {
85
- // Pretend to replace a book
86
- return {
87
- data: {
88
- type: 'books',
89
- id: id,
90
- attributes: inputRecord.data.attributes
91
- }
92
- };
93
- },
94
-
95
- dataPatch: async ({ scopeName, id, inputRecord }) => {
96
- // Pretend to update a book
97
- return {
98
- data: {
99
- type: 'books',
100
- id: id,
101
- attributes: inputRecord.data.attributes
102
- }
103
- };
104
- },
105
-
106
- dataDelete: async ({ scopeName, id }) => {
107
- // Just return success
108
- return { success: true };
109
- }
110
- }
111
- }
112
- });
113
-
114
- console.log('✓ Books resource created with all data helpers!');
115
- console.log(' Resource:', api.resources.books ? 'books resource exists' : 'ERROR: books resource missing');
116
- console.log(' Available methods:', api.resources.books ? Object.keys(api.resources.books).filter(k => typeof api.resources.books[k] === 'function').join(', ') : 'none');
@@ -1,140 +0,0 @@
1
- import { Api } from 'hooked-api';
2
- import { RestApiPlugin, FileHandlingPlugin, ExpressPlugin } from 'json-rest-api';
3
- import { LocalStorage } from 'json-rest-api';
4
- import express from 'express';
5
-
6
- // Create API
7
- const api = new Api({
8
- name: 'my-library-api',
9
- version: '1.0.0'
10
- });
11
-
12
- // Create storage for different file types
13
- const coverStorage = new LocalStorage({
14
- directory: './uploads/covers',
15
- baseUrl: 'http://localhost:3000/uploads/covers',
16
- nameStrategy: 'hash',
17
- allowedExtensions: ['.jpg', '.jpeg', '.png', '.gif']
18
- });
19
-
20
- const pdfStorage = new LocalStorage({
21
- directory: './uploads/pdfs',
22
- baseUrl: 'http://localhost:3000/uploads/pdfs',
23
- nameStrategy: 'timestamp'
24
- });
25
-
26
- // Use plugins
27
- api.use(RestApiPlugin);
28
- api.use(FileHandlingPlugin);
29
- api.use(ExpressPlugin); // File parser configuration shown in connector plugins section
30
-
31
- // Define schema with multiple file fields
32
- api.addResource('books', {
33
- schema: {
34
- title: { type: 'string', required: true },
35
- author: { type: 'string', required: true },
36
- year: { type: 'number' },
37
- cover: {
38
- type: 'file',
39
- storage: coverStorage,
40
- accepts: ['image/*'],
41
- maxSize: '5mb'
42
- },
43
- sample: {
44
- type: 'file',
45
- storage: pdfStorage,
46
- accepts: ['application/pdf'],
47
- maxSize: '10mb',
48
- required: false
49
- }
50
- }
51
- });
52
-
53
- // Simple data helpers
54
- api.customize({
55
- vars: {
56
- helpers: {
57
- dataPost: async ({ scopeName, inputRecord }) => {
58
- const newBook = {
59
- id: String(Date.now()),
60
- ...inputRecord.data.attributes
61
- };
62
-
63
- console.log('Created book:', newBook);
64
-
65
- return {
66
- data: {
67
- type: 'books',
68
- id: newBook.id,
69
- attributes: newBook
70
- }
71
- };
72
- },
73
-
74
- dataQuery: async () => {
75
- return { data: [] };
76
- }
77
- }
78
- }
79
- });
80
-
81
- // Wait for async plugin initialization
82
- await new Promise(resolve => setTimeout(resolve, 100));
83
-
84
- // Express setup
85
- const app = express();
86
- app.use('/uploads', express.static('./uploads'));
87
-
88
- // Test form
89
- app.get('/', (req, res) => {
90
- res.send(`
91
- <form action="/api/books" method="POST" enctype="multipart/form-data">
92
- <h2>Add a Book</h2>
93
- <p>Title: <input name="title" required></p>
94
- <p>Author: <input name="author" required></p>
95
- <p>Year: <input name="year" type="number"></p>
96
- <p>Cover: <input name="cover" type="file" accept="image/*"></p>
97
- <p>Sample PDF: <input name="sample" type="file" accept=".pdf"></p>
98
- <button type="submit">Add Book</button>
99
- </form>
100
- `);
101
- });
102
-
103
- app.use(api.http.express.router);
104
-
105
- const server = app.listen(3000, () => {
106
- console.log('Library API running at http://localhost:3000');
107
- console.log('Test form at http://localhost:3000');
108
- console.log('API endpoints at http://localhost:3000/api/books');
109
-
110
- // Test with a simple POST
111
- console.log('\nTesting JSON POST (without files)...');
112
- fetch('http://localhost:3000/api/books', {
113
- method: 'POST',
114
- headers: {
115
- 'Content-Type': 'application/json'
116
- },
117
- body: JSON.stringify({
118
- data: {
119
- type: 'books',
120
- attributes: {
121
- title: 'Test Book',
122
- author: 'Test Author',
123
- year: 2024
124
- }
125
- }
126
- })
127
- })
128
- .then(res => res.json())
129
- .then(result => {
130
- console.log('JSON POST result:', JSON.stringify(result, null, 2));
131
-
132
- // Keep server running for manual testing
133
- console.log('\nServer is running. Visit http://localhost:3000 to test file uploads.');
134
- console.log('Press Ctrl+C to stop.');
135
- })
136
- .catch(err => {
137
- console.error('Test failed:', err);
138
- server.close();
139
- });
140
- });
@@ -1,28 +0,0 @@
1
- import { Api } from 'hooked-api';
2
- import { RestApiPlugin } from 'json-rest-api';
3
-
4
- // Create a minimal test plugin to check what parameters are available
5
- const TestPlugin = {
6
- name: 'test-plugin',
7
- install(context) {
8
- console.log('Plugin install context keys:', Object.keys(context));
9
- console.log('api type:', typeof context.api);
10
- console.log('api value:', context.api);
11
-
12
- if (context.api) {
13
- console.log('api properties:', Object.keys(context.api));
14
- }
15
- }
16
- };
17
-
18
- const api = new Api({
19
- name: 'my-library-api',
20
- version: '1.0.0'
21
- });
22
-
23
- // First test with our debug plugin
24
- console.log('Testing with debug plugin...');
25
- api.use(TestPlugin);
26
-
27
- console.log('\nNow testing REST API plugin...');
28
- api.use(RestApiPlugin);
@@ -1,177 +0,0 @@
1
- import { Api } from 'hooked-api';
2
- import { RestApiPlugin, FileHandlingPlugin, ExpressPlugin } from 'json-rest-api';
3
- import express from 'express';
4
-
5
- const api = new Api({
6
- name: 'my-library-api',
7
- version: '1.0.0'
8
- });
9
-
10
- // Add plugins (ORDER MATTERS!)
11
- api.use(RestApiPlugin);
12
- api.use(FileHandlingPlugin); // Must come after RestApiPlugin
13
- api.use(ExpressPlugin, { // Must come after FileHandlingPlugin
14
- basePath: '/api', // Optional, defaults to '/api'
15
- });
16
-
17
- // Add books resource
18
- api.addResource('books', {
19
- schema: {
20
- title: { type: 'string', required: true },
21
- author: { type: 'string', required: true },
22
- year: { type: 'number' },
23
- isbn: { type: 'string' }
24
- }
25
- });
26
-
27
- // Add simple data helpers
28
- api.customize({
29
- vars: {
30
- helpers: {
31
- dataQuery: async ({ scopeName, queryParams }) => {
32
- const fakeBooks = [
33
- { id: '1', title: 'The Great Gatsby', author: 'F. Scott Fitzgerald', year: 1925 },
34
- { id: '2', title: '1984', author: 'George Orwell', year: 1949 },
35
- { id: '3', title: 'To Kill a Mockingbird', author: 'Harper Lee', year: 1960 }
36
- ];
37
-
38
- return {
39
- data: fakeBooks.map(book => ({
40
- type: 'books',
41
- id: book.id,
42
- attributes: {
43
- title: book.title,
44
- author: book.author,
45
- year: book.year
46
- }
47
- }))
48
- };
49
- },
50
-
51
- dataGet: async ({ scopeName, id }) => {
52
- const book = { id, title: 'Example Book', author: 'Example Author', year: 2024 };
53
-
54
- return {
55
- data: {
56
- type: 'books',
57
- id: book.id,
58
- attributes: {
59
- title: book.title,
60
- author: book.author,
61
- year: book.year
62
- }
63
- }
64
- };
65
- },
66
-
67
- dataPost: async ({ scopeName, inputRecord }) => {
68
- const newBook = {
69
- id: String(Date.now()),
70
- ...inputRecord.data.attributes
71
- };
72
-
73
- return {
74
- data: {
75
- type: 'books',
76
- id: newBook.id,
77
- attributes: {
78
- title: newBook.title,
79
- author: newBook.author,
80
- year: newBook.year
81
- }
82
- }
83
- };
84
- },
85
-
86
- dataPut: async ({ scopeName, id, inputRecord }) => {
87
- return {
88
- data: {
89
- type: 'books',
90
- id: id,
91
- attributes: inputRecord.data.attributes
92
- }
93
- };
94
- },
95
-
96
- dataPatch: async ({ scopeName, id, inputRecord }) => {
97
- return {
98
- data: {
99
- type: 'books',
100
- id: id,
101
- attributes: inputRecord.data.attributes
102
- }
103
- };
104
- },
105
-
106
- dataDelete: async ({ scopeName, id }) => {
107
- return { success: true };
108
- }
109
- }
110
- }
111
- });
112
-
113
- // Wait a bit for async plugin installation to complete
114
- await new Promise(resolve => setTimeout(resolve, 100));
115
-
116
- // Create Express app
117
- const app = express();
118
-
119
- // Debug: Check what's available
120
- console.log('api.http exists?', !!api.http);
121
- console.log('api.http.express exists?', !!api.http?.express);
122
- console.log('api.http.express.router exists?', !!api.http?.express?.router);
123
-
124
- // Mount the API routes - both approaches work:
125
- // Approach 1: Direct router usage (standard Express pattern)
126
- app.use(api.http.express.router);
127
-
128
- // Start the server
129
- const server = app.listen(3000, () => {
130
- console.log('✓ Express server started successfully!');
131
- console.log(' API running at http://localhost:3000/api');
132
- console.log('\nTesting endpoints with curl...\n');
133
-
134
- // Close server after tests
135
- setTimeout(() => {
136
- console.log('\nClosing server...');
137
- server.close();
138
- process.exit(0);
139
- }, 2000);
140
- });
141
-
142
- // Test with curl commands
143
- import { exec } from 'child_process';
144
- import { promisify } from 'util';
145
- const execAsync = promisify(exec);
146
-
147
- setTimeout(async () => {
148
- try {
149
- // Test GET all books
150
- console.log('1. Testing GET /api/books:');
151
- const { stdout: getAll } = await execAsync('curl -s http://localhost:3000/api/books');
152
- console.log('✓ Response:', getAll.substring(0, 100) + '...');
153
-
154
- // Test GET single book
155
- console.log('\n2. Testing GET /api/books/1:');
156
- const { stdout: getOne } = await execAsync('curl -s http://localhost:3000/api/books/1');
157
- console.log('✓ Response:', getOne.substring(0, 100) + '...');
158
-
159
- // Test POST
160
- console.log('\n3. Testing POST /api/books:');
161
- const postData = JSON.stringify({
162
- data: {
163
- type: 'books',
164
- attributes: {
165
- title: 'New Book',
166
- author: 'New Author',
167
- year: 2024
168
- }
169
- }
170
- });
171
- const { stdout: postRes } = await execAsync(`curl -s -X POST http://localhost:3000/api/books -H "Content-Type: application/json" -d '${postData}'`);
172
- console.log('✓ Response:', postRes.substring(0, 100) + '...');
173
-
174
- } catch (error) {
175
- console.error('Test error:', error.message);
176
- }
177
- }, 500);
@@ -1,28 +0,0 @@
1
- import { Api } from 'hooked-api';
2
- import { RestApiPlugin, FileHandlingPlugin, ExpressPlugin } from 'json-rest-api';
3
- import express from 'express';
4
-
5
- const api = new Api({
6
- name: 'my-library-api',
7
- version: '1.0.0'
8
- });
9
-
10
- try {
11
- // Add plugins
12
- api.use(RestApiPlugin);
13
- api.use(FileHandlingPlugin);
14
- api.use(ExpressPlugin);
15
-
16
- console.log('All plugins loaded successfully');
17
-
18
- // Wait for async installation
19
- await new Promise(resolve => setTimeout(resolve, 200));
20
-
21
- console.log('Checking API methods after wait:');
22
- console.log('- getExpressRouter:', typeof api.getExpressRouter);
23
- console.log('- mountExpress:', typeof api.mountExpress);
24
-
25
- } catch (error) {
26
- console.error('Plugin installation error:', error);
27
- process.exit(1);
28
- }
@@ -1,71 +0,0 @@
1
- // Import express first to ensure it's available
2
- import express from 'express';
3
- import { Api } from 'hooked-api';
4
- import { RestApiPlugin, FileHandlingPlugin, ExpressPlugin } from 'json-rest-api';
5
-
6
- // Make express available globally for the plugin
7
- global.express = express;
8
-
9
- const api = new Api({
10
- name: 'my-library-api',
11
- version: '1.0.0'
12
- });
13
-
14
- // Add plugins
15
- api.use(RestApiPlugin);
16
- api.use(FileHandlingPlugin);
17
-
18
- // Temporarily patch the Express plugin to use our express
19
- const originalInstall = ExpressPlugin.install;
20
- ExpressPlugin.install = async function(context) {
21
- // Override the express import in the plugin
22
- const patchedContext = {
23
- ...context,
24
- vars: { ...context.vars, _express: express }
25
- };
26
-
27
- // Call original install
28
- await originalInstall.call(this, patchedContext);
29
-
30
- // If express wasn't loaded, use our version
31
- if (!patchedContext.vars.express.router) {
32
- const router = express.Router({ mergeParams: true });
33
- patchedContext.vars.express.router = router;
34
- }
35
- };
36
-
37
- api.use(ExpressPlugin);
38
-
39
- // Add a simple test resource
40
- api.addResource('test', {
41
- schema: {
42
- name: { type: 'string', required: true }
43
- }
44
- });
45
-
46
- // Add test data helper
47
- api.customize({
48
- vars: {
49
- helpers: {
50
- dataQuery: async () => ({ data: [] })
51
- }
52
- }
53
- });
54
-
55
- console.log('✓ All plugins loaded successfully!');
56
-
57
- // Create Express app and test
58
- const app = express();
59
-
60
- // Check if methods are available
61
- console.log('API methods available:', Object.keys(api).filter(k => typeof api[k] === 'function'));
62
-
63
- // Try the simpler approach - using the Express router directly
64
- if (api.getExpressRouter) {
65
- app.use('/api', api.getExpressRouter());
66
- console.log('✓ Express router mounted successfully!');
67
- } else {
68
- console.log('✗ getExpressRouter method not found');
69
- }
70
-
71
- process.exit(0);