Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid generation sub doc type of the map #169

Open
d3m3vilurr opened this issue Jan 6, 2025 · 12 comments
Open

Invalid generation sub doc type of the map #169

d3m3vilurr opened this issue Jan 6, 2025 · 12 comments

Comments

@d3m3vilurr
Copy link

Hi. I got a trouble to transform a map type /w mongoose 8.9.3 & tsgen 9.5.0 (I used mongoose 8.6.2 & tsgen 9.2.10 before)

here is test snippet

  • test.js
const mongoose = require('mongoose');

const _schema = {
    test: {
        inner_map: {
            type: Map,
            required: false,
            of: {
                value: {
                    type: Number,
                    required: true,
                },
            },
        },
    },
};
// eslint-disable-line
const schema = new mongoose.Schema(
    _schema,
    {
        collection: 'test',
        minimize: false,
    }
);

module.exports = schema;
  • test.mtgen.ts
import * as mongoose from 'mongoose';
import Schema from './test';
export const Test = mongoose.model('Test', Schema);
  • transform logs
> npx mtgen test.mtgen.ts
Writing interfaces to src/interfaces/mongoose.gen.ts
Generating mongoose typescript definitions... !
(node:4026197) [DEP0180] DeprecationWarning: fs.Stats constructor is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
    SyntaxError: '=' expected. (18:31)
      16 |  * ```
      17 |  */
    > 18 | export type TestTestInner_map$* = {
         |                               ^
      19 | value: number;
      20 | _id: mongoose.Types.ObjectId;
      21 | }

a problem is getSubdocName's path contains $*. (in this case, it was test.inner_map.$*)

so, simple dirty hack was just filter the $* after split a path. (.filter((v) => v !== '$*')). but I don't know it's correct solution or not.

@francescov1 can you check this issue?

@d3m3vilurr
Copy link
Author

just filtering made another problem. added .map((v) => v.replace('$*', 'unk')) between split & map

@francescov1
Copy link
Owner

Hey @d3m3vilurr are you sure this is valid Mongoose syntax? See what ChatGPT said about it: https://chatgpt.com/share/677cb8c3-8804-800c-9f97-2c2df4195453

If its valid Im happy to add support for it, but want to make sure before I do

@francescov1
Copy link
Owner

Ive always used nested child schemas when doing this sort of logic. Seems like Mongoose docs use them too: https://mongoosejs.com/docs/schematypes.html#maps

@d3m3vilurr
Copy link
Author

d3m3vilurr commented Jan 7, 2025

well.. in a special reason, I(We) use homemade internal schema transformer for making a mongoose schema (js format) then re-transform ts definition using this project.

actually, I don't know it's valid or not...
a spec would be valid (in my practical experiance).
but maybe just gray area of the mongoose schema

because, we have an experience which handling large dataset with mongoose, but usually, we don't use sub document format without a reason but still we use it.
and also, this time is our very first time that we use map type of mongoose, I believe mongoose doesn't have different rule for sub doc of the map, and actually, it was works before updating a module.

anyway, mongoose doc link said
Mongoose supports a special $* syntax to populate all elements in a map. For example, suppose your socialMediaHandles map contains a ref:

this part seems pretty related my problem.

but i retest with example of the mongoose

const userSchema = new Schema({
  socialMediaHandles: {
    type: Map,
    of: new Schema({
      handle: String,
      oauth: {
        type: ObjectId,
        ref: 'OAuth'
      }
    })
  }
});

if it works, I close this issue then fix our side :)

@d3m3vilurr
Copy link
Author

it's same.

Generating mongoose typescript definitions... !
(node:3698538) [DEP0180] DeprecationWarning: fs.Stats constructor is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
    SyntaxError: '=' expected. (18:36)
      16 |  * ```
      17 |  */
    > 18 | export type UserSocialMediaHandles$* = {
         |                                    ^
      19 | handle?: string;
      20 | oauth?: OAuth["_id"] | OAuth;
      21 | _id: mongoose.Types.ObjectId;

@francescov1
Copy link
Owner

This latest PR should resolve the naming issue, were stripping out special characters from the Mongoose schema name now. Could you try upgrading to 9.5.1 and see if the problem persists? Again try with the subschema syntax:

const userSchema = new Schema({
  socialMediaHandles: {
    type: Map,
    of: new Schema({
      handle: String,
      oauth: {
        type: ObjectId,
        ref: 'OAuth'
      }
    })
  }
});

@d3m3vilurr
Copy link
Author

Hi @francescov1
I think you also tested it on your environ. but IDK what is different.

here is my testing subset.

  • schema/user.js
const mongoose = require('mongoose');

const _schema = {
    socialMediaHandles: {
        type: Map,
        of: new mongoose.Schema({
            handle: String,
            oauth: {
                type: mongoose.Types.ObjectId,
                ref: 'OAuth'
            }
        })
    }
};
// eslint-disable-line
const schema = new mongoose.Schema(
    _schema,
    {
        collection: 'user',
        minimize: false,
        shardKey: {
            _id: 1,
        },
    }
);

module.exports = schema;
  • schema/user.mtgen.ts
import * as mongoose from 'mongoose';
import Schema from './user';
export const AuthAccount = mongoose.model('User', Schema);
  • package.json
{
  "dependencies": {
    "mongoose": "^8.9.3",
    "mongoose-tsgen": "^9.5.1"
  }
}
  • npx mtgen "schema/**/*.mtgen.ts"
Writing interfaces to src/interfaces/mongoose.gen.ts
Generating mongoose typescript definitions... !
(node:3126110) [DEP0180] DeprecationWarning: fs.Stats constructor is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
    SyntaxError: '=' expected. (18:36)
      16 |  * ```
      17 |  */
    > 18 | export type UserSocialMediaHandles$* = {
         |                                    ^
      19 | handle?: string;
      20 | oauth?: OAuth["_id"] | OAuth;
      21 | _id: mongoose.Types.ObjectId;

and also, mongoose also uses non new Schema form for subdocument on their unittest codeset.
so imho, it's very old hidden feature of the mongoose schema.
(since mongoose 3.x or 4.x)

PS. we(our company) met another issues with mongoose map after version up mongoose 8.9.3. so we bump down mongoose to 8.8.4 from 8.9.x. but $* issues is still remained on tsgen.

@francescov1
Copy link
Owner

Okay let me look further, will report back

@francescov1
Copy link
Owner

@d3m3vilurr Im unable to reproduce your issue, seems to work fine in my environment. Can you provide a simple repo I can run to see the problem?

@d3m3vilurr
Copy link
Author

@francescov1 Hello. Sorry I'm late. https://github.com/d3m3vilurr/mongoose-tsgen-169-testcase here is testcase repo.

@francescov1
Copy link
Owner

@d3m3vilurr been a bit swamped with a move and new job, will try to get to by end of weekend

@d3m3vilurr
Copy link
Author

no problem. we are in lunar new year holiday break.
and long time ago, we temporary forked a project to inject mongoose-long type. so an issue is not urgent :)

thank you for your supporting & congrats new job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants