create-payload-app 4.0.0-internal.fa345ef → 4.0.0-internal.fec2230

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 (135) hide show
  1. package/README.md +5 -0
  2. package/dist/commands.d.ts +4 -0
  3. package/dist/commands.d.ts.map +1 -0
  4. package/dist/commands.js +5 -0
  5. package/dist/commands.js.map +1 -0
  6. package/dist/lib/agent-config.d.ts +15 -0
  7. package/dist/lib/agent-config.d.ts.map +1 -0
  8. package/dist/lib/agent-config.js +22 -0
  9. package/dist/lib/agent-config.js.map +1 -0
  10. package/dist/lib/agent-config.spec.js +23 -0
  11. package/dist/lib/agent-config.spec.js.map +1 -0
  12. package/dist/lib/ast/adapter-config.d.ts.map +1 -1
  13. package/dist/lib/ast/adapter-config.js +0 -10
  14. package/dist/lib/ast/adapter-config.js.map +1 -1
  15. package/dist/lib/ast/package-json.d.ts +9 -0
  16. package/dist/lib/ast/package-json.d.ts.map +1 -1
  17. package/dist/lib/ast/package-json.js +34 -8
  18. package/dist/lib/ast/package-json.js.map +1 -1
  19. package/dist/lib/ast/package-json.spec.js +73 -1
  20. package/dist/lib/ast/package-json.spec.js.map +1 -1
  21. package/dist/lib/ast/types.d.ts +2 -2
  22. package/dist/lib/ast/types.d.ts.map +1 -1
  23. package/dist/lib/ast/types.js +0 -1
  24. package/dist/lib/ast/types.js.map +1 -1
  25. package/dist/lib/configure-payload-tsconfig.d.ts +5 -0
  26. package/dist/lib/configure-payload-tsconfig.d.ts.map +1 -0
  27. package/dist/lib/configure-payload-tsconfig.js +26 -0
  28. package/dist/lib/configure-payload-tsconfig.js.map +1 -0
  29. package/dist/lib/configure-payload-tsconfig.spec.js +135 -0
  30. package/dist/lib/configure-payload-tsconfig.spec.js.map +1 -0
  31. package/dist/lib/configure-plugin-project.d.ts.map +1 -1
  32. package/dist/lib/create-project.d.ts +1 -2
  33. package/dist/lib/create-project.d.ts.map +1 -1
  34. package/dist/lib/create-project.js +5 -21
  35. package/dist/lib/create-project.js.map +1 -1
  36. package/dist/lib/create-project.spec.js +9 -0
  37. package/dist/lib/create-project.spec.js.map +1 -1
  38. package/dist/lib/generate-secret.js +1 -1
  39. package/dist/lib/generate-secret.js.map +1 -1
  40. package/dist/lib/init-next.d.ts.map +1 -1
  41. package/dist/lib/init-next.js +5 -34
  42. package/dist/lib/init-next.js.map +1 -1
  43. package/dist/lib/init-tanstack-default-template.spec.js +121 -0
  44. package/dist/lib/init-tanstack-default-template.spec.js.map +1 -0
  45. package/dist/lib/init-tanstack.d.ts +18 -0
  46. package/dist/lib/init-tanstack.d.ts.map +1 -0
  47. package/dist/lib/init-tanstack.js +150 -0
  48. package/dist/lib/init-tanstack.js.map +1 -0
  49. package/dist/lib/init-tanstack.spec.js +394 -0
  50. package/dist/lib/init-tanstack.spec.js.map +1 -0
  51. package/dist/lib/tanstack/detect.d.ts +5 -0
  52. package/dist/lib/tanstack/detect.d.ts.map +1 -0
  53. package/dist/lib/tanstack/detect.js +131 -0
  54. package/dist/lib/tanstack/detect.js.map +1 -0
  55. package/dist/lib/tanstack/detect.spec.js +227 -0
  56. package/dist/lib/tanstack/detect.spec.js.map +1 -0
  57. package/dist/lib/tanstack/prepare.d.ts +23 -0
  58. package/dist/lib/tanstack/prepare.d.ts.map +1 -0
  59. package/dist/lib/tanstack/prepare.js +114 -0
  60. package/dist/lib/tanstack/prepare.js.map +1 -0
  61. package/dist/lib/tanstack/prepare.spec.js +288 -0
  62. package/dist/lib/tanstack/prepare.spec.js.map +1 -0
  63. package/dist/lib/tanstack/template-files.d.ts +50 -0
  64. package/dist/lib/tanstack/template-files.d.ts.map +1 -0
  65. package/dist/lib/tanstack/template-files.js +64 -0
  66. package/dist/lib/tanstack/template-files.js.map +1 -0
  67. package/dist/lib/tanstack/transform-root-route.d.ts +7 -0
  68. package/dist/lib/tanstack/transform-root-route.d.ts.map +1 -0
  69. package/dist/lib/tanstack/transform-root-route.js +747 -0
  70. package/dist/lib/tanstack/transform-root-route.js.map +1 -0
  71. package/dist/lib/tanstack/transform-root-route.spec.js +484 -0
  72. package/dist/lib/tanstack/transform-root-route.spec.js.map +1 -0
  73. package/dist/lib/tanstack/transform-router.d.ts +5 -0
  74. package/dist/lib/tanstack/transform-router.d.ts.map +1 -0
  75. package/dist/lib/tanstack/transform-router.js +301 -0
  76. package/dist/lib/tanstack/transform-router.js.map +1 -0
  77. package/dist/lib/tanstack/transform-router.spec.js +264 -0
  78. package/dist/lib/tanstack/transform-router.spec.js.map +1 -0
  79. package/dist/lib/tanstack/transform-vite-config.d.ts +14 -0
  80. package/dist/lib/tanstack/transform-vite-config.d.ts.map +1 -0
  81. package/dist/lib/tanstack/transform-vite-config.js +576 -0
  82. package/dist/lib/tanstack/transform-vite-config.js.map +1 -0
  83. package/dist/lib/tanstack/transform-vite-config.spec.js +456 -0
  84. package/dist/lib/tanstack/transform-vite-config.spec.js.map +1 -0
  85. package/dist/lib/templates.d.ts.map +1 -1
  86. package/dist/lib/templates.js +6 -0
  87. package/dist/lib/templates.js.map +1 -1
  88. package/dist/lib/update-payload-in-project.d.ts +18 -3
  89. package/dist/lib/update-payload-in-project.d.ts.map +1 -1
  90. package/dist/lib/update-payload-in-project.js +98 -18
  91. package/dist/lib/update-payload-in-project.js.map +1 -1
  92. package/dist/lib/update-payload-in-project.spec.js +262 -0
  93. package/dist/lib/update-payload-in-project.spec.js.map +1 -0
  94. package/dist/lib/wrap-next-config.d.ts.map +1 -1
  95. package/dist/main.d.ts +20 -1
  96. package/dist/main.d.ts.map +1 -1
  97. package/dist/main.js +120 -29
  98. package/dist/main.js.map +1 -1
  99. package/dist/main.spec.js +102 -0
  100. package/dist/main.spec.js.map +1 -0
  101. package/dist/scripts/pack-template-files.js +18 -0
  102. package/dist/scripts/pack-template-files.js.map +1 -1
  103. package/dist/template/src/app/(frontend)/styles.css +1 -1
  104. package/dist/template/src/app/(payload)/layout.tsx +8 -2
  105. package/dist/template-tanstack/routes/_payload/admin.$.tsx +8 -0
  106. package/dist/template-tanstack/routes/_payload/admin.index.tsx +8 -0
  107. package/dist/template-tanstack/routes/_payload/api.$.ts +10 -0
  108. package/dist/template-tanstack/routes/_payload/importMap.js +32 -0
  109. package/dist/template-tanstack/routes/_payload/server.functions.ts +49 -0
  110. package/dist/template-tanstack/routes/_payload.tsx +30 -0
  111. package/dist/template-tanstack/src/collections/Folders.ts +16 -0
  112. package/dist/template-tanstack/src/collections/Media.ts +20 -0
  113. package/dist/template-tanstack/src/collections/Tags.ts +16 -0
  114. package/dist/template-tanstack/src/collections/Users.ts +14 -0
  115. package/dist/template-tanstack/src/payload.config.ts +40 -0
  116. package/dist/template-tanstack/src/payload.css +1 -0
  117. package/dist/types.d.ts +22 -3
  118. package/dist/types.d.ts.map +1 -1
  119. package/dist/types.js.map +1 -1
  120. package/dist/utils/casing.d.ts.map +1 -1
  121. package/dist/utils/log.d.ts.map +1 -1
  122. package/dist/utils/messages.d.ts +1 -0
  123. package/dist/utils/messages.d.ts.map +1 -1
  124. package/dist/utils/messages.js +8 -6
  125. package/dist/utils/messages.js.map +1 -1
  126. package/package.json +4 -4
  127. package/dist/lib/download-skill.d.ts +0 -8
  128. package/dist/lib/download-skill.d.ts.map +0 -1
  129. package/dist/lib/download-skill.js +0 -35
  130. package/dist/lib/download-skill.js.map +0 -1
  131. package/dist/lib/select-agent.d.ts +0 -16
  132. package/dist/lib/select-agent.d.ts.map +0 -1
  133. package/dist/lib/select-agent.js +0 -67
  134. package/dist/lib/select-agent.js.map +0 -1
  135. /package/dist/template/src/app/(payload)/{custom.scss → custom.css} +0 -0
