@ryanatkn/gro 0.112.0

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 (222) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +257 -0
  3. package/dist/args.d.ts +59 -0
  4. package/dist/args.js +132 -0
  5. package/dist/args.test.d.ts +1 -0
  6. package/dist/args.test.js +43 -0
  7. package/dist/build.task.d.ts +11 -0
  8. package/dist/build.task.js +24 -0
  9. package/dist/changelog.d.ts +8 -0
  10. package/dist/changelog.js +47 -0
  11. package/dist/changelog.test.d.ts +1 -0
  12. package/dist/changelog.test.js +118 -0
  13. package/dist/changeset.task.d.ts +49 -0
  14. package/dist/changeset.task.js +141 -0
  15. package/dist/check.task.d.ts +47 -0
  16. package/dist/check.task.js +77 -0
  17. package/dist/clean.task.d.ts +26 -0
  18. package/dist/clean.task.js +41 -0
  19. package/dist/clean_fs.d.ts +9 -0
  20. package/dist/clean_fs.js +27 -0
  21. package/dist/cli.d.ts +11 -0
  22. package/dist/cli.js +25 -0
  23. package/dist/commit.task.d.ts +11 -0
  24. package/dist/commit.task.js +22 -0
  25. package/dist/config.d.ts +21 -0
  26. package/dist/config.js +42 -0
  27. package/dist/config.test.d.ts +1 -0
  28. package/dist/config.test.js +8 -0
  29. package/dist/deploy.task.d.ts +47 -0
  30. package/dist/deploy.task.js +198 -0
  31. package/dist/dev.task.d.ts +22 -0
  32. package/dist/dev.task.js +32 -0
  33. package/dist/docs/README.gen.md.d.ts +5 -0
  34. package/dist/docs/README.gen.md.js +53 -0
  35. package/dist/docs/README.md +20 -0
  36. package/dist/docs/build.md +41 -0
  37. package/dist/docs/config.md +162 -0
  38. package/dist/docs/deploy.md +32 -0
  39. package/dist/docs/dev.md +40 -0
  40. package/dist/docs/gen.md +241 -0
  41. package/dist/docs/gro_plugin_sveltekit_frontend.md +97 -0
  42. package/dist/docs/package_json.md +29 -0
  43. package/dist/docs/plugin.md +50 -0
  44. package/dist/docs/publish.md +144 -0
  45. package/dist/docs/task.md +377 -0
  46. package/dist/docs/tasks.gen.md.d.ts +2 -0
  47. package/dist/docs/tasks.gen.md.js +60 -0
  48. package/dist/docs/tasks.md +35 -0
  49. package/dist/docs/test.md +52 -0
  50. package/dist/env.d.ts +10 -0
  51. package/dist/env.js +47 -0
  52. package/dist/esbuild_helpers.d.ts +14 -0
  53. package/dist/esbuild_helpers.js +36 -0
  54. package/dist/esbuild_plugin_external_worker.d.ts +22 -0
  55. package/dist/esbuild_plugin_external_worker.js +49 -0
  56. package/dist/esbuild_plugin_svelte.d.ts +9 -0
  57. package/dist/esbuild_plugin_svelte.js +49 -0
  58. package/dist/esbuild_plugin_sveltekit_local_imports.d.ts +7 -0
  59. package/dist/esbuild_plugin_sveltekit_local_imports.js +30 -0
  60. package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts +6 -0
  61. package/dist/esbuild_plugin_sveltekit_shim_alias.js +16 -0
  62. package/dist/esbuild_plugin_sveltekit_shim_app.d.ts +8 -0
  63. package/dist/esbuild_plugin_sveltekit_shim_app.js +23 -0
  64. package/dist/esbuild_plugin_sveltekit_shim_env.d.ts +10 -0
  65. package/dist/esbuild_plugin_sveltekit_shim_env.js +18 -0
  66. package/dist/format.task.d.ts +11 -0
  67. package/dist/format.task.js +24 -0
  68. package/dist/format_directory.d.ts +2 -0
  69. package/dist/format_directory.js +27 -0
  70. package/dist/format_file.d.ts +8 -0
  71. package/dist/format_file.js +42 -0
  72. package/dist/format_file.test.d.ts +1 -0
  73. package/dist/format_file.test.js +16 -0
  74. package/dist/fs.d.ts +7 -0
  75. package/dist/fs.js +19 -0
  76. package/dist/fs.test.d.ts +1 -0
  77. package/dist/fs.test.js +16 -0
  78. package/dist/gen.d.ts +57 -0
  79. package/dist/gen.js +81 -0
  80. package/dist/gen.task.d.ts +14 -0
  81. package/dist/gen.task.js +103 -0
  82. package/dist/gen.test.d.ts +1 -0
  83. package/dist/gen.test.js +239 -0
  84. package/dist/gen_module.d.ts +46 -0
  85. package/dist/gen_module.js +54 -0
  86. package/dist/gen_module.test.d.ts +1 -0
  87. package/dist/gen_module.test.js +30 -0
  88. package/dist/git.d.ts +76 -0
  89. package/dist/git.js +200 -0
  90. package/dist/git.test.d.ts +1 -0
  91. package/dist/git.test.js +18 -0
  92. package/dist/github.d.ts +35 -0
  93. package/dist/github.js +32 -0
  94. package/dist/gro.config.default.d.ts +12 -0
  95. package/dist/gro.config.default.js +31 -0
  96. package/dist/gro.d.ts +2 -0
  97. package/dist/gro.js +19 -0
  98. package/dist/gro_helpers.d.ts +43 -0
  99. package/dist/gro_helpers.js +79 -0
  100. package/dist/gro_plugin_gen.d.ts +6 -0
  101. package/dist/gro_plugin_gen.js +80 -0
  102. package/dist/gro_plugin_server.d.ts +77 -0
  103. package/dist/gro_plugin_server.js +152 -0
  104. package/dist/gro_plugin_sveltekit_app.d.ts +27 -0
  105. package/dist/gro_plugin_sveltekit_app.js +180 -0
  106. package/dist/gro_plugin_sveltekit_library.d.ts +4 -0
  107. package/dist/gro_plugin_sveltekit_library.js +42 -0
  108. package/dist/hash.d.ts +5 -0
  109. package/dist/hash.js +14 -0
  110. package/dist/hash.test.d.ts +1 -0
  111. package/dist/hash.test.js +25 -0
  112. package/dist/index.d.ts +4 -0
  113. package/dist/index.js +3 -0
  114. package/dist/input_path.d.ts +48 -0
  115. package/dist/input_path.js +161 -0
  116. package/dist/input_path.test.d.ts +1 -0
  117. package/dist/input_path.test.js +106 -0
  118. package/dist/invoke.d.ts +1 -0
  119. package/dist/invoke.js +18 -0
  120. package/dist/invoke_task.d.ts +20 -0
  121. package/dist/invoke_task.js +140 -0
  122. package/dist/lint.task.d.ts +11 -0
  123. package/dist/lint.task.js +29 -0
  124. package/dist/loader.d.ts +4 -0
  125. package/dist/loader.js +153 -0
  126. package/dist/module.d.ts +3 -0
  127. package/dist/module.js +6 -0
  128. package/dist/module.test.d.ts +1 -0
  129. package/dist/module.test.js +41 -0
  130. package/dist/modules.d.ts +60 -0
  131. package/dist/modules.js +103 -0
  132. package/dist/modules.test.d.ts +1 -0
  133. package/dist/modules.test.js +182 -0
  134. package/dist/package.d.ts +939 -0
  135. package/dist/package.gen.d.ts +7 -0
  136. package/dist/package.gen.js +26 -0
  137. package/dist/package.js +887 -0
  138. package/dist/package_json.d.ts +342 -0
  139. package/dist/package_json.js +212 -0
  140. package/dist/package_json.test.d.ts +1 -0
  141. package/dist/package_json.test.js +77 -0
  142. package/dist/path.d.ts +12 -0
  143. package/dist/path.js +8 -0
  144. package/dist/paths.d.ts +60 -0
  145. package/dist/paths.js +128 -0
  146. package/dist/paths.test.d.ts +1 -0
  147. package/dist/paths.test.js +49 -0
  148. package/dist/plugin.d.ts +36 -0
  149. package/dist/plugin.js +80 -0
  150. package/dist/plugin.test.d.ts +1 -0
  151. package/dist/plugin.test.js +54 -0
  152. package/dist/print_task.d.ts +4 -0
  153. package/dist/print_task.js +124 -0
  154. package/dist/publish.task.d.ts +32 -0
  155. package/dist/publish.task.js +125 -0
  156. package/dist/release.task.d.ts +5 -0
  157. package/dist/release.task.js +18 -0
  158. package/dist/resolve_node_specifier.d.ts +8 -0
  159. package/dist/resolve_node_specifier.js +39 -0
  160. package/dist/resolve_node_specifier.test.d.ts +1 -0
  161. package/dist/resolve_node_specifier.test.js +21 -0
  162. package/dist/resolve_specifier.d.ts +15 -0
  163. package/dist/resolve_specifier.js +51 -0
  164. package/dist/resolve_specifier.test.d.ts +1 -0
  165. package/dist/resolve_specifier.test.js +66 -0
  166. package/dist/run.task.d.ts +11 -0
  167. package/dist/run.task.js +31 -0
  168. package/dist/run_gen.d.ts +6 -0
  169. package/dist/run_gen.js +74 -0
  170. package/dist/run_gen.test.d.ts +1 -0
  171. package/dist/run_gen.test.js +182 -0
  172. package/dist/run_task.d.ts +13 -0
  173. package/dist/run_task.js +44 -0
  174. package/dist/run_task.test.d.ts +1 -0
  175. package/dist/run_task.test.js +63 -0
  176. package/dist/search_fs.d.ts +11 -0
  177. package/dist/search_fs.js +22 -0
  178. package/dist/search_fs.test.d.ts +1 -0
  179. package/dist/search_fs.test.js +46 -0
  180. package/dist/src_json.d.ts +256 -0
  181. package/dist/src_json.js +110 -0
  182. package/dist/src_json.test.d.ts +1 -0
  183. package/dist/src_json.test.js +52 -0
  184. package/dist/sveltekit_config.d.ts +36 -0
  185. package/dist/sveltekit_config.js +51 -0
  186. package/dist/sveltekit_shim_app.d.ts +10 -0
  187. package/dist/sveltekit_shim_app.js +31 -0
  188. package/dist/sveltekit_shim_app_environment.d.ts +10 -0
  189. package/dist/sveltekit_shim_app_environment.js +12 -0
  190. package/dist/sveltekit_shim_app_forms.d.ts +5 -0
  191. package/dist/sveltekit_shim_app_forms.js +13 -0
  192. package/dist/sveltekit_shim_app_navigation.d.ts +10 -0
  193. package/dist/sveltekit_shim_app_navigation.js +11 -0
  194. package/dist/sveltekit_shim_app_paths.d.ts +11 -0
  195. package/dist/sveltekit_shim_app_paths.js +6 -0
  196. package/dist/sveltekit_shim_app_stores.d.ts +6 -0
  197. package/dist/sveltekit_shim_app_stores.js +17 -0
  198. package/dist/sveltekit_shim_env.d.ts +4 -0
  199. package/dist/sveltekit_shim_env.js +23 -0
  200. package/dist/sync.task.d.ts +30 -0
  201. package/dist/sync.task.js +45 -0
  202. package/dist/task.d.ts +29 -0
  203. package/dist/task.js +17 -0
  204. package/dist/task.test.d.ts +1 -0
  205. package/dist/task.test.js +22 -0
  206. package/dist/task_module.d.ts +14 -0
  207. package/dist/task_module.js +19 -0
  208. package/dist/task_module.test.d.ts +1 -0
  209. package/dist/task_module.test.js +70 -0
  210. package/dist/test.task.d.ts +20 -0
  211. package/dist/test.task.js +43 -0
  212. package/dist/throttle.d.ts +16 -0
  213. package/dist/throttle.js +59 -0
  214. package/dist/throttle.test.d.ts +1 -0
  215. package/dist/throttle.test.js +49 -0
  216. package/dist/typecheck.task.d.ts +5 -0
  217. package/dist/typecheck.task.js +38 -0
  218. package/dist/upgrade.task.d.ts +14 -0
  219. package/dist/upgrade.task.js +37 -0
  220. package/dist/watch_dir.d.ts +30 -0
  221. package/dist/watch_dir.js +59 -0
  222. package/package.json +422 -0
