@nrwl/remix 13.7.1 → 14.7.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.
- package/README.md +2 -2
- package/generators.json +25 -0
- package/migrations.json +54 -0
- package/package.json +8 -4
- package/src/generators/action/action.impl.d.ts +3 -0
- package/src/generators/action/action.impl.js +48 -0
- package/src/generators/action/action.impl.js.map +1 -0
- package/src/generators/action/schema.d.ts +4 -0
- package/src/generators/action/schema.json +27 -0
- package/src/generators/application/application.impl.js +13 -11
- package/src/generators/application/application.impl.js.map +1 -1
- package/src/generators/application/files/.gitignore__tmpl__ +4 -0
- package/src/generators/application/files/app/entry.client.tsx__tmpl__ +2 -2
- package/src/generators/application/files/app/entry.server.tsx__tmpl__ +4 -4
- package/src/generators/application/files/app/root.tsx__tmpl__ +10 -156
- package/src/generators/application/files/app/routes/index.tsx__tmpl__ +28 -96
- package/src/generators/application/files/package.json__tmpl__ +4 -5
- package/src/generators/application/files/remix.config.js__tmpl__ +8 -7
- package/src/generators/application/files/tsconfig.json__tmpl__ +5 -4
- package/src/generators/cypress/cypress.impl.js +5 -5
- package/src/generators/cypress/cypress.impl.js.map +1 -1
- package/src/generators/library/library.impl.js +1 -1
- package/src/generators/loader/loader.impl.d.ts +3 -0
- package/src/generators/loader/loader.impl.js +48 -0
- package/src/generators/loader/loader.impl.js.map +1 -0
- package/src/generators/loader/schema.d.ts +4 -0
- package/src/generators/loader/schema.json +27 -0
- package/src/generators/meta/meta.impl.d.ts +3 -0
- package/src/generators/meta/meta.impl.js +29 -0
- package/src/generators/meta/meta.impl.js.map +1 -0
- package/src/generators/meta/schema.d.ts +4 -0
- package/src/generators/meta/schema.json +27 -0
- package/src/generators/preset/preset.impl.js +1 -1
- package/src/generators/resource-route/resource-route.impl.d.ts +3 -0
- package/src/generators/resource-route/resource-route.impl.js +32 -0
- package/src/generators/resource-route/resource-route.impl.js.map +1 -0
- package/src/generators/resource-route/schema.d.ts +6 -0
- package/src/generators/resource-route/schema.json +44 -0
- package/src/generators/route/route.impl.js +38 -62
- package/src/generators/route/route.impl.js.map +1 -1
- package/src/generators/route/schema.d.ts +3 -0
- package/src/generators/route/schema.json +24 -9
- package/src/generators/setup/setup.impl.js +1 -1
- package/src/generators/style/schema.d.ts +4 -0
- package/src/generators/style/schema.json +34 -0
- package/src/generators/style/style.impl.d.ts +3 -0
- package/src/generators/style/style.impl.js +41 -0
- package/src/generators/style/style.impl.js.map +1 -0
- package/src/migrations/update-14-5-4/update-tsconfig-and-remix-config-for-1-6-8.d.ts +6 -0
- package/src/migrations/update-14-5-4/update-tsconfig-and-remix-config-for-1-6-8.js +45 -0
- package/src/migrations/update-14-5-4/update-tsconfig-and-remix-config-for-1-6-8.js.map +1 -0
- package/src/utils/get-default-export-name.d.ts +2 -0
- package/src/utils/get-default-export-name.js +10 -0
- package/src/utils/get-default-export-name.js.map +1 -0
- package/src/utils/get-default-export.d.ts +2 -0
- package/src/utils/get-default-export.js +16 -0
- package/src/utils/get-default-export.js.map +1 -0
- package/src/utils/insert-import.d.ts +4 -0
- package/src/utils/insert-import.js +55 -0
- package/src/utils/insert-import.js.map +1 -0
- package/src/utils/insert-statement-after-imports.d.ts +5 -0
- package/src/utils/insert-statement-after-imports.js +29 -0
- package/src/utils/insert-statement-after-imports.js.map +1 -0
- package/src/utils/insert-statement-in-default-function.d.ts +2 -0
- package/src/utils/insert-statement-in-default-function.js +24 -0
- package/src/utils/insert-statement-in-default-function.js.map +1 -0
- package/src/utils/remix-route-utils.d.ts +11 -0
- package/src/utils/remix-route-utils.js +53 -0
- package/src/utils/remix-route-utils.js.map +1 -0
- package/src/generators/application/files/app/routes/demos/about/index.tsx__tmpl__ +0 -17
- package/src/generators/application/files/app/routes/demos/about/whoa.tsx__tmpl__ +0 -20
- package/src/generators/application/files/app/routes/demos/about.tsx__tmpl__ +0 -44
- package/src/generators/application/files/app/routes/demos/actions.tsx__tmpl__ +0 -101
- package/src/generators/application/files/app/routes/demos/correct.tsx__tmpl__ +0 -3
- package/src/generators/application/files/app/routes/demos/params/$id.tsx__tmpl__ +0 -110
- package/src/generators/application/files/app/routes/demos/params/index.tsx__tmpl__ +0 -40
- package/src/generators/application/files/app/routes/demos/params.tsx__tmpl__ +0 -43
- package/src/generators/application/files/app/styles/dark.css +0 -7
- package/src/generators/application/files/app/styles/demos/about.css +0 -26
- package/src/generators/application/files/app/styles/global.css +0 -216
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
const insert_import_1 = require("../../utils/insert-import");
|
|
6
|
+
const insert_statement_after_imports_1 = require("../../utils/insert-statement-after-imports");
|
|
7
|
+
const remix_route_utils_1 = require("../../utils/remix-route-utils");
|
|
8
|
+
function default_1(tree, options) {
|
|
9
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
10
|
+
const { fileName: routePath, className: componentName } = (0, devkit_1.names)(options.path.replace(/^\//, '').replace(/\/$/, '').replace('.tsx', ''));
|
|
11
|
+
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
12
|
+
if (!project)
|
|
13
|
+
throw new Error(`Project does not exist: ${options.project}`);
|
|
14
|
+
const normalizedRoutePath = (0, remix_route_utils_1.normalizeRoutePath)(routePath, project.root);
|
|
15
|
+
const stylesheetPath = (0, devkit_1.joinPathFragments)(project.root, 'app/styles', `${normalizedRoutePath}.css`);
|
|
16
|
+
tree.write(stylesheetPath, (0, devkit_1.stripIndents) `
|
|
17
|
+
:root {
|
|
18
|
+
--color-foreground: #fff;
|
|
19
|
+
--color-background: #143157;
|
|
20
|
+
--color-links: hsl(214, 73%, 69%);
|
|
21
|
+
--color-border: #275da8;
|
|
22
|
+
--font-body: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
23
|
+
Liberation Mono, Courier New, monospace;
|
|
24
|
+
}
|
|
25
|
+
`);
|
|
26
|
+
const routeFilePath = (0, remix_route_utils_1.resolveRemixRouteFile)(tree, options.path, options.project, '.tsx');
|
|
27
|
+
(0, insert_import_1.insertImport)(tree, routeFilePath, 'LinksFunction', '@remix-run/node', {
|
|
28
|
+
typeOnly: true,
|
|
29
|
+
});
|
|
30
|
+
(0, insert_statement_after_imports_1.insertStatementAfterImports)(tree, routeFilePath, `
|
|
31
|
+
import stylesUrl from '~/styles/${normalizedRoutePath}.css'
|
|
32
|
+
|
|
33
|
+
export const links: LinksFunction = () => {
|
|
34
|
+
return [{ rel: 'stylesheet', href: stylesUrl }];
|
|
35
|
+
};
|
|
36
|
+
`);
|
|
37
|
+
yield (0, devkit_1.formatFiles)(tree);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
exports.default = default_1;
|
|
41
|
+
//# sourceMappingURL=style.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.impl.js","sourceRoot":"","sources":["../../../../../../packages/remix/src/generators/style/style.impl.ts"],"names":[],"mappings":";;;AAAA,yCAOsB;AAGtB,6DAAyD;AACzD,+FAAyF;AACzF,qEAGuC;AAEvC,mBAA+B,IAAU,EAAE,OAAyB;;QAClE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,IAAA,cAAK,EAC7D,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CACvE,CAAC;QAEF,MAAM,OAAO,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAChE,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAE5E,MAAM,mBAAmB,GAAG,IAAA,sCAAkB,EAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAExE,MAAM,cAAc,GAAG,IAAA,0BAAiB,EACtC,OAAO,CAAC,IAAI,EACZ,YAAY,EACZ,GAAG,mBAAmB,MAAM,CAC7B,CAAC;QAEF,IAAI,CAAC,KAAK,CACR,cAAc,EACd,IAAA,qBAAY,EAAA;;;;;;;;;KASX,CACF,CAAC;QAEF,MAAM,aAAa,GAAG,IAAA,yCAAqB,EACzC,IAAI,EACJ,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,OAAO,EACf,MAAM,CACP,CAAC;QAEF,IAAA,4BAAY,EAAC,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE;YACpE,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,IAAA,4DAA2B,EACzB,IAAI,EACJ,aAAa,EACb;sCACkC,mBAAmB;;;;;GAKtD,CACA,CAAC;QAEF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA;AAtDD,4BAsDC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
/**
|
|
6
|
+
* Update tsconfig.json and remix.config.js to support importing workspaces libraries
|
|
7
|
+
* @param tree
|
|
8
|
+
*/
|
|
9
|
+
function update(tree) {
|
|
10
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
11
|
+
const projects = (0, devkit_1.getProjects)(tree);
|
|
12
|
+
const remixProjects = Array.from(projects.values()).filter((project) => {
|
|
13
|
+
const remixConfigPath = (0, devkit_1.joinPathFragments)(project.root, 'remix.config.js');
|
|
14
|
+
// if the project doesn't have a remix.config.js, it's not a Remix project so we can skip it
|
|
15
|
+
return tree.exists(remixConfigPath);
|
|
16
|
+
});
|
|
17
|
+
if (remixProjects.length === 0)
|
|
18
|
+
return;
|
|
19
|
+
remixProjects.forEach((project) => {
|
|
20
|
+
const remixConfigPath = (0, devkit_1.joinPathFragments)(project.root, 'remix.config.js');
|
|
21
|
+
try {
|
|
22
|
+
const remixConfigContent = tree.read(remixConfigPath, 'utf-8');
|
|
23
|
+
// if watchPaths is already there, we assume this project has been updated before
|
|
24
|
+
if (remixConfigContent.includes('watchPaths'))
|
|
25
|
+
return;
|
|
26
|
+
const projectOffsetFromRoot = (0, devkit_1.offsetFromRoot)(project.root);
|
|
27
|
+
const layout = (0, devkit_1.getWorkspaceLayout)(tree);
|
|
28
|
+
tree.write(remixConfigPath, remixConfigContent.replace('module.exports = {\n', `module.exports = { watchPaths: ['${(0, devkit_1.joinPathFragments)(projectOffsetFromRoot, layout.libsDir)}'],\n`));
|
|
29
|
+
const tsConfigPath = (0, devkit_1.joinPathFragments)(project.root, 'tsconfig.json');
|
|
30
|
+
const tsConfigContent = (0, devkit_1.readJson)(tree, tsConfigPath);
|
|
31
|
+
const newTsConfigContent = Object.assign(Object.assign({}, tsConfigContent), { extends: `${projectOffsetFromRoot}tsconfig.base.json` });
|
|
32
|
+
delete newTsConfigContent.compilerOptions.baseUrl;
|
|
33
|
+
devkit_1.logger.info(`Remix apps now support importing from non-buildable libs. However, you must remove the \`paths\` configuration from the project's \`tsconfig.json\`.\n\nMigrate any import paths using \`~\` to relative path imports and then delete the \`paths\` property from \`${tsConfigPath}\``);
|
|
34
|
+
(0, devkit_1.writeJson)(tree, tsConfigPath, newTsConfigContent);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
devkit_1.logger.error(err);
|
|
38
|
+
devkit_1.logger.error(`Unable to update ${remixConfigPath} for project ${project.root}.`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
yield (0, devkit_1.formatFiles)(tree);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
exports.default = update;
|
|
45
|
+
//# sourceMappingURL=update-tsconfig-and-remix-config-for-1-6-8.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-tsconfig-and-remix-config-for-1-6-8.js","sourceRoot":"","sources":["../../../../../../packages/remix/src/migrations/update-14-5-4/update-tsconfig-and-remix-config-for-1-6-8.ts"],"names":[],"mappings":";;;AAAA,yCAUsB;AAEtB;;;GAGG;AACH,SAA8B,MAAM,CAAC,IAAU;;QAC7C,MAAM,QAAQ,GAAG,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;QAEnC,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;YACrE,MAAM,eAAe,GAAG,IAAA,0BAAiB,EAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC3E,4FAA4F;YAC5F,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEvC,aAAa,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAChC,MAAM,eAAe,GAAG,IAAA,0BAAiB,EAAC,OAAO,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAE3E,IAAI;gBACF,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;gBAC/D,iFAAiF;gBACjF,IAAI,kBAAkB,CAAC,QAAQ,CAAC,YAAY,CAAC;oBAAE,OAAO;gBAEtD,MAAM,qBAAqB,GAAG,IAAA,uBAAc,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC3D,MAAM,MAAM,GAAG,IAAA,2BAAkB,EAAC,IAAI,CAAC,CAAC;gBACxC,IAAI,CAAC,KAAK,CACR,eAAe,EACf,kBAAkB,CAAC,OAAO,CACxB,sBAAsB,EACtB,qCAAqC,IAAA,0BAAiB,EACpD,qBAAqB,EACrB,MAAM,CAAC,OAAO,CACf,OAAO,CACT,CACF,CAAC;gBAEF,MAAM,YAAY,GAAG,IAAA,0BAAiB,EAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;gBACtE,MAAM,eAAe,GAAG,IAAA,iBAAQ,EAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBAErD,MAAM,kBAAkB,mCACnB,eAAe,KAClB,OAAO,EAAE,GAAG,qBAAqB,oBAAoB,GACtD,CAAC;gBAEF,OAAO,kBAAkB,CAAC,eAAe,CAAC,OAAO,CAAC;gBAElD,eAAM,CAAC,IAAI,CACT,uQAAuQ,YAAY,IAAI,CACxR,CAAC;gBAEF,IAAA,kBAAS,EAAC,IAAI,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC;aACnD;YAAC,OAAO,GAAG,EAAE;gBACZ,eAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClB,eAAM,CAAC,KAAK,CACV,oBAAoB,eAAe,gBAAgB,OAAO,CAAC,IAAI,GAAG,CACnE,CAAC;aACH;QACH,CAAC,CAAC,CAAC;QACH,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA;AAvDD,yBAuDC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultExportName = void 0;
|
|
4
|
+
const get_default_export_1 = require("./get-default-export");
|
|
5
|
+
function getDefaultExportName(tree, path) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
return (_b = (_a = (0, get_default_export_1.getDefaultExport)(tree, path)) === null || _a === void 0 ? void 0 : _a.name.text) !== null && _b !== void 0 ? _b : 'Unknown';
|
|
8
|
+
}
|
|
9
|
+
exports.getDefaultExportName = getDefaultExportName;
|
|
10
|
+
//# sourceMappingURL=get-default-export-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-default-export-name.js","sourceRoot":"","sources":["../../../../../packages/remix/src/utils/get-default-export-name.ts"],"names":[],"mappings":";;;AACA,6DAAwD;AAExD,SAAgB,oBAAoB,CAAC,IAAU,EAAE,IAAY;;IAC3D,OAAO,MAAA,MAAA,IAAA,qCAAgB,EAAC,IAAI,EAAE,IAAI,CAAC,0CAAE,IAAI,CAAC,IAAI,mCAAI,SAAS,CAAC;AAC9D,CAAC;AAFD,oDAEC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultExport = void 0;
|
|
4
|
+
const typescript_1 = require("typescript");
|
|
5
|
+
function getDefaultExport(tree, path) {
|
|
6
|
+
const contents = tree.read(path, 'utf-8');
|
|
7
|
+
const sourceFile = (0, typescript_1.createSourceFile)(path, contents, typescript_1.ScriptTarget.ESNext);
|
|
8
|
+
const functionDeclarations = sourceFile.statements.filter(typescript_1.isFunctionDeclaration);
|
|
9
|
+
return functionDeclarations.find((functionDeclaration) => {
|
|
10
|
+
const isDefault = functionDeclaration.modifiers.find((mod) => mod.kind === typescript_1.SyntaxKind.DefaultKeyword);
|
|
11
|
+
const isExport = functionDeclaration.modifiers.find((mod) => mod.kind === typescript_1.SyntaxKind.ExportKeyword);
|
|
12
|
+
return isDefault && isExport;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
exports.getDefaultExport = getDefaultExport;
|
|
16
|
+
//# sourceMappingURL=get-default-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-default-export.js","sourceRoot":"","sources":["../../../../../packages/remix/src/utils/get-default-export.ts"],"names":[],"mappings":";;;AACA,2CAKoB;AAEpB,SAAgB,gBAAgB,CAAC,IAAU,EAAE,IAAY;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,IAAI,EAAE,QAAQ,EAAE,yBAAY,CAAC,MAAM,CAAC,CAAC;IAEzE,MAAM,oBAAoB,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,CACvD,kCAAqB,CACtB,CAAC;IAEF,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,mBAAmB,EAAE,EAAE;QACvD,MAAM,SAAS,GAAG,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAClD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,uBAAU,CAAC,cAAc,CAChD,CAAC;QAEF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,SAAS,CAAC,IAAI,CACjD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,uBAAU,CAAC,aAAa,CAC/C,CAAC;QAEF,OAAO,SAAS,IAAI,QAAQ,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AApBD,4CAoBC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.insertImport = void 0;
|
|
4
|
+
const insert_statement_after_imports_1 = require("./insert-statement-after-imports");
|
|
5
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
6
|
+
const typescript_1 = require("typescript");
|
|
7
|
+
function insertImport(tree, path, name, modulePath, options = { typeOnly: false }) {
|
|
8
|
+
if (!tree.exists(path))
|
|
9
|
+
throw Error(`Could not insert import ${name} from ${modulePath} in ${path}: path not found`);
|
|
10
|
+
const contents = tree.read(path, 'utf-8');
|
|
11
|
+
const sourceFile = (0, typescript_1.createSourceFile)(path, contents, typescript_1.ScriptTarget.ESNext);
|
|
12
|
+
let importStatements = sourceFile.statements.filter(typescript_1.isImportDeclaration);
|
|
13
|
+
if (options.typeOnly) {
|
|
14
|
+
importStatements = importStatements.filter((node) => node.importClause.isTypeOnly);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
importStatements = importStatements.filter((node) => !node.importClause.isTypeOnly);
|
|
18
|
+
}
|
|
19
|
+
const existingImport = importStatements.find((statement) => (0, typescript_1.isStringLiteral)(statement.moduleSpecifier) &&
|
|
20
|
+
statement.moduleSpecifier
|
|
21
|
+
.getText(sourceFile)
|
|
22
|
+
.replace(/['"`]/g, '')
|
|
23
|
+
.trim() === modulePath &&
|
|
24
|
+
statement.importClause.namedBindings &&
|
|
25
|
+
(0, typescript_1.isNamedImports)(statement.importClause.namedBindings));
|
|
26
|
+
if (!existingImport) {
|
|
27
|
+
(0, insert_statement_after_imports_1.insertStatementAfterImports)(tree, path, options.typeOnly
|
|
28
|
+
? `import type { ${name} } from '${modulePath}';`
|
|
29
|
+
: `import { ${name} } from '${modulePath}';`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const namedImports = existingImport.importClause
|
|
33
|
+
.namedBindings;
|
|
34
|
+
const alreadyImported = namedImports.elements.find((element) => element.name.escapedText === name) !== undefined;
|
|
35
|
+
if (!alreadyImported) {
|
|
36
|
+
const index = namedImports.getEnd() - 1;
|
|
37
|
+
let text;
|
|
38
|
+
if (namedImports.elements.hasTrailingComma) {
|
|
39
|
+
text = `${name},`;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
text = `,${name}`;
|
|
43
|
+
}
|
|
44
|
+
const newContents = (0, devkit_1.applyChangesToString)(contents, [
|
|
45
|
+
{
|
|
46
|
+
type: devkit_1.ChangeType.Insert,
|
|
47
|
+
index,
|
|
48
|
+
text,
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
tree.write(path, newContents);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.insertImport = insertImport;
|
|
55
|
+
//# sourceMappingURL=insert-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insert-import.js","sourceRoot":"","sources":["../../../../../packages/remix/src/utils/insert-import.ts"],"names":[],"mappings":";;;AAAA,qFAA+E;AAC/E,yCAAsE;AACtE,2CAOoB;AAEpB,SAAgB,YAAY,CAC1B,IAAU,EACV,IAAY,EACZ,IAAY,EACZ,UAAkB,EAClB,UAAiC,EAAE,QAAQ,EAAE,KAAK,EAAE;IAEpD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QACpB,MAAM,KAAK,CACT,2BAA2B,IAAI,SAAS,UAAU,OAAO,IAAI,kBAAkB,CAChF,CAAC;IAEJ,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,IAAI,EAAE,QAAQ,EAAE,yBAAY,CAAC,MAAM,CAAC,CAAC;IAEzE,IAAI,gBAAgB,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,gCAAmB,CAAC,CAAC;IAEzE,IAAI,OAAO,CAAC,QAAQ,EAAE;QACpB,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CACxC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CACvC,CAAC;KACH;SAAM;QACL,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CACxC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CACxC,CAAC;KACH;IAED,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAC1C,CAAC,SAAS,EAAE,EAAE,CACZ,IAAA,4BAAe,EAAC,SAAS,CAAC,eAAe,CAAC;QAC1C,SAAS,CAAC,eAAe;aACtB,OAAO,CAAC,UAAU,CAAC;aACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;aACrB,IAAI,EAAE,KAAK,UAAU;QACxB,SAAS,CAAC,YAAY,CAAC,aAAa;QACpC,IAAA,2BAAc,EAAC,SAAS,CAAC,YAAY,CAAC,aAAa,CAAC,CACvD,CAAC;IAEF,IAAI,CAAC,cAAc,EAAE;QACnB,IAAA,4DAA2B,EACzB,IAAI,EACJ,IAAI,EACJ,OAAO,CAAC,QAAQ;YACd,CAAC,CAAC,iBAAiB,IAAI,YAAY,UAAU,IAAI;YACjD,CAAC,CAAC,YAAY,IAAI,YAAY,UAAU,IAAI,CAC/C,CAAC;QACF,OAAO;KACR;IAED,MAAM,YAAY,GAAG,cAAc,CAAC,YAAY;SAC7C,aAA6B,CAAC;IAEjC,MAAM,eAAe,GACnB,YAAY,CAAC,QAAQ,CAAC,IAAI,CACxB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,KAAK,IAAI,CAC/C,KAAK,SAAS,CAAC;IAElB,IAAI,CAAC,eAAe,EAAE;QACpB,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAExC,IAAI,IAAY,CAAC;QACjB,IAAI,YAAY,CAAC,QAAQ,CAAC,gBAAgB,EAAE;YAC1C,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC;SACnB;aAAM;YACL,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;SACnB;QAED,MAAM,WAAW,GAAG,IAAA,6BAAoB,EAAC,QAAQ,EAAE;YACjD;gBACE,IAAI,EAAE,mBAAU,CAAC,MAAM;gBACvB,KAAK;gBACL,IAAI;aACL;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;KAC/B;AACH,CAAC;AA9ED,oCA8EC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.insertStatementAfterImports = void 0;
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
const typescript_1 = require("typescript");
|
|
6
|
+
/**
|
|
7
|
+
* Insert a statement after the last import statement in a file
|
|
8
|
+
*/
|
|
9
|
+
function insertStatementAfterImports(tree, path, statement) {
|
|
10
|
+
const contents = tree.read(path, 'utf-8');
|
|
11
|
+
const sourceFile = (0, typescript_1.createSourceFile)(path, contents, typescript_1.ScriptTarget.ESNext);
|
|
12
|
+
const importStatements = sourceFile.statements.filter(typescript_1.isImportDeclaration);
|
|
13
|
+
const index = importStatements.length > 0
|
|
14
|
+
? importStatements[importStatements.length - 1].getEnd()
|
|
15
|
+
: 0;
|
|
16
|
+
if (importStatements.length > 0) {
|
|
17
|
+
statement = `\n${statement}`;
|
|
18
|
+
}
|
|
19
|
+
const newContents = (0, devkit_1.applyChangesToString)(contents, [
|
|
20
|
+
{
|
|
21
|
+
type: devkit_1.ChangeType.Insert,
|
|
22
|
+
index,
|
|
23
|
+
text: statement,
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
26
|
+
tree.write(path, newContents);
|
|
27
|
+
}
|
|
28
|
+
exports.insertStatementAfterImports = insertStatementAfterImports;
|
|
29
|
+
//# sourceMappingURL=insert-statement-after-imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insert-statement-after-imports.js","sourceRoot":"","sources":["../../../../../packages/remix/src/utils/insert-statement-after-imports.ts"],"names":[],"mappings":";;;AAAA,yCAAsE;AACtE,2CAIoB;AAEpB;;GAEG;AACH,SAAgB,2BAA2B,CACzC,IAAU,EACV,IAAY,EACZ,SAAiB;IAEjB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE1C,MAAM,UAAU,GAAG,IAAA,6BAAgB,EAAC,IAAI,EAAE,QAAQ,EAAE,yBAAY,CAAC,MAAM,CAAC,CAAC;IAEzE,MAAM,gBAAgB,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,gCAAmB,CAAC,CAAC;IAC3E,MAAM,KAAK,GACT,gBAAgB,CAAC,MAAM,GAAG,CAAC;QACzB,CAAC,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE;QACxD,CAAC,CAAC,CAAC,CAAC;IAER,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;QAC/B,SAAS,GAAG,KAAK,SAAS,EAAE,CAAC;KAC9B;IAED,MAAM,WAAW,GAAG,IAAA,6BAAoB,EAAC,QAAQ,EAAE;QACjD;YACE,IAAI,EAAE,mBAAU,CAAC,MAAM;YACvB,KAAK;YACL,IAAI,EAAE,SAAS;SAChB;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAChC,CAAC;AA5BD,kEA4BC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.insertStatementInDefaultFunction = void 0;
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
const get_default_export_1 = require("./get-default-export");
|
|
6
|
+
function insertStatementInDefaultFunction(tree, path, statement) {
|
|
7
|
+
const defaultExport = (0, get_default_export_1.getDefaultExport)(tree, path);
|
|
8
|
+
if (!defaultExport) {
|
|
9
|
+
throw Error('No default export found!');
|
|
10
|
+
}
|
|
11
|
+
const index = defaultExport.body.statements.length > 0
|
|
12
|
+
? defaultExport.body.statements[0].pos
|
|
13
|
+
: 0;
|
|
14
|
+
const newContents = (0, devkit_1.applyChangesToString)(tree.read(path, 'utf-8'), [
|
|
15
|
+
{
|
|
16
|
+
type: devkit_1.ChangeType.Insert,
|
|
17
|
+
index,
|
|
18
|
+
text: statement,
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
tree.write(path, newContents);
|
|
22
|
+
}
|
|
23
|
+
exports.insertStatementInDefaultFunction = insertStatementInDefaultFunction;
|
|
24
|
+
//# sourceMappingURL=insert-statement-in-default-function.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insert-statement-in-default-function.js","sourceRoot":"","sources":["../../../../../packages/remix/src/utils/insert-statement-in-default-function.ts"],"names":[],"mappings":";;;AAAA,yCAAsE;AACtE,6DAAwD;AAExD,SAAgB,gCAAgC,CAC9C,IAAU,EACV,IAAY,EACZ,SAAS;IAET,MAAM,aAAa,GAAG,IAAA,qCAAgB,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEnD,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,KAAK,CAAC,0BAA0B,CAAC,CAAC;KACzC;IAED,MAAM,KAAK,GACT,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACtC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG;QACtC,CAAC,CAAC,CAAC,CAAC;IAER,MAAM,WAAW,GAAG,IAAA,6BAAoB,EAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;QACjE;YACE,IAAI,EAAE,mBAAU,CAAC,MAAM;YACvB,KAAK;YACL,IAAI,EAAE,SAAS;SAChB;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAChC,CAAC;AAzBD,4EAyBC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Tree } from '@nrwl/devkit';
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param tree
|
|
5
|
+
* @param path to the route which could be fully specified or just "foo/bar"
|
|
6
|
+
* @param projectName the name of the project where the route should be added
|
|
7
|
+
* @param fileExtension the file extension to add to resolved route file
|
|
8
|
+
* @returns file path to the route
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveRemixRouteFile(tree: Tree, path: string, projectName: string, fileExtension?: string): string;
|
|
11
|
+
export declare function normalizeRoutePath(path: string, projectRoot: string): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeRoutePath = exports.resolveRemixRouteFile = void 0;
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param tree
|
|
8
|
+
* @param path to the route which could be fully specified or just "foo/bar"
|
|
9
|
+
* @param projectName the name of the project where the route should be added
|
|
10
|
+
* @param fileExtension the file extension to add to resolved route file
|
|
11
|
+
* @returns file path to the route
|
|
12
|
+
*/
|
|
13
|
+
function resolveRemixRouteFile(tree, path, projectName, fileExtension) {
|
|
14
|
+
const project = (0, devkit_1.readProjectConfiguration)(tree, projectName);
|
|
15
|
+
if (!project)
|
|
16
|
+
throw new Error(`Project does not exist: ${projectName}`);
|
|
17
|
+
const { fileName: routePath } = (0, devkit_1.names)(path.replace(/^\//, '').replace(/\/$/, ''));
|
|
18
|
+
const normalizedRoutePath = normalizeRoutePath(routePath, project.root);
|
|
19
|
+
// if no file extension specified, let's try to find it
|
|
20
|
+
if (!fileExtension) {
|
|
21
|
+
// see if the path already has it
|
|
22
|
+
const extensionMatch = path.match(/(\.[^.]+)$/);
|
|
23
|
+
if (extensionMatch) {
|
|
24
|
+
fileExtension = extensionMatch[0];
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// look for either .ts or .tsx to exist in tree
|
|
28
|
+
if (tree.exists(`${normalizedRoutePath}.ts`)) {
|
|
29
|
+
fileExtension = '.ts';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// default to .tsx if nothing else found
|
|
33
|
+
fileExtension = '.tsx';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const fileName = normalizedRoutePath.endsWith(fileExtension)
|
|
38
|
+
? normalizedRoutePath
|
|
39
|
+
: `${normalizedRoutePath}${fileExtension}`;
|
|
40
|
+
// TODO: what if someone changes the Remix app root folder in the remix.config.js?
|
|
41
|
+
const routeFilePath = (0, devkit_1.joinPathFragments)(project.root, 'app/routes', fileName);
|
|
42
|
+
return routeFilePath;
|
|
43
|
+
}
|
|
44
|
+
exports.resolveRemixRouteFile = resolveRemixRouteFile;
|
|
45
|
+
function normalizeRoutePath(path, projectRoot) {
|
|
46
|
+
if (path.indexOf(projectRoot) === -1)
|
|
47
|
+
return path;
|
|
48
|
+
if (path.indexOf('/routes/') > -1)
|
|
49
|
+
return path.substring(path.indexOf('/routes/') + 8);
|
|
50
|
+
return path.substring(projectRoot.length + 1);
|
|
51
|
+
}
|
|
52
|
+
exports.normalizeRoutePath = normalizeRoutePath;
|
|
53
|
+
//# sourceMappingURL=remix-route-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remix-route-utils.js","sourceRoot":"","sources":["../../../../../packages/remix/src/utils/remix-route-utils.ts"],"names":[],"mappings":";;;AAAA,yCAKsB;AAEtB;;;;;;;GAOG;AACH,SAAgB,qBAAqB,CACnC,IAAU,EACV,IAAY,EACZ,WAAmB,EACnB,aAAsB;IAEtB,MAAM,OAAO,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,WAAW,EAAE,CAAC,CAAC;IACxE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAA,cAAK,EACnC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAC3C,CAAC;IACF,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE,uDAAuD;IACvD,IAAI,CAAC,aAAa,EAAE;QAClB,iCAAiC;QACjC,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAEhD,IAAI,cAAc,EAAE;YAClB,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;SACnC;aAAM;YACL,+CAA+C;YAC/C,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,mBAAmB,KAAK,CAAC,EAAE;gBAC5C,aAAa,GAAG,KAAK,CAAC;aACvB;iBAAM;gBACL,wCAAwC;gBACxC,aAAa,GAAG,MAAM,CAAC;aACxB;SACF;KACF;IAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC1D,CAAC,CAAC,mBAAmB;QACrB,CAAC,CAAC,GAAG,mBAAmB,GAAG,aAAa,EAAE,CAAC;IAC7C,kFAAkF;IAClF,MAAM,aAAa,GAAG,IAAA,0BAAiB,EAAC,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC9E,OAAO,aAAa,CAAC;AACvB,CAAC;AArCD,sDAqCC;AAED,SAAgB,kBAAkB,CAAC,IAAY,EAAE,WAAmB;IAClE,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AALD,gDAKC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Link } from "remix";
|
|
2
|
-
|
|
3
|
-
export default function AboutIndex() {
|
|
4
|
-
return (
|
|
5
|
-
<div>
|
|
6
|
-
<p>
|
|
7
|
-
You are looking at the index route for the <code>/about</code> URL
|
|
8
|
-
segment, but there are nested routes as well!
|
|
9
|
-
</p>
|
|
10
|
-
<p>
|
|
11
|
-
<strong>
|
|
12
|
-
<Link to="whoa">Check out one of them here.</Link>
|
|
13
|
-
</strong>
|
|
14
|
-
</p>
|
|
15
|
-
</div>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Link } from "remix";
|
|
2
|
-
|
|
3
|
-
export default function AboutIndex() {
|
|
4
|
-
return (
|
|
5
|
-
<div>
|
|
6
|
-
<p>
|
|
7
|
-
Whoa, this is a nested route! We render the <code>/about</code> layout
|
|
8
|
-
route component, and its <code>Outlet</code> renders our route
|
|
9
|
-
component. 🤯
|
|
10
|
-
</p>
|
|
11
|
-
<p>
|
|
12
|
-
<strong>
|
|
13
|
-
<Link to="..">
|
|
14
|
-
Go back to the <code>/about</code> index.
|
|
15
|
-
</Link>
|
|
16
|
-
</strong>
|
|
17
|
-
</p>
|
|
18
|
-
</div>
|
|
19
|
-
);
|
|
20
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Outlet } from "remix";
|
|
2
|
-
import type { MetaFunction, LinksFunction } from "remix";
|
|
3
|
-
|
|
4
|
-
import stylesUrl from "~/styles/demos/about.css";
|
|
5
|
-
|
|
6
|
-
export let meta: MetaFunction = () => {
|
|
7
|
-
return {
|
|
8
|
-
title: "About Remix"
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export let links: LinksFunction = () => {
|
|
13
|
-
return [{ rel: "stylesheet", href: stylesUrl }];
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default function Index() {
|
|
17
|
-
return (
|
|
18
|
-
<div className="about">
|
|
19
|
-
<div className="about__intro">
|
|
20
|
-
<h2>About Us</h2>
|
|
21
|
-
<p>
|
|
22
|
-
Ok, so this page isn't really <em>about us</em>, but we did want to
|
|
23
|
-
show you a few more things Remix can do.
|
|
24
|
-
</p>
|
|
25
|
-
<p>
|
|
26
|
-
Did you notice that things look a little different on this page? The
|
|
27
|
-
CSS that we import in the route file and include in its{" "}
|
|
28
|
-
<code>links</code> export is only included on this route and its
|
|
29
|
-
children.
|
|
30
|
-
</p>
|
|
31
|
-
<p>
|
|
32
|
-
Wait a sec...<em>its children</em>? To understand what we mean by
|
|
33
|
-
this,{" "}
|
|
34
|
-
<a href="https://remix.run/tutorial/4-nested-routes-params">
|
|
35
|
-
read all about nested routes in the docs
|
|
36
|
-
</a>
|
|
37
|
-
.
|
|
38
|
-
</p>
|
|
39
|
-
<hr />
|
|
40
|
-
<Outlet />
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from "react";
|
|
2
|
-
import type { ActionFunction } from "remix";
|
|
3
|
-
import { Form, json, useActionData, redirect } from "remix";
|
|
4
|
-
|
|
5
|
-
export function meta() {
|
|
6
|
-
return { title: "Actions Demo" };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// When your form sends a POST, the action is called on the server.
|
|
10
|
-
// - https://remix.run/api/conventions#action
|
|
11
|
-
// - https://remix.run/guides/data-updates
|
|
12
|
-
export let action: ActionFunction = async ({ request }) => {
|
|
13
|
-
let formData = await request.formData();
|
|
14
|
-
let answer = formData.get("answer");
|
|
15
|
-
|
|
16
|
-
// Typical action workflows start with validating the form data that just came
|
|
17
|
-
// over the network. Clientside validation is fine, but you definitely need it
|
|
18
|
-
// server side. If there's a problem, return the the data and the component
|
|
19
|
-
// can render it.
|
|
20
|
-
if (typeof answer !== "string") {
|
|
21
|
-
return json("Come on, at least try!", { status: 400 });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (answer !== "egg") {
|
|
25
|
-
return json(`Sorry, ${answer} is not right.`, { status: 400 });
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Finally, if the data is valid, you'll typically write to a database or send or
|
|
29
|
-
// email or log the user in, etc. It's recommended to redirect after a
|
|
30
|
-
// successful action, even if it's to the same place so that non-JavaScript workflows
|
|
31
|
-
// from the browser doesn't repost the data if the user clicks back.
|
|
32
|
-
return redirect("/demos/correct");
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export default function ActionsDemo() {
|
|
36
|
-
// https://remix.run/api/remix#useactiondata
|
|
37
|
-
let actionMessage = useActionData<string>();
|
|
38
|
-
let answerRef = useRef<HTMLInputElement>(null);
|
|
39
|
-
|
|
40
|
-
// This form works without JavaScript, but when we have JavaScript we can make
|
|
41
|
-
// the experience better by selecting the input on wrong answers! Go ahead, disable
|
|
42
|
-
// JavaScript in your browser and see what happens.
|
|
43
|
-
useEffect(() => {
|
|
44
|
-
if (actionMessage && answerRef.current) {
|
|
45
|
-
answerRef.current.select();
|
|
46
|
-
}
|
|
47
|
-
}, [actionMessage]);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<div className="remix__page">
|
|
51
|
-
<main>
|
|
52
|
-
<h2>Actions!</h2>
|
|
53
|
-
<p>
|
|
54
|
-
This form submission will send a post request that we handle in our
|
|
55
|
-
`action` export. Any route can export an action to handle data
|
|
56
|
-
mutations.
|
|
57
|
-
</p>
|
|
58
|
-
<Form method="post" className="remix__form">
|
|
59
|
-
<h3>Post an Action</h3>
|
|
60
|
-
<p>
|
|
61
|
-
<i>What is more useful when it is broken?</i>
|
|
62
|
-
</p>
|
|
63
|
-
<label>
|
|
64
|
-
<div>Answer:</div>
|
|
65
|
-
<input ref={answerRef} name="answer" type="text" />
|
|
66
|
-
</label>
|
|
67
|
-
<div>
|
|
68
|
-
<button>Answer!</button>
|
|
69
|
-
</div>
|
|
70
|
-
{actionMessage ? (
|
|
71
|
-
<p>
|
|
72
|
-
<b>{actionMessage}</b>
|
|
73
|
-
</p>
|
|
74
|
-
) : null}
|
|
75
|
-
</Form>
|
|
76
|
-
</main>
|
|
77
|
-
|
|
78
|
-
<aside>
|
|
79
|
-
<h3>Additional Resources</h3>
|
|
80
|
-
<ul>
|
|
81
|
-
<li>
|
|
82
|
-
Guide:{" "}
|
|
83
|
-
<a href="https://remix.run/guides/data-writes">Data Writes</a>
|
|
84
|
-
</li>
|
|
85
|
-
<li>
|
|
86
|
-
API:{" "}
|
|
87
|
-
<a href="https://remix.run/api/conventions#action">
|
|
88
|
-
Route Action Export
|
|
89
|
-
</a>
|
|
90
|
-
</li>
|
|
91
|
-
<li>
|
|
92
|
-
API:{" "}
|
|
93
|
-
<a href="https://remix.run/api/remix#useactiondata">
|
|
94
|
-
<code>useActionData</code>
|
|
95
|
-
</a>
|
|
96
|
-
</li>
|
|
97
|
-
</ul>
|
|
98
|
-
</aside>
|
|
99
|
-
</div>
|
|
100
|
-
);
|
|
101
|
-
}
|