create-oke 0.1.6 → 0.2.2

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.
Files changed (122) hide show
  1. package/README.md +26 -6
  2. package/{templates → examples}/linkly/package.json +1 -1
  3. package/{templates → examples}/notes/package.json +1 -1
  4. package/{templates → examples}/provisions/package.json +1 -1
  5. package/{templates → examples}/skyport/package.json +1 -1
  6. package/package.json +6 -2
  7. package/src/agents-md.ts +99 -0
  8. package/src/cli.test.ts +318 -19
  9. package/src/cli.ts +561 -29
  10. package/src/docs-origin.ts +19 -0
  11. package/src/index.ts +3 -1
  12. package/src/scaffold.ts +59 -32
  13. package/src/sync-templates.ts +28 -7
  14. package/src/templates.ts +85 -12
  15. package/src/transform.ts +5 -2
  16. package/templates/full/README.md +49 -0
  17. package/templates/full/oke.config.ts +23 -0
  18. package/templates/full/package.json +15 -0
  19. package/templates/full/src/ai.ts +11 -0
  20. package/templates/full/src/app.ts +34 -0
  21. package/templates/full/src/channels.ts +9 -0
  22. package/templates/full/src/core.ts +4 -0
  23. package/templates/full/src/flows/main/index.ts +45 -0
  24. package/templates/full/src/flows/main/shapes.ts +3 -0
  25. package/templates/full/src/flows/main/signals.ts +8 -0
  26. package/templates/full/src/gates.ts +4 -0
  27. package/templates/full/src/locales/ar.ts +3 -0
  28. package/templates/full/src/locales/en.ts +3 -0
  29. package/templates/full/src/schema.ts +8 -0
  30. package/templates/full/src/vault.ts +9 -0
  31. package/templates/full/tests/full.test.ts +11 -0
  32. package/templates/hello/README.md +38 -0
  33. package/templates/hello/oke.config.ts +3 -0
  34. package/templates/hello/package.json +14 -0
  35. package/templates/hello/src/app.ts +10 -0
  36. package/templates/hello/src/flows/hello/index.ts +27 -0
  37. package/templates/hello/tests/hello.test.ts +10 -0
  38. package/templates/minimal/README.md +41 -0
  39. package/templates/minimal/oke.config.ts +7 -0
  40. package/templates/minimal/package.json +15 -0
  41. package/templates/minimal/src/app.ts +13 -0
  42. package/templates/minimal/src/core.ts +4 -0
  43. package/templates/minimal/src/flows/main/index.ts +49 -0
  44. package/templates/minimal/src/schema.ts +8 -0
  45. package/templates/minimal/tests/minimal.test.ts +13 -0
  46. package/templates/standard/README.md +47 -0
  47. package/templates/standard/oke.config.ts +19 -0
  48. package/templates/standard/package.json +15 -0
  49. package/templates/standard/src/app.ts +18 -0
  50. package/templates/standard/src/channels.ts +4 -0
  51. package/templates/standard/src/core.ts +4 -0
  52. package/templates/standard/src/flows/main/index.ts +31 -0
  53. package/templates/standard/src/flows/main/shapes.ts +2 -0
  54. package/templates/standard/src/flows/main/signals.ts +4 -0
  55. package/templates/standard/src/gates.ts +4 -0
  56. package/templates/standard/src/locales/ar.ts +2 -0
  57. package/templates/standard/src/locales/en.ts +2 -0
  58. package/templates/standard/src/schema.ts +9 -0
  59. package/templates/standard/src/vault.ts +4 -0
  60. package/templates/standard/tests/standard.test.ts +10 -0
  61. /package/{templates → examples}/linkly/oke.config.ts +0 -0
  62. /package/{templates → examples}/linkly/src/app.ts +0 -0
  63. /package/{templates → examples}/linkly/src/core.ts +0 -0
  64. /package/{templates → examples}/linkly/src/flows/analytics/index.ts +0 -0
  65. /package/{templates → examples}/linkly/src/flows/links/index.ts +0 -0
  66. /package/{templates → examples}/linkly/src/flows/links/shapes.ts +0 -0
  67. /package/{templates → examples}/linkly/src/flows/links/signals.ts +0 -0
  68. /package/{templates → examples}/linkly/src/gates.ts +0 -0
  69. /package/{templates → examples}/linkly/src/schema.ts +0 -0
  70. /package/{templates → examples}/linkly/tests/linkly.test.ts +0 -0
  71. /package/{templates → examples}/notes/oke.config.ts +0 -0
  72. /package/{templates → examples}/notes/src/app.ts +0 -0
  73. /package/{templates → examples}/notes/src/core.ts +0 -0
  74. /package/{templates → examples}/notes/src/flows/notes/index.ts +0 -0
  75. /package/{templates → examples}/notes/src/schema.ts +0 -0
  76. /package/{templates → examples}/notes/tests/notes.test.ts +0 -0
  77. /package/{templates → examples}/provisions/oke.config.ts +0 -0
  78. /package/{templates → examples}/provisions/src/app.ts +0 -0
  79. /package/{templates → examples}/provisions/src/channels.ts +0 -0
  80. /package/{templates → examples}/provisions/src/core.ts +0 -0
  81. /package/{templates → examples}/provisions/src/flows/notifications/index.ts +0 -0
  82. /package/{templates → examples}/provisions/src/flows/orders/index.ts +0 -0
  83. /package/{templates → examples}/provisions/src/flows/orders/shapes.ts +0 -0
  84. /package/{templates → examples}/provisions/src/flows/orders/signals.ts +0 -0
  85. /package/{templates → examples}/provisions/src/flows/payments/index.ts +0 -0
  86. /package/{templates → examples}/provisions/src/flows/payments/shapes.ts +0 -0
  87. /package/{templates → examples}/provisions/src/flows/payments/stripe.ts +0 -0
  88. /package/{templates → examples}/provisions/src/gates.ts +0 -0
  89. /package/{templates → examples}/provisions/src/locales/ar.ts +0 -0
  90. /package/{templates → examples}/provisions/src/locales/en.ts +0 -0
  91. /package/{templates → examples}/provisions/src/plugins/audit-schema.ts +0 -0
  92. /package/{templates → examples}/provisions/src/plugins/audit.ts +0 -0
  93. /package/{templates → examples}/provisions/src/schema.ts +0 -0
  94. /package/{templates → examples}/provisions/src/vault.ts +0 -0
  95. /package/{templates → examples}/provisions/tests/orders.test.ts +0 -0
  96. /package/{templates → examples}/skyport/evals/triage.jsonl +0 -0
  97. /package/{templates → examples}/skyport/oke.config.ts +0 -0
  98. /package/{templates → examples}/skyport/oke.images.lock +0 -0
  99. /package/{templates → examples}/skyport/src/ai.ts +0 -0
  100. /package/{templates → examples}/skyport/src/app.ts +0 -0
  101. /package/{templates → examples}/skyport/src/channels.ts +0 -0
  102. /package/{templates → examples}/skyport/src/core.ts +0 -0
  103. /package/{templates → examples}/skyport/src/flows/bookings/index.ts +0 -0
  104. /package/{templates → examples}/skyport/src/flows/bookings/shapes.ts +0 -0
  105. /package/{templates → examples}/skyport/src/flows/bookings/signals.ts +0 -0
  106. /package/{templates → examples}/skyport/src/flows/notifications/index.ts +0 -0
  107. /package/{templates → examples}/skyport/src/flows/payments/index.ts +0 -0
  108. /package/{templates → examples}/skyport/src/flows/payments/shapes.ts +0 -0
  109. /package/{templates → examples}/skyport/src/flows/support/index.ts +0 -0
  110. /package/{templates → examples}/skyport/src/flows/users/elements.ts +0 -0
  111. /package/{templates → examples}/skyport/src/flows/users/index.ts +0 -0
  112. /package/{templates → examples}/skyport/src/flows/users/shapes.ts +0 -0
  113. /package/{templates → examples}/skyport/src/gates.ts +0 -0
  114. /package/{templates → examples}/skyport/src/journeys.ts +0 -0
  115. /package/{templates → examples}/skyport/src/locales/ar.ts +0 -0
  116. /package/{templates → examples}/skyport/src/locales/en.ts +0 -0
  117. /package/{templates → examples}/skyport/src/plugins/audit-schema.ts +0 -0
  118. /package/{templates → examples}/skyport/src/plugins/audit.ts +0 -0
  119. /package/{templates → examples}/skyport/src/plugins/panel.tsx +0 -0
  120. /package/{templates → examples}/skyport/src/schema.ts +0 -0
  121. /package/{templates → examples}/skyport/src/vault.ts +0 -0
  122. /package/{templates → examples}/skyport/tests/support.test.ts +0 -0
