create-relkit 0.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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/generate-files.d.ts +16 -0
- package/dist/generate-files.d.ts.map +1 -0
- package/dist/generate-files.js +108 -0
- package/dist/generate-files.js.map +1 -0
- package/dist/generate-output.d.ts +20 -0
- package/dist/generate-output.d.ts.map +1 -0
- package/dist/generate-output.js +67 -0
- package/dist/generate-output.js.map +1 -0
- package/dist/generate-process.d.ts +9 -0
- package/dist/generate-process.d.ts.map +1 -0
- package/dist/generate-process.js +76 -0
- package/dist/generate-process.js.map +1 -0
- package/dist/generate.d.ts +42 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +103 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +38 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +113 -0
- package/dist/options.js.map +1 -0
- package/dist/templates/default/README.md +13 -0
- package/dist/templates/default/v1/agent/.env.example +3 -0
- package/dist/templates/default/v1/agent/README.md +23 -0
- package/dist/templates/default/v1/agent/gitignore +10 -0
- package/dist/templates/default/v1/agent/package.json +29 -0
- package/dist/templates/default/v1/agent/relkit.config.ts +23 -0
- package/dist/templates/default/v1/agent/src/agents/assistant.agent.ts +13 -0
- package/dist/templates/default/v1/agent/src/env.ts +7 -0
- package/dist/templates/default/v1/agent/src/functions/hello.function.ts +21 -0
- package/dist/templates/default/v1/agent/src/routes/hello/route.ts +7 -0
- package/dist/templates/default/v1/agent/tests/integration/hello.route.test.ts +13 -0
- package/dist/templates/default/v1/agent/tests/unit/assistant.agent.test.ts +29 -0
- package/dist/templates/default/v1/agent/tests/unit/hello.function.test.ts +9 -0
- package/dist/templates/default/v1/agent/tsconfig.json +23 -0
- package/dist/templates/default/v1/api/.env.example +4 -0
- package/dist/templates/default/v1/api/README.md +25 -0
- package/dist/templates/default/v1/api/gitignore +10 -0
- package/dist/templates/default/v1/api/package.json +30 -0
- package/dist/templates/default/v1/api/relkit.config.ts +19 -0
- package/dist/templates/default/v1/api/src/env.ts +8 -0
- package/dist/templates/default/v1/api/src/events/order-audit.event.ts +15 -0
- package/dist/templates/default/v1/api/src/events/order-confirmation.event.ts +11 -0
- package/dist/templates/default/v1/api/src/events/order-created.event.ts +15 -0
- package/dist/templates/default/v1/api/src/functions/echo.function.ts +10 -0
- package/dist/templates/default/v1/api/src/functions/hello.function.ts +13 -0
- package/dist/templates/default/v1/api/src/functions/orders/create-order.function.ts +29 -0
- package/dist/templates/default/v1/api/src/functions/orders/price-order.function.ts +10 -0
- package/dist/templates/default/v1/api/src/routes/echo/route.ts +6 -0
- package/dist/templates/default/v1/api/src/routes/hello/route.ts +6 -0
- package/dist/templates/default/v1/api/src/routes/orders/route.ts +9 -0
- package/dist/templates/default/v1/api/src/services/orders.service.ts +7 -0
- package/dist/templates/default/v1/api/tests/integration/echo.route.test.ts +17 -0
- package/dist/templates/default/v1/api/tests/integration/hello.route.test.ts +13 -0
- package/dist/templates/default/v1/api/tests/integration/order-events.test.ts +71 -0
- package/dist/templates/default/v1/api/tests/integration/orders.route.test.ts +24 -0
- package/dist/templates/default/v1/api/tests/unit/echo.function.test.ts +9 -0
- package/dist/templates/default/v1/api/tests/unit/hello.function.test.ts +9 -0
- package/dist/templates/default/v1/api/tests/unit/orders.function.test.ts +26 -0
- package/dist/templates/default/v1/api/tsconfig.json +23 -0
- package/dist/templates/default/v1/minimal/.env.example +1 -0
- package/dist/templates/default/v1/minimal/README.md +19 -0
- package/dist/templates/default/v1/minimal/gitignore +10 -0
- package/dist/templates/default/v1/minimal/package.json +29 -0
- package/dist/templates/default/v1/minimal/relkit.config.ts +10 -0
- package/dist/templates/default/v1/minimal/src/env.ts +5 -0
- package/dist/templates/default/v1/minimal/src/functions/hello.function.ts +14 -0
- package/dist/templates/default/v1/minimal/src/routes/hello/route.ts +7 -0
- package/dist/templates/default/v1/minimal/tests/integration/hello.route.test.ts +13 -0
- package/dist/templates/default/v1/minimal/tests/unit/hello.function.test.ts +9 -0
- package/dist/templates/default/v1/minimal/tsconfig.json +23 -0
- package/dist/validate.d.ts +23 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +156 -0
- package/dist/validate.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { createEventListenerTarget, eventListenerFunctionId } from "@relkit/app/events";
|
|
3
|
+
import { createTestEvent, invokeFunction } from "@relkit/testing";
|
|
4
|
+
import orderCreated from "@app/events/order-created.event.js";
|
|
5
|
+
import orderAudit from "@app/events/order-audit.event.js";
|
|
6
|
+
import orderConfirmation from "@app/events/order-confirmation.event.js";
|
|
7
|
+
import orders from "@app/services/orders.service.js";
|
|
8
|
+
|
|
9
|
+
const retry = {
|
|
10
|
+
maxAttempts: 1,
|
|
11
|
+
initialDelayMs: 0,
|
|
12
|
+
maxDelayMs: 0,
|
|
13
|
+
multiplier: 1,
|
|
14
|
+
jitter: "none" as const,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
test("order.created fans out deterministic independent deliveries", async () => {
|
|
18
|
+
const confirmationTarget = createEventListenerTarget(
|
|
19
|
+
orderConfirmation,
|
|
20
|
+
[orderCreated],
|
|
21
|
+
eventListenerFunctionId(orderConfirmation.id),
|
|
22
|
+
);
|
|
23
|
+
const auditTarget = createEventListenerTarget(
|
|
24
|
+
orderAudit,
|
|
25
|
+
[orderCreated],
|
|
26
|
+
eventListenerFunctionId(orderAudit.id),
|
|
27
|
+
);
|
|
28
|
+
const failingAuditTarget = {
|
|
29
|
+
...auditTarget,
|
|
30
|
+
handler: async (...args: Parameters<typeof auditTarget.handler>) => {
|
|
31
|
+
await auditTarget.handler(...args);
|
|
32
|
+
throw new Error("audit listener test failure");
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
const event = await createTestEvent({
|
|
36
|
+
event: orderCreated,
|
|
37
|
+
triggers: [
|
|
38
|
+
{ id: orderConfirmation.id, target: confirmationTarget, retry },
|
|
39
|
+
{ id: orderAudit.id, target: failingAuditTarget, retry },
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
await expect(
|
|
45
|
+
invokeFunction(
|
|
46
|
+
orders.createOrder,
|
|
47
|
+
{ orderId: "order-1", sku: "book", quantity: 3 },
|
|
48
|
+
{ clients: { events: { orderCreated: event.provider } } },
|
|
49
|
+
),
|
|
50
|
+
).resolves.toEqual({ orderId: "order-1", sku: "book", totalCents: 300 });
|
|
51
|
+
|
|
52
|
+
await expect(event.drain()).resolves.toMatchObject([
|
|
53
|
+
{
|
|
54
|
+
triggerId: "orders.audit",
|
|
55
|
+
status: "failed",
|
|
56
|
+
state: "dead-lettered",
|
|
57
|
+
attempt: 1,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
triggerId: "orders.confirmation",
|
|
61
|
+
status: "completed",
|
|
62
|
+
state: "completed",
|
|
63
|
+
attempt: 1,
|
|
64
|
+
},
|
|
65
|
+
]);
|
|
66
|
+
expect(event.completed("orders.confirmation")).toBe(1);
|
|
67
|
+
expect(event.completed("orders.audit")).toBe(0);
|
|
68
|
+
} finally {
|
|
69
|
+
await event.close();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { afterAll, expect, test } from "bun:test";
|
|
2
|
+
import { createTestApplication } from "@relkit/testing";
|
|
3
|
+
import config from "../../relkit.config.js";
|
|
4
|
+
|
|
5
|
+
const testApp = await createTestApplication(config);
|
|
6
|
+
testApp.fakes.setClient("events", "orderCreated", {
|
|
7
|
+
publish: async () => ({ accepted: true, instanceId: "event-1" }),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("POST /orders", async () => {
|
|
11
|
+
const response = await testApp.http.request("/orders", {
|
|
12
|
+
method: "POST",
|
|
13
|
+
headers: { "content-type": "application/json" },
|
|
14
|
+
body: JSON.stringify({ orderId: "order-1", sku: "book", quantity: 3 }),
|
|
15
|
+
});
|
|
16
|
+
expect(response.status).toBe(201);
|
|
17
|
+
expect(await response.json()).toEqual({
|
|
18
|
+
orderId: "order-1",
|
|
19
|
+
sku: "book",
|
|
20
|
+
totalCents: 300,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterAll(() => testApp.close());
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { invokeFunction } from "@relkit/testing";
|
|
3
|
+
import echo from "@app/functions/echo.function.js";
|
|
4
|
+
|
|
5
|
+
test("echo returns its input", async () => {
|
|
6
|
+
await expect(invokeFunction(echo, { message: "hello" })).resolves.toEqual({
|
|
7
|
+
message: "hello",
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { invokeFunction } from "@relkit/testing";
|
|
3
|
+
import hello from "@app/functions/hello.function.js";
|
|
4
|
+
|
|
5
|
+
test("hello returns a greeting", async () => {
|
|
6
|
+
await expect(invokeFunction(hello, { name: "Mustafa" })).resolves.toEqual({
|
|
7
|
+
message: "Hello, Mustafa!",
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { invokeFunction } from "@relkit/testing";
|
|
3
|
+
import orders from "@app/services/orders.service.js";
|
|
4
|
+
|
|
5
|
+
test("createOrder invokes pricing and publishes the order event", async () => {
|
|
6
|
+
const published: unknown[] = [];
|
|
7
|
+
const result = await invokeFunction(
|
|
8
|
+
orders.createOrder,
|
|
9
|
+
{ orderId: "order-1", sku: "book", quantity: 3 },
|
|
10
|
+
{
|
|
11
|
+
clients: {
|
|
12
|
+
events: {
|
|
13
|
+
orderCreated: {
|
|
14
|
+
publish: async (payload: unknown) => {
|
|
15
|
+
published.push(payload);
|
|
16
|
+
return { accepted: true, instanceId: "event-1" };
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
expect(result).toEqual({ orderId: "order-1", sku: "book", totalCents: 300 });
|
|
25
|
+
expect(published).toEqual([{ orderId: "order-1", sku: "book", totalCents: 300 }]);
|
|
26
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
|
+
"baseUrl": ".",
|
|
8
|
+
"paths": { "@app/*": ["src/*"] },
|
|
9
|
+
"lib": ["ES2022"],
|
|
10
|
+
"types": ["bun"],
|
|
11
|
+
"strict": true,
|
|
12
|
+
"noUncheckedIndexedAccess": true,
|
|
13
|
+
"exactOptionalPropertyTypes": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"skipLibCheck": true,
|
|
18
|
+
"forceConsistentCasingInFileNames": true
|
|
19
|
+
},
|
|
20
|
+
"files": [".relkit/generated/event-registry.d.ts"],
|
|
21
|
+
"include": ["src/**/*.ts", "tests/**/*.ts", "relkit.config.ts"],
|
|
22
|
+
"exclude": ["node_modules", ".relkit"]
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
LOG_LEVEL=info
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# my-app
|
|
2
|
+
|
|
3
|
+
A small RelKit TypeScript/Bun project with one function and one HTTP route.
|
|
4
|
+
Application code uses public RelKit descriptors and ordinary async handlers.
|
|
5
|
+
|
|
6
|
+
## Commands
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
bun install
|
|
10
|
+
bun run dev
|
|
11
|
+
bun run test
|
|
12
|
+
bun run check
|
|
13
|
+
bun run typecheck
|
|
14
|
+
bun run build
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The example route is `GET /hello?name=RelKit`. Development uses the local
|
|
18
|
+
provider set, tests use deterministic test providers, and production selects
|
|
19
|
+
the configured AWS provider set.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"packageManager": "bun@1.3.10",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "relkit dev",
|
|
8
|
+
"check": "relkit check",
|
|
9
|
+
"typecheck": "tsc --noEmit",
|
|
10
|
+
"test": "bun test",
|
|
11
|
+
"test:unit": "bun test tests/unit",
|
|
12
|
+
"test:integration": "bun test tests/integration",
|
|
13
|
+
"build": "relkit build",
|
|
14
|
+
"start": "relkit start",
|
|
15
|
+
"graph": "relkit graph print",
|
|
16
|
+
"deploy:preview": "relkit deploy preview",
|
|
17
|
+
"deploy": "relkit deploy up"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@relkit/app": "0.0.0",
|
|
21
|
+
"@relkit/providers-standard": "0.0.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/bun": "1.3.10",
|
|
25
|
+
"@relkit/cli": "0.0.0",
|
|
26
|
+
"@relkit/testing": "0.0.0",
|
|
27
|
+
"typescript": "5.9.2"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from "@relkit/app/config";
|
|
2
|
+
import env from "@app/env.js";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
env,
|
|
6
|
+
telemetry: { bodyCapture: { mode: "off" } },
|
|
7
|
+
server: { port: 3000, maxBodyBytes: 1_048_576 },
|
|
8
|
+
inspector: { port: 3210 },
|
|
9
|
+
deployment: { target: "aws", adapter: "pulumi" },
|
|
10
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineFunction } from "@relkit/app/functions";
|
|
2
|
+
import { z } from "@relkit/app/schema";
|
|
3
|
+
|
|
4
|
+
const hello = defineFunction({
|
|
5
|
+
id: "hello",
|
|
6
|
+
input: z.object({ name: z.string().min(1).default("world") }),
|
|
7
|
+
output: z.object({ message: z.string() }),
|
|
8
|
+
handler: async ({ name }, context) => {
|
|
9
|
+
context.log.info("hello invoked", { name });
|
|
10
|
+
return { message: `Hello, ${name}!` };
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export default hello;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { afterAll, expect, test } from "bun:test";
|
|
2
|
+
import { createTestApplication } from "@relkit/testing";
|
|
3
|
+
import config from "../../relkit.config.js";
|
|
4
|
+
|
|
5
|
+
const testApp = await createTestApplication(config);
|
|
6
|
+
|
|
7
|
+
test("GET /hello", async () => {
|
|
8
|
+
const response = await testApp.http.request("/hello?name=Mustafa");
|
|
9
|
+
expect(response.status).toBe(200);
|
|
10
|
+
expect(await response.json()).toEqual({ message: "Hello, Mustafa!" });
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterAll(() => testApp.close());
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { invokeFunction } from "@relkit/testing";
|
|
3
|
+
import hello from "@app/functions/hello.function.js";
|
|
4
|
+
|
|
5
|
+
test("hello returns a greeting", async () => {
|
|
6
|
+
await expect(invokeFunction(hello, { name: "Mustafa" })).resolves.toEqual({
|
|
7
|
+
message: "Hello, Mustafa!",
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
|
+
"baseUrl": ".",
|
|
8
|
+
"paths": { "@app/*": ["src/*"] },
|
|
9
|
+
"lib": ["ES2022"],
|
|
10
|
+
"types": ["bun"],
|
|
11
|
+
"strict": true,
|
|
12
|
+
"noUncheckedIndexedAccess": true,
|
|
13
|
+
"exactOptionalPropertyTypes": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"skipLibCheck": true,
|
|
18
|
+
"forceConsistentCasingInFileNames": true
|
|
19
|
+
},
|
|
20
|
+
"files": [".relkit/generated/event-registry.d.ts"],
|
|
21
|
+
"include": ["src/**/*.ts", "tests/**/*.ts", "relkit.config.ts"],
|
|
22
|
+
"exclude": ["node_modules", ".relkit"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CreateOptions } from "./options.js";
|
|
2
|
+
export declare class CreateValidationError extends Error {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
constructor(code: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export interface CreateValidationContext {
|
|
7
|
+
readonly cwd?: string;
|
|
8
|
+
readonly homeDirectory?: string;
|
|
9
|
+
readonly temporaryDirectory?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ValidatedCreateOptions extends CreateOptions {
|
|
12
|
+
readonly destination: string;
|
|
13
|
+
readonly destinationExists: boolean;
|
|
14
|
+
readonly destinationEmpty: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Returns whether a value is a valid unscoped or scoped npm package name. */
|
|
17
|
+
export declare function isValidPackageName(value: unknown): value is string;
|
|
18
|
+
/** Throws a stable validation error instead of normalizing an invalid name. */
|
|
19
|
+
export declare function validatePackageName(value: unknown): asserts value is string;
|
|
20
|
+
export declare function resolveCreateDestination(options: Pick<CreateOptions, "name" | "directory">, context?: CreateValidationContext): string;
|
|
21
|
+
/** Validates name, path, and destination state using read-only filesystem calls. */
|
|
22
|
+
export declare function validateCreateOptions(options: CreateOptions, context?: CreateValidationContext): ValidatedCreateOptions;
|
|
23
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD,qBAAa,qBAAsB,SAAQ,KAAK;IAE5C,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAKlB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAOlE;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAO3E;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,WAAW,CAAC,EAClD,OAAO,GAAE,uBAA4B,GACpC,MAAM,CAmBR;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAkCxB"}
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { lstatSync, readdirSync, realpathSync } from "node:fs";
|
|
2
|
+
import { homedir, tmpdir } from "node:os";
|
|
3
|
+
import { dirname, isAbsolute, join, parse, relative, resolve } from "node:path";
|
|
4
|
+
const PACKAGE_PART = /^(?![._])[a-z0-9._~-]+$/;
|
|
5
|
+
const WINDOWS_ABSOLUTE = /^(?:[A-Za-z]:[\\/]|\\\\)/;
|
|
6
|
+
const RESERVED_NAMES = new Set(["favicon.ico", "node_modules"]);
|
|
7
|
+
export class CreateValidationError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
constructor(code, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.name = "CreateValidationError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Returns whether a value is a valid unscoped or scoped npm package name. */
|
|
16
|
+
export function isValidPackageName(value) {
|
|
17
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 214)
|
|
18
|
+
return false;
|
|
19
|
+
const parts = value.startsWith("@") ? value.slice(1).split("/") : [value];
|
|
20
|
+
if (parts.length !== (value.startsWith("@") ? 2 : 1))
|
|
21
|
+
return false;
|
|
22
|
+
return parts.every((part) => part.length > 0 && PACKAGE_PART.test(part) && !RESERVED_NAMES.has(part));
|
|
23
|
+
}
|
|
24
|
+
/** Throws a stable validation error instead of normalizing an invalid name. */
|
|
25
|
+
export function validatePackageName(value) {
|
|
26
|
+
if (!isValidPackageName(value)) {
|
|
27
|
+
throw new CreateValidationError("RELKIT_CREATE_NAME_INVALID", "Project name must be a valid npm package name.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function resolveCreateDestination(options, context = {}) {
|
|
31
|
+
validatePackageName(options.name);
|
|
32
|
+
const workingDirectory = resolve(context.cwd ?? process.cwd());
|
|
33
|
+
const cwd = existingDirectory(workingDirectory, "current directory");
|
|
34
|
+
const input = options.directory ?? options.name;
|
|
35
|
+
if (typeof input !== "string" ||
|
|
36
|
+
input.length === 0 ||
|
|
37
|
+
input.includes("\0") ||
|
|
38
|
+
WINDOWS_ABSOLUTE.test(input)) {
|
|
39
|
+
throw new CreateValidationError("RELKIT_CREATE_DESTINATION_INVALID", "Destination must be a valid local path.");
|
|
40
|
+
}
|
|
41
|
+
const candidate = resolve(workingDirectory, input);
|
|
42
|
+
rejectBroadPath(canonicalizeMissingPath(candidate), cwd, context);
|
|
43
|
+
return candidate;
|
|
44
|
+
}
|
|
45
|
+
/** Validates name, path, and destination state using read-only filesystem calls. */
|
|
46
|
+
export function validateCreateOptions(options, context = {}) {
|
|
47
|
+
if (options === null || typeof options !== "object") {
|
|
48
|
+
throw new CreateValidationError("RELKIT_CREATE_DESTINATION_INVALID", "Create options are invalid.");
|
|
49
|
+
}
|
|
50
|
+
validatePackageName(options.name);
|
|
51
|
+
if (typeof options.forceEmptyDirectory !== "boolean") {
|
|
52
|
+
throw new CreateValidationError("RELKIT_CREATE_DESTINATION_INVALID", "The empty-directory override must be boolean.");
|
|
53
|
+
}
|
|
54
|
+
const destination = resolveCreateDestination(options, context);
|
|
55
|
+
const state = inspectDestination(destination);
|
|
56
|
+
if (state.exists && !state.empty) {
|
|
57
|
+
throw new CreateValidationError("RELKIT_CREATE_DESTINATION_NOT_EMPTY", "Destination must be absent or an empty directory.");
|
|
58
|
+
}
|
|
59
|
+
if (state.exists && !options.forceEmptyDirectory) {
|
|
60
|
+
throw new CreateValidationError("RELKIT_CREATE_DESTINATION_EXISTS", "Destination already exists; use --force-empty-directory only for an empty directory.");
|
|
61
|
+
}
|
|
62
|
+
return Object.freeze({
|
|
63
|
+
...options,
|
|
64
|
+
destination,
|
|
65
|
+
destinationExists: state.exists,
|
|
66
|
+
destinationEmpty: state.empty,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function inspectDestination(path) {
|
|
70
|
+
let info;
|
|
71
|
+
try {
|
|
72
|
+
info = lstatSync(path);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (isNotFound(error))
|
|
76
|
+
return { exists: false, empty: false };
|
|
77
|
+
throw invalidDestination("Destination could not be inspected.");
|
|
78
|
+
}
|
|
79
|
+
if (info.isSymbolicLink())
|
|
80
|
+
throw unsafeDestination("Destination must not be a symbolic link.");
|
|
81
|
+
if (!info.isDirectory())
|
|
82
|
+
throw invalidDestination("Destination is not a directory.");
|
|
83
|
+
try {
|
|
84
|
+
return { exists: true, empty: readdirSync(path).length === 0 };
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
throw invalidDestination("Destination directory could not be read.");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function canonicalizeMissingPath(path) {
|
|
91
|
+
let current = path;
|
|
92
|
+
const missing = [];
|
|
93
|
+
while (true) {
|
|
94
|
+
try {
|
|
95
|
+
const info = lstatSync(current);
|
|
96
|
+
if (missing.length > 0 && !info.isDirectory()) {
|
|
97
|
+
throw invalidDestination("A destination parent is not a directory.");
|
|
98
|
+
}
|
|
99
|
+
if (missing.length === 0 && info.isSymbolicLink()) {
|
|
100
|
+
throw unsafeDestination("Destination must not be a symbolic link.");
|
|
101
|
+
}
|
|
102
|
+
const base = realpathSync.native(current);
|
|
103
|
+
return missing.reverse().reduce((parent, part) => join(parent, part), base);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (!isNotFound(error)) {
|
|
107
|
+
if (error instanceof CreateValidationError)
|
|
108
|
+
throw error;
|
|
109
|
+
throw invalidDestination("Destination path could not be resolved.");
|
|
110
|
+
}
|
|
111
|
+
const parent = dirname(current);
|
|
112
|
+
if (parent === current)
|
|
113
|
+
throw invalidDestination("Destination path could not be resolved.");
|
|
114
|
+
missing.push(current.slice(parent.length + 1));
|
|
115
|
+
current = parent;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function rejectBroadPath(path, cwd, context) {
|
|
120
|
+
const broadRoots = [
|
|
121
|
+
cwd,
|
|
122
|
+
context.homeDirectory ?? homedir(),
|
|
123
|
+
context.temporaryDirectory ?? tmpdir(),
|
|
124
|
+
].map((root) => resolve(root));
|
|
125
|
+
if (path === parse(path).root || broadRoots.some((root) => isAncestorOrSame(path, root))) {
|
|
126
|
+
throw unsafeDestination("Destination is a current, root, or broad directory.");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function existingDirectory(path, label) {
|
|
130
|
+
const resolved = resolve(path);
|
|
131
|
+
try {
|
|
132
|
+
const info = lstatSync(resolved);
|
|
133
|
+
if (!info.isDirectory())
|
|
134
|
+
throw invalidDestination(`${label} is not a directory.`);
|
|
135
|
+
return realpathSync.native(resolved);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
if (error instanceof CreateValidationError)
|
|
139
|
+
throw error;
|
|
140
|
+
throw invalidDestination(`${label} could not be resolved.`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function isAncestorOrSame(parent, child) {
|
|
144
|
+
const relation = relative(parent, child);
|
|
145
|
+
return relation === "" || (!relation.startsWith("..") && !isAbsolute(relation));
|
|
146
|
+
}
|
|
147
|
+
function invalidDestination(message) {
|
|
148
|
+
return new CreateValidationError("RELKIT_CREATE_DESTINATION_INVALID", message);
|
|
149
|
+
}
|
|
150
|
+
function unsafeDestination(message) {
|
|
151
|
+
return new CreateValidationError("RELKIT_CREATE_DESTINATION_UNSAFE", message);
|
|
152
|
+
}
|
|
153
|
+
function isNotFound(error) {
|
|
154
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-relkit",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Create a RELKIT application from a supported project template.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/rel-kit/relkit.git",
|
|
9
|
+
"directory": "packages/create-relkit"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/rel-kit/relkit#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/rel-kit/relkit/issues"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"bun": ">=1.3.10"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"bin": {
|
|
26
|
+
"create-relkit": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -b && bun ../../scripts/package-create-relkit-templates.ts",
|
|
36
|
+
"check": "tsc -b --pretty false",
|
|
37
|
+
"typecheck": "tsc -b --pretty false"
|
|
38
|
+
}
|
|
39
|
+
}
|