rastack 0.0.16

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 (140) hide show
  1. package/CHANGELOG.md +43013 -0
  2. package/dist/.prettierrc +7 -0
  3. package/dist/compile/analyze.d.ts +12 -0
  4. package/dist/compile/analyze.js +233 -0
  5. package/dist/compile/index.d.ts +19 -0
  6. package/dist/compile/index.js +107 -0
  7. package/dist/compile/manifest.d.ts +4 -0
  8. package/dist/compile/manifest.js +12 -0
  9. package/dist/compile/model.d.ts +54 -0
  10. package/dist/compile/model.js +7 -0
  11. package/dist/compile/openapi.d.ts +11 -0
  12. package/dist/compile/openapi.js +233 -0
  13. package/dist/compile/program.d.ts +10 -0
  14. package/dist/compile/program.js +61 -0
  15. package/dist/csv-schema.d.ts +28 -0
  16. package/dist/csv-schema.js +162 -0
  17. package/dist/define/index.d.ts +117 -0
  18. package/dist/define/index.js +74 -0
  19. package/dist/entity-generation/delete-method.d.ts +1 -0
  20. package/dist/entity-generation/delete-method.js +31 -0
  21. package/dist/entity-generation/form.d.ts +13 -0
  22. package/dist/entity-generation/form.js +136 -0
  23. package/dist/entity-generation/get-method.d.ts +1 -0
  24. package/dist/entity-generation/get-method.js +67 -0
  25. package/dist/entity-generation/imports.d.ts +5 -0
  26. package/dist/entity-generation/imports.js +91 -0
  27. package/dist/entity-generation/sync-method.d.ts +30 -0
  28. package/dist/entity-generation/sync-method.js +158 -0
  29. package/dist/entity-generation/update-method.d.ts +1 -0
  30. package/dist/entity-generation/update-method.js +29 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +53 -0
  33. package/dist/rad-compile.d.ts +11 -0
  34. package/dist/rad-compile.js +82 -0
  35. package/dist/rad-wasm-build.d.ts +14 -0
  36. package/dist/rad-wasm-build.js +74 -0
  37. package/dist/rad.d.ts +17 -0
  38. package/dist/rad.js +88 -0
  39. package/dist/scan.d.ts +12 -0
  40. package/dist/scan.js +79 -0
  41. package/dist/schema/camel-to-pastel.d.ts +1 -0
  42. package/dist/schema/camel-to-pastel.js +7 -0
  43. package/dist/schema/capitalise-first-letter.d.ts +1 -0
  44. package/dist/schema/capitalise-first-letter.js +7 -0
  45. package/dist/schema/extract-response.d.ts +2 -0
  46. package/dist/schema/extract-response.js +30 -0
  47. package/dist/schema/fetch-schema.d.ts +7 -0
  48. package/dist/schema/fetch-schema.js +23 -0
  49. package/dist/schema/remove-non-model-paths.d.ts +2 -0
  50. package/dist/schema/remove-non-model-paths.js +15 -0
  51. package/dist/schema/to-camel-case.d.ts +1 -0
  52. package/dist/schema/to-camel-case.js +11 -0
  53. package/dist/schema/to-pastel-case.d.ts +1 -0
  54. package/dist/schema/to-pastel-case.js +10 -0
  55. package/dist/schema-convert.d.ts +1 -0
  56. package/dist/schema-convert.js +63 -0
  57. package/dist/schema-entities.d.ts +14 -0
  58. package/dist/schema-entities.js +293 -0
  59. package/dist/schema-fetch.d.ts +1 -0
  60. package/dist/schema-fetch.js +81 -0
  61. package/dist/schema-full.d.ts +1 -0
  62. package/dist/schema-full.js +45 -0
  63. package/dist/schema-index.d.ts +1 -0
  64. package/dist/schema-index.js +34 -0
  65. package/dist/schema-params.d.ts +1 -0
  66. package/dist/schema-params.js +100 -0
  67. package/dist/seed.d.ts +17 -0
  68. package/dist/seed.js +252 -0
  69. package/hooks/form/form.ts +207 -0
  70. package/hooks/form/index.ts +8 -0
  71. package/hooks/form/interfaces.ts +217 -0
  72. package/hooks/form/structure.ts +39 -0
  73. package/hooks/form/validate-schema.ts +49 -0
  74. package/hooks/index.ts +3 -0
  75. package/hooks/query/api.ts +42 -0
  76. package/hooks/query/delete.ts +45 -0
  77. package/hooks/query/fetch.ts +48 -0
  78. package/hooks/query/index.ts +21 -0
  79. package/hooks/query/interfaces.ts +111 -0
  80. package/hooks/query/list.ts +286 -0
  81. package/hooks/query/update.ts +88 -0
  82. package/hooks/query/url.ts +31 -0
  83. package/hooks/real-time/index.ts +1 -0
  84. package/hooks/real-time/pusher.ts +43 -0
  85. package/jest.config.cjs +6 -0
  86. package/package.json +57 -0
  87. package/provider/index.ts +13 -0
  88. package/provider/provider.tsx +187 -0
  89. package/provider/types.ts +114 -0
  90. package/provider/warehouse.ts +167 -0
  91. package/provider/wasm.ts +124 -0
  92. package/runtime.ts +3 -0
  93. package/src/.prettierrc +7 -0
  94. package/src/compile/analyze.ts +224 -0
  95. package/src/compile/index.ts +86 -0
  96. package/src/compile/manifest.ts +10 -0
  97. package/src/compile/model.ts +69 -0
  98. package/src/compile/openapi.ts +266 -0
  99. package/src/compile/program.ts +40 -0
  100. package/src/csv-schema.ts +187 -0
  101. package/src/define/index.ts +162 -0
  102. package/src/entity-generation/delete-method.ts +37 -0
  103. package/src/entity-generation/form.ts +169 -0
  104. package/src/entity-generation/get-method.ts +80 -0
  105. package/src/entity-generation/imports.ts +110 -0
  106. package/src/entity-generation/sync-method.ts +222 -0
  107. package/src/entity-generation/update-method.ts +38 -0
  108. package/src/index.ts +77 -0
  109. package/src/rad-compile.ts +88 -0
  110. package/src/rad-wasm-build.ts +102 -0
  111. package/src/rad.ts +101 -0
  112. package/src/scan.ts +89 -0
  113. package/src/schema/camel-to-pastel.ts +3 -0
  114. package/src/schema/capitalise-first-letter.ts +3 -0
  115. package/src/schema/extract-response.ts +38 -0
  116. package/src/schema/fetch-schema.ts +12 -0
  117. package/src/schema/remove-non-model-paths.ts +13 -0
  118. package/src/schema/to-camel-case.ts +7 -0
  119. package/src/schema/to-pastel-case.ts +6 -0
  120. package/src/schema-convert.ts +61 -0
  121. package/src/schema-entities.ts +401 -0
  122. package/src/schema-fetch.ts +82 -0
  123. package/src/schema-full.ts +38 -0
  124. package/src/schema-index.ts +29 -0
  125. package/src/schema-params.ts +116 -0
  126. package/src/seed.ts +297 -0
  127. package/sync/engine.ts +392 -0
  128. package/sync/hooks.ts +450 -0
  129. package/sync/index.ts +8 -0
  130. package/sync/persistence.ts +237 -0
  131. package/sync/provider.tsx +91 -0
  132. package/sync/registry.ts +36 -0
  133. package/sync/store.ts +126 -0
  134. package/sync/transactions.ts +300 -0
  135. package/sync/types.ts +94 -0
  136. package/test/compile.spec.ts +192 -0
  137. package/test/csv-schema.spec.ts +143 -0
  138. package/test/schema-entities.spec.ts +688 -0
  139. package/tsconfig.json +24 -0
  140. package/types.ts +19 -0
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDeleteAPIMethod = void 0;
4
+ const capitalise_first_letter_1 = require("../schema/capitalise-first-letter");
5
+ function generateDeleteAPIMethod(url, operationId, listQueryCacheKey) {
6
+ var _a;
7
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
8
+ let urlStructure = `'${url}'`;
9
+ const pathParams = ((_a = url.match(/{([^}]+)}/g)) === null || _a === void 0 ? void 0 : _a.map((param) => param.slice(1, -1))) || [];
10
+ if (pathParams.length > 0) {
11
+ urlStructure = url.replace(/{([^}]+)}/g, "${$1}");
12
+ const paramList = pathParams.join(", ");
13
+ urlStructure = `(${paramList}) => \`${urlStructure}\``;
14
+ }
15
+ const importStatements = new Set();
16
+ importStatements.add(`useDeleteQuery`);
17
+ const cacheKeyLine = listQueryCacheKey
18
+ ? `\n listQueryCacheKey: ${listQueryCacheKey},`
19
+ : "";
20
+ return [
21
+ `
22
+ export function use${operationIdUpper}() {
23
+ return useDeleteQuery({
24
+ deleteUrl: ${urlStructure},${cacheKeyLine}
25
+ });
26
+ }
27
+ `,
28
+ importStatements,
29
+ ];
30
+ }
31
+ exports.generateDeleteAPIMethod = generateDeleteAPIMethod;
@@ -0,0 +1,13 @@
1
+ type MutationOperation = {
2
+ operationId: string;
3
+ schema: string;
4
+ };
5
+ type MutationOperations = {
6
+ [path: string]: {
7
+ put?: MutationOperation;
8
+ post?: MutationOperation;
9
+ patch?: MutationOperation;
10
+ };
11
+ };
12
+ export declare function generateUpdateFormMethod(appName: string, modelName: string, mutationOperations: MutationOperations): (string | Set<string>)[];
13
+ export {};
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateUpdateFormMethod = void 0;
4
+ const to_pastel_case_1 = require("../schema/to-pastel-case");
5
+ function generateUpdateFormMethod(appName, modelName, mutationOperations) {
6
+ const modelDetail = (0, to_pastel_case_1.toPascalCase)(modelName);
7
+ const importStatements = new Set();
8
+ const groupedMutations = {};
9
+ Object.entries(mutationOperations).forEach(([path, operations]) => {
10
+ const pathParts = path.split("/");
11
+ const groupDetail = (0, to_pastel_case_1.toPascalCase)(pathParts.slice(3).join("_"));
12
+ const groupDetailClean = cleanGroupDetail(groupDetail);
13
+ const functionName = `useUpdate${modelDetail}${groupDetailClean}Form`;
14
+ const mutations = generateMutations(operations);
15
+ if (mutations) {
16
+ if (!groupedMutations[functionName]) {
17
+ groupedMutations[functionName] = {
18
+ groupDetailClean,
19
+ mutations: [],
20
+ };
21
+ }
22
+ groupedMutations[functionName].mutations.push(mutations);
23
+ Object.values(operations).forEach((operation) => {
24
+ if (operation && operation.schema) {
25
+ importStatements.add(`Deref${operation.schema}`);
26
+ }
27
+ });
28
+ }
29
+ });
30
+ const formCodeGen = Object.entries(groupedMutations)
31
+ .map(([functionName, { groupDetailClean, mutations }]) => generateFormMethod(groupDetailClean, mutations.join(",\n ")))
32
+ .join("\n\n");
33
+ return [formCodeGen, importStatements];
34
+ }
35
+ exports.generateUpdateFormMethod = generateUpdateFormMethod;
36
+ function cleanGroupDetail(groupDetail) {
37
+ return groupDetail
38
+ .replace("V1", "")
39
+ .split("_")
40
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
41
+ .join("")
42
+ .replace(/{([^}]+)}/g, "");
43
+ }
44
+ function generateFormMethod(groupDetailClean, mutations) {
45
+ return `
46
+ export function useUpdate${groupDetailClean}Form<
47
+ TFormValues extends object,
48
+ TPostParams,
49
+ TPutParams,
50
+ TPatchParams,
51
+ TPostPayload,
52
+ TPutPayload,
53
+ TPatchPayload,
54
+ TPostResult,
55
+ TPutResult,
56
+ TPatchResult,
57
+ TFormUpdate extends FormUpdate,
58
+ TSourceId extends string | undefined,
59
+ >({
60
+ id,
61
+ sourceData = {},
62
+ formValues,
63
+ formatResponse,
64
+ transformRequest,
65
+ transformResponse,
66
+ mutations = {
67
+ ${mutations}
68
+ },
69
+ updateType,
70
+ onSuccess
71
+ }: FormProps<
72
+ TFormValues,
73
+ TPostParams,
74
+ TPutParams,
75
+ TPatchParams,
76
+ TPostPayload,
77
+ TPutPayload,
78
+ TPatchPayload,
79
+ TPostResult,
80
+ TPutResult,
81
+ TPatchResult,
82
+ TFormUpdate,
83
+ TSourceId
84
+ >) {
85
+ return useForm<
86
+ TFormValues,
87
+ TPostParams,
88
+ TPutParams,
89
+ TPatchParams,
90
+ TPostPayload,
91
+ TPutPayload,
92
+ TPatchPayload,
93
+ TPostResult,
94
+ TPutResult,
95
+ TPatchResult,
96
+ TFormUpdate,
97
+ TSourceId
98
+ >({
99
+ id,
100
+ mutations,
101
+ formValues,
102
+ sourceData,
103
+ formatResponse,
104
+ transformRequest,
105
+ transformResponse,
106
+ updateType,
107
+ onSuccess
108
+ });
109
+ }`;
110
+ }
111
+ function generateMutations(operations) {
112
+ var _a, _b, _c, _d, _e, _f;
113
+ const mutationStrings = [];
114
+ if (((_a = operations.post) === null || _a === void 0 ? void 0 : _a.operationId) && ((_b = operations.post) === null || _b === void 0 ? void 0 : _b.schema)) {
115
+ mutationStrings.push(`post: {
116
+ // @ts-ignore
117
+ mutation: usePost${operations.post.operationId}(),
118
+ validation: Deref${operations.post.schema}
119
+ }`);
120
+ }
121
+ if (((_c = operations.put) === null || _c === void 0 ? void 0 : _c.operationId) && ((_d = operations.put) === null || _d === void 0 ? void 0 : _d.schema)) {
122
+ mutationStrings.push(`put: {
123
+ // @ts-ignore
124
+ mutation: usePut${operations.put.operationId}(),
125
+ validation: Deref${operations.put.schema}
126
+ }`);
127
+ }
128
+ if (((_e = operations.patch) === null || _e === void 0 ? void 0 : _e.operationId) && ((_f = operations.patch) === null || _f === void 0 ? void 0 : _f.schema)) {
129
+ mutationStrings.push(`patch: {
130
+ // @ts-ignore
131
+ mutation: usePatch${operations.patch.operationId}(),
132
+ validation: Deref${operations.patch.schema}
133
+ }`);
134
+ }
135
+ return mutationStrings.join(",\n ");
136
+ }
@@ -0,0 +1 @@
1
+ export declare function generateGetAPIMethod(url: string, model: string, operationId: string, responseBody: string | undefined, isList: boolean, pathParameters: string[], requiredParameters: string[], method: string, requestBodySchema: string): [string, Set<string>];
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateGetAPIMethod = void 0;
4
+ const capitalise_first_letter_1 = require("../schema/capitalise-first-letter");
5
+ const to_camel_case_1 = require("../schema/to-camel-case");
6
+ function generateGetAPIMethod(url, model, operationId, responseBody, isList, pathParameters, requiredParameters, method, requestBodySchema) {
7
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
8
+ const paramNames = method === "post" ? `I${requestBodySchema}` : `I${operationIdUpper}Params`;
9
+ const modelCamel = (0, to_camel_case_1.toCamelCase)(model);
10
+ url = url.replace("{", "${");
11
+ const pathParameterString = pathParameters.map((item) => {
12
+ return `const ${item} = options?.params?.${item};`;
13
+ });
14
+ const importStatements = new Set();
15
+ if (isList) {
16
+ importStatements.add(`ListQueryOptions, useGetPaginatedQueryList, useUpdateQuery`);
17
+ importStatements.add(paramNames);
18
+ importStatements.add(responseBody !== null && responseBody !== void 0 ? responseBody : "");
19
+ return [
20
+ `
21
+ export function use${operationIdUpper}(
22
+ options?: ListQueryOptions<${paramNames}, ${responseBody}>
23
+ ) {
24
+ const { isAuthenticated } = useAuth0();
25
+ const pathParameters: (keyof ${paramNames})[] = [${pathParameters.map((item) => `'${item}'`).join(", ")}]
26
+ ${pathParameterString.join("\n")}
27
+
28
+ return useGetPaginatedQueryList<${paramNames}, ${responseBody}>({
29
+ ${method}Url: \`${url}\`,
30
+ queryKey: ${modelCamel}QueriesKeys.${operationId},
31
+ pathParameters,
32
+ isAuthenticated,
33
+ options,
34
+ });
35
+ }`,
36
+ importStatements,
37
+ ];
38
+ }
39
+ else {
40
+ importStatements.add(`GetQueryOptions, useGetQuery`);
41
+ importStatements.add(paramNames);
42
+ importStatements.add(responseBody || "");
43
+ return [
44
+ `
45
+ export function use${operationIdUpper}(
46
+ options?: GetQueryOptions<${paramNames}>
47
+ ) {
48
+ const { isAuthenticated } = useAuth0();
49
+ const pathParameters: string[] = [${pathParameters.map((item) => `'${item}'`).join(", ")}]
50
+ ${pathParameterString.join("\n")}
51
+ const requiredParams: string[] = [${requiredParameters.map((item) => `'${item}'`).join(", ")}]
52
+ return useGetQuery<${paramNames}, ${responseBody}>({
53
+ ${method}Url: \`${url}\`,
54
+ queryKey: ${modelCamel}QueriesKeys.${operationId},
55
+ //@ts-ignore
56
+ pathParameters,
57
+ //@ts-ignore
58
+ requiredParams,
59
+ isAuthenticated,
60
+ options,
61
+ });
62
+ }`,
63
+ importStatements,
64
+ ];
65
+ }
66
+ }
67
+ exports.generateGetAPIMethod = generateGetAPIMethod;
@@ -0,0 +1,5 @@
1
+ export declare function removeDuplicateImports(importStatements: string): string;
2
+ export declare function generateImportStatements(importStatements: Set<string>, modelName: string): string;
3
+ export declare function generateKeyImports(model: string, operations: string[]): string;
4
+ export declare function generateIndexImports(model: string, operations: string[]): string;
5
+ export declare function generateFolderImports(models: string[]): string;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFolderImports = exports.generateIndexImports = exports.generateKeyImports = exports.generateImportStatements = exports.removeDuplicateImports = void 0;
4
+ function removeDuplicateImports(importStatements) {
5
+ const importLines = importStatements.split("\n");
6
+ const uniqueImports = new Set();
7
+ const radStackImports = new Set();
8
+ const radSyncImports = new Set();
9
+ const schemaImports = new Set();
10
+ importLines.forEach((line) => {
11
+ var _a, _b, _c;
12
+ if (line.includes("rad-stack/sync")) {
13
+ const imports = ((_a = line
14
+ .match(/\{([^}]+)\}/)) === null || _a === void 0 ? void 0 : _a[1].split(",").map((s) => s.trim())) || [];
15
+ imports.forEach((imp) => radSyncImports.add(imp));
16
+ }
17
+ else if (line.includes("rad-stack/hooks")) {
18
+ const imports = ((_b = line
19
+ .match(/\{([^}]+)\}/)) === null || _b === void 0 ? void 0 : _b[1].split(",").map((s) => s.trim())) || [];
20
+ imports.forEach((imp) => radStackImports.add(imp));
21
+ }
22
+ else if (line.includes("@repo/schema/schema")) {
23
+ const imports = ((_c = line
24
+ .match(/\{([^}]+)\}/)) === null || _c === void 0 ? void 0 : _c[1].split(",").map((s) => s.trim())) || [];
25
+ imports.forEach((imp) => schemaImports.add(imp));
26
+ }
27
+ else {
28
+ uniqueImports.add(line);
29
+ }
30
+ });
31
+ let result = Array.from(uniqueImports).join("\n") + "\n";
32
+ if (radStackImports.size > 0) {
33
+ result += `import { ${Array.from(radStackImports).join(", ")} } from 'rad-stack/hooks';\n`;
34
+ }
35
+ if (radSyncImports.size > 0) {
36
+ result += `import { ${Array.from(radSyncImports).join(", ")} } from 'rad-stack/sync';\n`;
37
+ }
38
+ if (schemaImports.size > 0) {
39
+ result += `import { ${Array.from(schemaImports).join(", ")} } from '@repo/schema/schema';\n`;
40
+ }
41
+ return result;
42
+ }
43
+ exports.removeDuplicateImports = removeDuplicateImports;
44
+ function generateImportStatements(importStatements, modelName) {
45
+ const entries = Array.from(importStatements);
46
+ const syncImports = entries
47
+ .filter((importStatement) => importStatement.startsWith("sync:"))
48
+ .map((importStatement) => importStatement.slice("sync:".length))
49
+ .join(", ");
50
+ const queryImports = entries
51
+ .filter((importStatement) => !importStatement.startsWith("sync:") && importStatement.includes("use"))
52
+ .join(", ");
53
+ const schemaImports = entries
54
+ .filter((importStatement) => importStatement.startsWith("I") || importStatement.startsWith("Deref"))
55
+ .join(", ");
56
+ let importData = "import { useForm, FormProps, FormUpdate, useUpdateQuery } from 'rad-stack/hooks';\n";
57
+ importData = importData + 'import { useAuth0 } from "@auth0/auth0-react";\n';
58
+ if (queryImports) {
59
+ importData += `import { ${queryImports} } from 'rad-stack/hooks';\n`;
60
+ }
61
+ if (syncImports) {
62
+ importData += `import { ${syncImports} } from 'rad-stack/sync';\n`;
63
+ }
64
+ if (schemaImports) {
65
+ importData += `import { ${schemaImports} } from '@repo/schema/schema';\n`;
66
+ }
67
+ return removeDuplicateImports(importData);
68
+ }
69
+ exports.generateImportStatements = generateImportStatements;
70
+ function generateKeyImports(model, operations) {
71
+ model = model.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
72
+ let keyData = `export const ${model}QueriesKeys = {\n`;
73
+ operations.forEach((item) => {
74
+ const snakeCase = item.replace(/([A-Z])/g, "-$1").toLowerCase();
75
+ keyData += ` ${item}: "${snakeCase}",\n`;
76
+ });
77
+ return `${keyData}}`;
78
+ }
79
+ exports.generateKeyImports = generateKeyImports;
80
+ function generateIndexImports(model, operations) {
81
+ return `export * from "./api"`;
82
+ }
83
+ exports.generateIndexImports = generateIndexImports;
84
+ function generateFolderImports(models) {
85
+ let importData = "";
86
+ models.map((model) => {
87
+ importData += `export * from "./${model}"\n`;
88
+ });
89
+ return importData;
90
+ }
91
+ exports.generateFolderImports = generateFolderImports;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generators for sync-mode entities (operations carrying the
3
+ * `x-rastack-sync` OpenAPI extension emitted by rastack). Reads bind to the
4
+ * local store, writes enqueue optimistic transactions, and operations the
5
+ * fat class marked as confirmed become blocking online-only mutations.
6
+ *
7
+ * Imports prefixed with "sync:" are routed to 'rad-stack/sync' by
8
+ * generateImportStatements.
9
+ */
10
+ export interface EntitySyncMeta {
11
+ sync: boolean;
12
+ /** Sync.load = "lazy": excluded from initial bootstrap, loaded on first use. */
13
+ lazy?: boolean;
14
+ /** Sync.client_ids = True: rows use client-generated UUID primary keys. */
15
+ clientIds?: boolean;
16
+ confirmedOperationIds: Set<string>;
17
+ listUrl?: string;
18
+ detailUrl?: string;
19
+ detailParam?: string;
20
+ listOperationId?: string;
21
+ detailOperationId?: string;
22
+ rowSchema?: string;
23
+ }
24
+ export declare function entityConstName(model: string): string;
25
+ export declare function generateEntityDescriptor(appName: string, modelName: string, meta: EntitySyncMeta): [string, Set<string>];
26
+ export declare function generateSyncListMethod(modelName: string, operationId: string, rowSchema: string | undefined): [string, Set<string>];
27
+ export declare function generateSyncRecordMethod(modelName: string, operationId: string, rowSchema: string | undefined, pathParameters: string[]): [string, Set<string>];
28
+ export declare function generateSyncUpdateMethod(url: string, method: string, modelName: string, operationId: string, requestBody: string | undefined, responseBody: string | undefined, pathParameters: string[]): [string, Set<string>];
29
+ export declare function generateSyncDeleteMethod(url: string, modelName: string, operationId: string): [string, Set<string>];
30
+ export declare function generateConfirmedMethod(url: string, method: string, operationId: string, requestBody: string | undefined, responseBody: string | undefined): [string, Set<string>];
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateConfirmedMethod = exports.generateSyncDeleteMethod = exports.generateSyncUpdateMethod = exports.generateSyncRecordMethod = exports.generateSyncListMethod = exports.generateEntityDescriptor = exports.entityConstName = void 0;
4
+ const capitalise_first_letter_1 = require("../schema/capitalise-first-letter");
5
+ const to_camel_case_1 = require("../schema/to-camel-case");
6
+ function entityConstName(model) {
7
+ return `${(0, to_camel_case_1.toCamelCase)(model)}Entity`;
8
+ }
9
+ exports.entityConstName = entityConstName;
10
+ function generateEntityDescriptor(appName, modelName, meta) {
11
+ const importStatements = new Set();
12
+ importStatements.add("sync:defineEntity");
13
+ if (meta.rowSchema) {
14
+ importStatements.add(meta.rowSchema);
15
+ }
16
+ const rowType = meta.rowSchema || "any";
17
+ const listUrl = meta.listUrl ||
18
+ (meta.detailUrl ? meta.detailUrl.replace(/\/?\{[^}]+\}.*$/, "") : "");
19
+ const detailUrl = meta.detailUrl
20
+ ? meta.detailUrl.replace(/\{[^}]+\}/, "${id}")
21
+ : `${listUrl.replace(/\/$/, "")}/\${id}`;
22
+ const lazyLine = meta.lazy ? `\n lazy: true,` : "";
23
+ const clientIdsLine = meta.clientIds ? `\n clientIds: true,` : "";
24
+ return [
25
+ `
26
+ export const ${entityConstName(modelName)} = defineEntity<${rowType}>({
27
+ app: "${appName}",
28
+ model: "${modelName}",
29
+ listUrl: \`${listUrl}\`,
30
+ detailUrl: (id) => \`${detailUrl}\`,${lazyLine}${clientIdsLine}
31
+ });
32
+ `,
33
+ importStatements,
34
+ ];
35
+ }
36
+ exports.generateEntityDescriptor = generateEntityDescriptor;
37
+ function generateSyncListMethod(modelName, operationId, rowSchema) {
38
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
39
+ const rowType = rowSchema || "any";
40
+ const importStatements = new Set();
41
+ importStatements.add("sync:useEntityList");
42
+ importStatements.add("sync:EntityListOptions");
43
+ if (rowSchema) {
44
+ importStatements.add(rowSchema);
45
+ }
46
+ return [
47
+ `
48
+ export function use${operationIdUpper}(
49
+ options?: EntityListOptions<${rowType}>
50
+ ) {
51
+ return useEntityList<${rowType}>(${entityConstName(modelName)}, options);
52
+ }`,
53
+ importStatements,
54
+ ];
55
+ }
56
+ exports.generateSyncListMethod = generateSyncListMethod;
57
+ function generateSyncRecordMethod(modelName, operationId, rowSchema, pathParameters) {
58
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
59
+ const rowType = rowSchema || "any";
60
+ const paramNames = `I${operationIdUpper}Params`;
61
+ const idParam = pathParameters[0];
62
+ const importStatements = new Set();
63
+ importStatements.add("sync:useEntityRecord");
64
+ importStatements.add(`GetQueryOptions, useGetQuery`);
65
+ importStatements.add(paramNames);
66
+ if (rowSchema) {
67
+ importStatements.add(rowSchema);
68
+ }
69
+ return [
70
+ `
71
+ export function use${operationIdUpper}(
72
+ options?: GetQueryOptions<${paramNames}>
73
+ ) {
74
+ const id = options?.params?.${idParam};
75
+ return useEntityRecord<${rowType}>(${entityConstName(modelName)}, id as string | number | undefined);
76
+ }`,
77
+ importStatements,
78
+ ];
79
+ }
80
+ exports.generateSyncRecordMethod = generateSyncRecordMethod;
81
+ function generateSyncUpdateMethod(url, method, modelName, operationId, requestBody, responseBody, pathParameters) {
82
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
83
+ const paramNames = `I${operationIdUpper}Params`;
84
+ const methodUpper = method.charAt(0).toUpperCase() + method.slice(1);
85
+ const isCreate = pathParameters.length === 0;
86
+ const idParam = pathParameters[0];
87
+ let urlStructure = url.replace(/{([^}]+)}/g, "${params.$1}");
88
+ urlStructure = `(params) => \`${urlStructure}\``;
89
+ const importStatements = new Set();
90
+ importStatements.add("sync:useEntityMutation");
91
+ importStatements.add(paramNames);
92
+ if (requestBody) {
93
+ importStatements.add(requestBody);
94
+ }
95
+ if (responseBody) {
96
+ importStatements.add(responseBody);
97
+ }
98
+ const idLine = isCreate
99
+ ? ""
100
+ : `\n id: (params) => params.${idParam} as string | number | undefined,`;
101
+ return [
102
+ `
103
+ export function use${methodUpper}${operationIdUpper}() {
104
+ return useEntityMutation<${paramNames}, ${requestBody || "any"}, ${responseBody || "any"}>(${entityConstName(modelName)}, {
105
+ op: "${isCreate ? "create" : "update"}",
106
+ method: "${method}",
107
+ url: ${urlStructure},${idLine}
108
+ });
109
+ }`,
110
+ importStatements,
111
+ ];
112
+ }
113
+ exports.generateSyncUpdateMethod = generateSyncUpdateMethod;
114
+ function generateSyncDeleteMethod(url, modelName, operationId) {
115
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
116
+ const urlStructure = url.replace(/{[^}]+}/, "${id}");
117
+ const importStatements = new Set();
118
+ importStatements.add("sync:useEntityDelete");
119
+ return [
120
+ `
121
+ export function use${operationIdUpper}() {
122
+ return useEntityDelete(${entityConstName(modelName)}, {
123
+ url: (id) => \`${urlStructure}\`,
124
+ });
125
+ }
126
+ `,
127
+ importStatements,
128
+ ];
129
+ }
130
+ exports.generateSyncDeleteMethod = generateSyncDeleteMethod;
131
+ function generateConfirmedMethod(url, method, operationId, requestBody, responseBody) {
132
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
133
+ const paramNames = `I${operationIdUpper}Params`;
134
+ const methodUpper = method.charAt(0).toUpperCase() + method.slice(1);
135
+ let urlStructure = url.replace(/{([^}]+)}/g, "${params.$1}");
136
+ urlStructure = `(params) => \`${urlStructure}\``;
137
+ const importStatements = new Set();
138
+ importStatements.add("sync:useConfirmedMutation");
139
+ importStatements.add(paramNames);
140
+ if (requestBody) {
141
+ importStatements.add(requestBody);
142
+ }
143
+ if (responseBody) {
144
+ importStatements.add(responseBody);
145
+ }
146
+ return [
147
+ `
148
+ // Confirmed ("sync") operation: blocking, online-only, no optimistic apply.
149
+ export function use${methodUpper}${operationIdUpper}() {
150
+ return useConfirmedMutation<${paramNames}, ${requestBody || "any"}, ${responseBody || "any"}>({
151
+ method: "${method}",
152
+ url: ${urlStructure},
153
+ });
154
+ }`,
155
+ importStatements,
156
+ ];
157
+ }
158
+ exports.generateConfirmedMethod = generateConfirmedMethod;
@@ -0,0 +1 @@
1
+ export declare function generateUpdateAPIMethod(url: string, method: string, operationId: string, requestBody: string | undefined, responseBody: string | undefined, listQueryCacheKey?: string, itemQueryCacheKey?: string): [string, Set<string>];
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateUpdateAPIMethod = void 0;
4
+ const capitalise_first_letter_1 = require("../schema/capitalise-first-letter");
5
+ function generateUpdateAPIMethod(url, method, operationId, requestBody, responseBody, listQueryCacheKey, itemQueryCacheKey) {
6
+ const operationIdUpper = (0, capitalise_first_letter_1.capitaliseFirstLetter)(operationId);
7
+ const paramNames = `I${operationIdUpper}Params`;
8
+ let urlStructure = url.replace(/{([^}]+)}/g, "${params.$1}");
9
+ urlStructure = `(params) => \`${urlStructure}\``;
10
+ const methodUpper = method.charAt(0).toUpperCase() + method.slice(1);
11
+ const importStatements = new Set();
12
+ importStatements.add(paramNames !== null && paramNames !== void 0 ? paramNames : "");
13
+ importStatements.add(requestBody !== null && requestBody !== void 0 ? requestBody : "");
14
+ importStatements.add(responseBody !== null && responseBody !== void 0 ? responseBody : "");
15
+ const cacheKeyLines = [
16
+ listQueryCacheKey ? `\n listQueryCacheKey: ${listQueryCacheKey},` : "",
17
+ itemQueryCacheKey ? `\n itemQueryCacheKey: ${itemQueryCacheKey},` : "",
18
+ ].join("");
19
+ return [
20
+ `
21
+ export function use${methodUpper}${operationIdUpper}() {
22
+ return useUpdateQuery<${paramNames}, ${requestBody}, ${responseBody}>({
23
+ ${method}Url: ${urlStructure},${cacheKeyLines}
24
+ });
25
+ }`,
26
+ importStatements,
27
+ ];
28
+ }
29
+ exports.generateUpdateAPIMethod = generateUpdateAPIMethod;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const child_process_1 = require("child_process");
10
+ const args = process.argv.slice(2);
11
+ const schemaOnly = args.includes("--schema-only");
12
+ const currentDir = process.cwd(); // Get the current working directory
13
+ const kodeDir = path_1.default.join(currentDir, ".kode");
14
+ const configFile = path_1.default.join(kodeDir, "generate-rad-sdk.json");
15
+ let config = {};
16
+ // Create the .kode directory if it doesn't exist
17
+ if (!fs_1.default.existsSync(kodeDir)) {
18
+ fs_1.default.mkdirSync(kodeDir);
19
+ }
20
+ // If the generate-schema-sdk-config.json file doesn't exist, create it with default values
21
+ if (!fs_1.default.existsSync(configFile)) {
22
+ config = {
23
+ schemaUrl: "http://127.0.0.1:8000/api/schema/",
24
+ };
25
+ fs_1.default.writeFileSync(configFile, JSON.stringify(config, null, 2));
26
+ }
27
+ else {
28
+ config = JSON.parse(fs_1.default.readFileSync(configFile, "utf-8"));
29
+ }
30
+ const projectPath = currentDir;
31
+ const schemaUrl = config.schemaUrl;
32
+ // Execute the script commands and print the output
33
+ const schemaFetchOutput = (0, child_process_1.execSync)(`node ${__dirname}/schema-fetch.js ${schemaUrl} ${projectPath}/packages/schema/schema/`).toString();
34
+ console.log(schemaFetchOutput);
35
+ const schemaConvertOutput = (0, child_process_1.execSync)(`node ${__dirname}/schema-convert.js ${projectPath}/packages/schema/schema/`).toString();
36
+ console.log(schemaConvertOutput);
37
+ process.chdir(`${projectPath}/packages/schema/schema/api-schema`);
38
+ const schemaFullOutput = (0, child_process_1.execSync)(`node ${__dirname}/schema-full.js ${projectPath}/packages/schema/schema/`).toString();
39
+ console.log(schemaFullOutput);
40
+ process.chdir(__dirname);
41
+ const schemaParamsOutput = (0, child_process_1.execSync)(`node ${__dirname}/schema-params.js ${schemaUrl} ${projectPath}/packages/schema/schema/`).toString();
42
+ console.log(schemaParamsOutput);
43
+ const schemaIndexOutput = (0, child_process_1.execSync)(`node ${__dirname}/schema-index.js ${projectPath}/packages/schema/schema/`).toString();
44
+ console.log(schemaIndexOutput);
45
+ if (!schemaOnly) {
46
+ // Generate entities if --schema-only flag is not provided
47
+ const schemaEntitiesOutput = (0, child_process_1.execSync)(`node ${__dirname}/schema-entities.js ${schemaUrl} ${projectPath}/packages/entities/`).toString();
48
+ console.log(schemaEntitiesOutput);
49
+ }
50
+ const prettierSchemaOutput = (0, child_process_1.execSync)(`${projectPath}/node_modules/.bin/prettier --write --config .prettierrc ${projectPath}/packages/schema/schema/`).toString();
51
+ console.log(prettierSchemaOutput);
52
+ const prettierEntitiesOutput = (0, child_process_1.execSync)(`${projectPath}/node_modules/.bin/prettier --write --config .prettierrc ${projectPath}/packages/entities/`).toString();
53
+ console.log(prettierEntitiesOutput);
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `rad compile | check | list | urls` — the TypeScript-first replacement for the
4
+ * old Django `manage.py rastack` command.
5
+ *
6
+ * rad compile [resourcesDir] [outDir] defs → schema.rad.json + openapi.json
7
+ * rad check [resourcesDir] validate the resource graph (exit != 0 on error)
8
+ * rad list [resourcesDir] print every resource + its fields/relations
9
+ * rad urls [resourcesDir] print the generated /api/{app}/v1/{model}/ routes
10
+ */
11
+ export {};