@@ -0,0 +1,38 @@
1
+ # hello
2
+
3
+ Fastest possible “it works” — one unit, two HTTP flows, **no Store**.
4
+
5
+ ## Run
6
+
7
+ ```bash
8
+ bun install
9
+ oke dev # app :6530 · Console :6533 · MCP :6535
10
+ ```
11
+
12
+ | Port | Try |
13
+ |---|---|
14
+ | `:6530` | `GET /` · `GET /hello` |
15
+ | `:6533` | Console |
16
+ | `:6535` | MCP |
17
+
18
+ ## What’s in this template
19
+
20
+ ```text
21
+ hello/
22
+ ├── oke.config.ts
23
+ ├── src/
24
+ │ ├── app.ts # oke({ name: "hello" }).adopt({ hello })
25
+ │ └── flows/hello/index.ts # GET / · GET /hello
26
+ └── tests/hello.test.ts
27
+ ```
28
+
29
+ - **Elements:** Flow only (no `store`, `gate`, `vault`, `channel`, or `ai`)
30
+ - **Unit:** `hello`
31
+ - **Flows:** `root` (`GET /`), `hello` (`GET /hello` → `{ message: "ok" }`)
32
+
33
+ Replace `/hello` with your first real route. When you need persistence, move up to
34
+ `minimal` or `standard` — or keep growing this tree.
35
+
36
+ ## Agent contract
37
+
38
+ See [`AGENTS.md`](./AGENTS.md). Handbook: [okengine.vercel.app/docs](https://okengine.vercel.app/docs)
@@ -0,0 +1,3 @@
1
+ import { defineConfig } from "okengine/config";
2
+
3
+ export default defineConfig({});
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@oke/template-hello",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "dependencies": {
7
+ "okengine": "file:../..",
8
+ "zod": "^4.4.3"
9
+ },
10
+ "scripts": {
11
+ "test": "bun test",
12
+ "dev": "oke dev"
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ import { oke } from "okengine";
2
+ import * as hello from "./flows/hello";
3
+
4
+ export const app = oke({ name: "hello" }).adopt({ hello });
5
+
6
+ export type App = typeof app;
7
+
8
+ Object.assign(app.$options, {
9
+ env: "test",
10
+ });
@@ -0,0 +1,27 @@
1
+ import { on, flow, http } from "okengine";
2
+ import { z } from "zod";
3
+
4
+ /** First-run welcome — visit :6530/ after `oke dev`. */
5
+ export const root = on(
6
+ http.get("/"),
7
+ flow({
8
+ out: z.object({
9
+ ok: z.literal(true),
10
+ console: z.string(),
11
+ try: z.string(),
12
+ }),
13
+ do: () => ({
14
+ ok: true as const,
15
+ console: "http://127.0.0.1:6533",
16
+ try: "/hello",
17
+ }),
18
+ }),
19
+ );
20
+
21
+ export const hello = on(
22
+ http.get("/hello"),
23
+ flow({
24
+ out: z.object({ message: z.string() }),
25
+ do: () => ({ message: "ok" }),
26
+ }),
27
+ );
@@ -0,0 +1,10 @@
1
+ import { test, expect } from "bun:test";
2
+ import { createTestApp } from "okengine/test";
3
+ import { app } from "../src/app";
4
+
5
+ test("boots and answers /hello", async () => {
6
+ const t = await createTestApp(app);
7
+ const { data, error } = await t.api.hello.hello({});
8
+ expect(error).toBeNull();
9
+ expect(data?.message).toBe("ok");
10
+ });
@@ -0,0 +1,41 @@
1
+ # minimal
2
+
3
+ Smallest shape you’d actually ship — **Store + HTTP flows** over a single table.
4
+
5
+ ## Run
6
+
7
+ ```bash
8
+ bun install
9
+ oke dev # app :6530 · Console :6533 · MCP :6535
10
+ ```
11
+
12
+ | Port | Try |
13
+ |---|---|
14
+ | `:6530` | `GET /` · `GET /entries` · `POST /entries` |
15
+ | `:6533` | Console |
16
+ | `:6535` | MCP |
17
+
18
+ ## What’s in this template
19
+
20
+ ```text
21
+ minimal/
22
+ ├── oke.config.ts
23
+ ├── src/
24
+ │ ├── app.ts # adopt({ main }), stores: [db]
25
+ │ ├── core.ts # store.sql("…")
26
+ │ ├── schema.ts # entries table (Drizzle)
27
+ │ └── flows/main/index.ts # GET / · GET|POST /entries
28
+ └── tests/minimal.test.ts
29
+ ```
30
+
31
+ - **Elements:** Flow · Store (`sql`)
32
+ - **Unit:** `main`
33
+ - **Flows:** `root`, `list` (`GET /entries`), `create` (`POST /entries` with `{ body }`)
34
+ - **Schema:** `entries` — `id`, `body`, `createdAt`
35
+
36
+ Swap `entries` for your domain table and grow flows beside it. Need gates,
37
+ channels, or locales? Use `standard`.
38
+
39
+ ## Agent contract
40
+
41
+ See [`AGENTS.md`](./AGENTS.md). Handbook: [okengine.vercel.app/docs](https://okengine.vercel.app/docs)
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from "okengine/config";
2
+
3
+ export default defineConfig({
4
+ drivers: {
5
+ store: { sql: { dev: "sqlite", test: "memory", prod: "postgres" } },
6
+ },
7
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@oke/template-minimal",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "dependencies": {
7
+ "okengine": "file:../..",
8
+ "drizzle-orm": "^1.0.0-rc.4",
9
+ "zod": "^4.4.3"
10
+ },
11
+ "scripts": {
12
+ "test": "bun test",
13
+ "dev": "oke dev"
14
+ }
15
+ }
@@ -0,0 +1,13 @@
1
+ import { db } from "./core";
2
+
3
+ import { oke } from "okengine";
4
+ import * as main from "./flows/main";
5
+
6
+ export const app = oke({ name: "minimal" }).adopt({ main });
7
+
8
+ export type App = typeof app;
9
+
10
+ Object.assign(app.$options, {
11
+ env: "test",
12
+ stores: [db],
13
+ });
@@ -0,0 +1,4 @@
1
+ import { store } from "okengine";
2
+ import * as schema from "./schema";
3
+
4
+ export const db = store.sql("app", { schema });
@@ -0,0 +1,49 @@
1
+ import { on, flow, http } from "okengine";
2
+ import { z } from "zod";
3
+ import { db } from "../../core";
4
+ import { entries } from "../../schema";
5
+
6
+ const NewEntry = z.object({ body: z.string().min(1) });
7
+ const EntryId = z.object({ id: z.string() });
8
+ const Entry = z.object({
9
+ id: z.string(),
10
+ body: z.string(),
11
+ createdAt: z.number(),
12
+ });
13
+
14
+ /** First-run welcome — visit :6530/ after `oke dev`. */
15
+ export const root = on(
16
+ http.get("/"),
17
+ flow({
18
+ out: z.object({
19
+ ok: z.literal(true),
20
+ console: z.string(),
21
+ try: z.string(),
22
+ }),
23
+ do: () => ({
24
+ ok: true as const,
25
+ console: "http://127.0.0.1:6533",
26
+ try: "GET /entries",
27
+ }),
28
+ }),
29
+ );
30
+
31
+ export const create = on(
32
+ http.post("/entries"),
33
+ flow({
34
+ in: NewEntry,
35
+ out: EntryId,
36
+ do: async (input, fx) => {
37
+ const [row] = await fx.store(db).insert(entries).values(input).returning();
38
+ return { id: row.id };
39
+ },
40
+ }),
41
+ );
42
+
43
+ export const list = on(
44
+ http.get("/entries"),
45
+ flow({
46
+ out: Entry.array(),
47
+ do: (_, fx) => fx.store(db).select().from(entries),
48
+ }),
49
+ );
@@ -0,0 +1,8 @@
1
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
2
+ import { id, now } from "okengine/store";
3
+
4
+ export const entries = sqliteTable("entries", {
5
+ id: text("id").primaryKey().$defaultFn(id),
6
+ body: text("body").notNull(),
7
+ createdAt: integer("created_at").notNull().$defaultFn(now),
8
+ });
@@ -0,0 +1,13 @@
1
+ import { test, expect } from "bun:test";
2
+ import { createTestApp } from "okengine/test";
3
+ import { app } from "../src/app";
4
+
5
+ test("boots — create then list", async () => {
6
+ const t = await createTestApp(app);
7
+ const { data, error } = await t.api.main.create({ body: "hello" });
8
+ expect(error).toBeNull();
9
+ expect(data?.id).toBeTruthy();
10
+ const { data: rows } = await t.api.main.list({});
11
+ expect(rows?.length).toBe(1);
12
+ expect(rows?.[0]?.body).toBe("hello");
13
+ });
@@ -0,0 +1,47 @@
1
+ # standard
2
+
3
+ Full recommended file layout with **empty scaffolding** — structure without
4
+ business logic. Default `create-oke` template.
5
+
6
+ ## Run
7
+
8
+ ```bash
9
+ bun install
10
+ oke dev # app :6530 · Console :6533 · MCP :6535
11
+ ```
12
+
13
+ | Port | Try |
14
+ |---|---|
15
+ | `:6530` | `GET /` · `GET /health` |
16
+ | `:6533` | Console |
17
+ | `:6535` | MCP |
18
+
19
+ ## What’s in this template
20
+
21
+ ```text
22
+ standard/
23
+ ├── oke.config.ts
24
+ ├── src/
25
+ │ ├── app.ts # adopt({ main }); wires stores + side modules
26
+ │ ├── core.ts / schema.ts # Store (replace the placeholder table)
27
+ │ ├── gates.ts # Gate stubs
28
+ │ ├── vault.ts # Vault stubs
29
+ │ ├── channels.ts # Channel stubs
30
+ │ ├── locales/en.ts · ar.ts # i18n stubs
31
+ │ └── flows/main/
32
+ │ ├── index.ts # GET / · GET /health
33
+ │ ├── shapes.ts # contracts live next to flows
34
+ │ └── signals.ts # Signal stubs
35
+ └── tests/standard.test.ts
36
+ ```
37
+
38
+ - **Elements stubbed:** Flow · Store · Signal · Gate · Vault · Channel (+ locales)
39
+ - **Unit:** `main`
40
+ - **Flows to replace:** `root`, `health` — delete or rename once your domain exists
41
+
42
+ Fill `schema.ts`, then add real flows under `src/flows/<unit>/`. Prefer this
43
+ layout for new products; use `hello` / `minimal` only when you want less surface.
44
+
45
+ ## Agent contract
46
+
47
+ See [`AGENTS.md`](./AGENTS.md). Handbook: [okengine.vercel.app/docs](https://okengine.vercel.app/docs)
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from "okengine/config";
2
+
3
+ export default defineConfig({
4
+ drivers: {
5
+ store: {
6
+ sql: { dev: "sqlite", test: "memory", prod: "postgres" },
7
+ kv: { dev: "memory", test: "memory", prod: "redis" },
8
+ },
9
+ signal: { dev: "memory", test: "memory", prod: "postgres" },
10
+ clock: { dev: "memory", test: "frozen", prod: "postgres" },
11
+ vault: { dev: "dotenv", test: "memory", prod: "sops" },
12
+ channel: {
13
+ email: { dev: "console", test: "console", prod: "smtp" },
14
+ sms: { dev: "console", test: "console", prod: "unifonic" },
15
+ whatsapp: { dev: "console", test: "console", prod: "wa-cloud" },
16
+ },
17
+ },
18
+ i18n: { locales: ["en", "ar"], default: "en", dir: { ar: "rtl" } },
19
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@oke/template-standard",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "dependencies": {
7
+ "okengine": "file:../..",
8
+ "drizzle-orm": "^1.0.0-rc.4",
9
+ "zod": "^4.4.3"
10
+ },
11
+ "scripts": {
12
+ "test": "bun test",
13
+ "dev": "oke dev"
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ import { db } from "./core";
2
+ import "./gates";
3
+ import "./vault";
4
+ import "./channels";
5
+ import "./locales/en";
6
+ import "./locales/ar";
7
+
8
+ import { oke } from "okengine";
9
+ import * as main from "./flows/main";
10
+
11
+ export const app = oke({ name: "standard" }).adopt({ main });
12
+
13
+ export type App = typeof app;
14
+
15
+ Object.assign(app.$options, {
16
+ env: "test",
17
+ stores: [db],
18
+ });
@@ -0,0 +1,4 @@
1
+ import { channel } from "okengine";
2
+
3
+ // add channel templates here
4
+ void channel;
@@ -0,0 +1,4 @@
1
+ import { store } from "okengine";
2
+ import * as schema from "./schema";
3
+
4
+ export const db = store.sql("app", { schema });
@@ -0,0 +1,31 @@
1
+ import { on, flow, http } from "okengine";
2
+ import { z } from "zod";
3
+
4
+ import "./shapes";
5
+ import "./signals";
6
+
7
+ /** First-run welcome — visit :6530/ after `oke dev`. */
8
+ export const root = on(
9
+ http.get("/"),
10
+ flow({
11
+ out: z.object({
12
+ ok: z.literal(true),
13
+ console: z.string(),
14
+ try: z.string(),
15
+ }),
16
+ do: () => ({
17
+ ok: true as const,
18
+ console: "http://127.0.0.1:6533",
19
+ try: "/health",
20
+ }),
21
+ }),
22
+ );
23
+
24
+ /** Replace with your unit's flows. */
25
+ export const health = on(
26
+ http.get("/health"),
27
+ flow({
28
+ out: z.object({ ok: z.literal(true) }),
29
+ do: () => ({ ok: true as const }),
30
+ }),
31
+ );
@@ -0,0 +1,2 @@
1
+ // add unit shapes here
2
+ export {};
@@ -0,0 +1,4 @@
1
+ import { signal } from "okengine";
2
+
3
+ // add unit signals here
4
+ void signal;
@@ -0,0 +1,4 @@
1
+ import { gate } from "okengine";
2
+
3
+ // add shared gates here
4
+ void gate;
@@ -0,0 +1,2 @@
1
+ /** Locale strings — add keys as channel templates need them. */
2
+ export default {};
@@ -0,0 +1,2 @@
1
+ /** Locale strings — add keys as channel templates need them. */
2
+ export default {};
@@ -0,0 +1,9 @@
1
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
2
+ import { id, now } from "okengine/store";
3
+
4
+ /** Replace with your tables — keep defaults on the schema. */
5
+ export const entries = sqliteTable("entries", {
6
+ id: text("id").primaryKey().$defaultFn(id),
7
+ body: text("body").notNull(),
8
+ createdAt: integer("created_at").notNull().$defaultFn(now),
9
+ });
@@ -0,0 +1,4 @@
1
+ import { vault } from "okengine";
2
+
3
+ // add shared secrets here
4
+ void vault;
@@ -0,0 +1,10 @@
1
+ import { test, expect } from "bun:test";
2
+ import { createTestApp } from "okengine/test";
3
+ import { app } from "../src/app";
4
+
5
+ test("boots — health flow", async () => {
6
+ const t = await createTestApp(app);
7
+ const { data, error } = await t.api.main.health({});
8
+ expect(error).toBeNull();
9
+ expect(data).toEqual({ ok: true });
10
+ });
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes