on-zero 0.1.22 → 0.1.24

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 (56) hide show
  1. package/dist/cjs/cli.cjs +17 -424
  2. package/dist/cjs/cli.js +7 -402
  3. package/dist/cjs/cli.js.map +2 -2
  4. package/dist/cjs/cli.native.js +15 -519
  5. package/dist/cjs/cli.native.js.map +1 -1
  6. package/dist/cjs/generate.cjs +370 -0
  7. package/dist/cjs/generate.js +339 -0
  8. package/dist/cjs/generate.js.map +6 -0
  9. package/dist/cjs/generate.native.js +464 -0
  10. package/dist/cjs/generate.native.js.map +1 -0
  11. package/dist/cjs/generate.test.cjs +113 -0
  12. package/dist/cjs/generate.test.js +126 -0
  13. package/dist/cjs/generate.test.js.map +6 -0
  14. package/dist/cjs/generate.test.native.js +116 -0
  15. package/dist/cjs/generate.test.native.js.map +1 -0
  16. package/dist/cjs/vite-plugin.cjs +37 -121
  17. package/dist/cjs/vite-plugin.js +41 -100
  18. package/dist/cjs/vite-plugin.js.map +1 -1
  19. package/dist/cjs/vite-plugin.native.js +47 -157
  20. package/dist/cjs/vite-plugin.native.js.map +1 -1
  21. package/dist/esm/cli.js +8 -388
  22. package/dist/esm/cli.js.map +2 -2
  23. package/dist/esm/cli.mjs +17 -402
  24. package/dist/esm/cli.mjs.map +1 -1
  25. package/dist/esm/cli.native.js +15 -497
  26. package/dist/esm/cli.native.js.map +1 -1
  27. package/dist/esm/generate.js +317 -0
  28. package/dist/esm/generate.js.map +6 -0
  29. package/dist/esm/generate.mjs +335 -0
  30. package/dist/esm/generate.mjs.map +1 -0
  31. package/dist/esm/generate.native.js +426 -0
  32. package/dist/esm/generate.native.js.map +1 -0
  33. package/dist/esm/generate.test.js +130 -0
  34. package/dist/esm/generate.test.js.map +6 -0
  35. package/dist/esm/generate.test.mjs +114 -0
  36. package/dist/esm/generate.test.mjs.map +1 -0
  37. package/dist/esm/generate.test.native.js +114 -0
  38. package/dist/esm/generate.test.native.js.map +1 -0
  39. package/dist/esm/vite-plugin.js +42 -102
  40. package/dist/esm/vite-plugin.js.map +1 -1
  41. package/dist/esm/vite-plugin.mjs +37 -121
  42. package/dist/esm/vite-plugin.mjs.map +1 -1
  43. package/dist/esm/vite-plugin.native.js +47 -157
  44. package/dist/esm/vite-plugin.native.js.map +1 -1
  45. package/package.json +6 -3
  46. package/readme.md +0 -29
  47. package/src/cli.ts +9 -646
  48. package/src/generate.test.ts +201 -0
  49. package/src/generate.ts +491 -0
  50. package/src/vite-plugin.ts +61 -189
  51. package/types/generate.d.ts +21 -0
  52. package/types/generate.d.ts.map +1 -0
  53. package/types/generate.test.d.ts +2 -0
  54. package/types/generate.test.d.ts.map +1 -0
  55. package/types/vite-plugin.d.ts +6 -29
  56. package/types/vite-plugin.d.ts.map +1 -1
