@banch0u/core-project-test-repository 2.0.5 → 2.1.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.
@@ -0,0 +1,749 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ /////////////////////////////// README ///////////////////////////////
5
+ // IN ORDER TO USE THIS SCRIPT YOU HAVETO CHANGE DIRECTION INTO
6
+ // /src/ then execute the script
7
+ //////////////////////////////////////////////////////////////////////////
8
+
9
+ var fs = require("fs");
10
+ var path = require("path");
11
+
12
+ ////////// === CONFIG === //////////
13
+ var questionnaireName = "Owners"; // change as needed
14
+ var constantColumnName = "Mülkiyyətçi";
15
+ var endpointName = "/owners";
16
+ ///////////////////////////////////
17
+
18
+ var upperName = questionnaireName.toUpperCase();
19
+ var pathConstA = "QUESTIONNAIRES_".concat(upperName);
20
+ var pathConstB = "SETTINGS_QUESTIONNAIRES_".concat(upperName);
21
+
22
+ /* ------------------ TEMPLATES ------------------ */
23
+ function lowercaseFirstChar(questionnaireName) {
24
+ if (!questionnaireName) return "";
25
+ return questionnaireName.charAt(0).toLowerCase() + questionnaireName.slice(1);
26
+ }
27
+ var boilerplateTemplate = "import React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport Cookies from \"js-cookie\";\nimport style from \"../Questionnaires.module.scss\";\nimport { Form, Input, Layout } from \"antd\";\nimport { PlusIcon } from \"../../../assets/icons\";\nimport FormModal from \"../../../components/FormModal\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport Delete from \"../../../components/Delete/Delete\";\nimport DeleteModal from \"../../../components/DeleteModal/DeleteModal\";\nimport Success from \"../../../components/Success/Success\";\nimport {\n setDeleteModalVisible,\n setViewModalVisible,\n} from \"../../../store/slices/global\";\nimport ViewModal from \"../../../components/ViewModal\";\nimport { getStreetColumns } from \"./constant\";\n\nimport Pagination from \"../../../components/Pagination\";\nimport ColSort from \"../../../components/ColSort\";\nimport { setPaginationLength } from \"../../../helpers/paginationLength\";\nimport Button from \"../../../components/Button\";\nimport Loading from \"../../../components/Loading\";\nimport Table from \"../../../components/Table\";\nimport Filter from \"../../../components/Filter\";\nimport {\n add".concat(questionnaireName, ",\n delete").concat(questionnaireName, ",\n edit").concat(questionnaireName, ",\n get").concat(questionnaireName, ",\n ").concat(questionnaireName, "Visibility,\n} from \"../../../store/slices/questionnaire\";\n\nconst { Content } = Layout;\nconst { Item } = Form;\nconst Questionnaires").concat(questionnaireName, "Content = () => {\n const [innerW, setInnerW] = useState(null);\n const ref = useRef();\n const dispatch = useDispatch();\n const [id, setId] = useState(0);\n const [page, setPage] = useState(1);\n const [size, setSize] = useState(\n Cookies.get(\"pagination-size-questionnaire-").concat(questionnaireName.toLowerCase(), "\")\n ? JSON.parse(Cookies.get(\"pagination-size-questionnaire-").concat(questionnaireName.toLowerCase(), "\"))\n : 20\n );\n const [query, setQuery] = useState({ name: \"\" });\n const { loading, ").concat(questionnaireName, "Render } = useSelector((state) => state.global);\n\n const ").concat(questionnaireName, " = useSelector(\n (state) => state.questionnaire.").concat(lowercaseFirstChar(questionnaireName), "\n );\n const paginationLength = setPaginationLength(\n ").concat(questionnaireName, "?.count,\n ").concat(questionnaireName, "?.size\n );\n\n const onSubmit = useCallback(\n async (data) => {\n dispatch(add").concat(questionnaireName, "(data));\n },\n [dispatch]\n );\n const onEdit = useCallback(\n (id, record) => {\n const data = {\n id: id,\n name: record?.name,\n };\n dispatch(edit").concat(questionnaireName, "(data));\n },\n [dispatch]\n );\n const onStatusChange = useCallback(\n (data, checked) => {\n const data_ = {\n id: data?.id,\n checked: checked,\n };\n dispatch(").concat(questionnaireName, "Visibility(data_));\n },\n [dispatch]\n );\n const closeOnViewModal = useCallback(() => {\n dispatch(setViewModalVisible(false));\n }, [dispatch]);\n const onClickModal = () => {\n ref?.current?.open();\n };\n const onEditClick = useCallback((data) => {\n ref?.current?.setEdit(data);\n }, []);\n const onDelete = useCallback((id) => {\n setId(id);\n }, []);\n const handleColumnToggle = (checked, dataIndex) => {\n setSelectedColumns((prevSelected) => {\n if (checked) {\n return [...prevSelected, dataIndex];\n } else {\n return prevSelected.filter((col) => col !== dataIndex);\n }\n });\n };\n\n let data = [];\n if (").concat(questionnaireName, "?.items) {\n data = ").concat(questionnaireName, "?.items?.map((dataObj, i) => ({\n num:\n ").concat(questionnaireName, "?.size * ").concat(questionnaireName, "?.page + i + 1 - ").concat(questionnaireName, "?.size,\n id: dataObj?.id,\n name: dataObj?.name,\n isActive: dataObj?.isActive,\n className: \"rowClassName1\",\n }));\n }\n const columns = useMemo(\n () => getStreetColumns(onEditClick, onDelete, onStatusChange, dispatch),\n [onEditClick, onDelete, onStatusChange, dispatch]\n );\n const [selectedColumns, setSelectedColumns] = useState(\n columns.map((col) => col.dataIndex)\n );\n useEffect(() => {\n if (window.innerWidth >= 1900) {\n setInnerW(210);\n } else {\n setInnerW(155);\n }\n const data = {\n page: page,\n size: size,\n query: query,\n visibility: \"nondeleted\",\n };\n dispatch(get").concat(questionnaireName, "(data));\n }, [dispatch, page, ").concat(questionnaireName, "Render, query, size]);\n const updateSize = (newSize) => {\n setSize(newSize); // Update state\n Cookies.set(\n \"pagination-size-questionnaire-").concat(questionnaireName.toLowerCase(), "\",\n JSON.stringify(newSize),\n {\n expires: 7,\n }\n ); // Save to cookies\n };\n\n return (\n <>\n {loading ? <Loading /> : null}\n <Layout className={style.layout}>\n <Content className={style.content}>\n <header className={style.header}>\n <Button onClick={onClickModal} color=\"green\">\n <PlusIcon /> Soraq\xE7a \u0259lav\u0259 et\n </Button>\n <Filter\n columns={columns}\n selectedColumns={selectedColumns}\n setQuery={setQuery}\n disabledElementCount={3}\n setPage={setPage}\n />\n </header>\n </Content>\n <Layout className={style.layout1}>\n <Content className={style.content}>\n <div className={style.table_header}>\n <h2>").concat(constantColumnName, "</h2>\n <div className={style.buttons}>\n <ColSort\n columns={columns}\n selectedColumns={selectedColumns}\n handleColumnToggle={handleColumnToggle}\n />\n </div>\n </div>\n <div className=\"bigTable\">\n <Table\n selectedColumns={selectedColumns}\n innerW={innerW}\n dataSource={data}\n columns={columns}\n disableDrag={true}\n />\n </div>\n <div className={style.pagination}>\n <Pagination\n size={size}\n setSize={updateSize}\n total={paginationLength}\n page={page}\n onChange={setPage}\n />\n </div>\n <FormModal\n ref={ref}\n width={454}\n title={\"Yeni soraq\xE7a yaratma\"}\n titleEdit={\"Soraq\xE7a redakt\u0259 etm\u0259\"}\n okText={\"Yadda saxla\"}\n cancelText={\"Ba\u011Fla\"}\n onSubmit={onSubmit}\n onEdit={onEdit}\n className={\"absolute\"}\n centered={false}>\n <Item\n rules={[\n { required: true, message: \"\" },\n { min: 3, message: \"\u018Fn az\u0131ndan 3 simvol olmal\u0131d\u0131r\" },\n ]}\n name={\"name\"}\n label={\"Ad\"}>\n <Input className={style.modal_input} />\n </Item>\n </FormModal>\n <DeleteModal\n onCancel={() => dispatch(setDeleteModalVisible(false))}\n width={280}>\n <Delete\n onDelete={() => dispatch(delete").concat(questionnaireName, "(id))}\n onCancel={() => dispatch(setDeleteModalVisible(false))}\n value={\"Soraq\xE7an\u0131\"}\n />\n </DeleteModal>\n <ViewModal onCancel={closeOnViewModal} width={695}>\n {<Success onClick={closeOnViewModal} value={\"Soraq\xE7a\"} />}\n </ViewModal>\n </Content>\n </Layout>\n </Layout>\n </>\n );\n};\n\nexport default Questionnaires").concat(questionnaireName, "Content;\n");
28
+ var constantBoilerplateTemplate = "import * as React from \"react\";\nimport { Switch, Tooltip } from \"antd\";\nimport style from \"../Questionnaires.module.scss\";\nimport { setDeleteModalVisible } from \"../../../store/slices/global\";\nimport { DeleteIconQ, EditIcon } from \"../../../assets/icons\";\n\nexport const getStreetColumns = (\n onEditClick,\n onDelete,\n onStatusChange,\n dispatch,\n innerW\n) => [\n {\n title: \"\u2116\",\n dataIndex: \"num\",\n showCheckbox: false,\n ellipsis: true,\n width: 35,\n },\n {\n title: \"".concat(constantColumnName, "\",\n dataIndex: \"name\",\n width: innerW,\n disabled: true,\n ellipsis: true,\n },\n {\n title: \"Status\",\n key: \"status\",\n disabled: true,\n\n filter: false,\n render: (data) => (\n <Tooltip placement=\"top\" title=\"Statusu d\u0259yi\u015F\">\n <Switch\n size=\"medium\"\n checked={data?.isActive}\n onChange={(checked) => onStatusChange(data, checked, dispatch)}\n />\n </Tooltip>\n ),\n },\n {\n title: \"\",\n key: \"actions\",\n showCheckbox: false,\n width: 80,\n render: (data) => (\n <>\n <div className={style.number}>\n <div className={style.actions}>\n <div onClick={() => onEditClick(data)}>\n <EditIcon />\n </div>\n <div\n onClick={() => {\n onDelete(data?.id);\n dispatch(setDeleteModalVisible(true));\n }}\n >\n <DeleteIconQ />\n </div>\n </div>\n </div>\n </>\n ),\n },\n ];\n");
29
+ var sliceBoilerplateTemplate = "\nexport const get".concat(questionnaireName, " = createAsyncThunk(\n \"/get").concat(questionnaireName, "\",\n async (data, { dispatch }) => {\n try {\n dispatch(setLoading(true));\n const response = await Services.get").concat(questionnaireName, "(\n data.size,\n data.page,\n data.query,\n data.visibility\n );\n dispatch(setLoading(false));\n return response?.data;\n } catch (error) {\n errorMessage(error.response?.data?.message);\n dispatch(setLoading(false));\n }\n }\n);\n\nexport const get").concat(questionnaireName, "All = createAsyncThunk(\n \"/get").concat(questionnaireName, "All\",\n async (visibility, { dispatch }) => {\n try {\n dispatch(setLoading(true));\n const response = await Services.get").concat(questionnaireName, "All(visibility);\n dispatch(setLoading(false));\n return response?.data;\n } catch (error) {\n errorMessage(error.response?.data?.message);\n dispatch(setLoading(false));\n }\n }\n);\n\nexport const add").concat(questionnaireName, " = createAsyncThunk(\n \"/add").concat(questionnaireName, "\",\n async (data, { dispatch }) => {\n try {\n dispatch(setLoading(true));\n await Services.add").concat(questionnaireName, "(data);\n dispatch(setLoading(false));\n dispatch(set").concat(questionnaireName, "Render((prev) => !prev));\n dispatch(setViewModalVisible(true));\n } catch (error) {\n errorMessage(error.response?.data?.message);\n dispatch(setLoading(false));\n }\n }\n);\nexport const edit").concat(questionnaireName, " = createAsyncThunk(\n \"/edit").concat(questionnaireName, "\",\n async (data, { dispatch }) => {\n try {\n dispatch(setLoading(true));\n const response = await Services.edit").concat(questionnaireName, "(data);\n dispatch(setLoading(false));\n dispatch(set").concat(questionnaireName, "Render((prev) => !prev));\n return response?.data;\n } catch (error) {\n errorMessage(error.response?.data?.message);\n dispatch(setLoading(false));\n }\n }\n);\n\nexport const delete").concat(questionnaireName, " = createAsyncThunk(\n \"/delete").concat(questionnaireName, "\",\n async (id, { dispatch }) => {\n try {\n dispatch(setLoading(true));\n await Services.delete").concat(questionnaireName, "(id);\n dispatch(setLoading(false));\n dispatch(setDeleteModalVisible(false));\n dispatch(set").concat(questionnaireName, "Render((prev) => !prev));\n } catch (error) {\n dispatch(setDeleteModalVisible(false));\n errorMessage(error.response?.data?.message);\n dispatch(setLoading(false));\n }\n }\n);\n\nexport const ").concat(questionnaireName, "Visibility = createAsyncThunk(\n \"").concat(questionnaireName, "Visibility\",\n async (data, { dispatch }) => {\n try {\n dispatch(setLoading(true));\n const response = await Services.").concat(questionnaireName, "Visibility(data);\n dispatch(setLoading(false));\n dispatch(set").concat(questionnaireName, "Render((prev) => !prev));\n return response?.data;\n } catch (error) {\n errorMessage(error.response?.data?.message);\n dispatch(setLoading(false));\n }\n }\n);\n\n// ---- end generated ----\n");
30
+ var servicesBoilerplateTemplate = "\n// ---- generated by questionnaireGenerator: ".concat(questionnaireName, " ----\n static get").concat(questionnaireName, " = async (size, page, query, visibility) => {\n const response = await api.get(`").concat(endpointName, "/${size}/page/${page}?visibility=${visibility}&name=${query?.name}`);\n return response?.data;\n };\n static get").concat(questionnaireName, "All = async (visibility) => {\n const response = await api.get(`").concat(endpointName, "?visibility=${visibility}`);\n return response?.data;\n };\n static add").concat(questionnaireName, " = async (value) => {\n const response = await api.post(\"").concat(endpointName, "\", value);\n return response?.data;\n };\n static edit").concat(questionnaireName, " = async (data) => {\n const response = await api.put(`").concat(endpointName, "/${data?.id}`, data);\n return response?.data;\n };\n static delete").concat(questionnaireName, " = async (id) => {\n const response = await api.delete(`").concat(endpointName, "/${id}`);\n return response?.data;\n };\n static ").concat(questionnaireName, "Visibility = async (data) => {\n const response = await api.patch(`").concat(endpointName, "/${data?.id}/visibility/${data?.checked}`);\n return response?.data;\n };\n// ---- end generated ----\n");
31
+ var pathExportsTemplate = "\n// ---- generated by questionnaireGenerator: ".concat(questionnaireName.toUpperCase(), " ----\nexport const ").concat(pathConstA, " = QUESTIONNAIRES + \"").concat(endpointName, "\";\nexport const ").concat(pathConstB, " = SETTINGS_QUESTIONNAIRES + \"").concat(endpointName, "\";\n// ---- end generated ----\n");
32
+
33
+ /* ------------------ HELPERS ------------------ */
34
+
35
+ function findRepoRoot(startDir) {
36
+ var dir = path.resolve(startDir);
37
+ var root = path.parse(dir).root;
38
+ while (true) {
39
+ var pkg = path.join(dir, "package.json");
40
+ if (fs.existsSync(pkg)) return dir;
41
+ if (dir === root) return null;
42
+ dir = path.dirname(dir);
43
+ }
44
+ }
45
+ function locateQuestionnaireSlice(repoRoot) {
46
+ var candidates = [path.join(repoRoot, "src", "store", "slices", "questionnaire", "index.js"), path.join(repoRoot, "src", "store", "slices", "questionnaire", "index.jsx"), path.join(repoRoot, "src", "store", "slices", "questionnaire.js"), path.join(repoRoot, "src", "store", "slices", "questionnaire", "index.ts"), path.join(repoRoot, "src", "store", "slices", "questionnaire", "index.tsx")];
47
+ for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
48
+ var p = _candidates[_i];
49
+ if (fs.existsSync(p)) return p;
50
+ }
51
+ return null;
52
+ }
53
+ function locateQuestionnaireService(repoRoot) {
54
+ var candidates = [path.join(repoRoot, "src", "store", "slices", "questionnaire", "service.js"), path.join(repoRoot, "src", "store", "slices", "questionnaire", "services.js"), path.join(repoRoot, "src", "services", "questionnaire.js"), path.join(repoRoot, "src", "services", "questionnaire", "index.js"), path.join(repoRoot, "src", "services", "questionnaire", "service.js")];
55
+ for (var _i2 = 0, _candidates2 = candidates; _i2 < _candidates2.length; _i2++) {
56
+ var p = _candidates2[_i2];
57
+ if (fs.existsSync(p)) return p;
58
+ }
59
+ return null;
60
+ }
61
+ function locateGlobalSlice(repoRoot) {
62
+ var candidates = [path.join(repoRoot, "src", "store", "slices", "global", "index.js"), path.join(repoRoot, "src", "store", "slices", "global", "index.jsx"), path.join(repoRoot, "src", "store", "slices", "global.js"), path.join(repoRoot, "src", "store", "slices", "global", "index.ts")];
63
+ for (var _i3 = 0, _candidates3 = candidates; _i3 < _candidates3.length; _i3++) {
64
+ var p = _candidates3[_i3];
65
+ if (fs.existsSync(p)) return p;
66
+ }
67
+ return null;
68
+ }
69
+ function locatePathUtils(repoRoot) {
70
+ var candidates = [path.join(repoRoot, "src", "utils", "path.js"), path.join(repoRoot, "src", "utils", "paths.js"), path.join(repoRoot, "src", "constants", "path.js"), path.join(repoRoot, "src", "utils", "path", "index.js")];
71
+ for (var _i4 = 0, _candidates4 = candidates; _i4 < _candidates4.length; _i4++) {
72
+ var p = _candidates4[_i4];
73
+ if (fs.existsSync(p)) return p;
74
+ }
75
+ return null;
76
+ }
77
+ function locateRoutesFile(repoRoot) {
78
+ var candidates = [path.join(repoRoot, "src", "routes", "QuestionnaireRoutes.jsx"), path.join(repoRoot, "src", "routes", "QuestionnaireRoutes.js"), path.join(repoRoot, "src", "routes", "questionnaireRoutes.jsx"), path.join(repoRoot, "src", "routes", "QuestionnairesRoutes.jsx")];
79
+ for (var _i5 = 0, _candidates5 = candidates; _i5 < _candidates5.length; _i5++) {
80
+ var p = _candidates5[_i5];
81
+ if (fs.existsSync(p)) return p;
82
+ }
83
+ return null;
84
+ }
85
+ function locateSidebarFile(repoRoot) {
86
+ var candidates = [path.join(repoRoot, "src", "layout", "QuestionnairesSidebar", "index.jsx"), path.join(repoRoot, "src", "layout", "QuestionnairesSidebar", "index.js"), path.join(repoRoot, "src", "layout", "QuestionnairesSidebar", "Index.jsx"), path.join(repoRoot, "src", "layout", "QuestionnairesSidebar", "index.tsx")];
87
+ for (var _i6 = 0, _candidates6 = candidates; _i6 < _candidates6.length; _i6++) {
88
+ var p = _candidates6[_i6];
89
+ if (fs.existsSync(p)) return p;
90
+ }
91
+ return null;
92
+ }
93
+
94
+ /**
95
+ * Insert insertionText into a class body identified by any of the classNamePatterns.
96
+ * Returns { updated, inserted, reason, classPattern }.
97
+ */
98
+ function insertIntoClassBody(content, classNamePatterns, insertionText, marker) {
99
+ if (marker && content.includes(marker)) return {
100
+ updated: content,
101
+ inserted: false,
102
+ reason: "marker_present"
103
+ };
104
+ var _iterator = _createForOfIteratorHelper(classNamePatterns),
105
+ _step;
106
+ try {
107
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
108
+ var pattern = _step.value;
109
+ var regex = new RegExp("class\\s+".concat(pattern, "\\s*\\{"), "m");
110
+ var match = content.match(regex);
111
+ if (match) {
112
+ var classStartIdx = match.index;
113
+ var openBraceIdx = content.indexOf("{", classStartIdx);
114
+ if (openBraceIdx === -1) continue;
115
+ var depth = 0;
116
+ var endIdx = -1;
117
+ for (var i = openBraceIdx; i < content.length; i++) {
118
+ var ch = content[i];
119
+ if (ch === "{") depth++;else if (ch === "}") {
120
+ depth--;
121
+ if (depth === 0) {
122
+ endIdx = i;
123
+ break;
124
+ }
125
+ }
126
+ }
127
+ if (endIdx === -1) continue;
128
+ var newContent = content.slice(0, endIdx) + "\n" + insertionText + "\n" + content.slice(endIdx);
129
+ return {
130
+ updated: newContent,
131
+ inserted: true,
132
+ reason: "inserted_in_class",
133
+ classPattern: pattern
134
+ };
135
+ }
136
+ }
137
+ } catch (err) {
138
+ _iterator.e(err);
139
+ } finally {
140
+ _iterator.f();
141
+ }
142
+ return {
143
+ updated: content,
144
+ inserted: false,
145
+ reason: "class_not_found"
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Insert a route block into a route parent block identified by startRegex.
151
+ * Finds parent <Route ...> ... </Route> and inserts insertionText before its closing </Route>.
152
+ *
153
+ * Robust approach:
154
+ * - Find the regex match for startRegex (which targets the path attribute).
155
+ * - Locate the opening '<Route' tag start (lastIndexOf before the match).
156
+ * - Determine if that opening tag is self-closing — if so, we cannot insert inside.
157
+ * - Otherwise, scan forward from that opening tag, counting nested <Route> openings and </Route> closings
158
+ * until we find the matching closing tag for the found parent, then insert before that closing tag.
159
+ */
160
+ function insertRouteIntoParentBlock(content, startRegex, insertionText, marker) {
161
+ if (marker && content.includes(marker)) return {
162
+ updated: content,
163
+ inserted: false,
164
+ reason: "marker_present"
165
+ };
166
+ var match = startRegex.exec(content);
167
+ if (!match) return {
168
+ updated: content,
169
+ inserted: false,
170
+ reason: "start_not_found"
171
+ };
172
+ var matchIndex = match.index;
173
+
174
+ // Find the opening "<Route" that contains this match (search backwards)
175
+ var openTagIdx = content.lastIndexOf("<Route", matchIndex);
176
+ if (openTagIdx === -1) return {
177
+ updated: content,
178
+ inserted: false,
179
+ reason: "open_tag_not_found"
180
+ };
181
+
182
+ // Find end of opening tag '>'
183
+ var openingTagEnd = content.indexOf(">", openTagIdx);
184
+ if (openingTagEnd === -1) return {
185
+ updated: content,
186
+ inserted: false,
187
+ reason: "opening_tag_end_not_found"
188
+ };
189
+ var openingTagText = content.slice(openTagIdx, openingTagEnd + 1);
190
+ // detect self-closing like '<Route ... />'
191
+ var selfClosing = /\/\s*>$/.test(openingTagText);
192
+ if (selfClosing) return {
193
+ updated: content,
194
+ inserted: false,
195
+ reason: "parent_self_closing"
196
+ };
197
+
198
+ // Now scan forward from openTagIdx and match nested <Route> ... </Route>
199
+ var openRe = /<Route\b/g;
200
+ var closeRe = /<\/Route>/g;
201
+ var idx = openTagIdx;
202
+ var depth = 0;
203
+ var endIdx = -1;
204
+
205
+ // initialize lastIndex for both regexes
206
+ openRe.lastIndex = idx;
207
+ closeRe.lastIndex = idx;
208
+ while (true) {
209
+ var nextOpen = openRe.exec(content);
210
+ var nextClose = closeRe.exec(content);
211
+ if (nextOpen && (!nextClose || nextOpen.index < nextClose.index)) {
212
+ // found another opening before the next closing
213
+ depth++;
214
+ idx = nextOpen.index + 6; // move past '<Route'
215
+ openRe.lastIndex = idx;
216
+ closeRe.lastIndex = idx;
217
+ continue;
218
+ } else if (nextClose) {
219
+ // found a closing tag
220
+ depth--;
221
+ idx = nextClose.index + 8; // move past '</Route>'
222
+ // when depth goes to zero we've closed the original open we counted
223
+ if (depth === 0) {
224
+ endIdx = nextClose.index;
225
+ break;
226
+ }
227
+ openRe.lastIndex = idx;
228
+ closeRe.lastIndex = idx;
229
+ continue;
230
+ } else {
231
+ // no more matches
232
+ break;
233
+ }
234
+ }
235
+ if (endIdx === -1) {
236
+ return {
237
+ updated: content,
238
+ inserted: false,
239
+ reason: "matching_close_not_found"
240
+ };
241
+ }
242
+
243
+ // Insert text before the found closing tag
244
+ var newContent = content.slice(0, endIdx) + insertionText + content.slice(endIdx);
245
+ return {
246
+ updated: newContent,
247
+ inserted: true,
248
+ reason: "inserted_into_parent"
249
+ };
250
+ }
251
+
252
+ /* ------------------ MAIN ------------------ */
253
+
254
+ try {
255
+ console.log("=== questionnaireGenerator starting ===");
256
+ var repoRoot = findRepoRoot(__dirname) || findRepoRoot(process.cwd());
257
+ var root = repoRoot || process.cwd();
258
+ console.log("repo root:", root);
259
+
260
+ // 1) create component & constant files
261
+ var targetFolder = path.join(root, "src", "pages", "Questionnnaires", "Questionnaires".concat(questionnaireName, "Content"));
262
+ fs.mkdirSync(targetFolder, {
263
+ recursive: true
264
+ });
265
+ var componentPath = path.join(targetFolder, "index.jsx");
266
+ fs.writeFileSync(componentPath, boilerplateTemplate, "utf8");
267
+ var constantPath = path.join(targetFolder, "constant.js");
268
+ fs.writeFileSync(constantPath, constantBoilerplateTemplate, "utf8");
269
+ console.log("Created component and constant:", componentPath, constantPath);
270
+
271
+ // 2) update questionnaire slice file
272
+ var slicePath = locateQuestionnaireSlice(root);
273
+ if (!slicePath) {
274
+ console.warn("questionnaire slice file not found — skipping slice update.");
275
+ } else {
276
+ console.log("Found questionnaire slice:", slicePath);
277
+ var sliceContent = fs.readFileSync(slicePath, "utf8");
278
+
279
+ // Ensure Services import
280
+ if (!/\bServices\b/.test(sliceContent)) {
281
+ var servicesImport = "import Services from \"../../../services/questionnaire\";\n";
282
+ sliceContent = servicesImport + sliceContent;
283
+ console.log("Added Services import to slice (verify path).");
284
+ }
285
+
286
+ // Ensure createAsyncThunk import
287
+ if (!/createAsyncThunk/.test(sliceContent)) {
288
+ sliceContent = "import { createAsyncThunk } from \"@reduxjs/toolkit\";\n" + sliceContent;
289
+ console.log("Added createAsyncThunk import to slice.");
290
+ }
291
+
292
+ // Add set{Questionnaire}Render import into global import or create new import
293
+ var renderName = "set".concat(questionnaireName, "Render");
294
+ var globalImportRegex = /import\s*\{\s*([^}]+)\}\s*from\s*['"]([^'"]*\/slices\/global|[^'"]*\/global)['"];?/m;
295
+ var globalImportMatch = sliceContent.match(globalImportRegex);
296
+ if (globalImportMatch) {
297
+ var fullImport = globalImportMatch[0];
298
+ var importedNames = globalImportMatch[1];
299
+ var modulePath = globalImportMatch[2];
300
+ var existing = importedNames.split(",").map(function (n) {
301
+ return n.trim();
302
+ }).filter(Boolean);
303
+ if (!existing.includes(renderName)) {
304
+ var merged = existing.concat([renderName]).join(", ");
305
+ sliceContent = sliceContent.replace(fullImport, "import { ".concat(merged, " } from \"").concat(modulePath, "\";"));
306
+ console.log("Added ".concat(renderName, " to existing global import."));
307
+ } else {
308
+ console.log("".concat(renderName, " already present in global import."));
309
+ }
310
+ } else {
311
+ sliceContent = "import { ".concat(renderName, " } from \"../../../store/slices/global\";\n") + sliceContent;
312
+ console.log("Added new global import for ".concat(renderName, " (verify path)."));
313
+ }
314
+
315
+ // Insert slice thunks before createSlice declaration (marker-protected)
316
+ if (!sliceContent.includes("// ---- generated by questionnaireGenerator: ".concat(questionnaireName, " ----"))) {
317
+ var createSliceRegex = /export\s+const\s+questionnaire\s*=\s*createSlice\s*\(\s*\{/m;
318
+ var match = sliceContent.match(createSliceRegex);
319
+ if (match) {
320
+ var idx = match.index;
321
+ sliceContent = sliceContent.slice(0, idx) + sliceBoilerplateTemplate + "\n" + sliceContent.slice(idx);
322
+ console.log("Inserted thunks before createSlice.");
323
+ } else {
324
+ var exportIdx = sliceContent.search(/export\s+default/);
325
+ if (exportIdx !== -1) {
326
+ sliceContent = sliceContent.slice(0, exportIdx) + sliceBoilerplateTemplate + sliceContent.slice(exportIdx);
327
+ console.log("createSlice not found: inserted thunks before export default.");
328
+ } else {
329
+ sliceContent += "\n" + sliceBoilerplateTemplate;
330
+ console.log("createSlice not found: appended thunks to end.");
331
+ }
332
+ }
333
+ } else {
334
+ console.log("Slice thunks already generated — skipping insertion.");
335
+ }
336
+
337
+ // Insert reducers into extraReducers builder block
338
+ var reducerLines = "\n // ---- generated reducers for ".concat(questionnaireName, " ----\n builder.addCase(get").concat(questionnaireName, ".fulfilled, (state, { payload }) => {\n state.").concat(lowercaseFirstChar(questionnaireName), " = payload;\n });\n builder.addCase(get").concat(questionnaireName, "All.fulfilled, (state, { payload }) => {\n state.").concat(lowercaseFirstChar(questionnaireName), "All = payload;\n });\n // ---- end generated reducers ----\n ");
339
+ var extraReducersRegex = /extraReducers\s*:\s*\(?\s*builder\s*\)?\s*=>\s*{?/m;
340
+ var extraMatch = sliceContent.match(extraReducersRegex);
341
+ if (extraMatch) {
342
+ var startIdx = extraMatch.index;
343
+ var arrowIdx = sliceContent.indexOf("=>", startIdx);
344
+ var firstBraceIdx = sliceContent.indexOf("{", arrowIdx);
345
+ if (firstBraceIdx === -1) {
346
+ sliceContent += "\n" + reducerLines;
347
+ console.warn("Couldn't find '{' after extraReducers arrow — appended reducers at file end.");
348
+ } else {
349
+ // find matching closing brace
350
+ var depth = 0;
351
+ var endIdx = -1;
352
+ for (var i = firstBraceIdx; i < sliceContent.length; i++) {
353
+ var ch = sliceContent[i];
354
+ if (ch === "{") depth++;else if (ch === "}") {
355
+ depth--;
356
+ if (depth === 0) {
357
+ endIdx = i;
358
+ break;
359
+ }
360
+ }
361
+ }
362
+ if (endIdx === -1) {
363
+ sliceContent += "\n" + reducerLines;
364
+ console.warn("Couldn't find matching closing brace for extraReducers — appended reducers at file end.");
365
+ } else {
366
+ if (!sliceContent.includes("builder.addCase(get".concat(questionnaireName, ".fulfilled"))) {
367
+ sliceContent = sliceContent.slice(0, endIdx) + reducerLines + sliceContent.slice(endIdx);
368
+ console.log("Inserted reducers into extraReducers block.");
369
+ } else {
370
+ console.log("Reducers already present in slice — skipping reducer insertion.");
371
+ }
372
+ }
373
+ }
374
+ } else {
375
+ sliceContent += "\n" + reducerLines;
376
+ console.warn("extraReducers not found — appended reducers at file end.");
377
+ }
378
+ fs.writeFileSync(slicePath, sliceContent, "utf8");
379
+ console.log("Updated slice file:", slicePath);
380
+ } // end slice update
381
+
382
+ // 3) update / insert into Services file
383
+ var servicePath = locateQuestionnaireService(root);
384
+ if (!servicePath) {
385
+ console.warn("Questionnaire service file not found — skipping service insertion.");
386
+ } else {
387
+ console.log("Found service file at:", servicePath);
388
+ var svcContent = fs.readFileSync(servicePath, "utf8");
389
+ var marker = "// ---- generated by questionnaireGenerator: ".concat(questionnaireName, " ----");
390
+ var classCandidates = ["Services", "QuestionnaireServices", "QuestionnaireService", "service", "ServicesClass"];
391
+ var result = insertIntoClassBody(svcContent, classCandidates, servicesBoilerplateTemplate, marker);
392
+ if (result.inserted) {
393
+ svcContent = result.updated;
394
+ fs.writeFileSync(servicePath, svcContent, "utf8");
395
+ console.log("Inserted service methods into class (".concat(result.classPattern, ") in:"), servicePath);
396
+ } else {
397
+ if (result.reason === "marker_present") {
398
+ console.log("Service methods already present in service file — skipping.");
399
+ } else if (result.reason === "class_not_found") {
400
+ if (!svcContent.includes(marker)) {
401
+ svcContent += "\n" + servicesBoilerplateTemplate;
402
+ fs.writeFileSync(servicePath, svcContent, "utf8");
403
+ console.warn("Could not find services class — appended service methods to end of file. Please move them into the class manually.");
404
+ } else {
405
+ console.log("Marker present — no changes made.");
406
+ }
407
+ } else {
408
+ console.warn("Service insertion not performed; reason:", result.reason);
409
+ }
410
+ }
411
+ }
412
+
413
+ // 4) update global slice (initialState, reducer, export list)
414
+ var globalPath = locateGlobalSlice(root);
415
+ if (!globalPath) {
416
+ console.warn("Global slice not found — please add set<...>Render manually if needed.");
417
+ } else {
418
+ console.log("Found global slice:", globalPath);
419
+ var globalContent = fs.readFileSync(globalPath, "utf8");
420
+
421
+ // 4.a add stateKey to initialState
422
+ var stateKey = "".concat(questionnaireName, "Render");
423
+ if (!new RegExp("\\b".concat(stateKey, "\\s*:")).test(globalContent)) {
424
+ if (/topicsRender\s*:\s*false,?/.test(globalContent)) {
425
+ globalContent = globalContent.replace(/(topicsRender\s*:\s*false,?)/, "$1\n ".concat(stateKey, ": false,"));
426
+ console.log("Inserted ".concat(stateKey, " after topicsRender."));
427
+ } else if (/notificationsRender\s*:\s*false,?/.test(globalContent)) {
428
+ globalContent = globalContent.replace(/(notificationsRender\s*:\s*false,?)/, "$1\n ".concat(stateKey, ": false,"));
429
+ console.log("Inserted ".concat(stateKey, " after notificationsRender."));
430
+ } else {
431
+ globalContent = globalContent.replace(/const\s+initialState\s*=\s*{/, "const initialState = {\n ".concat(stateKey, ": false,"));
432
+ console.log("Inserted ".concat(stateKey, " near initialState opening (fallback)."));
433
+ }
434
+ } else {
435
+ console.log("".concat(stateKey, " already exists in initialState."));
436
+ }
437
+
438
+ // 4.b add reducer function
439
+ var reducerName = "set".concat(questionnaireName, "Render");
440
+ if (!new RegExp("\\b".concat(reducerName, "\\b")).test(globalContent)) {
441
+ var reducersStart = globalContent.search(/reducers\s*:\s*{/m);
442
+ if (reducersStart !== -1) {
443
+ var insertPos = globalContent.indexOf("{", reducersStart) + 1;
444
+ var reducerText = "\n ".concat(reducerName, ": (state, { payload }) => {\n state.").concat(questionnaireName, "Render = payload;\n },\n");
445
+ globalContent = globalContent.slice(0, insertPos) + reducerText + globalContent.slice(insertPos);
446
+ console.log("Inserted reducer ".concat(reducerName, " into reducers block."));
447
+ } else {
448
+ globalContent = globalContent.replace(/reducers\s*:\s*{/, "reducers: {\n ".concat(reducerName, ": (state, { payload }) => {\n state.").concat(questionnaireName, "Render = payload;\n },"));
449
+ console.log("Inserted reducer ".concat(reducerName, " with fallback insertion."));
450
+ }
451
+ } else {
452
+ console.log("Reducer ".concat(reducerName, " already present."));
453
+ }
454
+
455
+ // 4.c add reducer name into export destructure
456
+ var exportDestructRegex = /export\s+const\s*\{\s*([\s\S]*?)\}\s*=\s*global\.actions\s*;/m;
457
+ var exportMatch = globalContent.match(exportDestructRegex);
458
+ if (exportMatch) {
459
+ var full = exportMatch[0];
460
+ var inner = exportMatch[1];
461
+ var names = inner.split(",").map(function (n) {
462
+ return n.trim();
463
+ }).filter(Boolean);
464
+ if (!names.includes(reducerName)) {
465
+ var insertIndex = names.findIndex(function (n) {
466
+ return /set.*Render$/.test(n);
467
+ });
468
+ if (insertIndex === -1) insertIndex = 0;
469
+ names.splice(insertIndex + 1, 0, reducerName);
470
+ var newInner = names.join(",\n ");
471
+ var newExport = "export const {\n ".concat(newInner, "\n} = global.actions;");
472
+ globalContent = globalContent.replace(full, newExport);
473
+ console.log("Added ".concat(reducerName, " to exported global actions."));
474
+ } else {
475
+ console.log("".concat(reducerName, " already present in exported global.actions."));
476
+ }
477
+ } else {
478
+ if (!new RegExp("export\\s+const\\s*\\{[\\s\\S]*".concat(reducerName, "[\\s\\S]*\\}\\s*=\\s*global\\.actions")).test(globalContent)) {
479
+ globalContent += "\nexport const { ".concat(reducerName, " } = global.actions;\n");
480
+ console.log("Appended a new export for ".concat(reducerName, " (fallback)."));
481
+ }
482
+ }
483
+ fs.writeFileSync(globalPath, globalContent, "utf8");
484
+ console.log("Updated global slice:", globalPath);
485
+ }
486
+
487
+ // 5) update utils/path.js with the two route constants
488
+ var pathUtils = locatePathUtils(root);
489
+ if (!pathUtils) {
490
+ console.warn("utils/path.js not found — skipping path constants insertion.");
491
+ } else {
492
+ console.log("Found path utils file:", pathUtils);
493
+ var pathContent = fs.readFileSync(pathUtils, "utf8");
494
+ var _marker = "// ---- generated by questionnaireGenerator: ".concat(questionnaireName.toUpperCase(), " ----");
495
+ if (pathContent.includes(_marker)) {
496
+ console.log("Path exports already present in utils/path.js — skipping.");
497
+ } else {
498
+ var insertAfterRegex = /(export\s+const\s+QUESTIONNAIRES\b[^\n]*\n)/m;
499
+ if (insertAfterRegex.test(pathContent)) {
500
+ pathContent = pathContent.replace(insertAfterRegex, "$1".concat(pathExportsTemplate));
501
+ console.log("Inserted path exports after QUESTIONNAIRES constant.");
502
+ } else {
503
+ pathContent += "\n" + pathExportsTemplate;
504
+ console.log("Appended path exports to end of utils/path.js (fallback).");
505
+ }
506
+ fs.writeFileSync(pathUtils, pathContent, "utf8");
507
+ console.log("Updated utils/path.js:", pathUtils);
508
+ }
509
+ }
510
+
511
+ // 6) update routes/QuestionnaireRoutes.jsx: add component import, add path constants to utils/path named import,
512
+ // and insert Route entries into Document and Settings parent blocks.
513
+ var routesPath = locateRoutesFile(root);
514
+ if (!routesPath) {
515
+ console.warn("QuestionnaireRoutes.jsx not found — skipping routes changes.");
516
+ } else {
517
+ console.log("Found routes file:", routesPath);
518
+ var routesContent = fs.readFileSync(routesPath, "utf8");
519
+
520
+ // 6.a Add the path constants into the named import from "../utils/path"
521
+ var pathImportRegex = /import\s*\{\s*([\s\S]*?)\}\s*from\s*['"]\.\.\/utils\/path['"];?/m;
522
+ var pathImportMatch = routesContent.match(pathImportRegex);
523
+ if (pathImportMatch) {
524
+ var _full = pathImportMatch[0];
525
+ var _inner = pathImportMatch[1];
526
+ // split names and clean
527
+ var _names = _inner.split(",").map(function (n) {
528
+ return n.replace(/[\n\r]/g, "").trim();
529
+ }).filter(Boolean);
530
+ var changed = false;
531
+ if (!_names.includes(pathConstA)) {
532
+ _names.push(pathConstA);
533
+ changed = true;
534
+ }
535
+ if (!_names.includes(pathConstB)) {
536
+ _names.push(pathConstB);
537
+ changed = true;
538
+ }
539
+ if (changed) {
540
+ // preserve multiline formatting
541
+ var hasMultiline = /\n/.test(_inner);
542
+ var _newInner = hasMultiline ? _names.join(",\n ") : _names.join(", ");
543
+ var newImport = "import {\n ".concat(_newInner, "\n} from \"../utils/path\";");
544
+ routesContent = routesContent.replace(_full, newImport);
545
+ console.log("Inserted path constants into ../utils/path named import in routes file.");
546
+ } else {
547
+ console.log("Path constants already present in ../utils/path import — skipping.");
548
+ }
549
+ } else {
550
+ // fallback: add a small named import
551
+ var safeImport = "import { ".concat(pathConstA, ", ").concat(pathConstB, " } from \"../utils/path\";\n");
552
+ // place after first import block
553
+ var firstNonImport = routesContent.indexOf("\n\n");
554
+ if (firstNonImport !== -1 && firstNonImport < 5000) {
555
+ routesContent = routesContent.slice(0, firstNonImport) + "\n" + safeImport + routesContent.slice(firstNonImport);
556
+ } else {
557
+ routesContent = safeImport + routesContent;
558
+ }
559
+ console.log("No ../utils/path named import found — added separate import for path constants.");
560
+ }
561
+
562
+ // 6.b add component import (separate import line), marker-protected
563
+ var componentImportLine = "import Questionnaires".concat(questionnaireName, "Content from \"../pages/Questionnnaires/Questionnaires").concat(questionnaireName, "Content\";\n");
564
+ var importMarker = "// ---- generated import by questionnaireGenerator: ".concat(questionnaireName, " ----");
565
+ if (!routesContent.includes(componentImportLine.trim())) {
566
+ // try insert near other Questionnnaires imports
567
+ var pagesImportRegex = /(import\s+[^;]*\.\.\/pages\/Questionnnaires[^;]*;\n)/g;
568
+ var lastMatch;
569
+ while (true) {
570
+ var m = pagesImportRegex.exec(routesContent);
571
+ if (!m) break;
572
+ lastMatch = m;
573
+ }
574
+ if (lastMatch && lastMatch.index !== undefined) {
575
+ var _insertPos = lastMatch.index + lastMatch[0].length;
576
+ routesContent = routesContent.slice(0, _insertPos) + "\n".concat(componentImportLine) + routesContent.slice(_insertPos);
577
+ routesContent = routesContent.replace(componentImportLine, "".concat(importMarker, "\n").concat(componentImportLine));
578
+ console.log("Inserted component import near other Questionnnaires imports.");
579
+ } else {
580
+ // fallback: append after top imports
581
+ var _firstNonImport = routesContent.indexOf("\n\n");
582
+ if (_firstNonImport !== -1 && _firstNonImport < 5000) {
583
+ routesContent = routesContent.slice(0, _firstNonImport) + "\n".concat(importMarker, "\n").concat(componentImportLine) + routesContent.slice(_firstNonImport);
584
+ console.log("Inserted component import near top of routes file (fallback).");
585
+ } else {
586
+ routesContent = "".concat(importMarker, "\n").concat(componentImportLine, "\n") + routesContent;
587
+ console.log("Prepended component import to routes file (fallback).");
588
+ }
589
+ }
590
+ } else {
591
+ console.log("Component import already present — skipping import insertion.");
592
+ }
593
+
594
+ // 6.c Insert Route entries (Document & Settings). Marker-protected.
595
+ // Use robust regexes that match path attribute regardless of attribute ordering / newlines
596
+ var docStartRegex = /<Route\b[^>]*\bpath=(?:["'])questionnaires(?:["'])[^>]*>/m;
597
+ var settingsStartRegex = /<Route\b[^>]*\bpath=(?:["'])settings\/questionnaires(?:["'])[^>]*>/m;
598
+ var docRouteMarker = "";
599
+ var setRouteMarker = "";
600
+ var routeEntryDocument = "\n".concat(docRouteMarker, "\n <Route\n path={").concat(pathConstA, "}\n element={<Questionnaires").concat(questionnaireName, "Content />}\n />\n");
601
+ var routeEntrySettings = "\n".concat(setRouteMarker, "\n <Route\n path={").concat(pathConstB, "}\n element={<Questionnaires").concat(questionnaireName, "Content />}\n />\n");
602
+
603
+ // Insert into Document Circulation Routes parent block
604
+ var resDoc = insertRouteIntoParentBlock(routesContent, docStartRegex, routeEntryDocument, docRouteMarker);
605
+ if (resDoc.inserted) {
606
+ routesContent = resDoc.updated;
607
+ console.log("Inserted document route entry.");
608
+ } else if (resDoc.reason === "marker_present") {
609
+ console.log("Document route marker present — skipping insertion.");
610
+ } else {
611
+ // fallback: try to insert before Settings Routes anchor
612
+ var settingsAnchor = routesContent.indexOf('{/* Settings Routes */}');
613
+ if (settingsAnchor !== -1) {
614
+ routesContent = routesContent.slice(0, settingsAnchor) + routeEntryDocument + routesContent.slice(settingsAnchor);
615
+ console.log("Fallback inserted document route before Settings anchor.");
616
+ } else {
617
+ console.warn("Couldn't reliably insert document route — please add manually. Reason:", resDoc.reason);
618
+ }
619
+ }
620
+
621
+ // Insert into Settings Routes parent block
622
+ var resSet = insertRouteIntoParentBlock(routesContent, settingsStartRegex, routeEntrySettings, setRouteMarker);
623
+ if (resSet.inserted) {
624
+ routesContent = resSet.updated;
625
+ console.log("Inserted settings route entry.");
626
+ } else if (resSet.reason === "marker_present") {
627
+ console.log("Settings route marker present — skipping insertion.");
628
+ } else {
629
+ // fallback: find the settings block and append before its closing tag
630
+ var settingsBlockRegex = /<Route\s*\n\s*path="settings\/questionnaires"[\s\S]*?<\/Route>/m;
631
+ if (settingsBlockRegex.test(routesContent)) {
632
+ routesContent = routesContent.replace(settingsBlockRegex, function (m) {
633
+ var idx = m.lastIndexOf("</Route>");
634
+ if (idx !== -1) {
635
+ return m.slice(0, idx) + routeEntrySettings + m.slice(idx);
636
+ }
637
+ return m;
638
+ });
639
+ console.log("Fallback inserted settings route into settings block.");
640
+ } else {
641
+ console.warn("Couldn't reliably insert settings route — please add manually. Reason:", resSet.reason);
642
+ }
643
+ }
644
+
645
+ // write back routes file
646
+ fs.writeFileSync(routesPath, routesContent, "utf8");
647
+ console.log("Updated routes file:", routesPath);
648
+ } // end routes update
649
+
650
+ // 7) update layout/QuestionnairesSidebar/index.jsx (add import of path constants & append menu item)
651
+ var sidebarPath = locateSidebarFile(root);
652
+ if (!sidebarPath) {
653
+ console.warn("QuestionnairesSidebar not found — skipping sidebar changes.");
654
+ } else {
655
+ console.log("Found sidebar file:", sidebarPath);
656
+ var sidebarContent = fs.readFileSync(sidebarPath, "utf8");
657
+
658
+ // Add path constants into the named import from "../../utils/path"
659
+ var sidebarPathImportRegex = /import\s*\{\s*([\s\S]*?)\}\s*from\s*['"]\.\.\/\.\.\/utils\/path['"];?/m;
660
+ var sidebarPathImportMatch = sidebarContent.match(sidebarPathImportRegex);
661
+ if (sidebarPathImportMatch) {
662
+ var _full2 = sidebarPathImportMatch[0];
663
+ var _inner2 = sidebarPathImportMatch[1];
664
+ var _names2 = _inner2.split(",").map(function (n) {
665
+ return n.replace(/[\n\r]/g, "").trim();
666
+ }).filter(Boolean);
667
+ var _changed = false;
668
+ if (!_names2.includes(pathConstA)) {
669
+ _names2.push(pathConstA);
670
+ _changed = true;
671
+ }
672
+ if (!_names2.includes(pathConstB)) {
673
+ _names2.push(pathConstB);
674
+ _changed = true;
675
+ }
676
+ if (_changed) {
677
+ var _hasMultiline = /\n/.test(_inner2);
678
+ var _newInner2 = _hasMultiline ? _names2.join(",\n ") : _names2.join(", ");
679
+ var _newImport = "import {\n ".concat(_newInner2, "\n} from \"../../utils/path\";");
680
+ sidebarContent = sidebarContent.replace(_full2, _newImport);
681
+ console.log("Inserted sidebar path constants into ../../utils/path named import.");
682
+ } else {
683
+ console.log("Sidebar already has path constants imported — skipping.");
684
+ }
685
+ } else {
686
+ // fallback: add import near top
687
+ var _safeImport = "import { ".concat(pathConstA, ", ").concat(pathConstB, " } from \"../../utils/path\";\n");
688
+ var _firstNonImport2 = sidebarContent.indexOf("\n\n");
689
+ if (_firstNonImport2 !== -1 && _firstNonImport2 < 5000) {
690
+ sidebarContent = sidebarContent.slice(0, _firstNonImport2) + "\n" + _safeImport + sidebarContent.slice(_firstNonImport2);
691
+ } else {
692
+ sidebarContent = _safeImport + sidebarContent;
693
+ }
694
+ console.log("Added separate import for sidebar path constants (fallback).");
695
+ }
696
+
697
+ // Append the item object into the items array end (marker-protected)
698
+ var sidebarMarker = "// ---- generated sidebar item by questionnaireGenerator: ".concat(questionnaireName, " ----");
699
+ if (!sidebarContent.includes(sidebarMarker)) {
700
+ // find the items = [ ... ] block
701
+ var itemsArrayRegex = /const\s+items\s*=\s*\[\s*([\s\S]*?)\s*\];/m;
702
+ var itemsMatch = sidebarContent.match(itemsArrayRegex);
703
+ var menuObject = " {\n key: \"".concat(endpointName.replace(/^\//, ""), "\", //delete the \"/\" at the start of string \n label: \"").concat(constantColumnName, "\", \n link:\n mainPath === \"/settings\"\n ? ").concat(pathConstB, " \n : ").concat(pathConstA, ", \n },\n");
704
+ if (itemsMatch) {
705
+ // insert before closing bracket of the items array
706
+ var _startIdx = itemsMatch.index;
707
+ var matchText = itemsMatch[0];
708
+ // insert at end of matchText before closing '];'
709
+ var _insertPos2 = _startIdx + matchText.lastIndexOf("]");
710
+ var newContent = sidebarContent.slice(0, _insertPos2) + "\n" + menuObject + sidebarMarker + "\n" + sidebarContent.slice(_insertPos2);
711
+ sidebarContent = newContent;
712
+ console.log("Inserted sidebar menu object into items array.");
713
+ } else {
714
+ // fallback: try to find 'const items = [' and append within file near where items is declared
715
+ var itemsStart = sidebarContent.indexOf("const items = [");
716
+ if (itemsStart !== -1) {
717
+ var _insertPos3 = sidebarContent.indexOf("];", itemsStart);
718
+ if (_insertPos3 !== -1) {
719
+ sidebarContent = sidebarContent.slice(0, _insertPos3) + ",\n" + menuObject + sidebarMarker + "\n" + sidebarContent.slice(_insertPos3);
720
+ console.log("Fallback inserted sidebar menu object into items array.");
721
+ } else {
722
+ console.warn("Couldn't find end of items array to insert menu object — manual insertion needed.");
723
+ }
724
+ } else {
725
+ console.warn("Couldn't find items array in sidebar file — manual insertion needed.");
726
+ }
727
+ }
728
+ } else {
729
+ console.log("Sidebar menu object marker present — skipping insertion.");
730
+ }
731
+
732
+ // write back sidebar file
733
+ fs.writeFileSync(sidebarPath, sidebarContent, "utf8");
734
+ console.log("Updated sidebar file:", sidebarPath);
735
+ }
736
+ console.log("=== Done. Please review the modified files ===");
737
+ console.log(" - component:", componentPath);
738
+ console.log(" - constant:", constantPath);
739
+ if (slicePath) console.log(" - questionnaire slice:", slicePath);
740
+ if (servicePath) console.log(" - questionnaire service:", servicePath);
741
+ if (globalPath) console.log(" - global slice:", globalPath);
742
+ if (pathUtils) console.log(" - utils/path:", pathUtils);
743
+ if (routesPath) console.log(" - routes file:", routesPath);
744
+ if (sidebarPath) console.log(" - sidebar file:", sidebarPath);
745
+ console.log("Review import paths, Unicode names, and run linter/build.");
746
+ } catch (err) {
747
+ console.error("Error:", err && err.stack ? err.stack : err);
748
+ process.exit(1);
749
+ }