@classytic/arc 1.0.0 → 1.0.5

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/bin/arc.js CHANGED
@@ -4,15 +4,18 @@
4
4
  * Arc CLI - Smart Backend Framework
5
5
  *
6
6
  * Commands:
7
- * arc generate resource <name> [options] Generate a new resource
8
- * arc generate controller <name> Generate a controller only
9
- * arc generate model <name> Generate a model only
10
- * arc introspect Show all registered resources
11
- * arc docs [output-path] Export OpenAPI specification
7
+ * arc init [name] Initialize a new Arc project
8
+ * arc generate resource <name> Generate a new resource
9
+ * arc generate controller <name> Generate a controller only
10
+ * arc generate model <name> Generate a model only
11
+ * arc introspect Show all registered resources
12
+ * arc docs [output-path] Export OpenAPI specification
12
13
  *
13
14
  * Examples:
14
- * arc generate resource product --module catalog
15
- * arc generate resource invoice --presets softDelete,multiTenant
15
+ * arc init my-api
16
+ * arc init my-api --mongokit --single --ts
17
+ * arc generate resource product
18
+ * arc g r invoice
16
19
  * arc introspect
17
20
  * arc docs ./openapi.json
18
21
  */
@@ -60,6 +63,11 @@ const [command, subcommand, ...rest] = args;
60
63
  async function main() {
61
64
  try {
62
65
  switch (command) {
66
+ case 'init':
67
+ case 'new':
68
+ await handleInit(subcommand ? [subcommand, ...rest] : rest);
69
+ break;
70
+
63
71
  case 'generate':
64
72
  case 'g':
65
73
  await handleGenerate(subcommand, rest);
@@ -76,12 +84,12 @@ async function main() {
76
84
  break;
77
85
 
78
86
  default:
79
- console.error(`❌ Unknown command: ${command}`);
87
+ console.error(`Unknown command: ${command}`);
80
88
  console.error('Run "arc --help" for usage');
81
89
  process.exit(1);
82
90
  }
83
91
  } catch (err) {
84
- console.error(`❌ Error: ${err.message}`);
92
+ console.error(`Error: ${err.message}`);
85
93
  if (process.env.DEBUG) {
86
94
  console.error(err.stack);
87
95
  }
@@ -93,13 +101,19 @@ async function main() {
93
101
  // Command Handlers
94
102
  // ============================================================================
95
103
 
104
+ async function handleInit(args) {
105
+ const options = parseInitOptions(args);
106
+ const { init } = await import('../dist/cli/commands/init.js');
107
+ await init(options);
108
+ }
109
+
96
110
  async function handleGenerate(type, args) {
97
111
  if (!type) {
98
- console.error('Missing type argument');
99
- console.log('\nUsage: arc generate <resource|controller|model> <name> [options]');
112
+ console.error('Missing type argument');
113
+ console.log('\nUsage: arc generate <resource|controller|model|repository|schemas> <name>');
100
114
  console.log('\nExamples:');
101
- console.log(' arc generate resource product --module catalog');
102
- console.log(' arc g r invoice --presets softDelete,multiTenant');
115
+ console.log(' arc generate resource product');
116
+ console.log(' arc g r invoice');
103
117
  process.exit(1);
104
118
  }
105
119
 
@@ -108,30 +122,32 @@ async function handleGenerate(type, args) {
108
122
  r: 'resource',
109
123
  c: 'controller',
110
124
  m: 'model',
125
+ repo: 'repository',
126
+ s: 'schemas',
111
127
  resource: 'resource',
112
128
  controller: 'controller',
113
129
  model: 'model',
130
+ repository: 'repository',
131
+ schemas: 'schemas',
114
132
  };
115
133
 
116
134
  const normalizedType = typeMap[type.toLowerCase()];
117
135
  if (!normalizedType) {
118
- console.error(`❌ Unknown type: ${type}`);
119
- console.log('Available types: resource (r), controller (c), model (m)');
136
+ console.error(`Unknown type: ${type}`);
137
+ console.log('Available types: resource (r), controller (c), model (m), repository (repo), schemas (s)');
120
138
  process.exit(1);
121
139
  }
122
140
 
123
141
  const name = args[0];
124
142
  if (!name) {
125
- console.error('Missing name argument');
126
- console.log(`\nUsage: arc generate ${normalizedType} <name> [options]`);
143
+ console.error('Missing name argument');
144
+ console.log(`\nUsage: arc generate ${normalizedType} <name>`);
127
145
  process.exit(1);
128
146
  }
129
147
 
130
- const options = parseGenerateOptions(args.slice(1));
131
-
132
148
  // Import and run
133
- const { generate } = await import('../dist/cli/index.js');
134
- await generate(normalizedType, name, options);
149
+ const { generate } = await import('../dist/cli/commands/generate.js');
150
+ await generate(normalizedType, args);
135
151
  }
136
152
 
137
153
  async function handleIntrospect(args) {
@@ -143,11 +159,11 @@ async function handleIntrospect(args) {
143
159
  const absolutePath = resolve(process.cwd(), entryPath);
144
160
  const fileUrl = pathToFileURL(absolutePath).href;
145
161
 
146
- console.log(`📦 Loading resources from: ${entryPath}\n`);
162
+ console.log(`Loading resources from: ${entryPath}\n`);
147
163
  try {
148
164
  await import(fileUrl);
149
165
  } catch (err) {
150
- console.error(`❌ Failed to load entry file: ${err.message}`);
166
+ console.error(`Failed to load entry file: ${err.message}`);
151
167
  if (process.env.DEBUG) {
152
168
  console.error(err.stack);
153
169
  }
@@ -168,11 +184,11 @@ async function handleDocs(args) {
168
184
  const absolutePath = resolve(process.cwd(), entryPath);
169
185
  const fileUrl = pathToFileURL(absolutePath).href;
170
186
 
171
- console.log(`📦 Loading resources from: ${entryPath}\n`);
187
+ console.log(`Loading resources from: ${entryPath}\n`);
172
188
  try {
173
189
  await import(fileUrl);
174
190
  } catch (err) {
175
- console.error(`❌ Failed to load entry file: ${err.message}`);
191
+ console.error(`Failed to load entry file: ${err.message}`);
176
192
  if (process.env.DEBUG) {
177
193
  console.error(err.stack);
178
194
  }
@@ -190,57 +206,54 @@ async function handleDocs(args) {
190
206
  // Option Parsing
191
207
  // ============================================================================
192
208
 
193
- function parseGenerateOptions(args) {
209
+ function parseInitOptions(args) {
194
210
  const opts = {
195
- module: undefined,
196
- presets: [],
197
- parentField: 'parent',
198
- withTests: true,
199
- dryRun: false,
211
+ name: undefined,
212
+ adapter: undefined,
213
+ tenant: undefined,
214
+ typescript: undefined,
215
+ skipInstall: false,
200
216
  force: false,
201
- typescript: true, // Default to TypeScript
202
- outputDir: process.cwd(),
203
217
  };
204
218
 
205
219
  for (let i = 0; i < args.length; i++) {
206
220
  const arg = args[i];
207
221
  const next = args[i + 1];
208
222
 
209
- switch (arg) {
210
- case '--module':
211
- case '-m':
212
- opts.module = next;
213
- i++;
214
- break;
223
+ // First non-flag argument is the project name
224
+ if (!arg.startsWith('-') && !opts.name) {
225
+ opts.name = arg;
226
+ continue;
227
+ }
215
228
 
216
- case '--presets':
217
- case '-p':
218
- opts.presets = next?.split(',').map((p) => p.trim()).filter(Boolean) || [];
229
+ switch (arg) {
230
+ case '--name':
231
+ case '-n':
232
+ opts.name = next;
219
233
  i++;
220
234
  break;
221
235
 
222
- case '--parent-field':
223
- opts.parentField = next;
224
- i++;
236
+ case '--mongokit':
237
+ opts.adapter = 'mongokit';
225
238
  break;
226
239
 
227
- case '--output':
228
- case '-o':
229
- opts.outputDir = next;
230
- i++;
240
+ case '--custom':
241
+ opts.adapter = 'custom';
231
242
  break;
232
243
 
233
- case '--no-tests':
234
- opts.withTests = false;
244
+ case '--multi-tenant':
245
+ case '--multi':
246
+ opts.tenant = 'multi';
235
247
  break;
236
248
 
237
- case '--dry-run':
238
- opts.dryRun = true;
249
+ case '--single-tenant':
250
+ case '--single':
251
+ opts.tenant = 'single';
239
252
  break;
240
253
 
241
- case '--force':
242
- case '-f':
243
- opts.force = true;
254
+ case '--ts':
255
+ case '--typescript':
256
+ opts.typescript = true;
244
257
  break;
245
258
 
246
259
  case '--js':
@@ -248,9 +261,13 @@ function parseGenerateOptions(args) {
248
261
  opts.typescript = false;
249
262
  break;
250
263
 
251
- case '--ts':
252
- case '--typescript':
253
- opts.typescript = true;
264
+ case '--skip-install':
265
+ opts.skipInstall = true;
266
+ break;
267
+
268
+ case '--force':
269
+ case '-f':
270
+ opts.force = true;
254
271
  break;
255
272
  }
256
273
  }
@@ -264,15 +281,14 @@ function parseGenerateOptions(args) {
264
281
 
265
282
  function printHelp() {
266
283
  console.log(`
267
- ╔═══════════════════════════════════════════════════════════════╗
268
- ║ 🔥 Arc CLI v${VERSION} ║
269
- ║ Resource-Oriented Backend Framework ║
270
- ╚═══════════════════════════════════════════════════════════════╝
284
+ Arc CLI v${VERSION}
285
+ Resource-Oriented Backend Framework
271
286
 
272
287
  USAGE
273
288
  arc <command> [options]
274
289
 
275
290
  COMMANDS
291
+ init, new Initialize a new Arc project
276
292
  generate, g Generate resources, controllers, or models
277
293
  introspect, i Show all registered resources
278
294
  docs, d Export OpenAPI specification
@@ -283,56 +299,55 @@ GLOBAL OPTIONS
283
299
  --version, -v Show version
284
300
  --help, -h Show this help
285
301
 
302
+ INIT OPTIONS
303
+ --mongokit Use MongoKit adapter (default, recommended)
304
+ --custom Use custom adapter (empty template)
305
+ --multi-tenant, --multi Multi-tenant mode (adds org scoping)
306
+ --single-tenant, --single Single-tenant mode (default)
307
+ --ts, --typescript Generate TypeScript (default)
308
+ --js, --javascript Generate JavaScript
309
+ --force, -f Overwrite existing directory
310
+ --skip-install Skip npm install after scaffolding
311
+
286
312
  GENERATE SUBCOMMANDS
287
- resource, r Generate full resource (model, repo, controller, routes)
288
- controller, c Generate controller only
289
- model, m Generate model only
290
-
291
- GENERATE OPTIONS
292
- --module, -m <name> Parent module (e.g., catalog, sales)
293
- --presets, -p <list> Comma-separated presets:
294
- softDelete - Soft delete with restore
295
- • slugLookup - GET by slug endpoint
296
- • ownedByUser - User ownership checks
297
- • multiTenant - Organization scoping
298
- • tree - Hierarchical data support
299
- • audited - Audit logging
300
- --parent-field <name> Custom parent field for tree preset
301
- --output, -o <path> Output directory (default: cwd)
302
- --no-tests Skip test file generation
303
- --dry-run Preview without creating files
304
- --force, -f Overwrite existing files
305
- --js, --javascript Generate JavaScript (default: TypeScript)
313
+ resource, r Generate full resource (model, repo, controller, schemas, resource)
314
+ controller, c Generate controller only
315
+ model, m Generate model only
316
+ repository, repo Generate repository only
317
+ schemas, s Generate schemas only
318
+
319
+ GENERATE NOTES
320
+ - Auto-detects TypeScript/JavaScript from tsconfig.json
321
+ - Files are created in src/resources/<name>/ directory
322
+ - Uses prefixed filenames: <name>.model.ts, <name>.repository.ts, etc.
306
323
 
307
324
  EXAMPLES
308
- # Generate a product resource in catalog module
309
- arc generate resource product --module catalog
325
+ # Initialize a new project (interactive prompts)
326
+ arc init my-api
310
327
 
311
- # Generate with presets (shorthand)
312
- arc g r invoice -m finance -p softDelete,multiTenant
328
+ # Initialize with all options (non-interactive)
329
+ arc init my-api --mongokit --single --ts
313
330
 
314
- # Generate controller only
315
- arc g controller auth
331
+ # Initialize a JavaScript single-tenant app
332
+ arc init my-api --mongokit --single --js
316
333
 
317
- # Preview what would be generated
318
- arc g r order --dry-run
334
+ # Generate a product resource
335
+ arc generate resource product
319
336
 
320
- # Export OpenAPI spec (load resources first)
321
- arc docs ./docs/openapi.json --entry ./index.js
337
+ # Shorthand for generating a resource
338
+ arc g r invoice
339
+
340
+ # Generate only a controller
341
+ arc g controller auth
322
342
 
323
- # Show registered resources (load resources first)
324
- arc introspect --entry ./index.js
343
+ # Generate only a model
344
+ arc g model order
325
345
 
326
- # Quick introspect (if resources already loaded)
327
- arc introspect
346
+ # Export OpenAPI spec (load resources first)
347
+ arc docs ./docs/openapi.json --entry ./dist/index.js
328
348
 
329
- PRESETS EXPLAINED
330
- softDelete Adds: deletedAt field, GET /deleted, POST /:id/restore
331
- slugLookup Adds: slug field, GET /slug/:slug endpoint
332
- ownedByUser Adds: createdBy field, ownership validation
333
- multiTenant Adds: organizationId field, org scoping middleware
334
- tree Adds: parent field, GET /tree, GET /:id/children
335
- audited Adds: audit log entries for all mutations
349
+ # Show registered resources
350
+ arc introspect --entry ./dist/index.js
336
351
 
337
352
  MORE INFO
338
353
  Documentation: https://github.com/classytic/arc
@@ -1,5 +1,5 @@
1
- import { D as DataAdapter, f as CrudRepository, i as RepositoryLike, p as SchemaMetadata, g as RouteSchemaOptions, af as OpenApiSchemas, h as QueryParserInterface, ae as ParsedQuery, V as ValidationResult } from '../index-DkAW8BXh.js';
2
- export { ag as AdapterFactory, F as FieldMetadata, q as RelationMetadata } from '../index-DkAW8BXh.js';
1
+ import { D as DataAdapter, y as CrudRepository, o as RepositoryLike, m as SchemaMetadata, f as RouteSchemaOptions, af as OpenApiSchemas, Q as QueryParserInterface, ae as ParsedQuery, V as ValidationResult } from '../index-WBEvhmWM.js';
2
+ export { ag as AdapterFactory, F as FieldMetadata, n as RelationMetadata } from '../index-WBEvhmWM.js';
3
3
  import { Model } from 'mongoose';
4
4
  import 'fastify';
5
5
  import '../types-B99TBmFV.js';
@@ -1,5 +1,5 @@
1
1
  import { FastifyPluginAsync, FastifyInstance, FastifyRequest } from 'fastify';
2
- import { H as HookSystem, b as ResourceRegistry } from './index-DkAW8BXh.js';
2
+ import { H as HookSystem, b as ResourceRegistry } from './index-WBEvhmWM.js';
3
3
 
4
4
  /**
5
5
  * Request ID Plugin
@@ -1,5 +1,5 @@
1
1
  import { FastifyPluginAsync } from 'fastify';
2
- import { A as AuthHelpers, a as AuthPluginOptions } from '../index-DkAW8BXh.js';
2
+ import { A as AuthHelpers, a as AuthPluginOptions } from '../index-WBEvhmWM.js';
3
3
  import 'mongoose';
4
4
  import '../types-B99TBmFV.js';
5
5
 
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Arc CLI - Generate Command
3
+ *
4
+ * Scaffolds resources with consistent naming:
5
+ * - src/resources/product/product.model.ts
6
+ * - src/resources/product/product.repository.ts
7
+ * - src/resources/product/product.resource.ts
8
+ * - src/resources/product/product.controller.ts
9
+ * - src/resources/product/product.schemas.ts
10
+ */
11
+ /**
12
+ * Generate command handler
13
+ */
14
+ declare function generate(type: string | undefined, args: string[]): Promise<void>;
15
+
16
+ export { generate as default, generate };