@@ -0,0 +1,342 @@
1
+ import { z } from 'zod';
2
+ export declare const transform_empty_object_to_undefined: (val: any) => any;
3
+ export declare const Package_Json_Repository: z.ZodUnion<[z.ZodString, z.ZodObject<{
4
+ type: z.ZodString;
5
+ url: z.ZodString;
6
+ directory: z.ZodOptional<z.ZodString>;
7
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
8
+ type: z.ZodString;
9
+ url: z.ZodString;
10
+ directory: z.ZodOptional<z.ZodString>;
11
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
12
+ type: z.ZodString;
13
+ url: z.ZodString;
14
+ directory: z.ZodOptional<z.ZodString>;
15
+ }, z.ZodTypeAny, "passthrough">>]>;
16
+ export type Package_Json_Repository = z.infer<typeof Package_Json_Repository>;
17
+ export declare const Package_Json_Author: z.ZodUnion<[z.ZodString, z.ZodObject<{
18
+ name: z.ZodString;
19
+ email: z.ZodOptional<z.ZodString>;
20
+ url: z.ZodOptional<z.ZodString>;
21
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
22
+ name: z.ZodString;
23
+ email: z.ZodOptional<z.ZodString>;
24
+ url: z.ZodOptional<z.ZodString>;
25
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
26
+ name: z.ZodString;
27
+ email: z.ZodOptional<z.ZodString>;
28
+ url: z.ZodOptional<z.ZodString>;
29
+ }, z.ZodTypeAny, "passthrough">>]>;
30
+ export type Package_Json_Author = z.infer<typeof Package_Json_Author>;
31
+ export declare const Package_Json_Funding: z.ZodUnion<[z.ZodString, z.ZodObject<{
32
+ type: z.ZodString;
33
+ url: z.ZodString;
34
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
35
+ type: z.ZodString;
36
+ url: z.ZodString;
37
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
38
+ type: z.ZodString;
39
+ url: z.ZodString;
40
+ }, z.ZodTypeAny, "passthrough">>]>;
41
+ export type Package_Json_Funding = z.infer<typeof Package_Json_Funding>;
42
+ export declare const Package_Json_Exports: z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
43
+ export type Package_Json_Exports = z.infer<typeof Package_Json_Exports>;
44
+ /**
45
+ * @see https://docs.npmjs.com/cli/v10/configuring-npm/package-json
46
+ */
47
+ export declare const Package_Json: z.ZodIntersection<z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodObject<{
48
+ name: z.ZodString;
49
+ version: z.ZodString;
50
+ public: z.ZodOptional<z.ZodBoolean>;
51
+ icon: z.ZodOptional<z.ZodString>;
52
+ private: z.ZodOptional<z.ZodBoolean>;
53
+ description: z.ZodOptional<z.ZodString>;
54
+ license: z.ZodOptional<z.ZodString>;
55
+ homepage: z.ZodOptional<z.ZodString>;
56
+ repository: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
57
+ type: z.ZodString;
58
+ url: z.ZodString;
59
+ directory: z.ZodOptional<z.ZodString>;
60
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
61
+ type: z.ZodString;
62
+ url: z.ZodString;
63
+ directory: z.ZodOptional<z.ZodString>;
64
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
65
+ type: z.ZodString;
66
+ url: z.ZodString;
67
+ directory: z.ZodOptional<z.ZodString>;
68
+ }, z.ZodTypeAny, "passthrough">>]>]>>;
69
+ author: z.ZodUnion<[z.ZodString, z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
70
+ name: z.ZodString;
71
+ email: z.ZodOptional<z.ZodString>;
72
+ url: z.ZodOptional<z.ZodString>;
73
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
74
+ name: z.ZodString;
75
+ email: z.ZodOptional<z.ZodString>;
76
+ url: z.ZodOptional<z.ZodString>;
77
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
78
+ name: z.ZodString;
79
+ email: z.ZodOptional<z.ZodString>;
80
+ url: z.ZodOptional<z.ZodString>;
81
+ }, z.ZodTypeAny, "passthrough">>]>>]>;
82
+ contributors: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
83
+ name: z.ZodString;
84
+ email: z.ZodOptional<z.ZodString>;
85
+ url: z.ZodOptional<z.ZodString>;
86
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
87
+ name: z.ZodString;
88
+ email: z.ZodOptional<z.ZodString>;
89
+ url: z.ZodOptional<z.ZodString>;
90
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
91
+ name: z.ZodString;
92
+ email: z.ZodOptional<z.ZodString>;
93
+ url: z.ZodOptional<z.ZodString>;
94
+ }, z.ZodTypeAny, "passthrough">>]>]>, "many">>;
95
+ bugs: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
96
+ url: z.ZodOptional<z.ZodString>;
97
+ email: z.ZodOptional<z.ZodString>;
98
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
99
+ url: z.ZodOptional<z.ZodString>;
100
+ email: z.ZodOptional<z.ZodString>;
101
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
102
+ url: z.ZodOptional<z.ZodString>;
103
+ email: z.ZodOptional<z.ZodString>;
104
+ }, z.ZodTypeAny, "passthrough">>]>>;
105
+ funding: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
106
+ type: z.ZodString;
107
+ url: z.ZodString;
108
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
109
+ type: z.ZodString;
110
+ url: z.ZodString;
111
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
112
+ type: z.ZodString;
113
+ url: z.ZodString;
114
+ }, z.ZodTypeAny, "passthrough">>]>, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
115
+ type: z.ZodString;
116
+ url: z.ZodString;
117
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
118
+ type: z.ZodString;
119
+ url: z.ZodString;
120
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
121
+ type: z.ZodString;
122
+ url: z.ZodString;
123
+ }, z.ZodTypeAny, "passthrough">>]>]>, "many">]>>;
124
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
125
+ scripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
126
+ bin: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
127
+ files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
128
+ exports: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>, any, Record<string, Record<string, string> | undefined>>>;
129
+ dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
130
+ devDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
131
+ peerDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
132
+ peerDependenciesMeta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
133
+ optionalDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
134
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
135
+ os: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
136
+ cpu: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
137
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
138
+ name: z.ZodString;
139
+ version: z.ZodString;
140
+ public: z.ZodOptional<z.ZodBoolean>;
141
+ icon: z.ZodOptional<z.ZodString>;
142
+ private: z.ZodOptional<z.ZodBoolean>;
143
+ description: z.ZodOptional<z.ZodString>;
144
+ license: z.ZodOptional<z.ZodString>;
145
+ homepage: z.ZodOptional<z.ZodString>;
146
+ repository: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
147
+ type: z.ZodString;
148
+ url: z.ZodString;
149
+ directory: z.ZodOptional<z.ZodString>;
150
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
151
+ type: z.ZodString;
152
+ url: z.ZodString;
153
+ directory: z.ZodOptional<z.ZodString>;
154
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
155
+ type: z.ZodString;
156
+ url: z.ZodString;
157
+ directory: z.ZodOptional<z.ZodString>;
158
+ }, z.ZodTypeAny, "passthrough">>]>]>>;
159
+ author: z.ZodUnion<[z.ZodString, z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
160
+ name: z.ZodString;
161
+ email: z.ZodOptional<z.ZodString>;
162
+ url: z.ZodOptional<z.ZodString>;
163
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
164
+ name: z.ZodString;
165
+ email: z.ZodOptional<z.ZodString>;
166
+ url: z.ZodOptional<z.ZodString>;
167
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
168
+ name: z.ZodString;
169
+ email: z.ZodOptional<z.ZodString>;
170
+ url: z.ZodOptional<z.ZodString>;
171
+ }, z.ZodTypeAny, "passthrough">>]>>]>;
172
+ contributors: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
173
+ name: z.ZodString;
174
+ email: z.ZodOptional<z.ZodString>;
175
+ url: z.ZodOptional<z.ZodString>;
176
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
177
+ name: z.ZodString;
178
+ email: z.ZodOptional<z.ZodString>;
179
+ url: z.ZodOptional<z.ZodString>;
180
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
181
+ name: z.ZodString;
182
+ email: z.ZodOptional<z.ZodString>;
183
+ url: z.ZodOptional<z.ZodString>;
184
+ }, z.ZodTypeAny, "passthrough">>]>]>, "many">>;
185
+ bugs: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
186
+ url: z.ZodOptional<z.ZodString>;
187
+ email: z.ZodOptional<z.ZodString>;
188
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
189
+ url: z.ZodOptional<z.ZodString>;
190
+ email: z.ZodOptional<z.ZodString>;
191
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
192
+ url: z.ZodOptional<z.ZodString>;
193
+ email: z.ZodOptional<z.ZodString>;
194
+ }, z.ZodTypeAny, "passthrough">>]>>;
195
+ funding: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
196
+ type: z.ZodString;
197
+ url: z.ZodString;
198
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
199
+ type: z.ZodString;
200
+ url: z.ZodString;
201
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
202
+ type: z.ZodString;
203
+ url: z.ZodString;
204
+ }, z.ZodTypeAny, "passthrough">>]>, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
205
+ type: z.ZodString;
206
+ url: z.ZodString;
207
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
208
+ type: z.ZodString;
209
+ url: z.ZodString;
210
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
211
+ type: z.ZodString;
212
+ url: z.ZodString;
213
+ }, z.ZodTypeAny, "passthrough">>]>]>, "many">]>>;
214
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
215
+ scripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
216
+ bin: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
217
+ files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
218
+ exports: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>, any, Record<string, Record<string, string> | undefined>>>;
219
+ dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
220
+ devDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
221
+ peerDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
222
+ peerDependenciesMeta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
223
+ optionalDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
224
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
225
+ os: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
226
+ cpu: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
227
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
228
+ name: z.ZodString;
229
+ version: z.ZodString;
230
+ public: z.ZodOptional<z.ZodBoolean>;
231
+ icon: z.ZodOptional<z.ZodString>;
232
+ private: z.ZodOptional<z.ZodBoolean>;
233
+ description: z.ZodOptional<z.ZodString>;
234
+ license: z.ZodOptional<z.ZodString>;
235
+ homepage: z.ZodOptional<z.ZodString>;
236
+ repository: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
237
+ type: z.ZodString;
238
+ url: z.ZodString;
239
+ directory: z.ZodOptional<z.ZodString>;
240
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
241
+ type: z.ZodString;
242
+ url: z.ZodString;
243
+ directory: z.ZodOptional<z.ZodString>;
244
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
245
+ type: z.ZodString;
246
+ url: z.ZodString;
247
+ directory: z.ZodOptional<z.ZodString>;
248
+ }, z.ZodTypeAny, "passthrough">>]>]>>;
249
+ author: z.ZodUnion<[z.ZodString, z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
250
+ name: z.ZodString;
251
+ email: z.ZodOptional<z.ZodString>;
252
+ url: z.ZodOptional<z.ZodString>;
253
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
254
+ name: z.ZodString;
255
+ email: z.ZodOptional<z.ZodString>;
256
+ url: z.ZodOptional<z.ZodString>;
257
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
258
+ name: z.ZodString;
259
+ email: z.ZodOptional<z.ZodString>;
260
+ url: z.ZodOptional<z.ZodString>;
261
+ }, z.ZodTypeAny, "passthrough">>]>>]>;
262
+ contributors: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
263
+ name: z.ZodString;
264
+ email: z.ZodOptional<z.ZodString>;
265
+ url: z.ZodOptional<z.ZodString>;
266
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
267
+ name: z.ZodString;
268
+ email: z.ZodOptional<z.ZodString>;
269
+ url: z.ZodOptional<z.ZodString>;
270
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
271
+ name: z.ZodString;
272
+ email: z.ZodOptional<z.ZodString>;
273
+ url: z.ZodOptional<z.ZodString>;
274
+ }, z.ZodTypeAny, "passthrough">>]>]>, "many">>;
275
+ bugs: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodObject<{
276
+ url: z.ZodOptional<z.ZodString>;
277
+ email: z.ZodOptional<z.ZodString>;
278
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
279
+ url: z.ZodOptional<z.ZodString>;
280
+ email: z.ZodOptional<z.ZodString>;
281
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
282
+ url: z.ZodOptional<z.ZodString>;
283
+ email: z.ZodOptional<z.ZodString>;
284
+ }, z.ZodTypeAny, "passthrough">>]>>;
285
+ funding: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
286
+ type: z.ZodString;
287
+ url: z.ZodString;
288
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
289
+ type: z.ZodString;
290
+ url: z.ZodString;
291
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
292
+ type: z.ZodString;
293
+ url: z.ZodString;
294
+ }, z.ZodTypeAny, "passthrough">>]>, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
295
+ type: z.ZodString;
296
+ url: z.ZodString;
297
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
298
+ type: z.ZodString;
299
+ url: z.ZodString;
300
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
301
+ type: z.ZodString;
302
+ url: z.ZodString;
303
+ }, z.ZodTypeAny, "passthrough">>]>]>, "many">]>>;
304
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
305
+ scripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
306
+ bin: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
307
+ files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
308
+ exports: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>, any, Record<string, Record<string, string> | undefined>>>;
309
+ dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
310
+ devDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
311
+ peerDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
312
+ peerDependenciesMeta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
313
+ optionalDependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
314
+ engines: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
315
+ os: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
316
+ cpu: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
317
+ }, z.ZodTypeAny, "passthrough">>>;
318
+ export type Package_Json = z.infer<typeof Package_Json>;
319
+ export interface Map_Package_Json {
320
+ (package_json: Package_Json): Package_Json | null | Promise<Package_Json | null>;
321
+ }
322
+ export declare const EMPTY_PACKAGE_JSON: Package_Json;
323
+ export declare const load_package_json: (dir?: string, cache?: Record<string, Package_Json>) => Promise<Package_Json>;
324
+ export declare const sync_package_json: (map_package_json: Map_Package_Json, log: Logger, check?: boolean, dir?: string, exports_dir?: string) => Promise<{
325
+ package_json: Package_Json | null;
326
+ changed: boolean;
327
+ }>;
328
+ export declare const load_gro_package_json: () => Promise<Package_Json>;
329
+ export declare const write_package_json: (serialized_package_json: string) => Promise<void>;
330
+ export declare const serialize_package_json: (package_json: Package_Json) => string;
331
+ /**
332
+ * Updates package.json. Writes to the filesystem only when contents change.
333
+ */
334
+ export declare const update_package_json: (dir: string | undefined, update: (package_json: Package_Json) => Package_Json | null | Promise<Package_Json | null>, write?: boolean) => Promise<{
335
+ package_json: Package_Json | null;
336
+ changed: boolean;
337
+ }>;
338
+ export declare const to_package_exports: (paths: string[]) => Package_Json_Exports;
339
+ export declare const parse_repo_url: (package_json: Package_Json) => {
340
+ owner: string;
341
+ repo: string;
342
+ } | undefined;
@@ -0,0 +1,212 @@
1
+ import { z } from 'zod';
2
+ import { join } from 'node:path';
3
+ import { readFile, writeFile } from 'node:fs/promises';
4
+ import { plural } from '@ryanatkn/belt/string.js';
5
+ import { strip_end } from '@ryanatkn/belt/string.js';
6
+ import { paths, gro_paths, is_this_project_gro, replace_extension, SVELTEKIT_DIST_DIRNAME, Url, Email, } from './paths.js';
7
+ import { search_fs } from './search_fs.js';
8
+ import { has_sveltekit_library } from './gro_plugin_sveltekit_library.js';
9
+ // TODO move this where?
10
+ export const transform_empty_object_to_undefined = (val) => {
11
+ if (val && Object.keys(val).length === 0) {
12
+ return undefined;
13
+ }
14
+ return val;
15
+ };
16
+ export const Package_Json_Repository = z.union([
17
+ z.string(),
18
+ z
19
+ .object({
20
+ type: z.string(),
21
+ url: Url,
22
+ directory: z.string().optional(),
23
+ })
24
+ .passthrough(),
25
+ ]);
26
+ export const Package_Json_Author = z.union([
27
+ z.string(),
28
+ z
29
+ .object({
30
+ name: z.string(),
31
+ email: Email.optional(),
32
+ url: Url.optional(),
33
+ })
34
+ .passthrough(),
35
+ ]);
36
+ export const Package_Json_Funding = z.union([
37
+ z.string(),
38
+ z
39
+ .object({
40
+ type: z.string(),
41
+ url: Url,
42
+ })
43
+ .passthrough(),
44
+ ]);
45
+ export const Package_Json_Exports = z.record(z.record(z.string()).optional());
46
+ /**
47
+ * @see https://docs.npmjs.com/cli/v10/configuring-npm/package-json
48
+ */
49
+ export const Package_Json = z.intersection(z.record(z.unknown()), z
50
+ .object({
51
+ // according to the npm docs, `name` and `version` are the only required properties
52
+ name: z.string(),
53
+ version: z.string(),
54
+ // Gro extensions
55
+ public: z
56
+ .boolean({
57
+ description: 'a Gro extension that enables publishing `.well-known/package.json` and `.well-known/src`',
58
+ })
59
+ .optional(),
60
+ icon: z.string({ description: 'a Gro extension' }).optional(), // TODO maybe base64 favicon?
61
+ private: z.boolean({ description: 'disallow npm publish' }).optional(),
62
+ description: z.string().optional(),
63
+ license: z.string().optional(),
64
+ homepage: Url.optional(),
65
+ repository: z.union([z.string(), Url, Package_Json_Repository]).optional(),
66
+ author: z.union([z.string(), Package_Json_Author.optional()]),
67
+ contributors: z.array(z.union([z.string(), Package_Json_Author])).optional(),
68
+ bugs: z
69
+ .union([z.string(), z.object({ url: Url.optional(), email: Email.optional() }).passthrough()])
70
+ .optional(),
71
+ funding: z
72
+ .union([Url, Package_Json_Funding, z.array(z.union([Url, Package_Json_Funding]))])
73
+ .optional(),
74
+ keywords: z.array(z.string()).optional(),
75
+ scripts: z.record(z.string()).optional(),
76
+ bin: z.record(z.string()).optional(),
77
+ files: z.array(z.string()).optional(),
78
+ exports: Package_Json_Exports.transform(transform_empty_object_to_undefined).optional(),
79
+ dependencies: z.record(z.string()).optional(),
80
+ devDependencies: z.record(z.string()).optional(),
81
+ peerDependencies: z.record(z.string()).optional(),
82
+ peerDependenciesMeta: z.record(z.record(z.string())).optional(),
83
+ optionalDependencies: z.record(z.string()).optional(),
84
+ engines: z.record(z.string()).optional(),
85
+ os: z.array(z.string()).optional(),
86
+ cpu: z.array(z.string()).optional(),
87
+ })
88
+ .passthrough());
89
+ export const EMPTY_PACKAGE_JSON = { name: '', version: '' };
90
+ export const load_package_json = async (dir = is_this_project_gro ? gro_paths.root : paths.root, cache) => {
91
+ let package_json;
92
+ if (cache && dir in cache) {
93
+ return cache[dir];
94
+ }
95
+ try {
96
+ package_json = JSON.parse(await load_package_json_contents(dir));
97
+ }
98
+ catch (err) {
99
+ throw Error('failed to load package.json at ' + dir);
100
+ }
101
+ if (cache)
102
+ cache[dir] = package_json;
103
+ return package_json;
104
+ };
105
+ export const sync_package_json = async (map_package_json, log, check = false, dir = paths.root, exports_dir = paths.lib) => {
106
+ const exported_files = await search_fs(exports_dir);
107
+ const exported_paths = Array.from(exported_files.keys());
108
+ const updated = await update_package_json(dir, async (package_json) => {
109
+ if (await has_sveltekit_library(package_json)) {
110
+ const exports = to_package_exports(exported_paths);
111
+ package_json.exports = exports;
112
+ }
113
+ const mapped = await map_package_json(package_json);
114
+ return mapped ? Package_Json.parse(mapped) : mapped;
115
+ }, !check);
116
+ const exports_count = updated.changed && updated.package_json?.exports
117
+ ? Object.keys(updated.package_json.exports).length
118
+ : 0;
119
+ log.info(updated.changed
120
+ ? `updated package.json exports with ${exports_count} total export${plural(exports_count)}`
121
+ : 'no changes to exports in package.json');
122
+ return updated;
123
+ };
124
+ export const load_gro_package_json = () => load_package_json(gro_paths.root);
125
+ // TODO probably make this nullable and make callers handle failures
126
+ const load_package_json_contents = (dir) => readFile(join(dir, 'package.json'), 'utf8');
127
+ export const write_package_json = async (serialized_package_json) => {
128
+ await writeFile(join(paths.root, 'package.json'), serialized_package_json);
129
+ };
130
+ export const serialize_package_json = (package_json) => {
131
+ Package_Json.parse(package_json);
132
+ return JSON.stringify(package_json, null, 2) + '\n';
133
+ };
134
+ /**
135
+ * Updates package.json. Writes to the filesystem only when contents change.
136
+ */
137
+ export const update_package_json = async (dir = paths.root, update, write = true) => {
138
+ const original_contents = await load_package_json_contents(dir);
139
+ const original = JSON.parse(original_contents);
140
+ const updated = await update(original);
141
+ if (updated === null) {
142
+ return { package_json: original, changed: false };
143
+ }
144
+ const updated_contents = serialize_package_json(updated);
145
+ if (updated_contents === original_contents) {
146
+ return { package_json: original, changed: false };
147
+ }
148
+ if (write)
149
+ await write_package_json(updated_contents);
150
+ return { package_json: updated, changed: true };
151
+ };
152
+ export const to_package_exports = (paths) => {
153
+ const sorted = paths
154
+ .slice()
155
+ .sort((a, b) => (a === 'index.ts' ? -1 : b === 'index.ts' ? 1 : a.localeCompare(b)));
156
+ const exports = {};
157
+ for (const path of sorted) {
158
+ if (path.endsWith('.json.d.ts')) {
159
+ const json_path = path.substring(0, path.length - 5);
160
+ exports['./' + json_path] = {
161
+ default: IMPORT_PREFIX + json_path, // assuming a matching json file
162
+ types: IMPORT_PREFIX + path,
163
+ };
164
+ }
165
+ else if (path.endsWith('.ts') && !path.endsWith('.d.ts')) {
166
+ const js_path = replace_extension(path, '.js');
167
+ const key = path === 'index.ts' ? '.' : './' + js_path;
168
+ exports[key] = {
169
+ default: IMPORT_PREFIX + js_path,
170
+ types: IMPORT_PREFIX + replace_extension(path, '.d.ts'),
171
+ };
172
+ }
173
+ else if (path.endsWith('.js')) {
174
+ const key = path === 'index.js' ? '.' : './' + path;
175
+ exports[key] = {
176
+ default: IMPORT_PREFIX + path,
177
+ types: IMPORT_PREFIX + replace_extension(path, '.d.ts'), // assuming JSDoc types
178
+ };
179
+ }
180
+ else if (path.endsWith('.svelte')) {
181
+ exports['./' + path] = {
182
+ svelte: IMPORT_PREFIX + path,
183
+ default: IMPORT_PREFIX + path, // needed for loader imports
184
+ types: IMPORT_PREFIX + path + '.d.ts',
185
+ };
186
+ }
187
+ else {
188
+ exports['./' + path] = {
189
+ default: IMPORT_PREFIX + path,
190
+ };
191
+ }
192
+ }
193
+ return Package_Json_Exports.parse(exports);
194
+ };
195
+ const IMPORT_PREFIX = './' + SVELTEKIT_DIST_DIRNAME + '/';
196
+ export const parse_repo_url = (package_json) => {
197
+ const { repository } = package_json;
198
+ const repo_url = repository
199
+ ? typeof repository === 'string'
200
+ ? repository
201
+ : repository.url
202
+ : undefined;
203
+ if (!repo_url) {
204
+ return undefined;
205
+ }
206
+ const parsed_repo_url = /.+github.com\/(.+)\/(.+)/u.exec(strip_end(strip_end(repo_url, '/'), '.git'));
207
+ if (!parsed_repo_url) {
208
+ return undefined;
209
+ }
210
+ const [, owner, repo] = parsed_repo_url;
211
+ return { owner, repo };
212
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,77 @@
1
+ import { test } from 'uvu';
2
+ import * as assert from 'uvu/assert';
3
+ import { Package_Json, load_package_json, parse_repo_url, serialize_package_json, to_package_exports, } from './package_json.js';
4
+ test('load_package_json', async () => {
5
+ const package_json = await load_package_json();
6
+ assert.ok(package_json);
7
+ const parsed = Package_Json.parse(package_json);
8
+ assert.ok(parsed);
9
+ serialize_package_json(package_json);
10
+ });
11
+ test('load_package_json with cache', async () => {
12
+ const cache = {};
13
+ const package_json1 = await load_package_json(undefined, cache);
14
+ assert.ok(package_json1);
15
+ assert.is(Object.keys(cache).length, 1);
16
+ const package_json2 = await load_package_json(undefined, cache);
17
+ assert.is(Object.keys(cache).length, 1);
18
+ assert.is(package_json1, package_json2);
19
+ });
20
+ test('Package_Json.parse', async () => {
21
+ Package_Json.parse({ name: 'abc', version: '123' });
22
+ });
23
+ test('Package_Json.parse fails with bad data', async () => {
24
+ let err;
25
+ try {
26
+ Package_Json.parse({ version: '123' });
27
+ }
28
+ catch (_err) {
29
+ err = _err;
30
+ }
31
+ assert.ok(err);
32
+ });
33
+ test('serialize_package_json', async () => {
34
+ serialize_package_json({ name: 'abc', version: '123' });
35
+ });
36
+ test('serialize_package_json fails with bad data', async () => {
37
+ let err;
38
+ try {
39
+ serialize_package_json({ version: '123' });
40
+ }
41
+ catch (_err) {
42
+ err = _err;
43
+ }
44
+ assert.ok(err);
45
+ });
46
+ test('to_package_exports', async () => {
47
+ assert.equal(to_package_exports(['a/b.ts']), {
48
+ './a/b.js': {
49
+ default: './dist/a/b.js',
50
+ types: './dist/a/b.d.ts',
51
+ },
52
+ });
53
+ assert.equal(to_package_exports([
54
+ 'a/b/Some_Test_Svelte.svelte',
55
+ 'a/b/some_test_ts.ts',
56
+ 'a/b/some_test_json.json',
57
+ ]), {
58
+ './a/b/some_test_json.json': {
59
+ default: './dist/a/b/some_test_json.json',
60
+ },
61
+ './a/b/Some_Test_Svelte.svelte': {
62
+ svelte: './dist/a/b/Some_Test_Svelte.svelte',
63
+ default: './dist/a/b/Some_Test_Svelte.svelte',
64
+ types: './dist/a/b/Some_Test_Svelte.svelte.d.ts',
65
+ },
66
+ './a/b/some_test_ts.js': {
67
+ default: './dist/a/b/some_test_ts.js',
68
+ types: './dist/a/b/some_test_ts.d.ts',
69
+ },
70
+ });
71
+ });
72
+ test('parse_repo_url', async () => {
73
+ const parsed = parse_repo_url(await load_package_json());
74
+ assert.is(parsed?.owner, 'ryanatkn');
75
+ assert.is(parsed?.repo, 'gro');
76
+ });
77
+ test.run();
package/dist/path.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export declare const to_file_path: (path_or_url: string | URL) => string;
2
+ export interface Path_Data {
3
+ id: string;
4
+ isDirectory: boolean;
5
+ }
6
+ export declare const to_path_data: (id: string, stats: Path_Stats) => Path_Data;
7
+ export interface Path_Stats {
8
+ isDirectory: () => boolean;
9
+ }
10
+ export interface Path_Filter {
11
+ (path: string, stats: Path_Stats): boolean;
12
+ }
package/dist/path.js ADDED
@@ -0,0 +1,8 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ export const to_file_path = (path_or_url) => typeof path_or_url === 'string' ? path_or_url : fileURLToPath(path_or_url.href);
3
+ export const to_path_data = (id, stats) => {
4
+ return {
5
+ id,
6
+ isDirectory: stats.isDirectory(),
7
+ };
8
+ };