@@ -0,0 +1,747 @@
1
+ import { Node, Project, QuoteKind, SyntaxKind } from 'ts-morph';
2
+ const PAYLOAD_CLIENT_MODULE = '@payloadcms/tanstack-start/client';
3
+ const ROUTER_MODULE = '@tanstack/react-router';
4
+ export function transformTanStackRootRoute({ content, kind }) {
5
+ const project = new Project({
6
+ manipulationSettings: {
7
+ quoteKind: QuoteKind.Single
8
+ },
9
+ useInMemoryFileSystem: true
10
+ });
11
+ const sourceFile = project.createSourceFile('__root.tsx', content);
12
+ const createRootRouteImport = getNamedImport({
13
+ importedName: 'createRootRoute',
14
+ moduleSpecifier: ROUTER_MODULE,
15
+ sourceFile
16
+ });
17
+ if (!createRootRouteImport) {
18
+ return failure('Could not identify the createRootRoute import.');
19
+ }
20
+ const createRootRouteCalls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call)=>call.getExpression().getText() === createRootRouteImport.localName);
21
+ if (createRootRouteCalls.length !== 1) {
22
+ return failure('Expected exactly one createRootRoute() call.');
23
+ }
24
+ const createRootRouteCall = createRootRouteCalls[0];
25
+ if (createRootRouteCall.getArguments().length !== 1) {
26
+ return failure('createRootRoute() must receive exactly one argument.');
27
+ }
28
+ const rootObject = createRootRouteCall.getArguments()[0];
29
+ if (!Node.isObjectLiteralExpression(rootObject)) {
30
+ return failure('createRootRoute() must receive an object literal.');
31
+ }
32
+ if (rootObject.getProperties().some(Node.isSpreadAssignment)) {
33
+ return failure('Root route object spreads cannot be transformed safely.');
34
+ }
35
+ return kind === 'start' ? transformStartRoot({
36
+ content,
37
+ rootObject,
38
+ sourceFile
39
+ }) : transformRouterOnlyRoot({
40
+ content,
41
+ rootObject,
42
+ sourceFile
43
+ });
44
+ }
45
+ function bindingNameIncludes({ localName, node }) {
46
+ if (Node.isIdentifier(node)) {
47
+ return node.getText() === localName;
48
+ }
49
+ if (Node.isArrayBindingPattern(node) || Node.isObjectBindingPattern(node)) {
50
+ return node.getElements().some((element)=>Node.isBindingElement(element) && bindingNameIncludes({
51
+ localName,
52
+ node: element.getNameNode()
53
+ }));
54
+ }
55
+ return false;
56
+ }
57
+ function ensureNamedImport({ importedName, moduleSpecifier, sourceFile }) {
58
+ const declaration = sourceFile.getImportDeclarations().find((candidate)=>candidate.getModuleSpecifierValue() === moduleSpecifier && !candidate.isTypeOnly() && !candidate.getNamespaceImport());
59
+ if (declaration?.getNamedImports().some((namedImport)=>namedImport.getName() === importedName && !namedImport.getAliasNode())) {
60
+ return;
61
+ }
62
+ if (declaration) {
63
+ declaration.addNamedImport(importedName);
64
+ } else {
65
+ sourceFile.addImportDeclaration({
66
+ moduleSpecifier,
67
+ namedImports: [
68
+ importedName
69
+ ]
70
+ });
71
+ }
72
+ }
73
+ function failure(reason) {
74
+ return {
75
+ reason,
76
+ success: false
77
+ };
78
+ }
79
+ function getAppStylesheetImport({ requireSideEffect, sourceFile }) {
80
+ const imports = sourceFile.getImportDeclarations().filter((declaration)=>{
81
+ const moduleSpecifier = declaration.getModuleSpecifierValue();
82
+ const isStylesheet = requireSideEffect ? /\.css$/.test(moduleSpecifier) : /\.css\?url$/.test(moduleSpecifier);
83
+ if (!isStylesheet) {
84
+ return false;
85
+ }
86
+ const hasNamedOrNamespaceImport = declaration.getNamedImports().length > 0 || Boolean(declaration.getNamespaceImport());
87
+ return requireSideEffect ? !declaration.getDefaultImport() && !hasNamedOrNamespaceImport : Boolean(declaration.getDefaultImport()) && !hasNamedOrNamespaceImport;
88
+ });
89
+ if (imports.length !== 1) {
90
+ return undefined;
91
+ }
92
+ const declaration = imports[0];
93
+ return {
94
+ declaration,
95
+ localName: declaration.getDefaultImport()?.getText(),
96
+ moduleSpecifier: declaration.getModuleSpecifierValue()
97
+ };
98
+ }
99
+ function getFunction({ functionName, sourceFile }) {
100
+ const functions = sourceFile.getFunctions().filter((declaration)=>declaration.getName() === functionName);
101
+ return functions.length === 1 ? functions[0] : undefined;
102
+ }
103
+ function getRouteComponentFunction({ component, sourceFile }) {
104
+ if (Node.isArrowFunction(component) || Node.isFunctionExpression(component)) {
105
+ return component;
106
+ }
107
+ if (!Node.isIdentifier(component)) {
108
+ return undefined;
109
+ }
110
+ const functions = sourceFile.getFunctions().filter((declaration)=>declaration.getName() === component.getText());
111
+ const variableFunctions = sourceFile.getVariableDeclarations().filter((declaration)=>declaration.getName() === component.getText()).map((declaration)=>declaration.getInitializer()).filter((initializer)=>Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer));
112
+ functions.push(...variableFunctions);
113
+ return functions.length === 1 ? functions[0] : undefined;
114
+ }
115
+ function isDocumentShellExpression(expression) {
116
+ if (!expression) {
117
+ return false;
118
+ }
119
+ const openingElements = expression.getDescendantsOfKind(SyntaxKind.JsxOpeningElement);
120
+ const selfClosingElements = expression.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement);
121
+ return [
122
+ ...openingElements,
123
+ ...selfClosingElements
124
+ ].some((element)=>element.getTagNameNode().getText() === 'html');
125
+ }
126
+ function routeComponentRendersDocumentShell({ component, sourceFile }) {
127
+ const componentFunction = getRouteComponentFunction({
128
+ component,
129
+ sourceFile
130
+ });
131
+ if (!componentFunction) {
132
+ return false;
133
+ }
134
+ const body = componentFunction.getBody();
135
+ if (!body) {
136
+ return false;
137
+ }
138
+ if (Node.isExpression(body) && isDocumentShellExpression(body)) {
139
+ return true;
140
+ }
141
+ return body.getDescendantsOfKind(SyntaxKind.ReturnStatement).filter((returnStatement)=>{
142
+ const containingFunction = returnStatement.getFirstAncestor((ancestor)=>Node.isArrowFunction(ancestor) || Node.isFunctionDeclaration(ancestor) || Node.isFunctionExpression(ancestor));
143
+ return containingFunction?.getStart() === componentFunction.getStart();
144
+ }).some((returnStatement)=>isDocumentShellExpression(returnStatement.getExpression()));
145
+ }
146
+ function getHeadContentNode({ functionDeclaration, localName }) {
147
+ const matches = functionDeclaration.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement).filter((element)=>element.getTagNameNode().getText() === localName);
148
+ return matches.length === 1 ? matches[0] : undefined;
149
+ }
150
+ function getLocalBindings({ localName, sourceFile }) {
151
+ const bindings = [];
152
+ for (const declaration of sourceFile.getImportDeclarations()){
153
+ const moduleSpecifier = declaration.getModuleSpecifierValue();
154
+ const defaultImport = declaration.getDefaultImport();
155
+ if (defaultImport?.getText() === localName) {
156
+ bindings.push({
157
+ importKind: 'default',
158
+ isTypeOnly: declaration.isTypeOnly(),
159
+ kind: 'import',
160
+ moduleSpecifier
161
+ });
162
+ }
163
+ const namespaceImport = declaration.getNamespaceImport();
164
+ if (namespaceImport?.getText() === localName) {
165
+ bindings.push({
166
+ importKind: 'namespace',
167
+ isTypeOnly: declaration.isTypeOnly(),
168
+ kind: 'import',
169
+ moduleSpecifier
170
+ });
171
+ }
172
+ for (const namedImport of declaration.getNamedImports()){
173
+ const namedImportLocalName = namedImport.getAliasNode()?.getText() ?? namedImport.getName();
174
+ if (namedImportLocalName === localName) {
175
+ bindings.push({
176
+ importedName: namedImport.getName(),
177
+ importKind: 'named',
178
+ isTypeOnly: declaration.isTypeOnly() || namedImport.isTypeOnly(),
179
+ kind: 'import',
180
+ moduleSpecifier
181
+ });
182
+ }
183
+ }
184
+ }
185
+ for (const declaration of sourceFile.getVariableDeclarations()){
186
+ if (bindingNameIncludes({
187
+ localName,
188
+ node: declaration.getNameNode()
189
+ })) {
190
+ bindings.push({
191
+ kind: 'variable'
192
+ });
193
+ }
194
+ }
195
+ const hasOtherDeclaration = [
196
+ ...sourceFile.getClasses(),
197
+ ...sourceFile.getEnums(),
198
+ ...sourceFile.getFunctions(),
199
+ ...sourceFile.getModules()
200
+ ].some((declaration)=>declaration.getName() === localName);
201
+ if (hasOtherDeclaration) {
202
+ bindings.push({
203
+ kind: 'other'
204
+ });
205
+ }
206
+ return bindings;
207
+ }
208
+ function getNamedImport({ importedName, moduleSpecifier, sourceFile }) {
209
+ const imports = sourceFile.getImportDeclarations().flatMap((declaration)=>declaration.getModuleSpecifierValue() === moduleSpecifier ? declaration.getNamedImports().filter((namedImport)=>namedImport.getName() === importedName).map((namedImport)=>({
210
+ declaration,
211
+ localName: namedImport.getAliasNode()?.getText() ?? namedImport.getName()
212
+ })) : []);
213
+ if (imports.length !== 1) {
214
+ return undefined;
215
+ }
216
+ const imported = imports[0];
217
+ const bindings = getLocalBindings({
218
+ localName: imported.localName,
219
+ sourceFile
220
+ });
221
+ const binding = bindings[0];
222
+ if (bindings.length !== 1 || binding?.kind !== 'import' || binding.importKind !== 'named' || binding.importedName !== importedName || binding.isTypeOnly || binding.moduleSpecifier !== moduleSpecifier) {
223
+ return undefined;
224
+ }
225
+ return imported;
226
+ }
227
+ function resolveRouterNamedImport({ importedName, sourceFile }) {
228
+ const matchingImports = sourceFile.getImportDeclarations().flatMap((declaration)=>declaration.getModuleSpecifierValue() === ROUTER_MODULE && !declaration.isTypeOnly() ? declaration.getNamedImports().filter((namedImport)=>namedImport.getName() === importedName && !namedImport.isTypeOnly()).map((namedImport)=>namedImport.getAliasNode()?.getText() ?? namedImport.getName()) : []);
229
+ if (matchingImports.length > 1) {
230
+ return {
231
+ reason: `The TanStack router module imports ${importedName} more than once.`,
232
+ success: false
233
+ };
234
+ }
235
+ const localName = matchingImports[0] ?? importedName;
236
+ const bindings = getLocalBindings({
237
+ localName,
238
+ sourceFile
239
+ });
240
+ const binding = bindings[0];
241
+ const isCompatible = binding?.kind === 'import' && binding.importKind === 'named' && binding.importedName === importedName && !binding.isTypeOnly && binding.moduleSpecifier === ROUTER_MODULE;
242
+ if (bindings.length > 0 && (bindings.length !== 1 || !isCompatible)) {
243
+ return {
244
+ reason: `Identifier "${localName}" is already bound incompatibly.`,
245
+ success: false
246
+ };
247
+ }
248
+ return {
249
+ importedName,
250
+ isPresent: matchingImports.length === 1,
251
+ localName,
252
+ success: true
253
+ };
254
+ }
255
+ function getSideEffectStylesheetImports(sourceFile) {
256
+ return sourceFile.getImportDeclarations().filter((declaration)=>/\.css$/.test(declaration.getModuleSpecifierValue()) && !declaration.getDefaultImport() && !declaration.getNamespaceImport() && declaration.getNamedImports().length === 0);
257
+ }
258
+ function getPropertyName(node) {
259
+ if (Node.isPropertyAssignment(node) || Node.isShorthandPropertyAssignment(node) || Node.isMethodDeclaration(node) || Node.isGetAccessorDeclaration(node) || Node.isSetAccessorDeclaration(node)) {
260
+ return node.getName();
261
+ }
262
+ }
263
+ function getPropertyAssignment({ object, propertyName }) {
264
+ const properties = object.getProperties().filter((property)=>getPropertyName(property) === propertyName);
265
+ return properties.length === 1 && Node.isPropertyAssignment(properties[0]) ? properties[0] : undefined;
266
+ }
267
+ function getRootHeadLinks(rootObject) {
268
+ const headProperty = getPropertyAssignment({
269
+ object: rootObject,
270
+ propertyName: 'head'
271
+ });
272
+ const headInitializer = headProperty?.getInitializer();
273
+ if (!headInitializer || !Node.isArrowFunction(headInitializer)) {
274
+ return {
275
+ reason: 'The root head declaration cannot be transformed safely.',
276
+ success: false
277
+ };
278
+ }
279
+ const body = headInitializer.getBody();
280
+ const headObject = Node.isParenthesizedExpression(body) ? body.getExpression() : body;
281
+ if (!Node.isObjectLiteralExpression(headObject)) {
282
+ return {
283
+ reason: 'The root head declaration cannot be transformed safely.',
284
+ success: false
285
+ };
286
+ }
287
+ const linksProperty = getPropertyAssignment({
288
+ object: headObject,
289
+ propertyName: 'links'
290
+ });
291
+ const links = linksProperty?.getInitializer();
292
+ if (!links || !Node.isArrayLiteralExpression(links) || links.getElements().some(Node.isSpreadElement)) {
293
+ return {
294
+ reason: 'The root head links cannot be transformed safely.',
295
+ success: false
296
+ };
297
+ }
298
+ return {
299
+ links,
300
+ success: true
301
+ };
302
+ }
303
+ function getShellState({ expectedComponent, rootObject, withPayloadRootLocalName }) {
304
+ const properties = rootObject.getProperties().filter((property)=>getPropertyName(property) === 'shellComponent');
305
+ if (properties.length === 0) {
306
+ if (!expectedComponent) {
307
+ return {
308
+ componentName: 'RootDocument',
309
+ isWrapped: false,
310
+ success: true
311
+ };
312
+ }
313
+ return {
314
+ reason: 'The existing shellComponent cannot be transformed safely.',
315
+ success: false
316
+ };
317
+ }
318
+ const property = properties[0];
319
+ if (properties.length !== 1 || !property || !Node.isPropertyAssignment(property)) {
320
+ return {
321
+ reason: 'The existing shellComponent cannot be transformed safely.',
322
+ success: false
323
+ };
324
+ }
325
+ const initializer = property.getInitializer();
326
+ if (Node.isIdentifier(initializer) && (!expectedComponent || initializer.getText() === expectedComponent)) {
327
+ return {
328
+ componentName: initializer.getText(),
329
+ isWrapped: false,
330
+ property,
331
+ success: true
332
+ };
333
+ }
334
+ if (Node.isCallExpression(initializer) && initializer.getExpression().getText() === withPayloadRootLocalName && initializer.getArguments().length === 1 && Node.isIdentifier(initializer.getArguments()[0]) && (!expectedComponent || initializer.getArguments()[0].getText() === expectedComponent)) {
335
+ return {
336
+ componentName: initializer.getArguments()[0].getText(),
337
+ isWrapped: true,
338
+ property,
339
+ success: true
340
+ };
341
+ }
342
+ return {
343
+ reason: 'The existing shellComponent cannot be transformed safely.',
344
+ success: false
345
+ };
346
+ }
347
+ function getStylesheetAttribute({ name, element }) {
348
+ const attribute = element.getAttributes().find((candidate)=>Node.isJsxAttribute(candidate) && candidate.getNameNode().getText() === name);
349
+ if (!attribute || !Node.isJsxAttribute(attribute)) {
350
+ return undefined;
351
+ }
352
+ const initializer = attribute.getInitializer();
353
+ if (Node.isStringLiteral(initializer)) {
354
+ return initializer.getLiteralValue();
355
+ }
356
+ if (Node.isJsxExpression(initializer)) {
357
+ return initializer.getExpression()?.getText();
358
+ }
359
+ }
360
+ function transformRouterOnlyRoot({ content, rootObject, sourceFile }) {
361
+ const withPayloadRootImport = getNamedImport({
362
+ importedName: 'withPayloadRoot',
363
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE,
364
+ sourceFile
365
+ });
366
+ const withPayloadRootLocalName = withPayloadRootImport?.localName ?? 'withPayloadRoot';
367
+ const shellState = getShellState({
368
+ rootObject,
369
+ withPayloadRootLocalName
370
+ });
371
+ if (!shellState.success) {
372
+ return shellState;
373
+ }
374
+ if (shellState.property && !shellState.isWrapped) {
375
+ return failure('The existing shellComponent cannot be transformed safely.');
376
+ }
377
+ if (shellState.isWrapped && getSideEffectStylesheetImports(sourceFile).length > 0) {
378
+ return failure('Side-effect stylesheet imports cannot be isolated from admin.');
379
+ }
380
+ const headContentImport = resolveRouterNamedImport({
381
+ importedName: 'HeadContent',
382
+ sourceFile
383
+ });
384
+ if (!headContentImport.success) {
385
+ return headContentImport;
386
+ }
387
+ const scriptsImport = resolveRouterNamedImport({
388
+ importedName: 'Scripts',
389
+ sourceFile
390
+ });
391
+ if (!scriptsImport.success) {
392
+ return scriptsImport;
393
+ }
394
+ const destinationValidation = validateRouterOnlyDestinations({
395
+ isAlreadyWrapped: shellState.isWrapped,
396
+ sourceFile,
397
+ withPayloadRootLocalName
398
+ });
399
+ if (!destinationValidation.success) {
400
+ return destinationValidation;
401
+ }
402
+ if (shellState.isWrapped) {
403
+ const stylesheetImport = getAppStylesheetImport({
404
+ requireSideEffect: false,
405
+ sourceFile
406
+ });
407
+ const rootDocument = getFunction({
408
+ functionName: 'RootDocument',
409
+ sourceFile
410
+ });
411
+ if (!stylesheetImport || stylesheetImport.localName !== 'appCss' || !rootDocument || !hasValidAppStylesheetLink({
412
+ functionDeclaration: rootDocument,
413
+ headContentLocalName: headContentImport.localName,
414
+ localName: 'appCss'
415
+ })) {
416
+ return failure('The existing Payload root shell does not match the supported configuration.');
417
+ }
418
+ const hasWithPayloadImport = Boolean(withPayloadRootImport);
419
+ const hasAllRequiredImports = hasWithPayloadImport && headContentImport.isPresent && scriptsImport.isPresent;
420
+ if (!hasAllRequiredImports) {
421
+ if (!hasWithPayloadImport) {
422
+ ensureNamedImport({
423
+ importedName: 'withPayloadRoot',
424
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE,
425
+ sourceFile
426
+ });
427
+ }
428
+ if (!headContentImport.isPresent) {
429
+ ensureNamedImport({
430
+ importedName: 'HeadContent',
431
+ moduleSpecifier: ROUTER_MODULE,
432
+ sourceFile
433
+ });
434
+ }
435
+ if (!scriptsImport.isPresent) {
436
+ ensureNamedImport({
437
+ importedName: 'Scripts',
438
+ moduleSpecifier: ROUTER_MODULE,
439
+ sourceFile
440
+ });
441
+ }
442
+ sourceFile.formatText({
443
+ indentSize: 2
444
+ });
445
+ return {
446
+ content: sourceFile.getFullText(),
447
+ modified: true,
448
+ success: true
449
+ };
450
+ }
451
+ return {
452
+ content,
453
+ modified: false,
454
+ success: true
455
+ };
456
+ }
457
+ const sideEffectStylesheets = getSideEffectStylesheetImports(sourceFile);
458
+ if (sideEffectStylesheets.length !== 1) {
459
+ return failure('Expected exactly one side-effect stylesheet import.');
460
+ }
461
+ const stylesheetImport = sideEffectStylesheets[0];
462
+ const componentProperties = rootObject.getProperties().filter((property)=>getPropertyName(property) === 'component');
463
+ const componentProperty = componentProperties[0];
464
+ if (componentProperties.length !== 1 || !Node.isPropertyAssignment(componentProperty) || !componentProperty.getInitializer()) {
465
+ return failure('The Router-only root must contain exactly one component option.');
466
+ }
467
+ if (routeComponentRendersDocumentShell({
468
+ component: componentProperty.getInitializer(),
469
+ sourceFile
470
+ })) {
471
+ return failure('The Router-only route component cannot render the document shell.');
472
+ }
473
+ stylesheetImport.setDefaultImport('appCss');
474
+ stylesheetImport.setModuleSpecifier(`${stylesheetImport.getModuleSpecifierValue()}?url`);
475
+ rootObject.addPropertyAssignment({
476
+ name: 'shellComponent',
477
+ initializer: `${withPayloadRootLocalName}(RootDocument)`
478
+ });
479
+ if (!withPayloadRootImport) {
480
+ ensureNamedImport({
481
+ importedName: 'withPayloadRoot',
482
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE,
483
+ sourceFile
484
+ });
485
+ }
486
+ if (!headContentImport.isPresent) {
487
+ ensureNamedImport({
488
+ importedName: 'HeadContent',
489
+ moduleSpecifier: ROUTER_MODULE,
490
+ sourceFile
491
+ });
492
+ }
493
+ if (!scriptsImport.isPresent) {
494
+ ensureNamedImport({
495
+ importedName: 'Scripts',
496
+ moduleSpecifier: ROUTER_MODULE,
497
+ sourceFile
498
+ });
499
+ }
500
+ sourceFile.addStatements(`
501
+ function RootDocument({ children }: { children: React.ReactNode }) {
502
+ return (
503
+ <html lang="en" suppressHydrationWarning>
504
+ <head>
505
+ <link href={appCss} rel="stylesheet" />
506
+ <${headContentImport.localName} />
507
+ </head>
508
+ <body>
509
+ {children}
510
+ <${scriptsImport.localName} />
511
+ </body>
512
+ </html>
513
+ )
514
+ }`);
515
+ sourceFile.formatText({
516
+ indentSize: 2
517
+ });
518
+ return {
519
+ content: sourceFile.getFullText(),
520
+ modified: true,
521
+ success: true
522
+ };
523
+ }
524
+ function transformStartRoot({ content, rootObject, sourceFile }) {
525
+ if (getSideEffectStylesheetImports(sourceFile).length > 0) {
526
+ return failure('Side-effect stylesheet imports cannot be isolated from admin.');
527
+ }
528
+ const withPayloadRootImport = getNamedImport({
529
+ importedName: 'withPayloadRoot',
530
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE,
531
+ sourceFile
532
+ });
533
+ const withPayloadRootLocalName = withPayloadRootImport?.localName ?? 'withPayloadRoot';
534
+ const shellState = getShellState({
535
+ expectedComponent: undefined,
536
+ rootObject,
537
+ withPayloadRootLocalName
538
+ });
539
+ if (!shellState.success || !shellState.property) {
540
+ return shellState.success ? failure('The existing shellComponent cannot be transformed safely.') : shellState;
541
+ }
542
+ const withPayloadValidation = validateNamedDestination({
543
+ importedName: 'withPayloadRoot',
544
+ localName: withPayloadRootLocalName,
545
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE,
546
+ sourceFile
547
+ });
548
+ if (!withPayloadValidation.success) {
549
+ return withPayloadValidation;
550
+ }
551
+ const hasWithPayloadImport = Boolean(withPayloadRootImport);
552
+ const headContentImport = getNamedImport({
553
+ importedName: 'HeadContent',
554
+ moduleSpecifier: ROUTER_MODULE,
555
+ sourceFile
556
+ });
557
+ const scriptsImport = getNamedImport({
558
+ importedName: 'Scripts',
559
+ moduleSpecifier: ROUTER_MODULE,
560
+ sourceFile
561
+ });
562
+ if (!headContentImport || !scriptsImport) {
563
+ return failure('Could not identify the Start document imports.');
564
+ }
565
+ const stylesheetImport = getAppStylesheetImport({
566
+ requireSideEffect: false,
567
+ sourceFile
568
+ });
569
+ if (!stylesheetImport?.localName) {
570
+ return failure('Could not identify the app stylesheet import.');
571
+ }
572
+ const stylesheetBindings = getLocalBindings({
573
+ localName: stylesheetImport.localName,
574
+ sourceFile
575
+ });
576
+ const stylesheetBinding = stylesheetBindings[0];
577
+ if (stylesheetBindings.length !== 1 || stylesheetBinding?.kind !== 'import' || stylesheetBinding.importKind !== 'default' || stylesheetBinding.isTypeOnly || stylesheetBinding.moduleSpecifier !== stylesheetImport.moduleSpecifier) {
578
+ return failure(`Identifier "${stylesheetImport.localName}" is already bound incompatibly.`);
579
+ }
580
+ const rootDocument = getFunction({
581
+ functionName: shellState.componentName,
582
+ sourceFile
583
+ });
584
+ if (!rootDocument) {
585
+ return failure('Could not identify the Start root document component.');
586
+ }
587
+ const headContentNode = getHeadContentNode({
588
+ functionDeclaration: rootDocument,
589
+ localName: headContentImport.localName
590
+ });
591
+ if (!headContentNode) {
592
+ return failure('Could not identify HeadContent in the Start root document.');
593
+ }
594
+ const headLinks = getRootHeadLinks(rootObject);
595
+ if (!headLinks.success) {
596
+ return headLinks;
597
+ }
598
+ let stylesheetIndex = -1;
599
+ for (const [index, element] of headLinks.links.getElements().entries()){
600
+ if (!Node.isObjectLiteralExpression(element)) {
601
+ return failure('The app stylesheet link cannot be relocated safely.');
602
+ }
603
+ if (element.getProperties().some(Node.isSpreadAssignment)) {
604
+ return failure('The app stylesheet link cannot be relocated safely.');
605
+ }
606
+ const rel = getStaticObjectPropertyValue({
607
+ object: element,
608
+ propertyName: 'rel'
609
+ });
610
+ if (rel !== 'stylesheet') {
611
+ continue;
612
+ }
613
+ const hrefProperty = getPropertyAssignment({
614
+ object: element,
615
+ propertyName: 'href'
616
+ });
617
+ if (hrefProperty?.getInitializer()?.getText() !== stylesheetImport.localName || stylesheetIndex !== -1) {
618
+ return failure('The app stylesheet link cannot be relocated safely.');
619
+ }
620
+ stylesheetIndex = index;
621
+ }
622
+ const hasStylesheetLink = hasValidAppStylesheetLink({
623
+ functionDeclaration: rootDocument,
624
+ headContentLocalName: headContentImport.localName,
625
+ localName: stylesheetImport.localName
626
+ });
627
+ if (stylesheetIndex === -1 && !hasStylesheetLink) {
628
+ return failure('The app stylesheet link cannot be relocated safely.');
629
+ }
630
+ if (shellState.isWrapped && stylesheetIndex === -1 && hasStylesheetLink && hasWithPayloadImport) {
631
+ return {
632
+ content,
633
+ modified: false,
634
+ success: true
635
+ };
636
+ }
637
+ if (stylesheetIndex !== -1) {
638
+ headLinks.links.removeElement(stylesheetIndex);
639
+ }
640
+ if (!hasStylesheetLink) {
641
+ headContentNode.replaceWithText(`<link href={${stylesheetImport.localName}} rel="stylesheet" />\n<${headContentImport.localName} />`);
642
+ }
643
+ if (!shellState.isWrapped) {
644
+ shellState.property.setInitializer(`${withPayloadRootLocalName}(${shellState.componentName})`);
645
+ }
646
+ if (!withPayloadRootImport) {
647
+ ensureNamedImport({
648
+ importedName: 'withPayloadRoot',
649
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE,
650
+ sourceFile
651
+ });
652
+ }
653
+ sourceFile.formatText({
654
+ indentSize: 2
655
+ });
656
+ return {
657
+ content: sourceFile.getFullText(),
658
+ modified: true,
659
+ success: true
660
+ };
661
+ }
662
+ function getStaticObjectPropertyValue({ object, propertyName }) {
663
+ const property = getPropertyAssignment({
664
+ object,
665
+ propertyName
666
+ });
667
+ const initializer = property?.getInitializer();
668
+ return Node.isStringLiteral(initializer) ? initializer.getLiteralValue() : undefined;
669
+ }
670
+ function hasValidAppStylesheetLink({ functionDeclaration, headContentLocalName, localName }) {
671
+ const links = functionDeclaration.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement).filter((element)=>element.getTagNameNode().getText() === 'link' && getStylesheetAttribute({
672
+ name: 'href',
673
+ element
674
+ }) === localName && getStylesheetAttribute({
675
+ name: 'rel',
676
+ element
677
+ }) === 'stylesheet');
678
+ const headContentElements = functionDeclaration.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement).filter((element)=>element.getTagNameNode().getText() === headContentLocalName);
679
+ if (links.length !== 1 || headContentElements.length !== 1) {
680
+ return false;
681
+ }
682
+ const link = links[0];
683
+ const headContent = headContentElements[0];
684
+ const linkParent = link.getFirstAncestorByKind(SyntaxKind.JsxElement);
685
+ const headContentParent = headContent.getFirstAncestorByKind(SyntaxKind.JsxElement);
686
+ return linkParent?.getStart() === headContentParent?.getStart() && linkParent?.getOpeningElement().getTagNameNode().getText() === 'head' && link.getStart() < headContent.getStart();
687
+ }
688
+ function validateNamedDestination({ importedName, localName, moduleSpecifier, sourceFile }) {
689
+ const bindings = getLocalBindings({
690
+ localName,
691
+ sourceFile
692
+ });
693
+ const binding = bindings[0];
694
+ const isCompatible = binding?.kind === 'import' && binding.importKind === 'named' && binding.importedName === importedName && !binding.isTypeOnly && binding.moduleSpecifier === moduleSpecifier;
695
+ if (bindings.length > 0 && (bindings.length !== 1 || !isCompatible)) {
696
+ return {
697
+ reason: `Identifier "${localName}" is already bound incompatibly.`,
698
+ success: false
699
+ };
700
+ }
701
+ return {
702
+ success: true
703
+ };
704
+ }
705
+ function validateRouterOnlyDestinations({ isAlreadyWrapped, sourceFile, withPayloadRootLocalName }) {
706
+ const destinations = [
707
+ {
708
+ importedName: 'withPayloadRoot',
709
+ localName: withPayloadRootLocalName,
710
+ moduleSpecifier: PAYLOAD_CLIENT_MODULE
711
+ }
712
+ ];
713
+ for (const destination of destinations){
714
+ const validation = validateNamedDestination({
715
+ ...destination,
716
+ sourceFile
717
+ });
718
+ if (!validation.success) {
719
+ return validation;
720
+ }
721
+ }
722
+ for (const localName of [
723
+ 'appCss',
724
+ 'RootDocument'
725
+ ]){
726
+ const bindings = getLocalBindings({
727
+ localName,
728
+ sourceFile
729
+ });
730
+ if (bindings.length === 0) {
731
+ continue;
732
+ }
733
+ const binding = bindings[0];
734
+ const isCompatible = isAlreadyWrapped && bindings.length === 1 && (localName === 'RootDocument' ? binding?.kind === 'other' : binding?.kind === 'import' && binding.importKind === 'default' && !binding.isTypeOnly && /\.css\?url$/.test(binding.moduleSpecifier));
735
+ if (!isCompatible) {
736
+ return {
737
+ reason: `Identifier "${localName}" is already bound incompatibly.`,
738
+ success: false
739
+ };
740
+ }
741
+ }
742
+ return {
743
+ success: true
744
+ };
745
+ }
746
+
747
+ //# sourceMappingURL=transform-root-route.js.map