Skip to content

feat:Add model management mock#1795

Merged
hexqi merged 6 commits intoopentiny:developfrom
lichunn:feat/info-material
Mar 31, 2026
Merged

feat:Add model management mock#1795
hexqi merged 6 commits intoopentiny:developfrom
lichunn:feat/info-material

Conversation

@lichunn
Copy link
Copy Markdown
Collaborator

@lichunn lichunn commented Mar 31, 2026

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced data persistence for models with automatic tracking of creation and modification timestamps.
  • Improvements

    • Added validation to prevent duplicate page routes within the same application.
  • Style

    • Refined spacing and sizing adjustments in lifecycle and page settings panels.

@github-actions github-actions bot added the enhancement New feature or request label Mar 31, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

Caution

Review failed

Failed to post review comments

Walkthrough

Backend services transition from static in-memory storage to NeDB persistence with database-backed CRUD operations, route conflict detection, and CSS styling refinements across Vue components.

Changes

Cohort / File(s) Summary
Model Service Refactoring
mockServer/src/assets/json/model.json, mockServer/src/services/model.js
Migrated model data storage from static JSON import to NeDB database with getDatabasePath('model.db'). Renamed AppsService to ModelService. Updated CRUD operations to persist data to NeDB, added numeric ID generation and ISO timestamps. Restructured defaultModel with new parameter schema and URL configuration.
Page Service Enhancement
mockServer/src/services/pages.js
Added non-unique index on route field alongside new index on app. Implemented route conflict detection during create: returns ROUTE_CONFLICT error (code 409) if a record with matching app and route already exists. Added default route derivation from name field.
Component Style Adjustments
packages/plugins/page/src/PageSetting.vue, packages/common/component/LifeCycles.vue, packages/plugins/block/src/BlockSetting.vue
Added .input-output margin styling in PageSetting. Increased .life-cycle-tips height from 16px to 30px in LifeCycles. Refactored BlockSetting's collapse item structure with relocated life-cycles-container class and updated corresponding deep selector styling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Whiskers twitch with glee—
NeDB now holds our models free,
Routes conflict no more,
Styles dance across the floor,
Changes bloom like clover three! 🍀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'feat:Add model management mock' is vague and inconsistent with the actual changeset. The PR makes significant backend changes to model service persistence (NeDB integration), request/response structures, and page route conflict handling—not simply 'adding model management mock'. Clarify the title to reflect the primary change, such as 'feat: Integrate NeDB persistence for model service' or 'feat: Add model and page database persistence layer' to accurately represent the scope of changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/info-material

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/plugins/page/src/PageSetting.vue (1)

502-506: Consider adding overflow handling for the fixed height.

Setting a fixed height: 80px without an overflow property may cause content to be clipped if the lifecycle configuration content exceeds this height.

♻️ Suggested improvement
 .input-output {
   :deep(.tiny-collapse-item__content) {
     height: 80px;
+    overflow-y: auto;
   }
 }

