@objectifthunes/create-sandstone 0.1.0 → 1.0.0
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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +31 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add-adapter.d.ts +2 -0
- package/dist/commands/add-adapter.d.ts.map +1 -0
- package/dist/commands/add-adapter.js +683 -0
- package/dist/commands/add-adapter.js.map +1 -0
- package/dist/commands/generate-adapter.d.ts +2 -0
- package/dist/commands/generate-adapter.d.ts.map +1 -0
- package/dist/commands/generate-adapter.js +467 -0
- package/dist/commands/generate-adapter.js.map +1 -0
- package/dist/commands/generate-entity.d.ts +2 -0
- package/dist/commands/generate-entity.d.ts.map +1 -0
- package/dist/commands/generate-entity.js +210 -0
- package/dist/commands/generate-entity.js.map +1 -0
- package/dist/generator.d.ts +3 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +85 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -61
- package/dist/index.js.map +1 -0
- package/dist/presets.d.ts +45 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +105 -0
- package/dist/presets.js.map +1 -0
- package/dist/prompts.d.ts +3 -13
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +222 -49
- package/dist/prompts.js.map +1 -0
- package/dist/templates/claude-md.d.ts +3 -0
- package/dist/templates/claude-md.d.ts.map +1 -0
- package/dist/templates/claude-md.js +853 -0
- package/dist/templates/claude-md.js.map +1 -0
- package/dist/templates/docker-compose.d.ts +3 -0
- package/dist/templates/docker-compose.d.ts.map +1 -0
- package/dist/templates/docker-compose.js +75 -0
- package/dist/templates/docker-compose.js.map +1 -0
- package/dist/templates/env-example.d.ts +3 -0
- package/dist/templates/env-example.d.ts.map +1 -0
- package/dist/templates/env-example.js +137 -0
- package/dist/templates/env-example.js.map +1 -0
- package/dist/templates/gitignore.d.ts +2 -0
- package/dist/templates/gitignore.d.ts.map +1 -0
- package/dist/templates/gitignore.js +11 -0
- package/dist/templates/gitignore.js.map +1 -0
- package/dist/templates/infrastructure.d.ts +3 -0
- package/dist/templates/infrastructure.d.ts.map +1 -0
- package/dist/templates/infrastructure.js +647 -0
- package/dist/templates/infrastructure.js.map +1 -0
- package/dist/templates/main-express.d.ts +3 -0
- package/dist/templates/main-express.d.ts.map +1 -0
- package/dist/templates/main-express.js +80 -0
- package/dist/templates/main-express.js.map +1 -0
- package/dist/templates/main-fastify.d.ts +3 -0
- package/dist/templates/main-fastify.d.ts.map +1 -0
- package/dist/templates/main-fastify.js +73 -0
- package/dist/templates/main-fastify.js.map +1 -0
- package/dist/templates/main-hono.d.ts +3 -0
- package/dist/templates/main-hono.d.ts.map +1 -0
- package/dist/templates/main-hono.js +83 -0
- package/dist/templates/main-hono.js.map +1 -0
- package/dist/templates/migrate-script.d.ts +2 -0
- package/dist/templates/migrate-script.d.ts.map +1 -0
- package/dist/templates/migrate-script.js +18 -0
- package/dist/templates/migrate-script.js.map +1 -0
- package/dist/templates/migration.d.ts +2 -0
- package/dist/templates/migration.d.ts.map +1 -0
- package/dist/templates/migration.js +17 -0
- package/dist/templates/migration.js.map +1 -0
- package/dist/templates/package-json.d.ts +3 -0
- package/dist/templates/package-json.d.ts.map +1 -0
- package/dist/templates/package-json.js +149 -0
- package/dist/templates/package-json.js.map +1 -0
- package/dist/templates/schema.d.ts +3 -0
- package/dist/templates/schema.d.ts.map +1 -0
- package/dist/templates/schema.js +108 -0
- package/dist/templates/schema.js.map +1 -0
- package/dist/templates/test-setup.d.ts +3 -0
- package/dist/templates/test-setup.d.ts.map +1 -0
- package/dist/templates/test-setup.js +12 -0
- package/dist/templates/test-setup.js.map +1 -0
- package/dist/templates/tsconfig.d.ts +2 -0
- package/dist/templates/tsconfig.d.ts.map +1 -0
- package/dist/templates/tsconfig.js +21 -0
- package/dist/templates/tsconfig.js.map +1 -0
- package/package.json +16 -9
- package/dist/generators.d.ts +0 -7
- package/dist/generators.js +0 -328
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { writeFile, mkdir, readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
const TS_TO_SQL = {
|
|
5
|
+
string: 'TEXT',
|
|
6
|
+
number: 'INTEGER',
|
|
7
|
+
boolean: 'BOOLEAN',
|
|
8
|
+
Date: 'TIMESTAMPTZ',
|
|
9
|
+
uuid: 'UUID',
|
|
10
|
+
};
|
|
11
|
+
const TS_TO_GRAPHQL = {
|
|
12
|
+
string: 'GraphQLString',
|
|
13
|
+
number: 'GraphQLInt',
|
|
14
|
+
boolean: 'GraphQLBoolean',
|
|
15
|
+
Date: 'DateTimeScalar',
|
|
16
|
+
uuid: 'UUIDScalar',
|
|
17
|
+
};
|
|
18
|
+
function pascalToSnake(name) {
|
|
19
|
+
return name
|
|
20
|
+
.replace(/([A-Z])/g, (match, letter, offset) => offset > 0 ? `_${letter.toLowerCase()}` : letter.toLowerCase())
|
|
21
|
+
.replace(/_{2,}/g, '_');
|
|
22
|
+
}
|
|
23
|
+
const SAFE_IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
24
|
+
function assertSafeIdentifier(value, label) {
|
|
25
|
+
if (!SAFE_IDENTIFIER.test(value)) {
|
|
26
|
+
throw new Error(`Invalid ${label}: "${value}". Must match /^[a-zA-Z_][a-zA-Z0-9_]*$/ (letters, digits, underscores only, cannot start with a digit).`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function parseFields(fieldsStr) {
|
|
30
|
+
return fieldsStr
|
|
31
|
+
.split(',')
|
|
32
|
+
.map((f) => f.trim())
|
|
33
|
+
.filter((f) => f.length > 0)
|
|
34
|
+
.map((f) => {
|
|
35
|
+
const parts = f.split(':').map((s) => s.trim());
|
|
36
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
37
|
+
throw new Error(`Invalid field definition: "${f}". Expected format: "name:type" (exactly one colon).`);
|
|
38
|
+
}
|
|
39
|
+
const name = parts[0];
|
|
40
|
+
const rawType = parts[1];
|
|
41
|
+
assertSafeIdentifier(name, 'field name');
|
|
42
|
+
const nullable = rawType.endsWith('?');
|
|
43
|
+
const type = nullable ? rawType.slice(0, -1) : rawType;
|
|
44
|
+
return { name, type, nullable };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function parseArgs(args) {
|
|
48
|
+
let name = null;
|
|
49
|
+
let fieldsStr = null;
|
|
50
|
+
for (let i = 0; i < args.length; i++) {
|
|
51
|
+
const arg = args[i];
|
|
52
|
+
if (arg === '--fields' || arg === '-f') {
|
|
53
|
+
fieldsStr = args[++i] ?? null;
|
|
54
|
+
}
|
|
55
|
+
else if (arg.startsWith('--fields=')) {
|
|
56
|
+
fieldsStr = arg.split('=').slice(1).join('=');
|
|
57
|
+
}
|
|
58
|
+
else if (!arg.startsWith('-')) {
|
|
59
|
+
name = arg;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (!name) {
|
|
63
|
+
console.error('Error: Entity name is required.');
|
|
64
|
+
console.error('Usage: sandstone generate entity <Name> --fields "field:type, ..."');
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
if (!fieldsStr) {
|
|
68
|
+
console.error('Error: --fields is required.');
|
|
69
|
+
console.error('Usage: sandstone generate entity <Name> --fields "title:string, published:boolean"');
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
return { name, fields: parseFields(fieldsStr) };
|
|
73
|
+
}
|
|
74
|
+
async function detectNextMigrationNumber(migrationsDir) {
|
|
75
|
+
if (!existsSync(migrationsDir)) {
|
|
76
|
+
return '001';
|
|
77
|
+
}
|
|
78
|
+
const entries = await readdir(migrationsDir);
|
|
79
|
+
const numbers = entries
|
|
80
|
+
.map((e) => {
|
|
81
|
+
const match = e.match(/^(\d+)/);
|
|
82
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
83
|
+
})
|
|
84
|
+
.filter((n) => n > 0);
|
|
85
|
+
if (numbers.length === 0)
|
|
86
|
+
return '001';
|
|
87
|
+
const next = Math.max(...numbers) + 1;
|
|
88
|
+
return String(next).padStart(3, '0');
|
|
89
|
+
}
|
|
90
|
+
function generateUpMigration(tableName, fields) {
|
|
91
|
+
const columns = [
|
|
92
|
+
' id UUID PRIMARY KEY DEFAULT gen_random_uuid()',
|
|
93
|
+
...fields.map((f) => {
|
|
94
|
+
const sqlType = TS_TO_SQL[f.type] ?? 'TEXT';
|
|
95
|
+
const nullable = f.nullable ? '' : ' NOT NULL';
|
|
96
|
+
return ` ${f.name} ${sqlType}${nullable}`;
|
|
97
|
+
}),
|
|
98
|
+
' created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()',
|
|
99
|
+
' updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()',
|
|
100
|
+
];
|
|
101
|
+
return `CREATE TABLE ${tableName} (\n${columns.join(',\n')}\n);\n`;
|
|
102
|
+
}
|
|
103
|
+
function generateDownMigration(tableName) {
|
|
104
|
+
return `DROP TABLE IF EXISTS ${tableName};\n`;
|
|
105
|
+
}
|
|
106
|
+
function generateTypeScriptModule(entityName, tableName, fields) {
|
|
107
|
+
const tsFields = [
|
|
108
|
+
' id: string;',
|
|
109
|
+
...fields.map((f) => {
|
|
110
|
+
const tsType = f.type === 'uuid' ? 'string' : f.type;
|
|
111
|
+
const optional = f.nullable ? '?' : '';
|
|
112
|
+
return ` ${f.name}${optional}: ${tsType};`;
|
|
113
|
+
}),
|
|
114
|
+
' created_at: Date;',
|
|
115
|
+
' updated_at: Date;',
|
|
116
|
+
];
|
|
117
|
+
return `import { createRepository } from '@objectifthunes/sandstone-sdk';
|
|
118
|
+
import type { Repository } from '@objectifthunes/sandstone-sdk';
|
|
119
|
+
|
|
120
|
+
export interface ${entityName} {
|
|
121
|
+
${tsFields.join('\n')}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const ${entityName.charAt(0).toLowerCase() + entityName.slice(1)}Repo: Repository<${entityName}> = createRepository<${entityName}>('${tableName}', {
|
|
125
|
+
primaryKey: 'id',
|
|
126
|
+
softDelete: false,
|
|
127
|
+
});
|
|
128
|
+
`;
|
|
129
|
+
}
|
|
130
|
+
function generateGraphQLSnippet(entityName, fields) {
|
|
131
|
+
const graphqlImports = new Set();
|
|
132
|
+
graphqlImports.add('GraphQLObjectType');
|
|
133
|
+
graphqlImports.add('GraphQLNonNull');
|
|
134
|
+
graphqlImports.add('GraphQLString');
|
|
135
|
+
const fieldEntries = [
|
|
136
|
+
` id: { type: new GraphQLNonNull(UUIDScalar) },`,
|
|
137
|
+
];
|
|
138
|
+
for (const f of fields) {
|
|
139
|
+
const gqlType = TS_TO_GRAPHQL[f.type] ?? 'GraphQLString';
|
|
140
|
+
graphqlImports.add(gqlType);
|
|
141
|
+
const wrapped = f.nullable ? gqlType : `new GraphQLNonNull(${gqlType})`;
|
|
142
|
+
fieldEntries.push(` ${f.name}: { type: ${wrapped} },`);
|
|
143
|
+
}
|
|
144
|
+
graphqlImports.add('DateTimeScalar');
|
|
145
|
+
fieldEntries.push(` created_at: { type: new GraphQLNonNull(DateTimeScalar) },`);
|
|
146
|
+
fieldEntries.push(` updated_at: { type: new GraphQLNonNull(DateTimeScalar) },`);
|
|
147
|
+
// Separate standard GraphQL types from Sandstone scalars
|
|
148
|
+
const standardTypes = [
|
|
149
|
+
'GraphQLObjectType',
|
|
150
|
+
'GraphQLNonNull',
|
|
151
|
+
'GraphQLString',
|
|
152
|
+
'GraphQLInt',
|
|
153
|
+
'GraphQLBoolean',
|
|
154
|
+
].filter((t) => graphqlImports.has(t));
|
|
155
|
+
const sandstoneScalars = ['DateTimeScalar', 'UUIDScalar', 'EmailScalar'].filter((t) => graphqlImports.has(t));
|
|
156
|
+
const lines = [];
|
|
157
|
+
lines.push(`import { ${standardTypes.join(', ')} } from 'graphql';`);
|
|
158
|
+
if (sandstoneScalars.length > 0) {
|
|
159
|
+
lines.push(`import { ${sandstoneScalars.join(', ')} } from '@objectifthunes/sandstone-sdk';`);
|
|
160
|
+
}
|
|
161
|
+
lines.push('');
|
|
162
|
+
lines.push(`export const ${entityName}Type = new GraphQLObjectType({`);
|
|
163
|
+
lines.push(` name: '${entityName}',`);
|
|
164
|
+
lines.push(` fields: () => ({`);
|
|
165
|
+
lines.push(fieldEntries.join('\n'));
|
|
166
|
+
lines.push(` }),`);
|
|
167
|
+
lines.push(`});`);
|
|
168
|
+
return lines.join('\n');
|
|
169
|
+
}
|
|
170
|
+
export async function generateEntity(args) {
|
|
171
|
+
const { name: entityName, fields } = parseArgs(args);
|
|
172
|
+
const snakeName = pascalToSnake(entityName);
|
|
173
|
+
const tableName = `${snakeName}s`;
|
|
174
|
+
assertSafeIdentifier(tableName, 'table name');
|
|
175
|
+
const cwd = process.cwd();
|
|
176
|
+
const migrationsDir = join(cwd, 'migrations');
|
|
177
|
+
const srcDir = join(cwd, 'src');
|
|
178
|
+
// Detect next migration number
|
|
179
|
+
const migrationNum = await detectNextMigrationNumber(migrationsDir);
|
|
180
|
+
// File paths
|
|
181
|
+
const upPath = join(migrationsDir, `${migrationNum}_create_${tableName}.up.sql`);
|
|
182
|
+
const downPath = join(migrationsDir, `${migrationNum}_create_${tableName}.down.sql`);
|
|
183
|
+
const modulePath = join(srcDir, `${snakeName}.ts`);
|
|
184
|
+
// Generate content
|
|
185
|
+
const upSql = generateUpMigration(tableName, fields);
|
|
186
|
+
const downSql = generateDownMigration(tableName);
|
|
187
|
+
const tsModule = generateTypeScriptModule(entityName, tableName, fields);
|
|
188
|
+
const graphqlSnippet = generateGraphQLSnippet(entityName, fields);
|
|
189
|
+
// Write files
|
|
190
|
+
await mkdir(migrationsDir, { recursive: true });
|
|
191
|
+
await mkdir(srcDir, { recursive: true });
|
|
192
|
+
await writeFile(upPath, upSql, 'utf-8');
|
|
193
|
+
await writeFile(downPath, downSql, 'utf-8');
|
|
194
|
+
await writeFile(modulePath, tsModule, 'utf-8');
|
|
195
|
+
// Report
|
|
196
|
+
console.log(`\n Generated entity: ${entityName}\n`);
|
|
197
|
+
console.log(` Files created:`);
|
|
198
|
+
console.log(` migrations/${migrationNum}_create_${tableName}.up.sql`);
|
|
199
|
+
console.log(` migrations/${migrationNum}_create_${tableName}.down.sql`);
|
|
200
|
+
console.log(` src/${snakeName}.ts`);
|
|
201
|
+
console.log();
|
|
202
|
+
console.log(` GraphQL type snippet (paste into your schema):`);
|
|
203
|
+
console.log();
|
|
204
|
+
console.log(graphqlSnippet
|
|
205
|
+
.split('\n')
|
|
206
|
+
.map((line) => ` ${line}`)
|
|
207
|
+
.join('\n'));
|
|
208
|
+
console.log();
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=generate-entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-entity.js","sourceRoot":"","sources":["../../src/commands/generate-entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAqBlD,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CA0EnB"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { packageJsonTemplate } from './templates/package-json.js';
|
|
4
|
+
import { tsconfigTemplate } from './templates/tsconfig.js';
|
|
5
|
+
import { gitignoreTemplate } from './templates/gitignore.js';
|
|
6
|
+
import { envExampleTemplate } from './templates/env-example.js';
|
|
7
|
+
import { dockerComposeTemplate } from './templates/docker-compose.js';
|
|
8
|
+
import { infrastructureTemplate } from './templates/infrastructure.js';
|
|
9
|
+
import { mainExpressTemplate } from './templates/main-express.js';
|
|
10
|
+
import { mainHonoTemplate } from './templates/main-hono.js';
|
|
11
|
+
import { mainFastifyTemplate } from './templates/main-fastify.js';
|
|
12
|
+
import { schemaTemplate } from './templates/schema.js';
|
|
13
|
+
import { testSetupTemplate } from './templates/test-setup.js';
|
|
14
|
+
import { migrationTemplate } from './templates/migration.js';
|
|
15
|
+
import { migrateScriptTemplate } from './templates/migrate-script.js';
|
|
16
|
+
import { claudeMdTemplate } from './templates/claude-md.js';
|
|
17
|
+
export async function generateProject(targetDir, config) {
|
|
18
|
+
const files = [];
|
|
19
|
+
// Root config files
|
|
20
|
+
files.push({ path: 'package.json', content: packageJsonTemplate(config) });
|
|
21
|
+
files.push({ path: 'tsconfig.json', content: tsconfigTemplate() });
|
|
22
|
+
files.push({ path: '.gitignore', content: gitignoreTemplate() });
|
|
23
|
+
files.push({ path: '.env.example', content: envExampleTemplate(config) });
|
|
24
|
+
if (!config.devMode) {
|
|
25
|
+
files.push({
|
|
26
|
+
path: 'docker-compose.yml',
|
|
27
|
+
content: dockerComposeTemplate(config),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
files.push({ path: 'CLAUDE.md', content: claudeMdTemplate(config) });
|
|
31
|
+
// Source files
|
|
32
|
+
files.push({
|
|
33
|
+
path: 'src/infrastructure.ts',
|
|
34
|
+
content: infrastructureTemplate(config),
|
|
35
|
+
});
|
|
36
|
+
if (config.framework === 'express') {
|
|
37
|
+
files.push({
|
|
38
|
+
path: 'src/main.ts',
|
|
39
|
+
content: mainExpressTemplate(config),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else if (config.framework === 'fastify') {
|
|
43
|
+
files.push({
|
|
44
|
+
path: 'src/main.ts',
|
|
45
|
+
content: mainFastifyTemplate(config),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
files.push({
|
|
50
|
+
path: 'src/main.ts',
|
|
51
|
+
content: mainHonoTemplate(config),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (config.graphql) {
|
|
55
|
+
files.push({ path: 'src/schema.ts', content: schemaTemplate(config) });
|
|
56
|
+
}
|
|
57
|
+
// Migrations
|
|
58
|
+
files.push({
|
|
59
|
+
path: 'migrations/001_notes.up.sql',
|
|
60
|
+
content: migrationTemplate(),
|
|
61
|
+
});
|
|
62
|
+
// Scripts
|
|
63
|
+
files.push({
|
|
64
|
+
path: 'scripts/migrate.ts',
|
|
65
|
+
content: migrateScriptTemplate(),
|
|
66
|
+
});
|
|
67
|
+
// Tests
|
|
68
|
+
if (config.tests) {
|
|
69
|
+
files.push({
|
|
70
|
+
path: 'tests/setup.ts',
|
|
71
|
+
content: testSetupTemplate(config),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// Ensure all directories exist, then write files
|
|
75
|
+
const createdFiles = [];
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
const fullPath = join(targetDir, file.path);
|
|
78
|
+
const dir = join(fullPath, '..');
|
|
79
|
+
await mkdir(dir, { recursive: true });
|
|
80
|
+
await writeFile(fullPath, file.content, 'utf-8');
|
|
81
|
+
createdFiles.push(file.path);
|
|
82
|
+
}
|
|
83
|
+
return createdFiles;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -1,70 +1,116 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { mkdir } from 'node:fs/promises';
|
|
4
5
|
import { runPrompts } from './prompts.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import { generateProject } from './generator.js';
|
|
7
|
+
import { PRESETS, isPresetName } from './presets.js';
|
|
8
|
+
function printHelp() {
|
|
9
|
+
console.log(`
|
|
10
|
+
Usage: npx @objectifthunes/create-sandstone [project-name] [options]
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
--yes, -y Non-interactive mode (use defaults or preset)
|
|
14
|
+
--template, -t Use a preset template (saas, api, minimal, prototype)
|
|
15
|
+
--help, -h Show this help message
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
npx @objectifthunes/create-sandstone my-backend
|
|
19
|
+
npx @objectifthunes/create-sandstone my-api --yes --template api
|
|
20
|
+
npx @objectifthunes/create-sandstone my-saas -y -t saas
|
|
21
|
+
npx @objectifthunes/create-sandstone my-app -y -t prototype
|
|
22
|
+
`);
|
|
23
|
+
}
|
|
24
|
+
function parseArgs(args) {
|
|
25
|
+
let name = null;
|
|
26
|
+
let yes = false;
|
|
27
|
+
let template = null;
|
|
28
|
+
let help = false;
|
|
29
|
+
for (let i = 0; i < args.length; i++) {
|
|
30
|
+
const arg = args[i];
|
|
31
|
+
if (arg === '--yes' || arg === '-y') {
|
|
32
|
+
yes = true;
|
|
33
|
+
}
|
|
34
|
+
else if (arg === '--help' || arg === '-h') {
|
|
35
|
+
help = true;
|
|
36
|
+
}
|
|
37
|
+
else if (arg === '--template' || arg === '-t') {
|
|
38
|
+
template = args[++i] ?? null;
|
|
39
|
+
}
|
|
40
|
+
else if (arg.startsWith('--template=')) {
|
|
41
|
+
template = arg.split('=')[1] ?? null;
|
|
42
|
+
}
|
|
43
|
+
else if (!arg.startsWith('-')) {
|
|
44
|
+
name = arg;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { name, yes, template, help };
|
|
10
48
|
}
|
|
11
49
|
async function main() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
await mkdir(dir, { recursive: true });
|
|
17
|
-
await mkdir(join(dir, 'src'), { recursive: true });
|
|
18
|
-
await mkdir(join(dir, 'migrations'), { recursive: true });
|
|
19
|
-
await mkdir(join(dir, 'tests', 'unit'), { recursive: true });
|
|
20
|
-
await write(dir, 'package.json', generatePackageJson(config));
|
|
21
|
-
await write(dir, 'tsconfig.json', generateTsConfig(config));
|
|
22
|
-
await write(dir, '.env.example', generateEnvExample(config));
|
|
23
|
-
await write(dir, '.gitignore', generateGitignore());
|
|
24
|
-
await write(dir, 'src/main.ts', generateMainTs(config));
|
|
25
|
-
if (config.docker) {
|
|
26
|
-
await write(dir, 'docker-compose.yml', generateDockerCompose());
|
|
50
|
+
const args = parseArgs(process.argv.slice(2));
|
|
51
|
+
if (args.help) {
|
|
52
|
+
printHelp();
|
|
53
|
+
process.exit(0);
|
|
27
54
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
55
|
+
const projectName = args.name ?? 'my-sandstone-app';
|
|
56
|
+
const targetDir = resolve(process.cwd(), projectName);
|
|
57
|
+
console.log();
|
|
58
|
+
console.log(` Creating a new Sandstone project in ${targetDir}`);
|
|
59
|
+
console.log();
|
|
60
|
+
let config;
|
|
61
|
+
if (args.yes) {
|
|
62
|
+
// Non-interactive mode
|
|
63
|
+
if (args.template) {
|
|
64
|
+
if (!isPresetName(args.template)) {
|
|
65
|
+
console.error(` Error: Unknown template "${args.template}". Available: saas, api, minimal`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
config = { name: projectName, ...PRESETS[args.template] };
|
|
69
|
+
console.log(` Using preset: ${args.template}`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
config = { name: projectName, ...PRESETS.minimal };
|
|
73
|
+
console.log(` Using default preset: minimal`);
|
|
74
|
+
}
|
|
75
|
+
console.log();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Interactive mode
|
|
79
|
+
const result = await runPrompts(projectName);
|
|
80
|
+
if (!result) {
|
|
81
|
+
console.log(' Cancelled.');
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
config = result;
|
|
85
|
+
console.log();
|
|
86
|
+
}
|
|
87
|
+
// Create target directory
|
|
88
|
+
if (existsSync(targetDir)) {
|
|
89
|
+
console.error(` Error: Directory "${projectName}" already exists.`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
await mkdir(targetDir, { recursive: true });
|
|
93
|
+
// Generate project files
|
|
94
|
+
const files = await generateProject(targetDir, config);
|
|
95
|
+
// Print summary
|
|
96
|
+
console.log(` Scaffolded ${files.length} files:`);
|
|
97
|
+
console.log();
|
|
98
|
+
for (const file of files) {
|
|
99
|
+
console.log(` ${file}`);
|
|
100
|
+
}
|
|
101
|
+
console.log();
|
|
102
|
+
console.log(` Next steps:`);
|
|
103
|
+
console.log();
|
|
104
|
+
console.log(` cd ${projectName}`);
|
|
105
|
+
console.log(` cp .env.example .env`);
|
|
106
|
+
console.log(` npm install`);
|
|
107
|
+
console.log(` docker compose up -d`);
|
|
108
|
+
console.log(` npm run db:migrate`);
|
|
109
|
+
console.log(` npm run dev`);
|
|
110
|
+
console.log();
|
|
66
111
|
}
|
|
67
112
|
main().catch((err) => {
|
|
68
|
-
console.error(err);
|
|
113
|
+
console.error('Error:', err instanceof Error ? err.message : String(err));
|
|
69
114
|
process.exit(1);
|
|
70
115
|
});
|
|
116
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type Framework = 'express' | 'hono' | 'fastify';
|
|
2
|
+
export type Database = 'pg' | 'supabase';
|
|
3
|
+
export type AuthStrategy = 'otp' | 'password+otp' | 'oauth+otp' | 'all' | null;
|
|
4
|
+
export type OAuthProviderChoice = 'google' | 'github' | 'apple' | 'discord';
|
|
5
|
+
export type EmailProvider = 'resend' | 'nodemailer' | null;
|
|
6
|
+
export type PaymentProvider = 'stripe' | 'revenuecat' | 'paddle' | 'lemonsqueezy' | null;
|
|
7
|
+
export type StorageProvider = 's3' | 'r2' | 'local' | null;
|
|
8
|
+
export type CacheProvider = 'upstash' | 'redis' | 'memory' | null;
|
|
9
|
+
export type SmsProvider = 'twilio' | 'sns' | null;
|
|
10
|
+
export type PushProvider = 'fcm' | 'apns' | 'both' | null;
|
|
11
|
+
export type RealtimeProvider = 'socketio' | 'pusher' | 'ably' | null;
|
|
12
|
+
export type SearchProvider = 'meilisearch' | 'typesense' | 'pg-search' | null;
|
|
13
|
+
export type QueueProvider = 'bullmq' | 'pg-boss' | null;
|
|
14
|
+
export type FlagProvider = 'pg-flags' | 'env-flags' | 'launchdarkly' | null;
|
|
15
|
+
export type AuthzProvider = 'pg-authz' | 'casbin' | null;
|
|
16
|
+
export interface ProjectConfig {
|
|
17
|
+
name: string;
|
|
18
|
+
framework: Framework;
|
|
19
|
+
database: Database;
|
|
20
|
+
auth: AuthStrategy;
|
|
21
|
+
oauthProviders: OAuthProviderChoice[];
|
|
22
|
+
email: EmailProvider;
|
|
23
|
+
payments: PaymentProvider;
|
|
24
|
+
storage: StorageProvider;
|
|
25
|
+
cache: CacheProvider;
|
|
26
|
+
sms: SmsProvider;
|
|
27
|
+
push: PushProvider;
|
|
28
|
+
realtime: RealtimeProvider;
|
|
29
|
+
search: SearchProvider;
|
|
30
|
+
queue: QueueProvider;
|
|
31
|
+
scheduler: boolean;
|
|
32
|
+
flags: FlagProvider;
|
|
33
|
+
tracing: boolean;
|
|
34
|
+
audit: boolean;
|
|
35
|
+
authz: AuthzProvider;
|
|
36
|
+
graphql: boolean;
|
|
37
|
+
dashboard: boolean;
|
|
38
|
+
tests: boolean;
|
|
39
|
+
e2e: boolean;
|
|
40
|
+
devMode?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export type PresetName = 'saas' | 'api' | 'minimal' | 'prototype';
|
|
43
|
+
export declare const PRESETS: Record<PresetName, Omit<ProjectConfig, 'name'>>;
|
|
44
|
+
export declare function isPresetName(value: string): value is PresetName;
|
|
45
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,UAAU,CAAC;AACzC,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,cAAc,GAAG,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC;AAC/E,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,IAAI,CAAC;AAC3D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,YAAY,GAAG,QAAQ,GAAG,cAAc,GAAG,IAAI,CAAC;AACzF,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAC;AACrE,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,GAAG,IAAI,CAAC;AAC9E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC;AACxD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,IAAI,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,cAAc,EAAE,mBAAmB,EAAE,CAAC;IACtC,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,CAAC;AAElE,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAoGnE,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D"}
|