rastack 0.0.16 → 0.0.20

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 (105) hide show
  1. package/CHANGELOG.md +43876 -43013
  2. package/dist/.prettierrc +7 -7
  3. package/dist/compile/analyze.js +19 -11
  4. package/dist/compile/index.js +26 -17
  5. package/dist/compile/manifest.js +2 -3
  6. package/dist/compile/openapi.js +5 -8
  7. package/dist/compile/program.js +19 -10
  8. package/dist/csv-schema.js +5 -6
  9. package/dist/define/index.js +2 -2
  10. package/dist/entity-generation/delete-method.js +8 -10
  11. package/dist/entity-generation/form.js +80 -82
  12. package/dist/entity-generation/get-method.js +35 -36
  13. package/dist/entity-generation/imports.js +24 -20
  14. package/dist/entity-generation/sync-method.d.ts +1 -1
  15. package/dist/entity-generation/sync-method.js +45 -46
  16. package/dist/entity-generation/update-method.js +9 -10
  17. package/dist/rad-wasm-build.d.ts +1 -1
  18. package/dist/rad-wasm-build.js +15 -6
  19. package/dist/rad.js +9 -2
  20. package/dist/schema/camel-to-pastel.js +1 -2
  21. package/dist/schema/capitalise-first-letter.js +1 -2
  22. package/dist/schema/extract-response.js +3 -4
  23. package/dist/schema/fetch-schema.js +4 -16
  24. package/dist/schema/remove-non-model-paths.js +1 -2
  25. package/dist/schema/to-camel-case.js +1 -2
  26. package/dist/schema/to-pastel-case.js +1 -2
  27. package/dist/schema-convert.js +22 -33
  28. package/dist/schema-entities.js +177 -189
  29. package/dist/schema-fetch.js +46 -63
  30. package/dist/schema-full.js +23 -36
  31. package/dist/schema-index.js +16 -27
  32. package/dist/schema-params.js +11 -22
  33. package/dist/seed.js +95 -97
  34. package/hooks/form/form.ts +207 -207
  35. package/hooks/form/index.ts +8 -8
  36. package/hooks/form/interfaces.ts +217 -217
  37. package/hooks/form/structure.ts +39 -39
  38. package/hooks/form/validate-schema.ts +49 -49
  39. package/hooks/index.ts +3 -3
  40. package/hooks/query/api.ts +42 -42
  41. package/hooks/query/delete.ts +45 -45
  42. package/hooks/query/fetch.ts +48 -48
  43. package/hooks/query/index.ts +21 -21
  44. package/hooks/query/interfaces.ts +111 -111
  45. package/hooks/query/list.ts +286 -286
  46. package/hooks/query/update.ts +88 -88
  47. package/hooks/query/url.ts +31 -31
  48. package/hooks/real-time/index.ts +1 -1
  49. package/hooks/real-time/pusher.ts +43 -43
  50. package/jest.config.cjs +6 -6
  51. package/package.json +57 -57
  52. package/provider/index.ts +13 -13
  53. package/provider/provider.tsx +187 -187
  54. package/provider/types.ts +114 -114
  55. package/provider/warehouse.ts +167 -167
  56. package/provider/wasm.ts +124 -124
  57. package/runtime.ts +3 -3
  58. package/src/.prettierrc +7 -7
  59. package/src/compile/analyze.ts +224 -224
  60. package/src/compile/index.ts +86 -86
  61. package/src/compile/manifest.ts +10 -10
  62. package/src/compile/model.ts +69 -69
  63. package/src/compile/openapi.ts +266 -266
  64. package/src/compile/program.ts +40 -40
  65. package/src/csv-schema.ts +187 -187
  66. package/src/define/index.ts +162 -162
  67. package/src/entity-generation/delete-method.ts +37 -37
  68. package/src/entity-generation/form.ts +169 -169
  69. package/src/entity-generation/get-method.ts +80 -80
  70. package/src/entity-generation/imports.ts +110 -110
  71. package/src/entity-generation/sync-method.ts +222 -222
  72. package/src/entity-generation/update-method.ts +38 -38
  73. package/src/index.ts +77 -77
  74. package/src/rad-compile.ts +88 -88
  75. package/src/rad-wasm-build.ts +102 -102
  76. package/src/rad.ts +101 -101
  77. package/src/scan.ts +89 -89
  78. package/src/schema/camel-to-pastel.ts +3 -3
  79. package/src/schema/capitalise-first-letter.ts +3 -3
  80. package/src/schema/extract-response.ts +38 -38
  81. package/src/schema/fetch-schema.ts +12 -12
  82. package/src/schema/remove-non-model-paths.ts +13 -13
  83. package/src/schema/to-camel-case.ts +7 -7
  84. package/src/schema/to-pastel-case.ts +6 -6
  85. package/src/schema-convert.ts +61 -61
  86. package/src/schema-entities.ts +401 -401
  87. package/src/schema-fetch.ts +82 -82
  88. package/src/schema-full.ts +38 -38
  89. package/src/schema-index.ts +29 -29
  90. package/src/schema-params.ts +116 -116
  91. package/src/seed.ts +297 -297
  92. package/sync/engine.ts +392 -392
  93. package/sync/hooks.ts +450 -450
  94. package/sync/index.ts +8 -8
  95. package/sync/persistence.ts +237 -237
  96. package/sync/provider.tsx +91 -91
  97. package/sync/registry.ts +36 -36
  98. package/sync/store.ts +126 -126
  99. package/sync/transactions.ts +300 -300
  100. package/sync/types.ts +94 -94
  101. package/test/compile.spec.ts +192 -192
  102. package/test/csv-schema.spec.ts +143 -143
  103. package/test/schema-entities.spec.ts +688 -688
  104. package/tsconfig.json +24 -24
  105. package/types.ts +18 -18