This ensures that if the content exceeds 80px, users can scroll to view it rather than having it clipped.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/plugins/page/src/PageSetting.vue` around lines 502 - 506, The
.input-output rule sets a fixed height on :deep(.tiny-collapse-item__content)
which can clip content; change it to handle overflow by replacing the fixed
height with max-height: 80px (or keep height: 80px) and add overflow-y: auto
(and optionally overflow-x: hidden) so users can scroll when lifecycle
configuration content exceeds 80px; update the CSS block referencing
.input-output and :deep(.tiny-collapse-item__content) accordingly.
mockServer/src/services/model.js (1)

29-58: Extract the repeated parameter schema into a shared constant.

The same id/name/status/test definition is copied into parameters and four separate children blocks. Any contract change now requires five manual edits, which is likely to drift quickly. A shared schema constant cloned into each location would keep the mock consistent.

Also applies to: 71-100, 129-158, 163-192, 233-262

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` around lines 29 - 58, Extract the repeated
parameter definitions (the objects for id, name, status, test) into a single
shared constant (e.g., BASE_PARAMETERS) in model.js and replace the inline
arrays in the top-level parameters and each children block with a cloned copy of
that constant; update all occurrences that currently repeat the same schema (the
arrays at the shown block and the similar blocks at the other ranges noted) to
reference a deep-cloned copy (e.g., using JSON.parse(JSON.stringify(...)) or a
utility clone) so each location gets its own instance but stays consistent when
the contract changes, and ensure any code that mutates these arrays uses the
cloned instance rather than the shared reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mockServer/src/services/model.js`:
- Around line 334-337: In create() and update() ensure the client-supplied
params cannot overwrite the server-generated id: when building newModel (the
object using mockId++) and when applying updates via the Mongo-like update using
$set: params, remove/omit the id field from params first (strip params.id) so
the server's id (mockId and stored record id) remains authoritative; update the
code paths that build newModel and that call the $set update to use the
sanitized params.
- Around line 346-363: The delete and update methods currently return
getResponseData(result) even when no record was found, producing a success
envelope with data: null; change delete (which calls this.db.findOneAsync and
this.db.removeAsync) to check whether the initial find returned a record (or
whether removeAsync reports affected rows) and, if missing, call
getResponseData({ error: { code: 'NOT_FOUND', message: 'Model not found' }})
instead of returning null data; similarly modify update to verify the
post-update findOneAsync result and return the same not-found error payload via
getResponseData when the record is absent; keep using the existing
getResponseData helper to format both success and error responses.
- Around line 329-343: The create() method currently treats this.modelList as
the source of truth causing duplicate IDs and stale responses; change it to
reload or read persisted records from the DB (don't rely on this.modelList),
compute the new id from persisted records (e.g., max id + 1), call and await the
DB's async insert method (use insertAsync or equivalent instead of
this.db.insert) and only return the persisted/listed records (either by awaiting
the insert result and returning that or by calling list() after insert
completes) so responses reflect the on-disk state and updates/deletes are not
lost.

---

Nitpick comments:
In `@mockServer/src/services/model.js`:
- Around line 29-58: Extract the repeated parameter definitions (the objects for
id, name, status, test) into a single shared constant (e.g., BASE_PARAMETERS) in
model.js and replace the inline arrays in the top-level parameters and each
children block with a cloned copy of that constant; update all occurrences that
currently repeat the same schema (the arrays at the shown block and the similar
blocks at the other ranges noted) to reference a deep-cloned copy (e.g., using
JSON.parse(JSON.stringify(...)) or a utility clone) so each location gets its
own instance but stays consistent when the contract changes, and ensure any code
that mutates these arrays uses the cloned instance rather than the shared
reference.

In `@packages/plugins/page/src/PageSetting.vue`:
- Around line 502-506: The .input-output rule sets a fixed height on
:deep(.tiny-collapse-item__content) which can clip content; change it to handle
overflow by replacing the fixed height with max-height: 80px (or keep height:
80px) and add overflow-y: auto (and optionally overflow-x: hidden) so users can
scroll when lifecycle configuration content exceeds 80px; update the CSS block
referencing .input-output and :deep(.tiny-collapse-item__content) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fe3a6d47-9c85-4f63-a4b1-32895b1d2f09

📥 Commits

Reviewing files that changed from the base of the PR and between e0821bc and 7d98c1a.

⛔ Files ignored due to path filters (1)
  • mockServer/src/database/model.db is excluded by !**/*.db
📒 Files selected for processing (4)
  • mockServer/src/assets/json/appinfo.json
  • mockServer/src/assets/json/model.json
  • mockServer/src/services/model.js
  • packages/plugins/page/src/PageSetting.vue

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
mockServer/src/services/model.js (2)

330-330: ⚠️ Potential issue | 🟠 Major

create() is still deriving state from a stale in-memory cache.

this.modelList starts empty and is never reconciled by delete() or update(). After a restart or one of those writes, Line 330 can allocate the next id from outdated data, and Lines 339-342 can return records that no longer match the DB.

Also applies to: 339-342

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` at line 330, create() computes mockId and
returns records from the stale in-memory cache this.modelList (and
delete()/update() never reconcile it), causing incorrect ids and returned
records; fix by removing reliance on this.modelList in create()—query the
authoritative DB/store for the current max id and the current records (recompute
mockId from that result) or ensure delete()/update() update this.modelList after
mutations so the cache stays consistent; specifically update the create() logic
that sets mockId and returns records, and either make delete()/update() mutate
this.modelList to reflect DB changes or eliminate modelList reads entirely and
always read fresh data from the DB/store.

