MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / ImportWorkspace

Method ImportWorkspace

internal/store/export.go:210–437  ·  view source on GitHub ↗

ImportWorkspace imports a workspace from an exported data structure. It creates a new workspace with regenerated IDs, remapping all references. If newName is non-empty, it overrides the workspace name and slug.

(data *models.WorkspaceExport, newName string, ownerID string)

Source from the content-addressed store, hash-verified

208// It creates a new workspace with regenerated IDs, remapping all references.
209// If newName is non-empty, it overrides the workspace name and slug.
210func (s *Store) ImportWorkspace(data *models.WorkspaceExport, newName string, ownerID string) (*models.Workspace, error) {
211 if data.Version != 1 {
212 return nil, fmt.Errorf("unsupported export version: %d", data.Version)
213 }
214
215 // Determine workspace name/slug
216 wsName := data.Workspace.Name
217 wsSlug := data.Workspace.Slug
218 if newName != "" {
219 wsName = newName
220 wsSlug = newName
221 }
222
223 ws, err := s.CreateWorkspace(models.WorkspaceCreate{
224 Name: wsName,
225 Slug: wsSlug,
226 Description: data.Workspace.Description,
227 Settings: data.Workspace.Settings,
228 OwnerID: ownerID,
229 })
230 if err != nil {
231 return nil, fmt.Errorf("create workspace: %w", err)
232 }
233
234 // Run all data inserts in a single transaction for atomicity
235 tx, err := s.db.Begin()
236 if err != nil {
237 return nil, fmt.Errorf("begin transaction: %w", err)
238 }
239 defer tx.Rollback()
240
241 // ID mapping: old ID -> new ID
242 collMap := make(map[string]string)
243 itemMap := make(map[string]string)
244
245 // Import collections
246 for _, c := range data.Collections {
247 newCollID := newID()
248 collMap[c.ID] = newCollID
249
250 // Coerce empty-string / malformed settings to a valid JSON object
251 // before insert. IDEA-1484 (PR #562) hardened collections.settings
252 // to NOT NULL DEFAULT '{}', but this INSERT explicitly supplies
253 // the settings column — so the DEFAULT clause does NOT fire when
254 // c.Settings is "". Without this coercion, Postgres rejects `""`
255 // at JSONB type-validation and SQLite silently stores invalid
256 // JSON. Legacy bundles and plain-JSON workspace imports
257 // (handlers_workspaces.go, handlers_import_bundle.go,
258 // cmd/pad/main.go's migrate command) can still carry "" or
259 // malformed settings, so normalization belongs at the import
260 // boundary rather than at the schema level. IDEA-1488 extends
261 // this to log-and-coerce on non-empty malformed JSON.
262 settings := coerceJSONForImport(c.Settings, "{}", "collections.settings", c.ID, ws.ID, true)
263
264 _, err := tx.Exec(s.q(`
265 INSERT INTO collections (id, workspace_id, name, slug, icon, description, schema, settings, prefix, sort_order, is_default, is_system, created_at, updated_at)
266 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),
267 newCollID, ws.ID, c.Name, c.Slug, c.Icon, c.Description, c.Schema, settings, c.Prefix, c.SortOrder, s.dialect.BoolToInt(c.IsDefault), s.dialect.BoolToInt(c.IsSystem),

Calls 9

CreateWorkspaceMethod · 0.95
qMethod · 0.95
makeFunction · 0.85
newIDFunction · 0.85
coerceJSONForImportFunction · 0.85
remapFieldIDsFunction · 0.85
ExecMethod · 0.80
BoolToIntMethod · 0.65