@@ -0,0 +1,114 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
5
+ import { generate } from "./generate.mjs";
6
+ const testDir = join(tmpdir(), "on-zero-test-" + Date.now());
7
+ beforeEach(() => {
8
+ mkdirSync(join(testDir, "models"), {
9
+ recursive: !0
10
+ }), mkdirSync(join(testDir, "queries"), {
11
+ recursive: !0
12
+ });
13
+ });
14
+ afterEach(() => {
15
+ rmSync(testDir, {
16
+ recursive: !0,
17
+ force: !0
18
+ });
19
+ });
20
+ describe("generate", () => {
21
+ test("generates models.ts, types.ts, tables.ts from model files", async () => {
22
+ writeFileSync(join(testDir, "models/post.ts"), `
23
+ import { table, string, boolean } from 'on-zero'
24
+
25
+ export const schema = table('post', {
26
+ id: string(),
27
+ title: string(),
28
+ published: boolean(),
29
+ })
30
+ `), writeFileSync(join(testDir, "models/comment.ts"), `
31
+ import { table, string } from 'on-zero'
32
+
33
+ export const schema = table('comment', {
34
+ id: string(),
35
+ postId: string(),
36
+ body: string(),
37
+ })
38
+ `);
39
+ const result = await generate({
40
+ dir: testDir,
41
+ silent: !0
42
+ });
43
+ expect(result.modelCount).toBe(2), expect(result.schemaCount).toBe(2), expect(result.filesChanged).toBeGreaterThan(0), expect(existsSync(join(testDir, "generated/models.ts"))).toBe(!0), expect(existsSync(join(testDir, "generated/types.ts"))).toBe(!0), expect(existsSync(join(testDir, "generated/tables.ts"))).toBe(!0);
44
+ const modelsContent = readFileSync(join(testDir, "generated/models.ts"), "utf-8");
45
+ expect(modelsContent).toContain("import * as comment from '../models/comment'"), expect(modelsContent).toContain("import * as post from '../models/post'"), expect(modelsContent).toContain("export const models = {");
46
+ const typesContent = readFileSync(join(testDir, "generated/types.ts"), "utf-8");
47
+ expect(typesContent).toContain("export type Post = TableInsertRow<typeof schema.post>"), expect(typesContent).toContain("export type Comment = TableInsertRow<typeof schema.comment>");
48
+ const tablesContent = readFileSync(join(testDir, "generated/tables.ts"), "utf-8");
49
+ expect(tablesContent).toContain("export { schema as post } from '../models/post'"), expect(tablesContent).toContain("export { schema as comment } from '../models/comment'");
50
+ }), test("generates query validators from query files", async () => {
51
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })"), writeFileSync(join(testDir, "queries/post.ts"), `
52
+ import { zero } from '../zero'
53
+
54
+ export const allPosts = () => zero.query.post
55
+
56
+ export const postById = ({ id }: { id: string }) => zero.query.post.where('id', id)
57
+
58
+ export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: number }) =>
59
+ zero.query.post.where('authorId', authorId).limit(limit ?? 10)
60
+ `);
61
+ const result = await generate({
62
+ dir: testDir,
63
+ silent: !0
64
+ });
65
+ expect(result.queryCount).toBe(3), expect(existsSync(join(testDir, "generated/groupedQueries.ts"))).toBe(!0), expect(existsSync(join(testDir, "generated/syncedQueries.ts"))).toBe(!0);
66
+ const groupedContent = readFileSync(join(testDir, "generated/groupedQueries.ts"), "utf-8");
67
+ expect(groupedContent).toContain("export * as post from '../queries/post'");
68
+ const syncedContent = readFileSync(join(testDir, "generated/syncedQueries.ts"), "utf-8");
69
+ expect(syncedContent).toContain("allPosts: defineQuery"), expect(syncedContent).toContain("postById: defineQuery"), expect(syncedContent).toContain("postsByAuthor: defineQuery"), expect(syncedContent).toContain("v.object");
70
+ }), test("skips permission exports in queries", async () => {
71
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })"), writeFileSync(join(testDir, "queries/post.ts"), `
72
+ export const permission = () => ({ canRead: true })
73
+ export const allPosts = () => zero.query.post
74
+ `);
75
+ const result = await generate({
76
+ dir: testDir,
77
+ silent: !0
78
+ });
79
+ expect(result.queryCount).toBe(1);
80
+ const syncedContent = readFileSync(join(testDir, "generated/syncedQueries.ts"), "utf-8");
81
+ expect(syncedContent).toContain("allPosts"), expect(syncedContent).not.toContain("permission:");
82
+ }), test("handles user model special case (userPublic)", async () => {
83
+ writeFileSync(join(testDir, "models/user.ts"), "export const schema = table('user', { id: string(), name: string() })"), await generate({
84
+ dir: testDir,
85
+ silent: !0
86
+ });
87
+ const modelsContent = readFileSync(join(testDir, "generated/models.ts"), "utf-8");
88
+ expect(modelsContent).toContain("import * as userPublic from '../models/user'"), expect(modelsContent).toContain("userPublic,");
89
+ const typesContent = readFileSync(join(testDir, "generated/types.ts"), "utf-8");
90
+ expect(typesContent).toContain("typeof schema.userPublic");
91
+ }), test("runs after command when files change", async () => {
92
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })");
93
+ const markerFile = join(testDir, "after-ran"),
94
+ result = await generate({
95
+ dir: testDir,
96
+ silent: !0,
97
+ after: `touch ${markerFile}`
98
+ });
99
+ expect(result.filesChanged).toBeGreaterThan(0), expect(existsSync(markerFile)).toBe(!0);
100
+ }), test("does not regenerate when nothing changed", async () => {
101
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })");
102
+ const first = await generate({
103
+ dir: testDir,
104
+ silent: !0
105
+ });
106
+ expect(first.filesChanged).toBeGreaterThan(0);
107
+ const second = await generate({
108
+ dir: testDir,
109
+ silent: !0
110
+ });
111
+ expect(second.filesChanged).toBe(0);
112
+ });
113
+ });
114
+ //# sourceMappingURL=generate.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","tmpdir","join","afterEach","beforeEach","describe","expect","test","generate","testDir","Date","now","recursive","force","result","dir","silent","modelCount","toBe","schemaCount","filesChanged","toBeGreaterThan","modelsContent","toContain","typesContent","tablesContent","queryCount","groupedContent","syncedContent","not","markerFile","after","first","second"],"sources":["../../src/generate.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,114 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
2
+ import { tmpdir } from "os";
3
+ import { join } from "path";
4
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
5
+ import { generate } from "./generate.native.js";
6
+ var testDir = join(tmpdir(), "on-zero-test-" + Date.now());
7
+ beforeEach(function () {
8
+ mkdirSync(join(testDir, "models"), {
9
+ recursive: !0
10
+ }), mkdirSync(join(testDir, "queries"), {
11
+ recursive: !0
12
+ });
13
+ });
14
+ afterEach(function () {
15
+ rmSync(testDir, {
16
+ recursive: !0,
17
+ force: !0
18
+ });
19
+ });
20
+ describe("generate", function () {
21
+ test("generates models.ts, types.ts, tables.ts from model files", async function () {
22
+ writeFileSync(join(testDir, "models/post.ts"), `
23
+ import { table, string, boolean } from 'on-zero'
24
+
25
+ export const schema = table('post', {
26
+ id: string(),
27
+ title: string(),
28
+ published: boolean(),
29
+ })
30
+ `), writeFileSync(join(testDir, "models/comment.ts"), `
31
+ import { table, string } from 'on-zero'
32
+
33
+ export const schema = table('comment', {
34
+ id: string(),
35
+ postId: string(),
36
+ body: string(),
37
+ })
38
+ `);
39
+ var result = await generate({
40
+ dir: testDir,
41
+ silent: !0
42
+ });
43
+ expect(result.modelCount).toBe(2), expect(result.schemaCount).toBe(2), expect(result.filesChanged).toBeGreaterThan(0), expect(existsSync(join(testDir, "generated/models.ts"))).toBe(!0), expect(existsSync(join(testDir, "generated/types.ts"))).toBe(!0), expect(existsSync(join(testDir, "generated/tables.ts"))).toBe(!0);
44
+ var modelsContent = readFileSync(join(testDir, "generated/models.ts"), "utf-8");
45
+ expect(modelsContent).toContain("import * as comment from '../models/comment'"), expect(modelsContent).toContain("import * as post from '../models/post'"), expect(modelsContent).toContain("export const models = {");
46
+ var typesContent = readFileSync(join(testDir, "generated/types.ts"), "utf-8");
47
+ expect(typesContent).toContain("export type Post = TableInsertRow<typeof schema.post>"), expect(typesContent).toContain("export type Comment = TableInsertRow<typeof schema.comment>");
48
+ var tablesContent = readFileSync(join(testDir, "generated/tables.ts"), "utf-8");
49
+ expect(tablesContent).toContain("export { schema as post } from '../models/post'"), expect(tablesContent).toContain("export { schema as comment } from '../models/comment'");
50
+ }), test("generates query validators from query files", async function () {
51
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })"), writeFileSync(join(testDir, "queries/post.ts"), `
52
+ import { zero } from '../zero'
53
+
54
+ export const allPosts = () => zero.query.post
55
+
56
+ export const postById = ({ id }: { id: string }) => zero.query.post.where('id', id)
57
+
58
+ export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: number }) =>
59
+ zero.query.post.where('authorId', authorId).limit(limit ?? 10)
60
+ `);
61
+ var result = await generate({
62
+ dir: testDir,
63
+ silent: !0
64
+ });
65
+ expect(result.queryCount).toBe(3), expect(existsSync(join(testDir, "generated/groupedQueries.ts"))).toBe(!0), expect(existsSync(join(testDir, "generated/syncedQueries.ts"))).toBe(!0);
66
+ var groupedContent = readFileSync(join(testDir, "generated/groupedQueries.ts"), "utf-8");
67
+ expect(groupedContent).toContain("export * as post from '../queries/post'");
68
+ var syncedContent = readFileSync(join(testDir, "generated/syncedQueries.ts"), "utf-8");
69
+ expect(syncedContent).toContain("allPosts: defineQuery"), expect(syncedContent).toContain("postById: defineQuery"), expect(syncedContent).toContain("postsByAuthor: defineQuery"), expect(syncedContent).toContain("v.object");
70
+ }), test("skips permission exports in queries", async function () {
71
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })"), writeFileSync(join(testDir, "queries/post.ts"), `
72
+ export const permission = () => ({ canRead: true })
73
+ export const allPosts = () => zero.query.post
74
+ `);
75
+ var result = await generate({
76
+ dir: testDir,
77
+ silent: !0
78
+ });
79
+ expect(result.queryCount).toBe(1);
80
+ var syncedContent = readFileSync(join(testDir, "generated/syncedQueries.ts"), "utf-8");
81
+ expect(syncedContent).toContain("allPosts"), expect(syncedContent).not.toContain("permission:");
82
+ }), test("handles user model special case (userPublic)", async function () {
83
+ writeFileSync(join(testDir, "models/user.ts"), "export const schema = table('user', { id: string(), name: string() })"), await generate({
84
+ dir: testDir,
85
+ silent: !0
86
+ });
87
+ var modelsContent = readFileSync(join(testDir, "generated/models.ts"), "utf-8");
88
+ expect(modelsContent).toContain("import * as userPublic from '../models/user'"), expect(modelsContent).toContain("userPublic,");
89
+ var typesContent = readFileSync(join(testDir, "generated/types.ts"), "utf-8");
90
+ expect(typesContent).toContain("typeof schema.userPublic");
91
+ }), test("runs after command when files change", async function () {
92
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })");
93
+ var markerFile = join(testDir, "after-ran"),
94
+ result = await generate({
95
+ dir: testDir,
96
+ silent: !0,
97
+ after: `touch ${markerFile}`
98
+ });
99
+ expect(result.filesChanged).toBeGreaterThan(0), expect(existsSync(markerFile)).toBe(!0);
100
+ }), test("does not regenerate when nothing changed", async function () {
101
+ writeFileSync(join(testDir, "models/post.ts"), "export const schema = table('post', { id: string() })");
102
+ var first = await generate({
103
+ dir: testDir,
104
+ silent: !0
105
+ });
106
+ expect(first.filesChanged).toBeGreaterThan(0);
107
+ var second = await generate({
108
+ dir: testDir,
109
+ silent: !0
110
+ });
111
+ expect(second.filesChanged).toBe(0);
112
+ });
113
+ });
114
+ //# sourceMappingURL=generate.test.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","tmpdir","join","afterEach","beforeEach","describe","expect","test","generate","testDir","Date","now","recursive","force","result","dir","silent","modelCount","toBe","schemaCount","filesChanged","toBeGreaterThan","modelsContent","toContain","typesContent","tablesContent","queryCount","groupedContent","syncedContent","not","markerFile","after","first","second"],"sources":["../../src/generate.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -1,127 +1,67 @@
1
- import { createHash } from "node:crypto";
2
- import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
3
- import { basename, resolve } from "node:path";
4
- const hash = (s) => createHash("sha256").update(s).digest("hex");
5
- let generateCache = {};
6
- function writeFileIfChanged(filePath, content) {
7
- const contentHash = hash(content);
8
- return generateCache[filePath] === contentHash && existsSync(filePath) ? !1 : (writeFileSync(filePath, content, "utf-8"), generateCache[filePath] = contentHash, !0);
9
- }
10
- function generateModelsFile(modelFiles) {
11
- const modelNames = modelFiles.map((f) => basename(f, ".ts")).sort(), getImportName = (name) => name === "user" ? "userPublic" : name, imports = modelNames.map((name) => `import * as ${getImportName(name)} from '../models/${name}'`).join(`
12
- `), modelsObj = `export const models = {
13
- ${[...modelNames].sort(
14
- (a, b) => getImportName(a).localeCompare(getImportName(b))
15
- ).map((name) => ` ${getImportName(name)},`).join(`
16
- `)}
17
- }`;
18
- return `// auto-generated by on-zero vite plugin
19
- ${imports}
20
-
21
- ${modelsObj}
22
-
23
- if (import.meta.hot) {
24
- import.meta.hot.accept()
25
- }
26
- `;
27
- }
28
- function generateTypesFile(modelFiles) {
29
- const modelNames = modelFiles.map((f) => basename(f, ".ts")).sort(), getSchemaName = (name) => name === "user" ? "userPublic" : name;
30
- return `import type { TableInsertRow, TableUpdateRow } from 'on-zero'
31
- import type * as schema from './tables'
32
-
33
- ${modelNames.map((name) => {
34
- const pascalName = name.charAt(0).toUpperCase() + name.slice(1), schemaName = getSchemaName(name);
35
- return `export type ${pascalName} = TableInsertRow<typeof schema.${schemaName}>
36
- export type ${pascalName}Update = TableUpdateRow<typeof schema.${schemaName}>`;
37
- }).join(`
38
-
39
- `)}
40
- `;
41
- }
42
- function generateTablesFile(modelFiles) {
43
- const modelNames = modelFiles.map((f) => basename(f, ".ts")).sort(), getExportName = (name) => name === "user" ? "userPublic" : name;
44
- return `// auto-generated by on-zero vite plugin
45
-
46
- ${modelNames.map((name) => `export { schema as ${getExportName(name)} } from '../models/${name}'`).join(`
47
- `)}
48
- `;
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { generate } from "./generate";
3
+ function createOnZeroHmrPlugin(hmrInclude = []) {
4
+ const hmrPaths = ["/models/", "/generated/", "/queries/", ...hmrInclude];
5
+ return {
6
+ name: "on-zero:hmr",
7
+ apply: "serve",
8
+ enforce: "post",
9
+ transform(code, id) {
10
+ if (!(!hmrPaths.some((p) => id.includes(p)) || !/\.tsx?$/.test(id)) && code.includes("import.meta.hot.invalidate"))
11
+ return {
12
+ code: code.replace(
13
+ /if\s*\(invalidateMessage\)\s*import\.meta\.hot\.invalidate\(invalidateMessage\);?/g,
14
+ "/* on-zero: HMR invalidate disabled */"
15
+ ),
16
+ map: null
17
+ };
18
+ }
19
+ };
49
20
  }
50
- async function runGenerate(options) {
51
- const { modelsDir, generatedDir, silent } = options;
52
- existsSync(generatedDir) || mkdirSync(generatedDir, { recursive: !0 });
53
- const allModelFiles = readdirSync(modelsDir).filter((f) => f.endsWith(".ts")).sort(), filesWithSchema = allModelFiles.filter(
54
- (f) => readFileSync(resolve(modelsDir, f), "utf-8").includes("export const schema = table(")
55
- ), filesChanged = [
56
- writeFileIfChanged(
57
- resolve(generatedDir, "models.ts"),
58
- generateModelsFile(allModelFiles)
59
- ),
60
- writeFileIfChanged(
61
- resolve(generatedDir, "types.ts"),
62
- generateTypesFile(filesWithSchema)
63
- ),
64
- writeFileIfChanged(
65
- resolve(generatedDir, "tables.ts"),
66
- generateTablesFile(filesWithSchema)
67
- )
68
- ].filter(Boolean).length;
69
- return filesChanged > 0 && !silent && console.info(`[on-zero] generated ${filesChanged} file(s)`), filesChanged;
21
+ function isWithinDirectory(file, dir) {
22
+ const rel = relative(dir, file);
23
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
70
24
  }
71
25
  function onZeroPlugin(options = {}) {
72
- const dataDir = options.dataDir || "src/data", hmrPaths = ["/models/", "/generated/", ...options.hmrInclude || []];
73
- let modelsDir, generatedDir;
26
+ const dir = options.dir ?? "src/data";
27
+ let dataDir, modelsDir, queriesDir;
28
+ const runGenerate = (silent) => generate({
29
+ dir: dataDir,
30
+ after: options.after,
31
+ silent
32
+ });
74
33
  return [
75
- // generation plugin
76
34
  {
77
- name: "on-zero:generate",
35
+ name: "on-zero:serve",
78
36
  apply: "serve",
79
37
  configResolved(config) {
80
- modelsDir = resolve(config.root, dataDir, "models"), generatedDir = resolve(config.root, dataDir, "generated");
38
+ dataDir = resolve(config.root, dir), modelsDir = resolve(dataDir, "models"), queriesDir = resolve(dataDir, "queries");
81
39
  },
82
40
  async buildStart() {
83
- options.disableGenerate || await runGenerate({ modelsDir, generatedDir, silent: !1 });
41
+ options.disableGenerate || await runGenerate(!1);
84
42
  },
85
43
  configureServer(server) {
86
- options.disableGenerate || (server.watcher.on("change", async (file) => {
87
- file.includes(modelsDir) && await runGenerate({ modelsDir, generatedDir, silent: !1 });
88
- }), server.watcher.on("add", async (file) => {
89
- file.includes(modelsDir) && await runGenerate({ modelsDir, generatedDir, silent: !1 });
90
- }), server.watcher.on("unlink", async (file) => {
91
- file.includes(modelsDir) && await runGenerate({ modelsDir, generatedDir, silent: !1 });
92
- }));
44
+ if (options.disableGenerate) return;
45
+ const handler = async (file) => {
46
+ /\.tsx?$/.test(file) && (isWithinDirectory(file, modelsDir) || isWithinDirectory(file, queriesDir)) && await runGenerate(!1);
47
+ };
48
+ server.watcher.on("change", handler), server.watcher.on("add", handler), server.watcher.on("unlink", handler);
93
49
  }
94
50
  },
95
- // HMR plugin - removes invalidate calls to prevent cascade
96
- {
97
- name: "on-zero:hmr",
98
- apply: "serve",
99
- enforce: "post",
100
- transform(code, id) {
101
- if (hmrPaths.some((p) => id.includes(p)) && /\.tsx?$/.test(id) && code.includes("import.meta.hot.invalidate"))
102
- return {
103
- code: code.replace(
104
- /if\s*\(invalidateMessage\)\s*import\.meta\.hot\.invalidate\(invalidateMessage\);?/g,
105
- "/* on-zero: HMR invalidate disabled */"
106
- ),
107
- map: null
108
- };
109
- }
110
- },
111
- // build plugin - generate once before build
112
51
  {
113
52
  name: "on-zero:build",
114
53
  apply: "build",
115
54
  configResolved(config) {
116
- modelsDir = resolve(config.root, dataDir, "models"), generatedDir = resolve(config.root, dataDir, "generated");
55
+ dataDir = resolve(config.root, dir);
117
56
  },
118
57
  async buildStart() {
119
- options.disableGenerate || await runGenerate({ modelsDir, generatedDir, silent: !0 });
58
+ options.disableGenerate || await runGenerate(!0);
120
59
  }
121
- }
60
+ },
61
+ createOnZeroHmrPlugin(options.hmrInclude)
122
62
  ];
123
63
  }
124
- const onZeroHmrPlugin = (options) => onZeroPlugin({ hmrInclude: options?.include, disableGenerate: !0 })[1];
64
+ const onZeroHmrPlugin = (options) => createOnZeroHmrPlugin(options?.include);
125
65
  var vite_plugin_default = onZeroPlugin;
126
66
  export {
127
67
  vite_plugin_default as default,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/vite-plugin.ts"],
4
- "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,YAAY,WAAW,aAAa,cAAc,qBAAqB;AAChF,SAAS,UAAU,eAAe;AAIlC,MAAM,OAAO,CAAC,MAAc,WAAW,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK;AAGvE,IAAI,gBAAwC,CAAC;AAE7C,SAAS,mBAAmB,UAAkB,SAA0B;AACtE,QAAM,cAAc,KAAK,OAAO;AAChC,SAAI,cAAc,QAAQ,MAAM,eAAe,WAAW,QAAQ,IACzD,MAET,cAAc,UAAU,SAAS,OAAO,GACxC,cAAc,QAAQ,IAAI,aACnB;AACT;AAEA,SAAS,mBAAmB,YAAsB;AAChD,QAAM,aAAa,WAAW,IAAI,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,EAAE,KAAK,GAC5D,gBAAgB,CAAC,SAAkB,SAAS,SAAS,eAAe,MAEpE,UAAU,WACb,IAAI,CAAC,SAAS,eAAe,cAAc,IAAI,CAAC,oBAAoB,IAAI,GAAG,EAC3E,KAAK;AAAA,CAAI,GAKN,YAAY;AAAA,EAHS,CAAC,GAAG,UAAU,EAAE;AAAA,IAAK,CAAC,GAAG,MAClD,cAAc,CAAC,EAAE,cAAc,cAAc,CAAC,CAAC;AAAA,EACjD,EACiE,IAAI,CAAC,SAAS,KAAK,cAAc,IAAI,CAAC,GAAG,EAAE,KAAK;AAAA,CAAI,CAAC;AAAA;AAQtH,SAAO;AAAA,EAA6C,OAAO;AAAA;AAAA,EAAO,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAC7E;AAEA,SAAS,kBAAkB,YAAsB;AAC/C,QAAM,aAAa,WAAW,IAAI,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,EAAE,KAAK,GAC5D,gBAAgB,CAAC,SAAkB,SAAS,SAAS,eAAe;AAU1E,SAAO;AAAA;AAAA;AAAA,EARa,WACjB,IAAI,CAAC,SAAS;AACb,UAAM,aAAa,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,GACxD,aAAa,cAAc,IAAI;AACrC,WAAO,eAAe,UAAU,mCAAmC,UAAU;AAAA,cAAkB,UAAU,yCAAyC,UAAU;AAAA,EAC9J,CAAC,EACA,KAAK;AAAA;AAAA,CAAM,CAEiH;AAAA;AACjI;AAEA,SAAS,mBAAmB,YAAsB;AAChD,QAAM,aAAa,WAAW,IAAI,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,EAAE,KAAK,GAC5D,gBAAgB,CAAC,SAAkB,SAAS,SAAS,eAAe;AAM1E,SAAO;AAAA;AAAA,EAJS,WACb,IAAI,CAAC,SAAS,sBAAsB,cAAc,IAAI,CAAC,sBAAsB,IAAI,GAAG,EACpF,KAAK;AAAA,CAAI,CAEiD;AAAA;AAC/D;AAEA,eAAe,YAAY,SAIxB;AACD,QAAM,EAAE,WAAW,cAAc,OAAO,IAAI;AAE5C,EAAK,WAAW,YAAY,KAC1B,UAAU,cAAc,EAAE,WAAW,GAAK,CAAC;AAG7C,QAAM,gBAAgB,YAAY,SAAS,EACxC,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,EAC/B,KAAK,GAEF,kBAAkB,cAAc;AAAA,IAAO,CAAC,MAC5C,aAAa,QAAQ,WAAW,CAAC,GAAG,OAAO,EAAE,SAAS,8BAA8B;AAAA,EACtF,GAiBM,eAfe;AAAA,IACnB;AAAA,MACE,QAAQ,cAAc,WAAW;AAAA,MACjC,mBAAmB,aAAa;AAAA,IAClC;AAAA,IACA;AAAA,MACE,QAAQ,cAAc,UAAU;AAAA,MAChC,kBAAkB,eAAe;AAAA,IACnC;AAAA,IACA;AAAA,MACE,QAAQ,cAAc,WAAW;AAAA,MACjC,mBAAmB,eAAe;AAAA,IACpC;AAAA,EACF,EAEkC,OAAO,OAAO,EAAE;AAClD,SAAI,eAAe,KAAK,CAAC,UACvB,QAAQ,KAAK,uBAAuB,YAAY,UAAU,GAGrD;AACT;AAqCO,SAAS,aAAa,UAA+B,CAAC,GAAa;AACxE,QAAM,UAAU,QAAQ,WAAW,YAC7B,WAAW,CAAC,YAAY,eAAe,GAAI,QAAQ,cAAc,CAAC,CAAE;AAE1E,MAAI,WACA;AAEJ,SAAO;AAAA;AAAA,IAEL;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MAEP,eAAe,QAAQ;AACrB,oBAAY,QAAQ,OAAO,MAAM,SAAS,QAAQ,GAClD,eAAe,QAAQ,OAAO,MAAM,SAAS,WAAW;AAAA,MAC1D;AAAA,MAEA,MAAM,aAAa;AACjB,QAAI,QAAQ,mBACZ,MAAM,YAAY,EAAE,WAAW,cAAc,QAAQ,GAAM,CAAC;AAAA,MAC9D;AAAA,MAEA,gBAAgB,QAAQ;AACtB,QAAI,QAAQ,oBAGZ,OAAO,QAAQ,GAAG,UAAU,OAAO,SAAS;AAC1C,UAAI,KAAK,SAAS,SAAS,KACzB,MAAM,YAAY,EAAE,WAAW,cAAc,QAAQ,GAAM,CAAC;AAAA,QAEhE,CAAC,GAED,OAAO,QAAQ,GAAG,OAAO,OAAO,SAAS;AACvC,UAAI,KAAK,SAAS,SAAS,KACzB,MAAM,YAAY,EAAE,WAAW,cAAc,QAAQ,GAAM,CAAC;AAAA,QAEhE,CAAC,GAED,OAAO,QAAQ,GAAG,UAAU,OAAO,SAAS;AAC1C,UAAI,KAAK,SAAS,SAAS,KACzB,MAAM,YAAY,EAAE,WAAW,cAAc,QAAQ,GAAM,CAAC;AAAA,QAEhE,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA,IAGA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS;AAAA,MAET,UAAU,MAAM,IAAI;AAGlB,YAFwB,SAAS,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,UAAU,KAAK,EAAE,KAE1D,KAAK,SAAS,4BAA4B;AAC/D,iBAAO;AAAA,YACL,MAAM,KAAK;AAAA,cACT;AAAA,cACA;AAAA,YACF;AAAA,YACA,KAAK;AAAA,UACP;AAAA,MAEJ;AAAA,IACF;AAAA;AAAA,IAGA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MAEP,eAAe,QAAQ;AACrB,oBAAY,QAAQ,OAAO,MAAM,SAAS,QAAQ,GAClD,eAAe,QAAQ,OAAO,MAAM,SAAS,WAAW;AAAA,MAC1D;AAAA,MAEA,MAAM,aAAa;AACjB,QAAI,QAAQ,mBACZ,MAAM,YAAY,EAAE,WAAW,cAAc,QAAQ,GAAK,CAAC;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AACF;AAGO,MAAM,kBAAkB,CAAC,YACvB,aAAa,EAAE,YAAY,SAAS,SAAS,iBAAiB,GAAK,CAAC,EAAE,CAAC;AAGhF,IAAO,sBAAQ;",
4
+ "mappings": "AAAA,SAAS,YAAY,UAAU,eAAe;AAE9C,SAAS,gBAAsC;AAa/C,SAAS,sBAAsB,aAAuB,CAAC,GAAW;AAChE,QAAM,WAAW,CAAC,YAAY,eAAe,aAAa,GAAG,UAAU;AAEvE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IAET,UAAU,MAAM,IAAI;AAClB,UAAI,GAAC,SAAS,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,MAC1D,KAAK,SAAS,4BAA4B;AAE/C,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,YACT;AAAA,YACA;AAAA,UACF;AAAA,UACA,KAAK;AAAA,QACP;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,MAAc,KAAsB;AAC7D,QAAM,MAAM,SAAS,KAAK,IAAI;AAC9B,SAAO,QAAQ,MAAM,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,WAAW,GAAG;AAC/D;AAEO,SAAS,aAAa,UAA+B,CAAC,GAAa;AACxE,QAAM,MAAM,QAAQ,OAAO;AAE3B,MAAI,SACA,WACA;AAEJ,QAAM,cAAc,CAAC,WACnB,SAAS;AAAA,IACP,KAAK;AAAA,IACL,OAAO,QAAQ;AAAA,IACf;AAAA,EACF,CAAC;AAEH,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MAEP,eAAe,QAAQ;AACrB,kBAAU,QAAQ,OAAO,MAAM,GAAG,GAClC,YAAY,QAAQ,SAAS,QAAQ,GACrC,aAAa,QAAQ,SAAS,SAAS;AAAA,MACzC;AAAA,MAEA,MAAM,aAAa;AACjB,QAAK,QAAQ,mBAAiB,MAAM,YAAY,EAAK;AAAA,MACvD;AAAA,MAEA,gBAAgB,QAAQ;AACtB,YAAI,QAAQ,gBAAiB;AAE7B,cAAM,UAAU,OAAO,SAAiB;AACtC,UAAK,UAAU,KAAK,IAAI,MACpB,kBAAkB,MAAM,SAAS,KAAK,kBAAkB,MAAM,UAAU,MAC1E,MAAM,YAAY,EAAK;AAAA,QAE3B;AAEA,eAAO,QAAQ,GAAG,UAAU,OAAO,GACnC,OAAO,QAAQ,GAAG,OAAO,OAAO,GAChC,OAAO,QAAQ,GAAG,UAAU,OAAO;AAAA,MACrC;AAAA,IACF;AAAA,IAEA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MAEP,eAAe,QAAQ;AACrB,kBAAU,QAAQ,OAAO,MAAM,GAAG;AAAA,MACpC;AAAA,MAEA,MAAM,aAAa;AACjB,QAAK,QAAQ,mBAAiB,MAAM,YAAY,EAAI;AAAA,MACtD;AAAA,IACF;AAAA,IAEA,sBAAsB,QAAQ,UAAU;AAAA,EAC1C;AACF;AAEO,MAAM,kBAAkB,CAAC,YACvB,sBAAsB,SAAS,OAAO;AAG/C,IAAO,sBAAQ;",
5
5
  "names": []
6
6
  }
@@ -1,143 +1,59 @@
1
- import { createHash } from "node:crypto";
2
- import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
3
- import { basename, resolve } from "node:path";
4
- const hash = s => createHash("sha256").update(s).digest("hex");
5
- let generateCache = {};
6
- function writeFileIfChanged(filePath, content) {
7
- const contentHash = hash(content);
8
- return generateCache[filePath] === contentHash && existsSync(filePath) ? !1 : (writeFileSync(filePath, content, "utf-8"), generateCache[filePath] = contentHash, !0);
9
- }
10
- function generateModelsFile(modelFiles) {
11
- const modelNames = modelFiles.map(f => basename(f, ".ts")).sort(),
12
- getImportName = name => name === "user" ? "userPublic" : name,
13
- imports = modelNames.map(name => `import * as ${getImportName(name)} from '../models/${name}'`).join(`
14
- `),
15
- modelsObj = `export const models = {
16
- ${[...modelNames].sort((a, b) => getImportName(a).localeCompare(getImportName(b))).map(name => ` ${getImportName(name)},`).join(`
17
- `)}
18
- }`;
19
- return `// auto-generated by on-zero vite plugin
20
- ${imports}
21
-
22
- ${modelsObj}
23
-
24
- if (import.meta.hot) {
25
- import.meta.hot.accept()
26
- }
27
- `;
28
- }
29
- function generateTypesFile(modelFiles) {
30
- const modelNames = modelFiles.map(f => basename(f, ".ts")).sort(),
31
- getSchemaName = name => name === "user" ? "userPublic" : name;
32
- return `import type { TableInsertRow, TableUpdateRow } from 'on-zero'
33
- import type * as schema from './tables'
34
-
35
- ${modelNames.map(name => {
36
- const pascalName = name.charAt(0).toUpperCase() + name.slice(1),
37
- schemaName = getSchemaName(name);
38
- return `export type ${pascalName} = TableInsertRow<typeof schema.${schemaName}>
39
- export type ${pascalName}Update = TableUpdateRow<typeof schema.${schemaName}>`;
40
- }).join(`
41
-
42
- `)}
43
- `;
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { generate } from "./generate.mjs";
3
+ function createOnZeroHmrPlugin(hmrInclude = []) {
4
+ const hmrPaths = ["/models/", "/generated/", "/queries/", ...hmrInclude];
5
+ return {
6
+ name: "on-zero:hmr",
7
+ apply: "serve",
8
+ enforce: "post",
9
+ transform(code, id) {
10
+ if (!(!hmrPaths.some(p => id.includes(p)) || !/\.tsx?$/.test(id)) && code.includes("import.meta.hot.invalidate")) return {
11
+ code: code.replace(/if\s*\(invalidateMessage\)\s*import\.meta\.hot\.invalidate\(invalidateMessage\);?/g, "/* on-zero: HMR invalidate disabled */"),
12
+ map: null
13
+ };
14
+ }
15
+ };
44
16
  }
45
- function generateTablesFile(modelFiles) {
46
- const modelNames = modelFiles.map(f => basename(f, ".ts")).sort(),
47
- getExportName = name => name === "user" ? "userPublic" : name;
48
- return `// auto-generated by on-zero vite plugin
49
-
50
- ${modelNames.map(name => `export { schema as ${getExportName(name)} } from '../models/${name}'`).join(`
51
- `)}
52
- `;
17
+ function isWithinDirectory(file, dir) {
18
+ const rel = relative(dir, file);
19
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
53
20
  }
54
- async function runGenerate(options) {
55
- const {
56
- modelsDir,
57
- generatedDir,
21
+ function onZeroPlugin(options = {}) {
22
+ const dir = options.dir ?? "src/data";
23
+ let dataDir, modelsDir, queriesDir;
24
+ const runGenerate = silent => generate({
25
+ dir: dataDir,
26
+ after: options.after,
58
27
  silent
59
- } = options;
60
- existsSync(generatedDir) || mkdirSync(generatedDir, {
61
- recursive: !0
62
28
  });
63
- const allModelFiles = readdirSync(modelsDir).filter(f => f.endsWith(".ts")).sort(),
64
- filesWithSchema = allModelFiles.filter(f => readFileSync(resolve(modelsDir, f), "utf-8").includes("export const schema = table(")),
65
- filesChanged = [writeFileIfChanged(resolve(generatedDir, "models.ts"), generateModelsFile(allModelFiles)), writeFileIfChanged(resolve(generatedDir, "types.ts"), generateTypesFile(filesWithSchema)), writeFileIfChanged(resolve(generatedDir, "tables.ts"), generateTablesFile(filesWithSchema))].filter(Boolean).length;
66
- return filesChanged > 0 && !silent && console.info(`[on-zero] generated ${filesChanged} file(s)`), filesChanged;
67
- }
68
- function onZeroPlugin(options = {}) {
69
- const dataDir = options.dataDir || "src/data",
70
- hmrPaths = ["/models/", "/generated/", ...(options.hmrInclude || [])];
71
- let modelsDir, generatedDir;
72
- return [
73
- // generation plugin
74
- {
75
- name: "on-zero:generate",
29
+ return [{
30
+ name: "on-zero:serve",
76
31
  apply: "serve",
77
32
  configResolved(config) {
78
- modelsDir = resolve(config.root, dataDir, "models"), generatedDir = resolve(config.root, dataDir, "generated");
33
+ dataDir = resolve(config.root, dir), modelsDir = resolve(dataDir, "models"), queriesDir = resolve(dataDir, "queries");
79
34
  },
80
35
  async buildStart() {
81
- options.disableGenerate || (await runGenerate({
82
- modelsDir,
83
- generatedDir,
84
- silent: !1
85
- }));
36
+ options.disableGenerate || (await runGenerate(!1));
86
37
  },
87
38
  configureServer(server) {
88
- options.disableGenerate || (server.watcher.on("change", async file => {
89
- file.includes(modelsDir) && (await runGenerate({
90
- modelsDir,
91
- generatedDir,
92
- silent: !1
93
- }));
94
- }), server.watcher.on("add", async file => {
95
- file.includes(modelsDir) && (await runGenerate({
96
- modelsDir,
97
- generatedDir,
98
- silent: !1
99
- }));
100
- }), server.watcher.on("unlink", async file => {
101
- file.includes(modelsDir) && (await runGenerate({
102
- modelsDir,
103
- generatedDir,
104
- silent: !1
105
- }));
106
- }));
107
- }
108
- },
109
- // HMR plugin - removes invalidate calls to prevent cascade
110
- {
111
- name: "on-zero:hmr",
112
- apply: "serve",
113
- enforce: "post",
114
- transform(code, id) {
115
- if (hmrPaths.some(p => id.includes(p)) && /\.tsx?$/.test(id) && code.includes("import.meta.hot.invalidate")) return {
116
- code: code.replace(/if\s*\(invalidateMessage\)\s*import\.meta\.hot\.invalidate\(invalidateMessage\);?/g, "/* on-zero: HMR invalidate disabled */"),
117
- map: null
39
+ if (options.disableGenerate) return;
40
+ const handler = async file => {
41
+ /\.tsx?$/.test(file) && (isWithinDirectory(file, modelsDir) || isWithinDirectory(file, queriesDir)) && (await runGenerate(!1));
118
42
  };
43
+ server.watcher.on("change", handler), server.watcher.on("add", handler), server.watcher.on("unlink", handler);
119
44
  }
120
- },
121
- // build plugin - generate once before build
122
- {
45
+ }, {
123
46
  name: "on-zero:build",
124
47
  apply: "build",
125
48
  configResolved(config) {
126
- modelsDir = resolve(config.root, dataDir, "models"), generatedDir = resolve(config.root, dataDir, "generated");
49
+ dataDir = resolve(config.root, dir);
127
50
  },
128
51
  async buildStart() {
129
- options.disableGenerate || (await runGenerate({
130
- modelsDir,
131
- generatedDir,
132
- silent: !0
133
- }));
52
+ options.disableGenerate || (await runGenerate(!0));
134
53
  }
135
- }];
54
+ }, createOnZeroHmrPlugin(options.hmrInclude)];
136
55
  }
137
- const onZeroHmrPlugin = options => onZeroPlugin({
138
- hmrInclude: options?.include,
139
- disableGenerate: !0
140
- })[1];
56
+ const onZeroHmrPlugin = options => createOnZeroHmrPlugin(options?.include);
141
57
  var vite_plugin_default = onZeroPlugin;
142
58
  export { vite_plugin_default as default, onZeroHmrPlugin, onZeroPlugin };
143
59
  //# sourceMappingURL=vite-plugin.mjs.map