331-336: ⚠️ Potential issue | 🔴 Critical

Keep id and audit timestamps server-owned.

Line 336 still lets the request body overwrite the generated id / created_at / updated_at, and Line 359 applies params verbatim on update. That lets clients rewrite the record key, leaves updated_at stale unless the client sends it, and can make Line 360 return null after a successful id change.

🔒 Suggested fix
 async create(params) {
+  const { id: _ignoredId, created_at: _ignoredCreatedAt, updated_at: _ignoredUpdatedAt, ...payload } = params || {}
   const newModel = {
     ...defaultModel,
     id: mockId++,
     created_at: new Date().toISOString(),
     updated_at: new Date().toISOString(),
-    ...params
+    ...payload
   }
 async update(id, params) {
-  await this.db.updateAsync({ id: Number(id) }, { $set: params })
+  const { id: _ignoredId, created_at: _ignoredCreatedAt, updated_at: _ignoredUpdatedAt, ...payload } = params || {}
+  await this.db.updateAsync(
+    { id: Number(id) },
+    { $set: { ...payload, updated_at: new Date().toISOString() } }
+  )
   const result = await this.db.findOneAsync({ id: Number(id) })

Also applies to: 359-360

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` around lines 331 - 336, The server
currently allows client-supplied params to overwrite server-owned fields: in the
newModel creation (where newModel, defaultModel and mockId are used) and in the
update code that spreads params onto an existing record, stop params from
mutating id/created_at/updated_at; specifically, when building newModel remove
id/created_at/updated_at from params (or apply params first and then explicitly
set id: mockId++, created_at: new Date().toISOString(), updated_at: new
Date().toISOString()), and in the update routine (the block that spreads params
onto the existing model) strip id and created_at from incoming params and always
set updated_at = new Date().toISOString() before saving so clients cannot change
the primary key or timestamps and updated_at is always server-updated.
🧹 Nitpick comments (1)
mockServer/src/services/model.js (1)

28-57: Extract the repeated parameter schema into a shared definition.

The same four-field schema is duplicated five times here. Any later field change has to stay in lockstep across every copy, which is easy to miss. A shared constant/helper would keep the mock metadata consistent.

Also applies to: 70-99, 128-157, 162-191, 232-261

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` around lines 28 - 57, The repeated
four-field parameter schema in the "parameters" arrays should be extracted into
a single shared constant (e.g., COMMON_PARAMETERS) and reused wherever the same
schema appears (locations with parameter arrays at lines shown in the review).
Replace the duplicated inline array in each occurrence (the object with props
'id','name','status','test') by referencing or spreading the shared constant
(for example parameters: COMMON_PARAMETERS or parameters:
[...COMMON_PARAMETERS]) so future changes are made in one place; update
exports/imports in mockServer/src/services/model.js as needed to use the shared
definition.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mockServer/src/services/model.js`:
- Around line 322-325: The code currently creates a unique index on NeDB's
internal _id via this.db.ensureIndex but the API uses the field id; modify the
indexing to ensure uniqueness on the API-facing id field by adding/adjusting the
call to this.db.ensureIndex({ fieldName: 'id', unique: true }), and verify this
change alongside the create(), findOneAsync, updateAsync, and removeAsync logic
(and any reliance on this.modelList-generated ids) so duplicate API ids cannot
be inserted after restart.

---

Duplicate comments:
In `@mockServer/src/services/model.js`:
- Line 330: create() computes mockId and returns records from the stale
in-memory cache this.modelList (and delete()/update() never reconcile it),
causing incorrect ids and returned records; fix by removing reliance on
this.modelList in create()—query the authoritative DB/store for the current max
id and the current records (recompute mockId from that result) or ensure
delete()/update() update this.modelList after mutations so the cache stays
consistent; specifically update the create() logic that sets mockId and returns
records, and either make delete()/update() mutate this.modelList to reflect DB
changes or eliminate modelList reads entirely and always read fresh data from
the DB/store.
- Around line 331-336: The server currently allows client-supplied params to
overwrite server-owned fields: in the newModel creation (where newModel,
defaultModel and mockId are used) and in the update code that spreads params
onto an existing record, stop params from mutating id/created_at/updated_at;
specifically, when building newModel remove id/created_at/updated_at from params
(or apply params first and then explicitly set id: mockId++, created_at: new
Date().toISOString(), updated_at: new Date().toISOString()), and in the update
routine (the block that spreads params onto the existing model) strip id and
created_at from incoming params and always set updated_at = new
Date().toISOString() before saving so clients cannot change the primary key or
timestamps and updated_at is always server-updated.

---

Nitpick comments:
In `@mockServer/src/services/model.js`:
- Around line 28-57: The repeated four-field parameter schema in the
"parameters" arrays should be extracted into a single shared constant (e.g.,
COMMON_PARAMETERS) and reused wherever the same schema appears (locations with
parameter arrays at lines shown in the review). Replace the duplicated inline
array in each occurrence (the object with props 'id','name','status','test') by
referencing or spreading the shared constant (for example parameters:
COMMON_PARAMETERS or parameters: [...COMMON_PARAMETERS]) so future changes are
made in one place; update exports/imports in mockServer/src/services/model.js as
needed to use the shared definition.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 49c47084-dbd6-4334-a98a-8194defa6c22

📥 Commits

Reviewing files that changed from the base of the PR and between 7d98c1a and 4998430.

📒 Files selected for processing (4)
  • mockServer/src/services/model.js
  • packages/common/component/LifeCycles.vue
  • packages/plugins/block/src/BlockSetting.vue
  • packages/plugins/page/src/PageSetting.vue
✅ Files skipped from review due to trivial changes (2)
  • packages/plugins/page/src/PageSetting.vue
  • packages/common/component/LifeCycles.vue

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
mockServer/src/services/model.js (3)

358-363: ⚠️ Potential issue | 🟡 Minor

this.modelList cache is not updated after update.

Similar to delete(), the in-memory cache becomes stale after an update. This affects subsequent create() calls that read from modelList.

♻️ Suggested fix
 async update(id, params) {
+  const { id: _ignoredId, ...safeParams } = params  // Strip id from params
-  await this.db.updateAsync({ id: Number(id) }, { $set: params })
+  await this.db.updateAsync({ id: Number(id) }, { $set: safeParams })
   const result = await this.db.findOneAsync({ id: Number(id) })
+  this.modelList = await this.db.findAsync()

   return getResponseData(result)
 }

The diff also strips id from params to prevent clients from changing a record's primary key, which was flagged in a previous review.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` around lines 358 - 363, The update(id,
params) method currently updates the DB but does not refresh the in-memory cache
this.modelList and also allows params.id to overwrite the primary key; modify
update(id, params) to remove/ignore params.id before calling db.updateAsync,
then after retrieving the updated row via findOneAsync update the corresponding
entry in this.modelList (replace the object with the fresh result or rebuild the
list entry with the new fields) so subsequent create() and other methods see the
latest data, and finally return getResponseData(result).

339-342: ⚠️ Potential issue | 🔴 Critical

this.db.insert() is not awaited — response may return before persistence completes.

The insert operation is fire-and-forget. If it fails or is slow, the response already returns stale data. Other services in this codebase (e.g., pages.js, blockGroup.js) await insertAsync to ensure data integrity.

🐛 Proposed fix
-    this.db.insert(newModel)
-    this.modelList.push(newModel)
-
-    return getResponseData({ records: this.modelList })
+    await this.db.insertAsync(newModel)
+    this.modelList = await this.db.findAsync()
+
+    return getResponseData({ records: this.modelList })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` around lines 339 - 342, Await the DB insert
so the response waits for persistence: replace the fire-and-forget
this.db.insert(newModel) with an awaited call (use this.db.insertAsync(newModel)
if available, or await this.db.insert(...) and make the enclosing function
async), keep pushing to this.modelList only after successful insert, and
propagate/handle errors (reject or return an error response) before calling
return getResponseData({ records: this.modelList }).

345-350: ⚠️ Potential issue | 🟡 Minor

this.modelList cache is not updated after deletion.

After removeAsync, the in-memory modelList still contains the deleted record. Subsequent calls to create() will compute mockId from stale data, and if list() hasn't been called, the cache remains inconsistent.

♻️ Suggested fix
 async delete(id) {
   const result = await this.db.findOneAsync({ id: Number(id) })
   await this.db.removeAsync({ id: Number(id) })
+  this.modelList = await this.db.findAsync()

   return getResponseData(result)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mockServer/src/services/model.js` around lines 345 - 350, The delete(id)
method removes the record from the DB but never updates the in-memory cache
this.modelList, causing stale data (and wrong mockId in create()); after calling
this.db.removeAsync(...) update this.modelList by removing the matching entry
(or invalidate it so list() reloads) so that subsequent create() and list() use
consistent state—modify the delete method (and any related cache-invalidation
logic) to either splice out the item from this.modelList or set this.modelList =
null/[] after successful deletion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mockServer/src/services/model.js`:
- Line 13: The import has a typo: change the default import name from DateStore
to Datastore to match the `@seald-io/nedb` export, and update any instantiation
sites (e.g., where new DateStore(...) is used) to use Datastore instead (refer
to the import statement and the constructor call around the model
initialization/instantiation). Ensure the import reads "import Datastore from
'@seald-io/nedb'" and all references (constructor calls and variables) use the
exact symbol "Datastore".

---

Duplicate comments:
In `@mockServer/src/services/model.js`:
- Around line 358-363: The update(id, params) method currently updates the DB
but does not refresh the in-memory cache this.modelList and also allows
params.id to overwrite the primary key; modify update(id, params) to
remove/ignore params.id before calling db.updateAsync, then after retrieving the
updated row via findOneAsync update the corresponding entry in this.modelList
(replace the object with the fresh result or rebuild the list entry with the new
fields) so subsequent create() and other methods see the latest data, and
finally return getResponseData(result).
- Around line 339-342: Await the DB insert so the response waits for
persistence: replace the fire-and-forget this.db.insert(newModel) with an
awaited call (use this.db.insertAsync(newModel) if available, or await
this.db.insert(...) and make the enclosing function async), keep pushing to
this.modelList only after successful insert, and propagate/handle errors (reject
or return an error response) before calling return getResponseData({ records:
this.modelList }).
- Around line 345-350: The delete(id) method removes the record from the DB but
never updates the in-memory cache this.modelList, causing stale data (and wrong
mockId in create()); after calling this.db.removeAsync(...) update
this.modelList by removing the matching entry (or invalidate it so list()
reloads) so that subsequent create() and list() use consistent state—modify the
delete method (and any related cache-invalidation logic) to either splice out
the item from this.modelList or set this.modelList = null/[] after successful
deletion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 92d7e13a-4936-4dca-a100-df5ec363e644

📥 Commits

Reviewing files that changed from the base of the PR and between 4998430 and 3098135.

📒 Files selected for processing (1)
  • mockServer/src/services/model.js

chilingling
chilingling previously approved these changes Mar 31, 2026
@hexqi hexqi merged commit 06b9cd8 into opentiny:develop Mar 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants