@slingr/cli 0.0.2 → 0.0.4

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 (251) hide show
  1. package/LICENSE.txt +202 -0
  2. package/README.md +490 -319
  3. package/bin/dev.cmd +2 -2
  4. package/bin/dev.js +5 -5
  5. package/bin/run.cmd +2 -2
  6. package/bin/run.js +4 -4
  7. package/bin/slingr +1 -0
  8. package/dist/commands/build.d.ts +20 -0
  9. package/dist/commands/build.d.ts.map +1 -0
  10. package/dist/commands/build.js +206 -0
  11. package/dist/commands/build.js.map +1 -0
  12. package/dist/commands/create-app.d.ts +0 -1
  13. package/dist/commands/create-app.d.ts.map +1 -1
  14. package/dist/commands/create-app.js +38 -57
  15. package/dist/commands/create-app.js.map +1 -1
  16. package/dist/commands/debug.d.ts +28 -0
  17. package/dist/commands/debug.d.ts.map +1 -0
  18. package/dist/commands/debug.js +474 -0
  19. package/dist/commands/debug.js.map +1 -0
  20. package/dist/commands/ds.d.ts +14 -1
  21. package/dist/commands/ds.d.ts.map +1 -1
  22. package/dist/commands/ds.js +450 -121
  23. package/dist/commands/ds.js.map +1 -1
  24. package/dist/commands/gql.d.ts +1 -1
  25. package/dist/commands/gql.d.ts.map +1 -1
  26. package/dist/commands/gql.js +190 -184
  27. package/dist/commands/gql.js.map +1 -1
  28. package/dist/commands/infra/down.d.ts.map +1 -1
  29. package/dist/commands/infra/down.js +8 -7
  30. package/dist/commands/infra/down.js.map +1 -1
  31. package/dist/commands/infra/up.d.ts.map +1 -1
  32. package/dist/commands/infra/up.js +8 -7
  33. package/dist/commands/infra/up.js.map +1 -1
  34. package/dist/commands/infra/update.d.ts +1 -0
  35. package/dist/commands/infra/update.d.ts.map +1 -1
  36. package/dist/commands/infra/update.js +33 -69
  37. package/dist/commands/infra/update.js.map +1 -1
  38. package/dist/commands/run.d.ts +29 -2
  39. package/dist/commands/run.d.ts.map +1 -1
  40. package/dist/commands/run.js +628 -130
  41. package/dist/commands/run.js.map +1 -1
  42. package/dist/commands/setup.d.ts +1 -1
  43. package/dist/commands/setup.d.ts.map +1 -1
  44. package/dist/commands/setup.js +34 -71
  45. package/dist/commands/setup.js.map +1 -1
  46. package/dist/commands/sync-metadata.d.ts +15 -0
  47. package/dist/commands/sync-metadata.d.ts.map +1 -0
  48. package/dist/commands/sync-metadata.js +225 -0
  49. package/dist/commands/sync-metadata.js.map +1 -0
  50. package/dist/commands/users.d.ts +30 -0
  51. package/dist/commands/users.d.ts.map +1 -0
  52. package/dist/commands/users.js +472 -0
  53. package/dist/commands/users.js.map +1 -0
  54. package/dist/commands/views.d.ts +11 -0
  55. package/dist/commands/views.d.ts.map +1 -0
  56. package/dist/commands/views.js +73 -0
  57. package/dist/commands/views.js.map +1 -0
  58. package/dist/projectStructure.d.ts +2 -2
  59. package/dist/projectStructure.d.ts.map +1 -1
  60. package/dist/projectStructure.js +281 -69
  61. package/dist/projectStructure.js.map +1 -1
  62. package/dist/scripts/generate-metadata.d.ts +13 -0
  63. package/dist/scripts/generate-metadata.d.ts.map +1 -0
  64. package/dist/scripts/generate-metadata.js +412 -0
  65. package/dist/scripts/generate-metadata.js.map +1 -0
  66. package/dist/scripts/generate-metadata.ts +498 -0
  67. package/dist/scripts/generate-schema.d.ts +1 -1
  68. package/dist/scripts/generate-schema.js +168 -74
  69. package/dist/scripts/generate-schema.js.map +1 -1
  70. package/dist/scripts/generate-schema.ts +258 -143
  71. package/dist/templates/.env.template +23 -0
  72. package/dist/templates/.firebaserc.template +5 -0
  73. package/dist/templates/.github/copilot-instructions.md.template +652 -17
  74. package/dist/templates/backend/Dockerfile.template +30 -0
  75. package/dist/templates/config/datasource.ts.template +12 -9
  76. package/dist/templates/config/jest.config.ts +30 -30
  77. package/dist/templates/config/jest.setup.ts +1 -1
  78. package/dist/templates/config/tsconfig.json.template +50 -29
  79. package/dist/templates/dataSources/mysql.ts.template +16 -13
  80. package/dist/templates/dataSources/postgres.ts.template +15 -13
  81. package/dist/templates/dataset-generator-script.ts.template +139 -139
  82. package/dist/templates/datasets/mysql-default/.slingr-schema.json.template +5 -0
  83. package/dist/templates/datasets/mysql-default/Address.jsonl.template +3 -3
  84. package/dist/templates/datasets/mysql-default/App.jsonl.template +4 -4
  85. package/dist/templates/datasets/mysql-default/Company.jsonl.template +3 -3
  86. package/dist/templates/datasets/mysql-default/Person.jsonl.template +2 -2
  87. package/dist/templates/datasets/mysql-default/User.jsonl.template +1 -0
  88. package/dist/templates/datasets/mysql-default/instructions.md.template +1 -0
  89. package/dist/templates/datasets/postgres-default/.slingr-schema.json.template +5 -0
  90. package/dist/templates/datasets/postgres-default/Address.jsonl.template +3 -3
  91. package/dist/templates/datasets/postgres-default/App.jsonl.template +4 -4
  92. package/dist/templates/datasets/postgres-default/Company.jsonl.template +3 -3
  93. package/dist/templates/datasets/postgres-default/Person.jsonl.template +2 -2
  94. package/dist/templates/datasets/postgres-default/User.jsonl.template +1 -0
  95. package/dist/templates/datasets/postgres-default/instructions.md.template +1 -0
  96. package/dist/templates/docker-compose.prod-test.yml.template +32 -0
  97. package/dist/templates/docker-compose.yml.template +24 -0
  98. package/dist/templates/docs/app-description.md.template +33 -33
  99. package/dist/templates/firebase.json.template +68 -0
  100. package/dist/templates/frontend/.umirc.ts.template +23 -0
  101. package/dist/templates/frontend/package.json.template +45 -0
  102. package/dist/templates/frontend/public/config.json +6 -0
  103. package/dist/templates/frontend/public/logo.svg +6 -0
  104. package/dist/templates/frontend/src/app.tsx.template +44 -0
  105. package/dist/templates/frontend/src/global.less.template +117 -0
  106. package/dist/templates/frontend/src/layouts/MainLayout.tsx.template +75 -0
  107. package/dist/templates/frontend/src/types/graphql-augmentation.d.ts.template +44 -0
  108. package/dist/templates/frontend/src/views/customViews/user/UserCreateView.tsx.template +18 -0
  109. package/dist/templates/frontend/src/views/customViews/user/UserEditView.tsx.template +29 -0
  110. package/dist/templates/frontend/src/views/customViews/user/UserReadView.tsx.template +24 -0
  111. package/dist/templates/frontend/src/views/customViews/user/UserTableView.tsx.template +38 -0
  112. package/dist/templates/frontend/src/views/customViews/welcome.tsx.template +34 -0
  113. package/dist/templates/frontend/tsconfig.json.template +50 -0
  114. package/dist/templates/gql/codegen.yml.template +25 -25
  115. package/dist/templates/gql/index.ts.template +17 -24
  116. package/dist/templates/gql/operations.graphql.template +30 -30
  117. package/dist/templates/ops/README.md.template +1045 -0
  118. package/dist/templates/ops/cloudbuild.yaml.template +161 -0
  119. package/dist/templates/ops/scripts/_utils.js.template +217 -0
  120. package/dist/templates/ops/scripts/deploy.js.template +145 -0
  121. package/dist/templates/ops/scripts/setup-gcp.js.template +330 -0
  122. package/dist/templates/ops/scripts/setup-secrets.js.template +76 -0
  123. package/dist/templates/ops/scripts/test-prod-local.js.template +49 -0
  124. package/dist/templates/package.json.template +50 -38
  125. package/dist/templates/pnpm-workspace.yaml.template +3 -0
  126. package/dist/templates/prompt-analysis.md.template +110 -110
  127. package/dist/templates/prompt-script-generation.md.template +258 -258
  128. package/dist/templates/src/Address.ts.template +28 -31
  129. package/dist/templates/src/App.ts.template +17 -61
  130. package/dist/templates/src/Company.ts.template +41 -47
  131. package/dist/templates/src/Models.test.ts.template +654 -654
  132. package/dist/templates/src/Person.test.ts.template +289 -289
  133. package/dist/templates/src/Person.ts.template +90 -105
  134. package/dist/templates/src/actions/index.ts.template +11 -11
  135. package/dist/templates/src/auth/permissions.ts.template +34 -0
  136. package/dist/templates/src/data/App.ts.template +48 -0
  137. package/dist/templates/src/data/User.ts.template +35 -0
  138. package/dist/templates/src/types/gql.d.ts.template +17 -17
  139. package/dist/templates/vscode/extensions.json +4 -3
  140. package/dist/templates/vscode/settings.json +17 -11
  141. package/dist/templates/workspace-package.json.template +21 -0
  142. package/dist/utils/buildCache.d.ts +12 -0
  143. package/dist/utils/buildCache.d.ts.map +1 -0
  144. package/dist/utils/buildCache.js +102 -0
  145. package/dist/utils/buildCache.js.map +1 -0
  146. package/dist/utils/checkFramework.d.ts +27 -0
  147. package/dist/utils/checkFramework.d.ts.map +1 -0
  148. package/dist/utils/checkFramework.js +104 -0
  149. package/dist/utils/checkFramework.js.map +1 -0
  150. package/dist/utils/datasourceParser.d.ts +11 -0
  151. package/dist/utils/datasourceParser.d.ts.map +1 -1
  152. package/dist/utils/datasourceParser.js +154 -56
  153. package/dist/utils/datasourceParser.js.map +1 -1
  154. package/dist/utils/dockerManager.d.ts +25 -0
  155. package/dist/utils/dockerManager.d.ts.map +1 -0
  156. package/dist/utils/dockerManager.js +281 -0
  157. package/dist/utils/dockerManager.js.map +1 -0
  158. package/dist/utils/infraFileParser.d.ts +26 -0
  159. package/dist/utils/infraFileParser.d.ts.map +1 -0
  160. package/dist/utils/infraFileParser.js +75 -0
  161. package/dist/utils/infraFileParser.js.map +1 -0
  162. package/dist/utils/jsonlLoader.d.ts +91 -12
  163. package/dist/utils/jsonlLoader.d.ts.map +1 -1
  164. package/dist/utils/jsonlLoader.js +674 -63
  165. package/dist/utils/jsonlLoader.js.map +1 -1
  166. package/dist/utils/model-analyzer.d.ts.map +1 -1
  167. package/dist/utils/model-analyzer.js +67 -13
  168. package/dist/utils/model-analyzer.js.map +1 -1
  169. package/dist/utils/userManagement.d.ts +57 -0
  170. package/dist/utils/userManagement.d.ts.map +1 -0
  171. package/dist/utils/userManagement.js +288 -0
  172. package/dist/utils/userManagement.js.map +1 -0
  173. package/dist/utils/viewsGenerator.d.ts +15 -0
  174. package/dist/utils/viewsGenerator.d.ts.map +1 -0
  175. package/dist/utils/viewsGenerator.js +311 -0
  176. package/dist/utils/viewsGenerator.js.map +1 -0
  177. package/oclif.manifest.json +445 -20
  178. package/package.json +29 -27
  179. package/src/templates/.env.template +23 -0
  180. package/src/templates/.firebaserc.template +5 -0
  181. package/src/templates/.github/copilot-instructions.md.template +652 -17
  182. package/src/templates/backend/Dockerfile.template +30 -0
  183. package/src/templates/config/datasource.ts.template +12 -9
  184. package/src/templates/config/jest.config.ts +30 -30
  185. package/src/templates/config/jest.setup.ts +1 -1
  186. package/src/templates/config/tsconfig.json.template +50 -29
  187. package/src/templates/dataSources/mysql.ts.template +16 -13
  188. package/src/templates/dataSources/postgres.ts.template +15 -13
  189. package/src/templates/dataset-generator-script.ts.template +139 -139
  190. package/src/templates/datasets/mysql-default/.slingr-schema.json.template +5 -0
  191. package/src/templates/datasets/mysql-default/Address.jsonl.template +3 -3
  192. package/src/templates/datasets/mysql-default/App.jsonl.template +4 -4
  193. package/src/templates/datasets/mysql-default/Company.jsonl.template +3 -3
  194. package/src/templates/datasets/mysql-default/Person.jsonl.template +2 -2
  195. package/src/templates/datasets/mysql-default/User.jsonl.template +1 -0
  196. package/src/templates/datasets/mysql-default/instructions.md.template +1 -0
  197. package/src/templates/datasets/postgres-default/.slingr-schema.json.template +5 -0
  198. package/src/templates/datasets/postgres-default/Address.jsonl.template +3 -3
  199. package/src/templates/datasets/postgres-default/App.jsonl.template +4 -4
  200. package/src/templates/datasets/postgres-default/Company.jsonl.template +3 -3
  201. package/src/templates/datasets/postgres-default/Person.jsonl.template +2 -2
  202. package/src/templates/datasets/postgres-default/User.jsonl.template +1 -0
  203. package/src/templates/datasets/postgres-default/instructions.md.template +1 -0
  204. package/src/templates/docker-compose.prod-test.yml.template +32 -0
  205. package/src/templates/docker-compose.yml.template +24 -0
  206. package/src/templates/docs/app-description.md.template +33 -33
  207. package/src/templates/firebase.json.template +68 -0
  208. package/src/templates/frontend/.umirc.ts.template +23 -0
  209. package/src/templates/frontend/package.json.template +45 -0
  210. package/src/templates/frontend/public/config.json +6 -0
  211. package/src/templates/frontend/public/logo.svg +6 -0
  212. package/src/templates/frontend/src/app.tsx.template +44 -0
  213. package/src/templates/frontend/src/global.less.template +117 -0
  214. package/src/templates/frontend/src/layouts/MainLayout.tsx.template +75 -0
  215. package/src/templates/frontend/src/types/graphql-augmentation.d.ts.template +44 -0
  216. package/src/templates/frontend/src/views/customViews/user/UserCreateView.tsx.template +18 -0
  217. package/src/templates/frontend/src/views/customViews/user/UserEditView.tsx.template +29 -0
  218. package/src/templates/frontend/src/views/customViews/user/UserReadView.tsx.template +24 -0
  219. package/src/templates/frontend/src/views/customViews/user/UserTableView.tsx.template +38 -0
  220. package/src/templates/frontend/src/views/customViews/welcome.tsx.template +34 -0
  221. package/src/templates/frontend/tsconfig.json.template +50 -0
  222. package/src/templates/gql/codegen.yml.template +25 -25
  223. package/src/templates/gql/index.ts.template +17 -24
  224. package/src/templates/gql/operations.graphql.template +30 -30
  225. package/src/templates/ops/README.md.template +1045 -0
  226. package/src/templates/ops/cloudbuild.yaml.template +161 -0
  227. package/src/templates/ops/scripts/_utils.js.template +217 -0
  228. package/src/templates/ops/scripts/deploy.js.template +145 -0
  229. package/src/templates/ops/scripts/setup-gcp.js.template +330 -0
  230. package/src/templates/ops/scripts/setup-secrets.js.template +76 -0
  231. package/src/templates/ops/scripts/test-prod-local.js.template +49 -0
  232. package/src/templates/package.json.template +50 -38
  233. package/src/templates/pnpm-workspace.yaml.template +3 -0
  234. package/src/templates/prompt-analysis.md.template +110 -110
  235. package/src/templates/prompt-script-generation.md.template +258 -258
  236. package/src/templates/src/Address.ts.template +28 -31
  237. package/src/templates/src/App.ts.template +17 -61
  238. package/src/templates/src/Company.ts.template +41 -47
  239. package/src/templates/src/Models.test.ts.template +654 -654
  240. package/src/templates/src/Person.test.ts.template +289 -289
  241. package/src/templates/src/Person.ts.template +90 -105
  242. package/src/templates/src/actions/index.ts.template +11 -11
  243. package/src/templates/src/auth/permissions.ts.template +34 -0
  244. package/src/templates/src/data/App.ts.template +48 -0
  245. package/src/templates/src/data/User.ts.template +35 -0
  246. package/src/templates/src/types/gql.d.ts.template +17 -17
  247. package/src/templates/vscode/extensions.json +4 -3
  248. package/src/templates/vscode/settings.json +17 -11
  249. package/src/templates/workspace-package.json.template +21 -0
  250. package/dist/templates/src/index.ts +0 -66
  251. package/src/templates/src/index.ts +0 -66
@@ -1,105 +1,90 @@
1
- import { Field, Text, Email, Html, Boolean, Model, BaseModel, Uuid, Integer, SharedComposition } from "slingr-framework";
2
- import { Address } from "./Address";
3
- import { {{DATASOURCE_NAME}} } from "../dataSources/{{DATASOURCE_FILE}}";
4
-
5
- @Model({
6
- docs: "Represents a person",
7
- dataSource: {{DATASOURCE_NAME}}
8
- })
9
- export class Person extends BaseModel {
10
- @Field({
11
- required: true,
12
- primaryKey: true,
13
- })
14
- @Uuid(
15
- {
16
- generated: true
17
- }
18
- )
19
- id!: string;
20
-
21
- @Field({
22
- required: true,
23
- })
24
- @Text({
25
- minLength: 2,
26
- maxLength: 30,
27
- regex: /^[a-zA-Z]+$/,
28
- regexMessage: "firstName must contain only letters",
29
- })
30
- firstName!: string;
31
-
32
- @Field({
33
- required: true,
34
- })
35
- @Text({
36
- minLength: 2,
37
- maxLength: 30,
38
- regex: /^[a-zA-Z]+$/,
39
- regexMessage: "lastName must contain only letters",
40
- })
41
- lastName!: string;
42
-
43
- @Field()
44
- @Email()
45
- email!: string;
46
-
47
- @Field({
48
- validation: (_: number, person: Person) => {
49
- let errors = [];
50
- if (person.age < 0 || person.age > 120) {
51
- errors.push({
52
- constraint: "invalidAge",
53
- message: "Age must be between 0 and 120",
54
- });
55
- }
56
- return errors;
57
- },
58
- required: true,
59
- })
60
- @Integer()
61
- age!: number;
62
-
63
-
64
- @Field({
65
- required: (person: Person) => {
66
- return (person.age < 18);
67
- },
68
- })
69
- @Email()
70
- parentEmail!: string;
71
-
72
-
73
- @Field({
74
- available: false, // This field should be excluded from JSON operations
75
- docs: "Internal identifier not exposed in JSON"
76
- })
77
- @Text()
78
- internalId!: string;
79
-
80
- @Field({
81
- required: false,
82
- available: (person: Person) => {
83
- return person.age >= 18;
84
- },
85
- })
86
- @Text()
87
- phoneNumber!: string;
88
-
89
- @Field()
90
- @Html()
91
- additionalInfo!: string;
92
-
93
- @Field({
94
- required: false,
95
- })
96
- @Boolean()
97
- isActive!: boolean;
98
-
99
- @Field({
100
- required: false
101
- })
102
- @SharedComposition({ elementType: () => Address })
103
- address!: Address;
104
-
105
- }
1
+ import { TextField, EmailField, HtmlField, BooleanField, DataModel, BaseDataModel, UuidField, IntegerField, SharedCompositionField } from "@slingr/framework-backend";
2
+ import { Address } from "./Address";
3
+ import { {{DATASOURCE_NAME}} } from "@/dataSources/{{DATASOURCE_FILE}}";
4
+
5
+ @DataModel({
6
+ docs: "Represents a person",
7
+ dataSource: {{DATASOURCE_NAME}}
8
+ })
9
+ export class Person extends BaseDataModel {
10
+ @UuidField({
11
+ required: true,
12
+ primaryKey: true,
13
+ generated: true
14
+ })
15
+ id!: string;
16
+
17
+ @TextField({
18
+ required: true,
19
+ minLength: 2,
20
+ maxLength: 30,
21
+ regex: /^[a-zA-Z]+$/,
22
+ regexMessage: "firstName must contain only letters",
23
+ })
24
+ firstName!: string;
25
+
26
+ @TextField({
27
+ required: true,
28
+ minLength: 2,
29
+ maxLength: 30,
30
+ regex: /^[a-zA-Z]+$/,
31
+ regexMessage: "lastName must contain only letters",
32
+ })
33
+ lastName!: string;
34
+
35
+ @EmailField()
36
+ email!: string;
37
+
38
+ @IntegerField({
39
+ validation: (_: number, person: Person) => {
40
+ let errors = [];
41
+ if (person.age < 0 || person.age > 120) {
42
+ errors.push({
43
+ constraint: "invalidAge",
44
+ message: "Age must be between 0 and 120",
45
+ });
46
+ }
47
+ return errors;
48
+ },
49
+ required: true,
50
+ })
51
+ age!: number;
52
+
53
+
54
+ @EmailField({
55
+ required: (person: Person) => {
56
+ return (person.age < 18);
57
+ },
58
+ })
59
+ parentEmail!: string;
60
+
61
+
62
+ @TextField({
63
+ available: false, // This field should be excluded from JSON operations
64
+ docs: "Internal identifier not exposed in JSON"
65
+ })
66
+ internalId!: string;
67
+
68
+ @TextField({
69
+ required: false,
70
+ available: (person: Person) => {
71
+ return person.age >= 18;
72
+ },
73
+ })
74
+ phoneNumber!: string;
75
+
76
+ @HtmlField()
77
+ additionalInfo!: string;
78
+
79
+ @BooleanField({
80
+ required: false,
81
+ })
82
+ isActive!: boolean;
83
+
84
+ @SharedCompositionField({
85
+ required: false,
86
+ type: () => Address
87
+ })
88
+ address!: Address;
89
+
90
+ }
@@ -1,12 +1,12 @@
1
- /**
2
- * Actions index file for {{APP_NAME}}
3
- * This file exports all actions that should be available in the GraphQL schema
4
- */
5
-
6
- // Import any custom actions here
7
- // Example:
8
- // export * from './userActions';
9
- // export * from './companyActions';
10
-
11
- // For now, we'll just export an empty object to make the file valid
1
+ /**
2
+ * Actions index file for {{APP_NAME}}
3
+ * This file exports all actions that should be available in the GraphQL schema
4
+ */
5
+
6
+ // Import any custom actions here
7
+ // Example:
8
+ // export * from './userActions';
9
+ // export * from './companyActions';
10
+
11
+ // For now, we'll just export an empty object to make the file valid
12
12
  export {};
@@ -0,0 +1,34 @@
1
+ import { app } from '@slingr/framework-backend';
2
+ import { Role } from '../data/User';
3
+
4
+ // Guest permissions (non-authenticated users)
5
+ // Define what unauthenticated users can access
6
+ app.defineGuestPermissions(({ can, cannot }) => {
7
+ // Example: Allow guests to read public content
8
+ // can('read', 'PublicContent');
9
+ });
10
+
11
+ // Global permissions (all authenticated users)
12
+ // Define what all logged-in users can access
13
+ app.defineGlobalPermissions((user, { can, cannot }) => {
14
+ // Example: Allow all users to read their own profile
15
+ // can('read', 'User', { id: user.id });
16
+ // can('update', 'User', { id: user.id });
17
+ });
18
+
19
+ // Role-based permissions
20
+ // System role can manage everything
21
+ app.definePermissionsForRole(Role.System, (user, { can, cannot }) => {
22
+ can('manage', 'all');
23
+ });
24
+
25
+ // Add more role permissions as needed:
26
+ // app.definePermissionsForRole(Role.Admin, (user, { can, cannot }) => {
27
+ // can('manage', 'User');
28
+ // can('read', 'all');
29
+ // });
30
+ //
31
+ // app.definePermissionsForRole(Role.User, (user, { can, cannot }) => {
32
+ // can('read', 'User', { id: user.id });
33
+ // can('update', 'User', { id: user.id });
34
+ // });
@@ -0,0 +1,48 @@
1
+ import { TextField, DataModel, BaseDataModel, UuidField, ReferenceField } from "@slingr/framework-backend";
2
+ import { Company } from "./Company";
3
+ import { {{DATASOURCE_NAME}} } from "@/dataSources/{{DATASOURCE_FILE}}";
4
+
5
+ @DataModel({
6
+ docs: "Represents an application managed in the system",
7
+ dataSource: {{DATASOURCE_NAME}}
8
+ })
9
+ export class App extends BaseDataModel {
10
+ @UuidField({
11
+ required: true,
12
+ primaryKey: true,
13
+ generated: true
14
+ })
15
+ id!: string;
16
+
17
+ @TextField({
18
+ docs: "The name of the application",
19
+ required: true,
20
+ minLength: 1,
21
+ maxLength: 100,
22
+ regex: /^[A-Za-z0-9][A-Za-z0-9._]*$/,
23
+ regexMessage: "App name must start with a letter or digit and contain only letters, digits, dots, and underscores"
24
+ })
25
+ name!: string;
26
+
27
+ @TextField({
28
+ docs: "The version of the application in format NN.NN.NN",
29
+ required: true,
30
+ regex: /^\d{2}\.\d{2}\.\d{2}$/,
31
+ regexMessage: "Version must follow the format NN.NN.NN (e.g. 01.00.01)"
32
+ })
33
+ version!: string;
34
+
35
+ @TextField({
36
+ docs: "A brief description of the application",
37
+ required: false,
38
+ maxLength: 500
39
+ })
40
+ description?: string;
41
+
42
+ @ReferenceField({
43
+ docs: "The company that owns this application",
44
+ required: true,
45
+ type: () => Company
46
+ })
47
+ ownerCompany!: Company;
48
+ }
@@ -0,0 +1,35 @@
1
+ import { DataModel, Field, UuidField, DateTimeField, ChoiceField, AppUser } from '@slingr/framework-backend';
2
+ import { {{DATASOURCE_NAME}} } from '@/dataSources/{{DATASOURCE_FILE}}';
3
+
4
+ export enum Role {
5
+ System = 'system',
6
+ }
7
+
8
+ @DataModel({
9
+ dataSource: {{DATASOURCE_NAME}},
10
+ crud: {
11
+ generate: true,
12
+ api: 'gql',
13
+ actions: ['create', 'findById', 'findBy', 'update', 'deleteById']
14
+ },
15
+ ui: {
16
+ api: 'gql',
17
+ actions: ['crud', 'refresh']{{USER_UI_VIEW_REFS}}
18
+ }
19
+ })
20
+ export class User extends AppUser<Role> {
21
+ @UuidField({
22
+ primaryKey: true,
23
+ generated: true
24
+ })
25
+ id?: string;
26
+
27
+ @DateTimeField()
28
+ createdAt?: Date;
29
+
30
+ @DateTimeField()
31
+ updatedAt?: Date;
32
+
33
+ @ChoiceField({ type: () => Role })
34
+ roles!: Role[];
35
+ }
@@ -1,18 +1,18 @@
1
- /**
2
- * Temporary type declaration for @gql module
3
- * This file prevents TypeScript compilation errors when the GraphQL SDK hasn't been generated yet.
4
- * It will be automatically replaced when you run: slingr gql generate-sdk
5
- */
6
-
7
- declare module '@gql' {
8
- // Placeholder interface for when SDK is not generated yet
9
- interface PlaceholderGQL {
10
- TestQuery?: () => Promise<any>;
11
- [key: string]: any;
12
- }
13
-
14
- const gql: PlaceholderGQL;
15
- export default gql;
16
- }
17
-
1
+ /**
2
+ * Temporary type declaration for @gql module
3
+ * This file prevents TypeScript compilation errors when the GraphQL SDK hasn't been generated yet.
4
+ * It will be automatically replaced when you run: slingr gql generate-sdk
5
+ */
6
+
7
+ declare module '@gql' {
8
+ // Placeholder interface for when SDK is not generated yet
9
+ interface PlaceholderGQL {
10
+ TestQuery?: () => Promise<any>;
11
+ [key: string]: any;
12
+ }
13
+
14
+ const gql: PlaceholderGQL;
15
+ export default gql;
16
+ }
17
+
18
18
  // This file can be safely deleted after running: slingr gql generate-sdk
@@ -1,3 +1,4 @@
1
- {
2
- "recommendations": ["github.copilot", "slingr.slingr"]
3
- }
1
+ {
2
+ "recommendations": ["github.copilot-chat", "slingr.slingr"],
3
+ "unwantedRecommendations": ["github.copilot"]
4
+ }
@@ -1,11 +1,17 @@
1
- {
2
- "editor.formatOnSave": true,
3
- "editor.inlineSuggest.enabled": true,
4
- "github.copilot.advanced": {},
5
- "github.copilot.enable": {
6
- "*": true,
7
- "markdown": true,
8
- "plaintext": true
9
- },
10
- "typescript.preferences.importModuleSpecifier": "relative"
11
- }
1
+ {
2
+ "editor.tabSize": 4,
3
+ "editor.insertSpaces": true,
4
+ "editor.formatOnSave": true,
5
+ "editor.inlineSuggest.enabled": true,
6
+ "files.autoSave": "afterDelay",
7
+ "github.copilot.advanced": {},
8
+ "github.copilot.enable": {
9
+ "*": true,
10
+ "markdown": true,
11
+ "plaintext": true
12
+ },
13
+ "typescript.preferences.importModuleSpecifier": "non-relative",
14
+ "javascript.preferences.importModuleSpecifier": "non-relative",
15
+ "typescript.updateImportsOnFileMove.enabled": "always",
16
+ "javascript.updateImportsOnFileMove.enabled": "always"
17
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "{{APP_NAME}}",
3
+ "version": "1.0.0",
4
+ "description": "{{DESCRIPTION}}",
5
+ "private": true,
6
+ "scripts": {
7
+ "install:all": "pnpm install",
8
+ "build": "pnpm -r build",
9
+ "build:backend": "pnpm --filter ./backend build",
10
+ "build:frontend": "pnpm --filter ./frontend build",
11
+ "dev": "pnpm --filter ./backend dev",
12
+ "dev:frontend": "pnpm --filter ./frontend dev",
13
+ "start": "pnpm --filter ./backend start",
14
+ "test": "pnpm --filter ./backend test"
15
+ },
16
+ "keywords": [
17
+ "slingr"
18
+ ],
19
+ "author": "",
20
+ "license": "MIT"
21
+ }
@@ -0,0 +1,12 @@
1
+ export interface UpToDateOptions {
2
+ cwd: string;
3
+ sourceGlobs: string[];
4
+ outputFiles: string[];
5
+ sidecarFile?: string;
6
+ }
7
+ export declare function isUpToDate(opts: UpToDateOptions): Promise<boolean>;
8
+ /**
9
+ * Call after generating outputs to update the sidecar file with the current file set.
10
+ */
11
+ export declare function updateFileSetSidecar(opts: UpToDateOptions): Promise<void>;
12
+ //# sourceMappingURL=buildCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildCache.d.ts","sourceRoot":"","sources":["../../src/utils/buildCache.ts"],"names":[],"mappings":"AA8CA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAmCxE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/E"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isUpToDate = isUpToDate;
7
+ exports.updateFileSetSidecar = updateFileSetSidecar;
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const glob_1 = require("glob");
11
+ async function resolveGlobs(baseDir, patterns) {
12
+ const results = [];
13
+ for (const pattern of patterns) {
14
+ if (/[*?{]/.test(pattern)) {
15
+ const matches = await (0, glob_1.glob)(pattern, { cwd: baseDir, absolute: true });
16
+ results.push(...matches);
17
+ }
18
+ else {
19
+ results.push(node_path_1.default.resolve(baseDir, pattern));
20
+ }
21
+ }
22
+ // Sort for deterministic order
23
+ return results.sort();
24
+ }
25
+ async function newestMtime(files) {
26
+ let newest = -Infinity;
27
+ for (const file of files) {
28
+ try {
29
+ newest = Math.max(newest, (await fs_extra_1.default.stat(file)).mtimeMs);
30
+ }
31
+ catch (err) {
32
+ // Intentionally ignore errors when reading mtimes (e.g. missing or transiently inaccessible files)
33
+ void err;
34
+ }
35
+ }
36
+ return newest;
37
+ }
38
+ async function oldestMtime(files) {
39
+ if (files.length === 0) {
40
+ return Infinity;
41
+ }
42
+ let oldest = Infinity;
43
+ for (const file of files) {
44
+ try {
45
+ oldest = Math.min(oldest, (await fs_extra_1.default.stat(file)).mtimeMs);
46
+ }
47
+ catch {
48
+ return -Infinity; // any missing output → stale
49
+ }
50
+ }
51
+ return oldest;
52
+ }
53
+ async function isUpToDate(opts) {
54
+ try {
55
+ const sources = await resolveGlobs(opts.cwd, opts.sourceGlobs);
56
+ if (sources.length === 0) {
57
+ return false;
58
+ } // conservative: no sources → always run
59
+ const outputs = opts.outputFiles.map(f => node_path_1.default.resolve(opts.cwd, f));
60
+ const [newestSrc, oldestOut] = await Promise.all([newestMtime(sources), oldestMtime(outputs)]);
61
+ if (oldestOut === -Infinity) {
62
+ return false;
63
+ } // missing output
64
+ // --- File set tracking logic ---
65
+ if (opts.sidecarFile) {
66
+ const sidecarPath = node_path_1.default.resolve(opts.cwd, opts.sidecarFile);
67
+ let prevFileSet;
68
+ try {
69
+ if (await fs_extra_1.default.pathExists(sidecarPath)) {
70
+ const json = await fs_extra_1.default.readFile(sidecarPath, 'utf-8');
71
+ prevFileSet = JSON.parse(json)?.files;
72
+ }
73
+ }
74
+ catch {
75
+ // ignore, treat as missing
76
+ }
77
+ // Compare sets (sorted)
78
+ const relSources = sources.map(f => node_path_1.default.relative(opts.cwd, f)).sort();
79
+ if (!prevFileSet || prevFileSet.length !== relSources.length || prevFileSet.some((f, i) => f !== relSources[i])) {
80
+ return false; // file set changed
81
+ }
82
+ }
83
+ return oldestOut >= newestSrc;
84
+ }
85
+ catch {
86
+ return false; // graceful fallback: always rebuild on error
87
+ }
88
+ }
89
+ /**
90
+ * Call after generating outputs to update the sidecar file with the current file set.
91
+ */
92
+ async function updateFileSetSidecar(opts) {
93
+ if (!opts.sidecarFile) {
94
+ return;
95
+ }
96
+ const sources = await resolveGlobs(opts.cwd, opts.sourceGlobs);
97
+ const relSources = sources.map(f => node_path_1.default.relative(opts.cwd, f)).sort();
98
+ const sidecarPath = node_path_1.default.resolve(opts.cwd, opts.sidecarFile);
99
+ await fs_extra_1.default.ensureDir(node_path_1.default.dirname(sidecarPath));
100
+ await fs_extra_1.default.writeFile(sidecarPath, JSON.stringify({ files: relSources }, null, 2), 'utf-8');
101
+ }
102
+ //# sourceMappingURL=buildCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildCache.js","sourceRoot":"","sources":["../../src/utils/buildCache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Gets the backend directory path for a Slingr application.
3
+ * All Slingr applications use a workspace structure with backend/ directory.
4
+ *
5
+ * @param cwd - The current working directory (defaults to process.cwd())
6
+ * @returns The path to the backend directory
7
+ */
8
+ export declare function getBackendPath(cwd?: string): string;
9
+ /**
10
+ * Checks if the current directory contains a Slingr application by looking for
11
+ * @slingr/framework-backend in backend/package.json dependencies or devDependencies.
12
+ * Also handles symlinked packages (npm link).
13
+ *
14
+ * @param cwd - The current working directory (defaults to process.cwd())
15
+ * @returns true if framework is found, false otherwise
16
+ */
17
+ export declare function hasSlingrFramework(cwd?: string): Promise<boolean>;
18
+ /**
19
+ * Gets the path to the @slingr/framework-backend package.
20
+ * Checks both backend/node_modules (regular install) and root node_modules (npm workspaces).
21
+ * Handles symlinked packages (npm link).
22
+ *
23
+ * @param cwd - The current working directory (defaults to process.cwd())
24
+ * @returns The path to the framework package, or null if not found
25
+ */
26
+ export declare function getFrameworkPath(cwd?: string): Promise<string | null>;
27
+ //# sourceMappingURL=checkFramework.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkFramework.d.ts","sourceRoot":"","sources":["../../src/utils/checkFramework.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAElE;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAatF;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8B1F"}