@@ -1,162 +1,162 @@
1
- /**
2
- * rad-tools authoring DSL — the TypeScript-first source of truth.
3
- *
4
- * Resources are authored as plain TypeScript. The compiler
5
- * (`tools/src/compile`) reads these definitions and, crucially, **infers
6
- * foreign-key relations directly from the field types** via the TypeScript type
7
- * checker: a field whose type is a {@link Ref} to another {@link ResourceType}
8
- * is recorded as a foreign key, with the target app/model recovered from the
9
- * `Ref`'s string-literal type arguments.
10
- *
11
- * ```ts
12
- * import { resource, s } from "rad-tools/define";
13
- *
14
- * export const Airport = resource("airports", "airport", {
15
- * code: s.string({ maxLength: 3, unique: true }),
16
- * name: s.string({ maxLength: 120 }),
17
- * }, { search: ["code", "name"], admin: { listDisplay: ["code", "name"] } });
18
- *
19
- * export const Terminal = resource("airports", "terminal", {
20
- * airport: s.ref(() => Airport), // FK inferred from the type of this field
21
- * label: s.string({ maxLength: 20 }),
22
- * });
23
- * ```
24
- */
25
-
26
- /** A scalar field. The literal `__radScalar` type is what the compiler reads. */
27
- export interface Scalar<T extends string> {
28
- readonly __radScalar: T;
29
- }
30
-
31
- /**
32
- * A foreign-key field. `App`/`Model` are carried as string-literal type
33
- * arguments so the compiler can recover the relation target purely from types.
34
- */
35
- export interface Ref<App extends string, Model extends string> {
36
- readonly __radRef: true;
37
- readonly __app: App;
38
- readonly __model: Model;
39
- }
40
-
41
- export interface StringOptions {
42
- maxLength?: number;
43
- unique?: boolean;
44
- primaryKey?: boolean;
45
- default?: string;
46
- null?: boolean;
47
- }
48
-
49
- export interface NumberOptions {
50
- unique?: boolean;
51
- primaryKey?: boolean;
52
- default?: number;
53
- null?: boolean;
54
- }
55
-
56
- export interface BoolOptions {
57
- default?: boolean;
58
- null?: boolean;
59
- }
60
-
61
- export interface DateOptions {
62
- autoNow?: boolean;
63
- autoNowAdd?: boolean;
64
- null?: boolean;
65
- }
66
-
67
- /**
68
- * Field builders. Each returns a phantom value whose *type* encodes the field
69
- * kind; the runtime object is never used at compile time (the compiler analyses
70
- * the source, it does not execute it) but is real so the DSL is also usable at
71
- * runtime if a consumer wants it.
72
- */
73
- export const s = {
74
- string(_opts?: StringOptions): Scalar<"string"> {
75
- return { __radScalar: "string" } as Scalar<"string">;
76
- },
77
- int(_opts?: NumberOptions): Scalar<"int"> {
78
- return { __radScalar: "int" } as Scalar<"int">;
79
- },
80
- float(_opts?: NumberOptions): Scalar<"float"> {
81
- return { __radScalar: "float" } as Scalar<"float">;
82
- },
83
- bool(_opts?: BoolOptions): Scalar<"bool"> {
84
- return { __radScalar: "bool" } as Scalar<"bool">;
85
- },
86
- datetime(_opts?: DateOptions): Scalar<"datetime"> {
87
- return { __radScalar: "datetime" } as Scalar<"datetime">;
88
- },
89
- uuid(_opts?: StringOptions): Scalar<"uuid"> {
90
- return { __radScalar: "uuid" } as Scalar<"uuid">;
91
- },
92
- /**
93
- * A foreign key. The target is `() => SomeResource`; the compiler resolves
94
- * the relation from the *type* `Ref<App, Model>` this returns — it does not
95
- * need to run the thunk.
96
- */
97
- ref<A extends string, M extends string>(
98
- _thunk: () => ResourceType<A, M, any>,
99
- ): Ref<A, M> {
100
- return { __radRef: true } as Ref<A, M>;
101
- },
102
- };
103
-
104
- export type AnyField = Scalar<string> | Ref<string, string>;
105
-
106
- /** Local-first sync configuration (mirrors the old Python `class Sync:`). */
107
- export interface SyncOptions {
108
- mode?: "server" | "local";
109
- scope?: string;
110
- confirmed?: string[];
111
- load?: "instant" | "lazy";
112
- clientIds?: boolean;
113
- }
114
-
115
- export interface ResourceOptions {
116
- /** DRF-style search fields. */
117
- search?: string[];
118
- /** Orderable fields. */
119
- ordering?: string[];
120
- /** Admin config, or `false` to opt out of the admin. */
121
- admin?: { listDisplay?: string[] } | false;
122
- /** Local-first replication config. */
123
- sync?: SyncOptions;
124
- /** Access policy (secure by default). */
125
- permission?: "authenticatedOrReadOnly" | "authenticated" | "public";
126
- }
127
-
128
- /**
129
- * A resource definition. `App`/`Model` are preserved as string-literal type
130
- * arguments so a {@link Ref} to this resource carries a recoverable target.
131
- */
132
- export interface ResourceType<App extends string, Model extends string, F> {
133
- readonly __rad: "resource";
134
- readonly __app: App;
135
- readonly __model: Model;
136
- readonly app: App;
137
- readonly model: Model;
138
- readonly fields: F;
139
- readonly options: ResourceOptions;
140
- }
141
-
142
- /** Define a resource. Capture app/model as literal types for FK inference. */
143
- export function resource<
144
- App extends string,
145
- Model extends string,
146
- F extends Record<string, AnyField>,
147
- >(
148
- app: App,
149
- model: Model,
150
- fields: F,
151
- options: ResourceOptions = {},
152
- ): ResourceType<App, Model, F> {
153
- return {
154
- __rad: "resource",
155
- __app: app,
156
- __model: model,
157
- app,
158
- model,
159
- fields,
160
- options,
161
- };
162
- }
1
+ /**
2
+ * rad-tools authoring DSL — the TypeScript-first source of truth.
3
+ *
4
+ * Resources are authored as plain TypeScript. The compiler
5
+ * (`tools/src/compile`) reads these definitions and, crucially, **infers
6
+ * foreign-key relations directly from the field types** via the TypeScript type
7
+ * checker: a field whose type is a {@link Ref} to another {@link ResourceType}
8
+ * is recorded as a foreign key, with the target app/model recovered from the
9
+ * `Ref`'s string-literal type arguments.
10
+ *
11
+ * ```ts
12
+ * import { resource, s } from "rad-tools/define";
13
+ *
14
+ * export const Airport = resource("airports", "airport", {
15
+ * code: s.string({ maxLength: 3, unique: true }),
16
+ * name: s.string({ maxLength: 120 }),
17
+ * }, { search: ["code", "name"], admin: { listDisplay: ["code", "name"] } });
18
+ *
19
+ * export const Terminal = resource("airports", "terminal", {
20
+ * airport: s.ref(() => Airport), // FK inferred from the type of this field
21
+ * label: s.string({ maxLength: 20 }),
22
+ * });
23
+ * ```
24
+ */
25
+
26
+ /** A scalar field. The literal `__radScalar` type is what the compiler reads. */
27
+ export interface Scalar<T extends string> {
28
+ readonly __radScalar: T;
29
+ }
30
+
31
+ /**
32
+ * A foreign-key field. `App`/`Model` are carried as string-literal type
33
+ * arguments so the compiler can recover the relation target purely from types.
34
+ */
35
+ export interface Ref<App extends string, Model extends string> {
36
+ readonly __radRef: true;
37
+ readonly __app: App;
38
+ readonly __model: Model;
39
+ }
40
+
41
+ export interface StringOptions {
42
+ maxLength?: number;
43
+ unique?: boolean;
44
+ primaryKey?: boolean;
45
+ default?: string;
46
+ null?: boolean;
47
+ }
48
+
49
+ export interface NumberOptions {
50
+ unique?: boolean;
51
+ primaryKey?: boolean;
52
+ default?: number;
53
+ null?: boolean;
54
+ }
55
+
56
+ export interface BoolOptions {
57
+ default?: boolean;
58
+ null?: boolean;
59
+ }
60
+
61
+ export interface DateOptions {
62
+ autoNow?: boolean;
63
+ autoNowAdd?: boolean;
64
+ null?: boolean;
65
+ }
66
+
67
+ /**
68
+ * Field builders. Each returns a phantom value whose *type* encodes the field
69
+ * kind; the runtime object is never used at compile time (the compiler analyses
70
+ * the source, it does not execute it) but is real so the DSL is also usable at
71
+ * runtime if a consumer wants it.
72
+ */
73
+ export const s = {
74
+ string(_opts?: StringOptions): Scalar<"string"> {
75
+ return { __radScalar: "string" } as Scalar<"string">;
76
+ },
77
+ int(_opts?: NumberOptions): Scalar<"int"> {
78
+ return { __radScalar: "int" } as Scalar<"int">;
79
+ },
80
+ float(_opts?: NumberOptions): Scalar<"float"> {
81
+ return { __radScalar: "float" } as Scalar<"float">;
82
+ },
83
+ bool(_opts?: BoolOptions): Scalar<"bool"> {
84
+ return { __radScalar: "bool" } as Scalar<"bool">;
85
+ },
86
+ datetime(_opts?: DateOptions): Scalar<"datetime"> {
87
+ return { __radScalar: "datetime" } as Scalar<"datetime">;
88
+ },
89
+ uuid(_opts?: StringOptions): Scalar<"uuid"> {
90
+ return { __radScalar: "uuid" } as Scalar<"uuid">;
91
+ },
92
+ /**
93
+ * A foreign key. The target is `() => SomeResource`; the compiler resolves
94
+ * the relation from the *type* `Ref<App, Model>` this returns — it does not
95
+ * need to run the thunk.
96
+ */
97
+ ref<A extends string, M extends string>(
98
+ _thunk: () => ResourceType<A, M, any>,
99
+ ): Ref<A, M> {
100
+ return { __radRef: true } as Ref<A, M>;
101
+ },
102
+ };
103
+
104
+ export type AnyField = Scalar<string> | Ref<string, string>;
105
+
106
+ /** Local-first sync configuration (mirrors the old Python `class Sync:`). */
107
+ export interface SyncOptions {
108
+ mode?: "server" | "local";
109
+ scope?: string;
110
+ confirmed?: string[];
111
+ load?: "instant" | "lazy";
112
+ clientIds?: boolean;
113
+ }
114
+
115
+ export interface ResourceOptions {
116
+ /** DRF-style search fields. */
117
+ search?: string[];
118
+ /** Orderable fields. */
119
+ ordering?: string[];
120
+ /** Admin config, or `false` to opt out of the admin. */
121
+ admin?: { listDisplay?: string[] } | false;
122
+ /** Local-first replication config. */
123
+ sync?: SyncOptions;
124
+ /** Access policy (secure by default). */
125
+ permission?: "authenticatedOrReadOnly" | "authenticated" | "public";
126
+ }
127
+
128
+ /**
129
+ * A resource definition. `App`/`Model` are preserved as string-literal type
130
+ * arguments so a {@link Ref} to this resource carries a recoverable target.
131
+ */
132
+ export interface ResourceType<App extends string, Model extends string, F> {
133
+ readonly __rad: "resource";
134
+ readonly __app: App;
135
+ readonly __model: Model;
136
+ readonly app: App;
137
+ readonly model: Model;
138
+ readonly fields: F;
139
+ readonly options: ResourceOptions;
140
+ }
141
+
142
+ /** Define a resource. Capture app/model as literal types for FK inference. */
143
+ export function resource<
144
+ App extends string,
145
+ Model extends string,
146
+ F extends Record<string, AnyField>,
147
+ >(
148
+ app: App,
149
+ model: Model,
150
+ fields: F,
151
+ options: ResourceOptions = {},
152
+ ): ResourceType<App, Model, F> {
153
+ return {
154
+ __rad: "resource",
155
+ __app: app,
156
+ __model: model,
157
+ app,
158
+ model,
159
+ fields,
160
+ options,
161
+ };
162
+ }
@@ -1,37 +1,37 @@
1
- import { capitaliseFirstLetter } from "../schema/capitalise-first-letter";
2
-
3
- export function generateDeleteAPIMethod(
4
- url: string,
5
- operationId: string,
6
- listQueryCacheKey?: string,
7
- ): [string, Set<string>] {
8
- const operationIdUpper = capitaliseFirstLetter(operationId);
9
-
10
- let urlStructure = `'${url}'`;
11
- const pathParams =
12
- url.match(/{([^}]+)}/g)?.map((param) => param.slice(1, -1)) || [];
13
-
14
- if (pathParams.length > 0) {
15
- urlStructure = url.replace(/{([^}]+)}/g, "${$1}");
16
- const paramList = pathParams.join(", ");
17
- urlStructure = `(${paramList}) => \`${urlStructure}\``;
18
- }
19
-
20
- const importStatements = new Set<string>();
21
- importStatements.add(`useDeleteQuery`);
22
-
23
- const cacheKeyLine = listQueryCacheKey
24
- ? `\n listQueryCacheKey: ${listQueryCacheKey},`
25
- : "";
26
-
27
- return [
28
- `
29
- export function use${operationIdUpper}() {
30
- return useDeleteQuery({
31
- deleteUrl: ${urlStructure},${cacheKeyLine}
32
- });
33
- }
34
- `,
35
- importStatements,
36
- ];
37
- }
1
+ import { capitaliseFirstLetter } from "../schema/capitalise-first-letter";
2
+
3
+ export function generateDeleteAPIMethod(
4
+ url: string,
5
+ operationId: string,
6
+ listQueryCacheKey?: string,
7
+ ): [string, Set<string>] {
8
+ const operationIdUpper = capitaliseFirstLetter(operationId);
9
+
10
+ let urlStructure = `'${url}'`;
11
+ const pathParams =
12
+ url.match(/{([^}]+)}/g)?.map((param) => param.slice(1, -1)) || [];
13
+
14
+ if (pathParams.length > 0) {
15
+ urlStructure = url.replace(/{([^}]+)}/g, "${$1}");
16
+ const paramList = pathParams.join(", ");
17
+ urlStructure = `(${paramList}) => \`${urlStructure}\``;
18
+ }
19
+
20
+ const importStatements = new Set<string>();
21
+ importStatements.add(`useDeleteQuery`);
22
+
23
+ const cacheKeyLine = listQueryCacheKey
24
+ ? `\n listQueryCacheKey: ${listQueryCacheKey},`
25
+ : "";
26
+
27
+ return [
28
+ `
29
+ export function use${operationIdUpper}() {
30
+ return useDeleteQuery({
31
+ deleteUrl: ${urlStructure},${cacheKeyLine}
32
+ });
33
+ }
34
+ `,
35
+ importStatements,
36
+ ];
37
+ }