@jigx/sdk-tools 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/CHANGELOG.md +8 -0
- package/dist/builder/__tests__/build.test.d.ts +2 -0
- package/dist/builder/__tests__/build.test.d.ts.map +1 -0
- package/dist/builder/__tests__/build.test.js +88 -0
- package/dist/builder/__tests__/build.test.js.map +1 -0
- package/dist/builder/__tests__/extract-to-folder.test.d.ts +2 -0
- package/dist/builder/__tests__/extract-to-folder.test.d.ts.map +1 -0
- package/dist/builder/__tests__/extract-to-folder.test.js +198 -0
- package/dist/builder/__tests__/extract-to-folder.test.js.map +1 -0
- package/dist/builder/__tests__/fixtures/sample-application.d.ts +2 -0
- package/dist/builder/__tests__/fixtures/sample-application.d.ts.map +1 -0
- package/dist/builder/__tests__/fixtures/sample-application.js +56 -0
- package/dist/builder/__tests__/fixtures/sample-application.js.map +1 -0
- package/dist/builder/build.d.ts +12 -0
- package/dist/builder/build.d.ts.map +1 -0
- package/dist/builder/build.js +44 -0
- package/dist/builder/build.js.map +1 -0
- package/dist/builder/extract-to-folder.d.ts +11 -0
- package/dist/builder/extract-to-folder.d.ts.map +1 -0
- package/dist/builder/extract-to-folder.js +162 -0
- package/dist/builder/extract-to-folder.js.map +1 -0
- package/dist/builder/index.d.ts +3 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +2 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -0
- package/dist/creator/__tests__/create.test.d.ts +2 -0
- package/dist/creator/__tests__/create.test.d.ts.map +1 -0
- package/dist/creator/__tests__/create.test.js +66 -0
- package/dist/creator/__tests__/create.test.js.map +1 -0
- package/dist/creator/create.d.ts +33 -0
- package/dist/creator/create.d.ts.map +1 -0
- package/dist/creator/create.js +65 -0
- package/dist/creator/create.js.map +1 -0
- package/dist/creator/index.d.ts +3 -0
- package/dist/creator/index.d.ts.map +1 -0
- package/dist/creator/index.js +2 -0
- package/dist/creator/index.js.map +1 -0
- package/dist/deployer/__tests__/deploy-to-strata.test.d.ts +2 -0
- package/dist/deployer/__tests__/deploy-to-strata.test.d.ts.map +1 -0
- package/dist/deployer/__tests__/deploy-to-strata.test.js +174 -0
- package/dist/deployer/__tests__/deploy-to-strata.test.js.map +1 -0
- package/dist/deployer/__tests__/deploy.test.d.ts +2 -0
- package/dist/deployer/__tests__/deploy.test.d.ts.map +1 -0
- package/dist/deployer/__tests__/deploy.test.js +116 -0
- package/dist/deployer/__tests__/deploy.test.js.map +1 -0
- package/dist/deployer/deploy-to-strata.d.ts +29 -0
- package/dist/deployer/deploy-to-strata.d.ts.map +1 -0
- package/dist/deployer/deploy-to-strata.js +161 -0
- package/dist/deployer/deploy-to-strata.js.map +1 -0
- package/dist/deployer/deploy.d.ts +7 -0
- package/dist/deployer/deploy.d.ts.map +1 -0
- package/dist/deployer/deploy.js +15 -0
- package/dist/deployer/deploy.js.map +1 -0
- package/dist/deployer/index.d.ts +5 -0
- package/dist/deployer/index.d.ts.map +1 -0
- package/dist/deployer/index.js +3 -0
- package/dist/deployer/index.js.map +1 -0
- package/dist/env-loader/__tests__/load-env.test.d.ts +2 -0
- package/dist/env-loader/__tests__/load-env.test.d.ts.map +1 -0
- package/dist/env-loader/__tests__/load-env.test.js +46 -0
- package/dist/env-loader/__tests__/load-env.test.js.map +1 -0
- package/dist/env-loader/index.d.ts +3 -0
- package/dist/env-loader/index.d.ts.map +1 -0
- package/dist/env-loader/index.js +2 -0
- package/dist/env-loader/index.js.map +1 -0
- package/dist/env-loader/load-env.d.ts +12 -0
- package/dist/env-loader/load-env.d.ts.map +1 -0
- package/dist/env-loader/load-env.js +50 -0
- package/dist/env-loader/load-env.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +2 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/prompts.d.ts +11 -0
- package/dist/prompts/prompts.d.ts.map +1 -0
- package/dist/prompts/prompts.js +45 -0
- package/dist/prompts/prompts.js.map +1 -0
- package/dist/scaffolder/__tests__/scaffold.test.d.ts +2 -0
- package/dist/scaffolder/__tests__/scaffold.test.d.ts.map +1 -0
- package/dist/scaffolder/__tests__/scaffold.test.js +112 -0
- package/dist/scaffolder/__tests__/scaffold.test.js.map +1 -0
- package/dist/scaffolder/index.d.ts +4 -0
- package/dist/scaffolder/index.d.ts.map +1 -0
- package/dist/scaffolder/index.js +2 -0
- package/dist/scaffolder/index.js.map +1 -0
- package/dist/scaffolder/scaffold.d.ts +16 -0
- package/dist/scaffolder/scaffold.d.ts.map +1 -0
- package/dist/scaffolder/scaffold.js +45 -0
- package/dist/scaffolder/scaffold.js.map +1 -0
- package/dist/scaffolder/templates.d.ts +13 -0
- package/dist/scaffolder/templates.d.ts.map +1 -0
- package/dist/scaffolder/templates.js +124 -0
- package/dist/scaffolder/templates.js.map +1 -0
- package/dist/slug/__tests__/validate.test.d.ts +2 -0
- package/dist/slug/__tests__/validate.test.d.ts.map +1 -0
- package/dist/slug/__tests__/validate.test.js +51 -0
- package/dist/slug/__tests__/validate.test.js.map +1 -0
- package/dist/slug/index.d.ts +3 -0
- package/dist/slug/index.d.ts.map +1 -0
- package/dist/slug/index.js +2 -0
- package/dist/slug/index.js.map +1 -0
- package/dist/slug/validate.d.ts +11 -0
- package/dist/slug/validate.d.ts.map +1 -0
- package/dist/slug/validate.js +29 -0
- package/dist/slug/validate.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { cancel, isCancel, select, text } from '@clack/prompts';
|
|
2
|
+
import { slugifyTitle, validateApplicationName } from '../slug/index.js';
|
|
3
|
+
export class PromptCancelledError extends Error {
|
|
4
|
+
constructor() {
|
|
5
|
+
super('Application creation cancelled.');
|
|
6
|
+
this.name = 'PromptCancelledError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function ensureNotCancelled(value) {
|
|
10
|
+
if (isCancel(value)) {
|
|
11
|
+
cancel('Application creation cancelled.');
|
|
12
|
+
throw new PromptCancelledError();
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
export async function runCreatePrompts() {
|
|
17
|
+
const title = ensureNotCancelled(await text({
|
|
18
|
+
message: 'Application title',
|
|
19
|
+
placeholder: 'Customer Selection',
|
|
20
|
+
validate: (value) => {
|
|
21
|
+
if (!value || value.trim().length === 0)
|
|
22
|
+
return 'Application title is required.';
|
|
23
|
+
return undefined;
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
const trimmedTitle = title.trim();
|
|
27
|
+
const applicationName = ensureNotCancelled(await text({
|
|
28
|
+
message: 'Application name (slug)',
|
|
29
|
+
initialValue: slugifyTitle(trimmedTitle),
|
|
30
|
+
validate: (value) => {
|
|
31
|
+
const result = validateApplicationName(value);
|
|
32
|
+
return result.ok ? undefined : result.error;
|
|
33
|
+
},
|
|
34
|
+
}));
|
|
35
|
+
const type = ensureNotCancelled(await select({
|
|
36
|
+
message: 'Application type',
|
|
37
|
+
options: [
|
|
38
|
+
{ value: 'app', label: 'app — interactive Application' },
|
|
39
|
+
{ value: 'data', label: 'data — data-only Application' },
|
|
40
|
+
],
|
|
41
|
+
initialValue: 'app',
|
|
42
|
+
}));
|
|
43
|
+
return { title: trimmedTitle, applicationName, type };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/prompts/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE/D,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AASxE,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,cAAc;QACZ,KAAK,CAAC,iCAAiC,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IAAA,CACnC;CACF;AAED,SAAS,kBAAkB,CAAI,KAAiB,EAAK;IACnD,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,CAAC,iCAAiC,CAAC,CAAA;QACzC,MAAM,IAAI,oBAAoB,EAAE,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AAAA,CACb;AAQD,MAAM,CAAC,KAAK,UAAU,gBAAgB,GAAiC;IACrE,MAAM,KAAK,GAAG,kBAAkB,CAC9B,MAAM,IAAI,CAAC;QACT,OAAO,EAAE,mBAAmB;QAC5B,WAAW,EAAE,oBAAoB;QACjC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,gCAAgC,CAAA;YAChF,OAAO,SAAS,CAAA;QAAA,CACjB;KACF,CAAC,CACH,CAAA;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAEjC,MAAM,eAAe,GAAG,kBAAkB,CACxC,MAAM,IAAI,CAAC;QACT,OAAO,EAAE,yBAAyB;QAClC,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC;QACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAA;YAC7C,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAA;QAAA,CAC5C;KACF,CAAC,CACH,CAAA;IAED,MAAM,IAAI,GAAG,kBAAkB,CAC7B,MAAM,MAAM,CAAkB;QAC5B,OAAO,EAAE,kBAAkB;QAC3B,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iCAA+B,EAAE;YACxD,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gCAA8B,EAAE;SACzD;QACD,YAAY,EAAE,KAAK;KACpB,CAAC,CACH,CAAA;IAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,CAAA;AAAA,CACtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.test.d.ts","sourceRoot":"","sources":["../../../src/scaffolder/__tests__/scaffold.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
|
|
5
|
+
import { scaffold, ScaffoldError } from '../scaffold.js';
|
|
6
|
+
describe('Scaffolder.scaffold', () => {
|
|
7
|
+
let workdir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
workdir = undefined;
|
|
10
|
+
});
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
if (workdir)
|
|
13
|
+
await rm(workdir, { recursive: true, force: true });
|
|
14
|
+
});
|
|
15
|
+
test('writes the canonical file tree with prompt values substituted', async () => {
|
|
16
|
+
workdir = await mkdtemp(path.join(tmpdir(), 'jigx-scaffold-test-'));
|
|
17
|
+
const destinationPath = path.join(workdir, 'customer-selection');
|
|
18
|
+
const result = await scaffold({
|
|
19
|
+
title: 'Customer Selection',
|
|
20
|
+
applicationName: 'customer-selection',
|
|
21
|
+
type: 'app',
|
|
22
|
+
destinationPath,
|
|
23
|
+
});
|
|
24
|
+
expect(result.destinationPath).toBe(destinationPath);
|
|
25
|
+
expect(result.filesWritten.map((p) => path.relative(destinationPath, p)).sort()).toEqual([
|
|
26
|
+
'.env.example',
|
|
27
|
+
'.gitignore',
|
|
28
|
+
'README.md',
|
|
29
|
+
'package.json',
|
|
30
|
+
'src/app.ts',
|
|
31
|
+
'tsconfig.json',
|
|
32
|
+
].sort());
|
|
33
|
+
const pkg = JSON.parse(await readFile(path.join(destinationPath, 'package.json'), 'utf8'));
|
|
34
|
+
expect(pkg).toMatchObject({
|
|
35
|
+
name: 'customer-selection',
|
|
36
|
+
private: true,
|
|
37
|
+
type: 'module',
|
|
38
|
+
scripts: { build: 'jigx build', deploy: 'jigx deploy' },
|
|
39
|
+
dependencies: { '@jigx/core-sdk': expect.any(String) },
|
|
40
|
+
devDependencies: {
|
|
41
|
+
'@jigx/sdk-tools': expect.any(String),
|
|
42
|
+
tsx: expect.any(String),
|
|
43
|
+
typescript: expect.any(String),
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const gitignoreContent = await readFile(path.join(destinationPath, '.gitignore'), 'utf8');
|
|
47
|
+
expect(gitignoreContent).toContain('.env');
|
|
48
|
+
expect(gitignoreContent).toContain('node_modules/');
|
|
49
|
+
expect(gitignoreContent).toContain('build/');
|
|
50
|
+
const envExampleContent = await readFile(path.join(destinationPath, '.env.example'), 'utf8');
|
|
51
|
+
expect(envExampleContent).toContain('JIGX_API_KEY');
|
|
52
|
+
expect(envExampleContent).toContain('JIGX_ORGANIZATION_ID');
|
|
53
|
+
const readmeContent = await readFile(path.join(destinationPath, 'README.md'), 'utf8');
|
|
54
|
+
expect(readmeContent).toContain('Customer Selection');
|
|
55
|
+
expect(readmeContent).toContain('customer-selection');
|
|
56
|
+
expect(readmeContent).toContain('NPM_TOKEN');
|
|
57
|
+
expect(readmeContent).toContain('JIGX_API_KEY');
|
|
58
|
+
expect(readmeContent).toContain('JIGX_ORGANIZATION_ID');
|
|
59
|
+
expect(readmeContent).toContain('jigx build');
|
|
60
|
+
expect(readmeContent).toContain('jigx deploy');
|
|
61
|
+
const appTsContent = await readFile(path.join(destinationPath, 'src', 'app.ts'), 'utf8');
|
|
62
|
+
expect(appTsContent).toContain("name: 'customer-selection'");
|
|
63
|
+
expect(appTsContent).toContain('title: "Customer Selection"');
|
|
64
|
+
expect(appTsContent).toContain("type: 'app'");
|
|
65
|
+
expect(appTsContent).toContain('ApplicationBuilder');
|
|
66
|
+
expect(appTsContent).toContain('export const app');
|
|
67
|
+
expect(appTsContent).toContain("screenId: 'home'");
|
|
68
|
+
});
|
|
69
|
+
test('aborts when destination already exists', async () => {
|
|
70
|
+
workdir = await mkdtemp(path.join(tmpdir(), 'jigx-scaffold-test-'));
|
|
71
|
+
const destinationPath = path.join(workdir, 'taken');
|
|
72
|
+
await scaffold({
|
|
73
|
+
title: 'Taken',
|
|
74
|
+
applicationName: 'taken',
|
|
75
|
+
type: 'app',
|
|
76
|
+
destinationPath,
|
|
77
|
+
});
|
|
78
|
+
await expect(scaffold({
|
|
79
|
+
title: 'Taken Again',
|
|
80
|
+
applicationName: 'taken',
|
|
81
|
+
type: 'data',
|
|
82
|
+
destinationPath,
|
|
83
|
+
})).rejects.toBeInstanceOf(ScaffoldError);
|
|
84
|
+
});
|
|
85
|
+
test('embeds the data type in app.ts when type === "data"', async () => {
|
|
86
|
+
workdir = await mkdtemp(path.join(tmpdir(), 'jigx-scaffold-test-'));
|
|
87
|
+
const destinationPath = path.join(workdir, 'data-app');
|
|
88
|
+
await scaffold({
|
|
89
|
+
title: 'Data App',
|
|
90
|
+
applicationName: 'data-app',
|
|
91
|
+
type: 'data',
|
|
92
|
+
destinationPath,
|
|
93
|
+
});
|
|
94
|
+
const appTsContent = await readFile(path.join(destinationPath, 'src', 'app.ts'), 'utf8');
|
|
95
|
+
expect(appTsContent).toContain("type: 'data'");
|
|
96
|
+
});
|
|
97
|
+
test('safely escapes titles containing quotes, backslashes, and newlines in src/app.ts', async () => {
|
|
98
|
+
workdir = await mkdtemp(path.join(tmpdir(), 'jigx-scaffold-test-'));
|
|
99
|
+
const destinationPath = path.join(workdir, 'tricky');
|
|
100
|
+
const trickyTitle = 'Bob\'s "weird" \\back\nline';
|
|
101
|
+
await scaffold({
|
|
102
|
+
title: trickyTitle,
|
|
103
|
+
applicationName: 'bobs-app',
|
|
104
|
+
type: 'app',
|
|
105
|
+
destinationPath,
|
|
106
|
+
});
|
|
107
|
+
const appTsContent = await readFile(path.join(destinationPath, 'src', 'app.ts'), 'utf8');
|
|
108
|
+
expect(appTsContent).toContain(`title: ${JSON.stringify(trickyTitle)}`);
|
|
109
|
+
expect(appTsContent).toContain(`title: ${JSON.stringify(`Welcome to ${trickyTitle}`)}`);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=scaffold.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.test.js","sourceRoot":"","sources":["../../../src/scaffolder/__tests__/scaffold.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scaffolder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AACvD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACpE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scaffolder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ApplicationType } from './templates.js';
|
|
2
|
+
export interface ScaffoldOptions {
|
|
3
|
+
readonly title: string;
|
|
4
|
+
readonly applicationName: string;
|
|
5
|
+
readonly type: ApplicationType;
|
|
6
|
+
readonly destinationPath: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ScaffoldResult {
|
|
9
|
+
readonly destinationPath: string;
|
|
10
|
+
readonly filesWritten: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
export declare class ScaffoldError extends Error {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
export declare function scaffold(options: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
16
|
+
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/scaffolder/scaffold.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,eAAe,EAMrB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAE9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CACzC;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAqBD,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8BhF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { mkdir, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { appTs, envExample, gitignore, packageJson, readme, tsconfigJson, } from './templates.js';
|
|
4
|
+
export class ScaffoldError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'ScaffoldError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
async function exists(filePath) {
|
|
11
|
+
try {
|
|
12
|
+
await stat(filePath);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function scaffold(options) {
|
|
23
|
+
const { title, applicationName, type, destinationPath } = options;
|
|
24
|
+
if (await exists(destinationPath)) {
|
|
25
|
+
throw new ScaffoldError(`Destination already exists: ${destinationPath}. Choose a different Application name or remove the existing directory.`);
|
|
26
|
+
}
|
|
27
|
+
const inputs = { title, applicationName, type };
|
|
28
|
+
await mkdir(path.join(destinationPath, 'src'), { recursive: true });
|
|
29
|
+
const files = [
|
|
30
|
+
{ relPath: 'package.json', content: packageJson(inputs) },
|
|
31
|
+
{ relPath: 'tsconfig.json', content: tsconfigJson() },
|
|
32
|
+
{ relPath: '.gitignore', content: gitignore() },
|
|
33
|
+
{ relPath: '.env.example', content: envExample() },
|
|
34
|
+
{ relPath: 'README.md', content: readme(inputs) },
|
|
35
|
+
{ relPath: path.join('src', 'app.ts'), content: appTs(inputs) },
|
|
36
|
+
];
|
|
37
|
+
const filesWritten = [];
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
const absPath = path.join(destinationPath, file.relPath);
|
|
40
|
+
await writeFile(absPath, file.content, 'utf8');
|
|
41
|
+
filesWritten.push(absPath);
|
|
42
|
+
}
|
|
43
|
+
return { destinationPath, filesWritten };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/scaffolder/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EACL,KAAK,EAEL,UAAU,EACV,SAAS,EACT,WAAW,EACX,MAAM,EACN,YAAY,GACb,MAAM,gBAAgB,CAAA;AAevB,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe,EAAE;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAAA,CAC5B;CACF;AAED,KAAK,UAAU,MAAM,CAAC,QAAgB,EAAoB;IACxD,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzE,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AAAA,CACF;AASD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB,EAA2B;IAChF,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,OAAO,CAAA;IAEjE,IAAI,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,aAAa,CACrB,+BAA+B,eAAe,yEAAyE,CACxH,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,CAAA;IAE/C,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEnE,MAAM,KAAK,GAA0E;QACnF,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE;QACzD,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE;QACrD,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;QAC/C,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE;QAClD,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE;QACjD,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;KAChE,CAAA;IAED,MAAM,YAAY,GAAa,EAAE,CAAA;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACxD,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC9C,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAA;AAAA,CACzC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface TemplateInputs {
|
|
2
|
+
readonly title: string;
|
|
3
|
+
readonly applicationName: string;
|
|
4
|
+
readonly type: ApplicationType;
|
|
5
|
+
}
|
|
6
|
+
export type ApplicationType = 'app' | 'data';
|
|
7
|
+
export declare function packageJson(inputs: TemplateInputs): string;
|
|
8
|
+
export declare function tsconfigJson(): string;
|
|
9
|
+
export declare function gitignore(): string;
|
|
10
|
+
export declare function envExample(): string;
|
|
11
|
+
export declare function readme(inputs: TemplateInputs): string;
|
|
12
|
+
export declare function appTs(inputs: TemplateInputs): string;
|
|
13
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/scaffolder/templates.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAC/B;AAED,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,CAAA;AAK5C,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAqB1D;AAED,wBAAgB,YAAY,IAAI,MAAM,CAkBrC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAQnC;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAyCrD;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAwBpD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import pkg from '../../package.json' with { type: 'json' };
|
|
2
|
+
const sdkToolsVersion = pkg.version;
|
|
3
|
+
const coreSdkRange = '*';
|
|
4
|
+
export function packageJson(inputs) {
|
|
5
|
+
const { applicationName } = inputs;
|
|
6
|
+
const body = {
|
|
7
|
+
name: applicationName,
|
|
8
|
+
version: '0.0.0',
|
|
9
|
+
private: true,
|
|
10
|
+
type: 'module',
|
|
11
|
+
scripts: {
|
|
12
|
+
build: 'jigx build',
|
|
13
|
+
deploy: 'jigx deploy',
|
|
14
|
+
},
|
|
15
|
+
dependencies: {
|
|
16
|
+
'@jigx/core-sdk': coreSdkRange,
|
|
17
|
+
},
|
|
18
|
+
devDependencies: {
|
|
19
|
+
'@jigx/sdk-tools': `^${sdkToolsVersion}`,
|
|
20
|
+
tsx: '^4.21.0',
|
|
21
|
+
typescript: '^5.9.3',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
return `${JSON.stringify(body, null, 2)}\n`;
|
|
25
|
+
}
|
|
26
|
+
export function tsconfigJson() {
|
|
27
|
+
const body = {
|
|
28
|
+
compilerOptions: {
|
|
29
|
+
target: 'es2024',
|
|
30
|
+
module: 'nodenext',
|
|
31
|
+
moduleResolution: 'nodenext',
|
|
32
|
+
lib: ['es2024'],
|
|
33
|
+
strict: true,
|
|
34
|
+
esModuleInterop: true,
|
|
35
|
+
skipLibCheck: true,
|
|
36
|
+
resolveJsonModule: true,
|
|
37
|
+
noEmit: true,
|
|
38
|
+
isolatedModules: true,
|
|
39
|
+
forceConsistentCasingInFileNames: true,
|
|
40
|
+
},
|
|
41
|
+
include: ['src/**/*.ts'],
|
|
42
|
+
};
|
|
43
|
+
return `${JSON.stringify(body, null, 2)}\n`;
|
|
44
|
+
}
|
|
45
|
+
export function gitignore() {
|
|
46
|
+
return ['.env', 'node_modules/', 'build/', ''].join('\n');
|
|
47
|
+
}
|
|
48
|
+
export function envExample() {
|
|
49
|
+
return [
|
|
50
|
+
'# Jigx API credentials. Required for `jigx deploy`.',
|
|
51
|
+
'# Get these from the Jigx manage UI under Organization → Settings → API Keys.',
|
|
52
|
+
'JIGX_API_KEY=',
|
|
53
|
+
'JIGX_ORGANIZATION_ID=',
|
|
54
|
+
'',
|
|
55
|
+
].join('\n');
|
|
56
|
+
}
|
|
57
|
+
export function readme(inputs) {
|
|
58
|
+
const { title, applicationName, type } = inputs;
|
|
59
|
+
return `# ${title}
|
|
60
|
+
|
|
61
|
+
A Jigx Application scaffolded with \`@jigx/sdk-tools\`.
|
|
62
|
+
|
|
63
|
+
- Application name: \`${applicationName}\`
|
|
64
|
+
- Type: \`${type}\`
|
|
65
|
+
|
|
66
|
+
## Prerequisites
|
|
67
|
+
|
|
68
|
+
\`@jigx/core-sdk\` and \`@jigx/sdk-tools\` are published to npm with **restricted access**.
|
|
69
|
+
You need an \`NPM_TOKEN\` from the Jigx npm org before installing or running any
|
|
70
|
+
\`jigx\` command. Configure it via either:
|
|
71
|
+
|
|
72
|
+
- A user-level \`~/.npmrc\` containing \`//registry.npmjs.org/:_authToken=\${NPM_TOKEN}\`
|
|
73
|
+
with \`NPM_TOKEN\` set in your shell environment, or
|
|
74
|
+
- A project-level \`.npmrc\` next to this README with the same line
|
|
75
|
+
|
|
76
|
+
## Environment variables
|
|
77
|
+
|
|
78
|
+
Copy \`.env.example\` to \`.env\` and fill in the two required values:
|
|
79
|
+
|
|
80
|
+
\`\`\`bash
|
|
81
|
+
cp .env.example .env
|
|
82
|
+
\`\`\`
|
|
83
|
+
|
|
84
|
+
| Variable | Description |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| \`JIGX_API_KEY\` | API key issued by your Jigx organization. Used to authenticate every deploy request. |
|
|
87
|
+
| \`JIGX_ORGANIZATION_ID\` | Identifier of the organization that owns this Application. |
|
|
88
|
+
|
|
89
|
+
\`.env\` is gitignored — never commit it.
|
|
90
|
+
|
|
91
|
+
## Scripts
|
|
92
|
+
|
|
93
|
+
| Script | Wraps | What it does |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| \`yarn build\` | \`jigx build\` | Compiles \`src/app.ts\` into \`build/output.json\` and the canonical Builder folder layout under \`build/app/\` for inspection. |
|
|
96
|
+
| \`yarn deploy\` | \`jigx deploy\` | Builds, then deploys content to the prod environment. Pass \`--env dev\` to deploy to staging. |
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
export function appTs(inputs) {
|
|
100
|
+
const { title, applicationName, type } = inputs;
|
|
101
|
+
const titleLiteral = JSON.stringify(title);
|
|
102
|
+
const welcomeLiteral = JSON.stringify(`Welcome to ${title}`);
|
|
103
|
+
return `import { ApplicationBuilder } from '@jigx/core-sdk'
|
|
104
|
+
|
|
105
|
+
export const app = new ApplicationBuilder({
|
|
106
|
+
name: '${applicationName}',
|
|
107
|
+
title: ${titleLiteral},
|
|
108
|
+
type: '${type}',
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
app
|
|
112
|
+
.addScreen.default({
|
|
113
|
+
screenId: 'home',
|
|
114
|
+
title: ${titleLiteral},
|
|
115
|
+
})
|
|
116
|
+
.summary()
|
|
117
|
+
.addControl.default({
|
|
118
|
+
instanceId: 'welcome',
|
|
119
|
+
title: ${welcomeLiteral},
|
|
120
|
+
subtitle: 'Edit src/app.ts to start building your Application.',
|
|
121
|
+
})
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/scaffolder/templates.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,oBAAoB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAU1D,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAA;AACnC,MAAM,YAAY,GAAG,GAAG,CAAA;AAExB,MAAM,UAAU,WAAW,CAAC,MAAsB,EAAU;IAC1D,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAA;IAClC,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE;YACP,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,aAAa;SACtB;QACD,YAAY,EAAE;YACZ,gBAAgB,EAAE,YAAY;SAC/B;QACD,eAAe,EAAE;YACf,iBAAiB,EAAE,IAAI,eAAe,EAAE;YACxC,GAAG,EAAE,SAAS;YACd,UAAU,EAAE,QAAQ;SACrB;KACF,CAAA;IACD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAA;AAAA,CAC5C;AAED,MAAM,UAAU,YAAY,GAAW;IACrC,MAAM,IAAI,GAAG;QACX,eAAe,EAAE;YACf,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,UAAU;YAClB,gBAAgB,EAAE,UAAU;YAC5B,GAAG,EAAE,CAAC,QAAQ,CAAC;YACf,MAAM,EAAE,IAAI;YACZ,eAAe,EAAE,IAAI;YACrB,YAAY,EAAE,IAAI;YAClB,iBAAiB,EAAE,IAAI;YACvB,MAAM,EAAE,IAAI;YACZ,eAAe,EAAE,IAAI;YACrB,gCAAgC,EAAE,IAAI;SACvC;QACD,OAAO,EAAE,CAAC,aAAa,CAAC;KACzB,CAAA;IACD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAA;AAAA,CAC5C;AAED,MAAM,UAAU,SAAS,GAAW;IAClC,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAAA,CAC1D;AAED,MAAM,UAAU,UAAU,GAAW;IACnC,OAAO;QACL,qDAAqD;QACrD,mFAA+E;QAC/E,eAAe;QACf,uBAAuB;QACvB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAAA,CACb;AAED,MAAM,UAAU,MAAM,CAAC,MAAsB,EAAU;IACrD,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,MAAM,CAAA;IAC/C,OAAO,KAAK,KAAK;;;;wBAIK,eAAe;YAC3B,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCf,CAAA;AAAA,CACA;AAED,MAAM,UAAU,KAAK,CAAC,MAAsB,EAAU;IACpD,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,MAAM,CAAA;IAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,KAAK,EAAE,CAAC,CAAA;IAC5D,OAAO;;;WAGE,eAAe;WACf,YAAY;WACZ,IAAI;;;;;;aAMF,YAAY;;;;;aAKZ,cAAc;;;CAG1B,CAAA;AAAA,CACA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../../src/slug/__tests__/validate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { slugifyTitle, validateApplicationName } from '../validate.js';
|
|
3
|
+
describe('slugifyTitle', () => {
|
|
4
|
+
const cases = [
|
|
5
|
+
['Customer Selection', 'customer-selection'],
|
|
6
|
+
[' Customer Selection ', 'customer-selection'],
|
|
7
|
+
['Café Crème!', 'cafe-creme'],
|
|
8
|
+
['Foo_Bar/Baz', 'foo-bar-baz'],
|
|
9
|
+
['---trim---', 'trim'],
|
|
10
|
+
['UPPER', 'upper'],
|
|
11
|
+
['mixed 123 thing', 'mixed-123-thing'],
|
|
12
|
+
['$$$', ''],
|
|
13
|
+
['', ''],
|
|
14
|
+
];
|
|
15
|
+
test.each(cases)('slugifyTitle(%j) === %j', (input, expected) => {
|
|
16
|
+
expect(slugifyTitle(input)).toBe(expected);
|
|
17
|
+
});
|
|
18
|
+
test('truncates to 50 characters', () => {
|
|
19
|
+
const longInput = 'a'.repeat(60);
|
|
20
|
+
expect(slugifyTitle(longInput).length).toBe(50);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('validateApplicationName', () => {
|
|
24
|
+
const valid = [
|
|
25
|
+
'a1',
|
|
26
|
+
'customer-selection',
|
|
27
|
+
'app',
|
|
28
|
+
'a'.repeat(50),
|
|
29
|
+
'0-9-abc',
|
|
30
|
+
'123',
|
|
31
|
+
];
|
|
32
|
+
const invalid = [
|
|
33
|
+
['', /2–50 characters/],
|
|
34
|
+
['a', /2–50 characters/],
|
|
35
|
+
['a'.repeat(51), /2–50 characters/],
|
|
36
|
+
['Customer-Selection', /\[a-z0-9-\]\+/],
|
|
37
|
+
['customer_selection', /\[a-z0-9-\]\+/],
|
|
38
|
+
['customer selection', /\[a-z0-9-\]\+/],
|
|
39
|
+
['hello!', /\[a-z0-9-\]\+/],
|
|
40
|
+
];
|
|
41
|
+
test.each(valid)('accepts %j', (name) => {
|
|
42
|
+
expect(validateApplicationName(name)).toEqual({ ok: true });
|
|
43
|
+
});
|
|
44
|
+
test.each(invalid)('rejects %j', (name, pattern) => {
|
|
45
|
+
const result = validateApplicationName(name);
|
|
46
|
+
expect(result.ok).toBe(false);
|
|
47
|
+
if (!result.ok)
|
|
48
|
+
expect(result.error).toMatch(pattern);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=validate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../../../src/slug/__tests__/validate.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAEtE,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC;IAC7B,MAAM,KAAK,GAA6C;QACtD,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;QAC5C,CAAC,yBAAyB,EAAE,oBAAoB,CAAC;QACjD,CAAC,eAAa,EAAE,YAAY,CAAC;QAC7B,CAAC,aAAa,EAAE,aAAa,CAAC;QAC9B,CAAC,YAAY,EAAE,MAAM,CAAC;QACtB,CAAC,OAAO,EAAE,OAAO,CAAC;QAClB,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;QACtC,CAAC,KAAK,EAAE,EAAE,CAAC;QACX,CAAC,EAAE,EAAE,EAAE,CAAC;KACT,CAAA;IAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;QAC/D,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAAA,CAC3C,CAAC,CAAA;IAEF,IAAI,CAAC,4BAA4B,EAAE,GAAG,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAAA,CAChD,CAAC,CAAA;AAAA,CACH,CAAC,CAAA;AAEF,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC;IACxC,MAAM,KAAK,GAAsB;QAC/B,IAAI;QACJ,oBAAoB;QACpB,KAAK;QACL,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACd,SAAS;QACT,KAAK;KACN,CAAA;IAED,MAAM,OAAO,GAA6C;QACxD,CAAC,EAAE,EAAE,mBAAiB,CAAC;QACvB,CAAC,GAAG,EAAE,mBAAiB,CAAC;QACxB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,mBAAiB,CAAC;QACnC,CAAC,oBAAoB,EAAE,eAAe,CAAC;QACvC,CAAC,oBAAoB,EAAE,eAAe,CAAC;QACvC,CAAC,oBAAoB,EAAE,eAAe,CAAC;QACvC,CAAC,QAAQ,EAAE,eAAe,CAAC;KAC5B,CAAA;IAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IAAA,CAC5D,CAAC,CAAA;IAEF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAAA,CACtD,CAAC,CAAA;AAAA,CACH,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slug/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AACrE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/slug/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ValidationOk {
|
|
2
|
+
readonly ok: true;
|
|
3
|
+
}
|
|
4
|
+
export interface ValidationError {
|
|
5
|
+
readonly ok: false;
|
|
6
|
+
readonly error: string;
|
|
7
|
+
}
|
|
8
|
+
export type ValidationResult = ValidationOk | ValidationError;
|
|
9
|
+
export declare function slugifyTitle(title: string): string;
|
|
10
|
+
export declare function validateApplicationName(name: string): ValidationResult;
|
|
11
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/slug/validate.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAA;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,eAAe,CAAA;AAS7D,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASlD;AAOD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CActE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const APPLICATION_NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
2
|
+
const MIN_LENGTH = 2;
|
|
3
|
+
const MAX_LENGTH = 50;
|
|
4
|
+
export function slugifyTitle(title) {
|
|
5
|
+
return title
|
|
6
|
+
.normalize('NFKD')
|
|
7
|
+
.replace(/[̀-ͯ]/g, '')
|
|
8
|
+
.toLowerCase()
|
|
9
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
10
|
+
.replace(/^-+|-+$/g, '')
|
|
11
|
+
.slice(0, MAX_LENGTH)
|
|
12
|
+
.replace(/-+$/g, '');
|
|
13
|
+
}
|
|
14
|
+
export function validateApplicationName(name) {
|
|
15
|
+
if (name.length < MIN_LENGTH || name.length > MAX_LENGTH) {
|
|
16
|
+
return {
|
|
17
|
+
ok: false,
|
|
18
|
+
error: `Application name must be ${MIN_LENGTH}–${MAX_LENGTH} characters (got ${name.length}).`,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (!APPLICATION_NAME_PATTERN.test(name)) {
|
|
22
|
+
return {
|
|
23
|
+
ok: false,
|
|
24
|
+
error: `Application name must match [a-z0-9-]+ (lowercase letters, digits, hyphens).`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { ok: true };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/slug/validate.ts"],"names":[],"mappings":"AAMA,MAAM,wBAAwB,GAAG,cAAc,CAAA;AAC/C,MAAM,UAAU,GAAG,CAAC,CAAA;AACpB,MAAM,UAAU,GAAG,EAAE,CAAA;AAoBrB,MAAM,UAAU,YAAY,CAAC,KAAa,EAAU;IAClD,OAAO,KAAK;SACT,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,UAAQ,EAAE,EAAE,CAAC;SACrB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AAAA,CACvB;AAOD,MAAM,UAAU,uBAAuB,CAAC,IAAY,EAAoB;IACtE,IAAI,IAAI,CAAC,MAAM,GAAG,UAAU,IAAI,IAAI,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QACzD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,4BAA4B,UAAU,MAAI,UAAU,oBAAoB,IAAI,CAAC,MAAM,IAAI;SAC/F,CAAA;IACH,CAAC;IACD,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,8EAA8E;SACtF,CAAA;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AAAA,CACpB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jigx/sdk-tools",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Jigx SDK toolkit (jigx CLI) — scaffold, build, and publish Jigx Application projects",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"jigx": "dist/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": {
|
|
15
|
+
"source": "./src/index.ts",
|
|
16
|
+
"default": "./dist/index.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"source": "./src/index.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist/**/*",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/jigx-com/jigx-sdk.git"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"test": " NODE_OPTIONS='--max-old-space-size=4096' vitest run --reporter=dot",
|
|
32
|
+
"test:debug": "NODE_OPTIONS='--max-old-space-size=4096' vitest run --no-threads --reporter=verbose",
|
|
33
|
+
"lint": " eslint src",
|
|
34
|
+
"lint:fix": " yarn lint --fix || true",
|
|
35
|
+
"typecheck": " yarn tsgo --noEmit",
|
|
36
|
+
"tc": " yarn typecheck",
|
|
37
|
+
"code-check": "yarn typecheck && yarn lint && yarn test",
|
|
38
|
+
"cc": " yarn code-check",
|
|
39
|
+
"clean": " rm -rf dist .nyc_output coverage node_modules/.tmp",
|
|
40
|
+
"build": " yarn tsgo --build"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@clack/prompts": "^0.11.0",
|
|
44
|
+
"tsx": "^4.21.0",
|
|
45
|
+
"yaml": "^2.8.3"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@typescript/native-preview": "^7.0.0-dev.20260216.1",
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
50
|
+
"eslint": "^9.39.2",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"vitest": "*"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "restricted",
|
|
56
|
+
"registry": "https://registry.npmjs.org/"
|
|
57
|
+
}
|
|
58
|
+
}
|